Monday, March 28, 2011

Configuring the BeagleBoard to have network over usb0

After some experimenting, I have a kernel .config based on the kernel from the Angstrom BeagleBoard Demo. The original provided kernel with gether did not boot on my (loaned) BeagleBoard Rev B5. Only after disabling USB completely (kernel parameter nousb). As gether is the part I am most interested in, booting without USB is pretty pointless. Fortunately the kernel provides /proc/config.gz. Using this configuration, some little tuning (i.e. turning off the staging-modules because they do not compile), a kernel and suitable modules could be built.

Fedora almost expects using a initramfs for booting, and well, it surely makes troubleshooting easier! Getting dracut to run on a system where no network is available takes quite a lot of reboots (the BeagleBoard has one SD-slot for the filesystem, one mini-USB for power, a serial port for the console and nothing else that makes transport of files easy). Installing all the dependencies and disabling some dracut-modules /etc/dracut.conf (crypt dmraid mdraid multipath plymouth) in /etc/dracut.conf allows creating an initramfs.img. Before u-boot can use the initramfs.img, it needs to be converted with a command like:
# mkimage -A arm -O linux -T ramdisk -C none -e 0 -a 0 -n initramfs-2.6.38 -d /boot/initramfs-2.6.38.img /boot/uinitramfs-2.6.38.img

Currently, the generated files are on a VFAT-partition on an SD-card. This BeagleBoard boots from this card and uses the following settings to start the Fedora 13 ARM system:
OMAP3 beagleboard.org # printenv bootargs
bootargs=console=ttyO2,115200n8 root=/dev/mmcblk0p2 ro

OMAP3 beagleboard.org # printenv bootcmd
bootcmd=mmcinit ; fatload mmc 0:1 0x80000000 uimage-2.6.38 ; fatload mmc 0:1 0x81600000 uinitramfs-2.6.38.img ; bootm 0x80000000 0x81600000

OMAP3 beagleboard.org # boot

During boot, there are some messages that indicate that Ethernet-over-USB will be available:
[    0.334960] musb-hdrc: version 6.0, musb-dma, otg (peripheral+host), debug=0
[    0.335571] musb-hdrc musb-hdrc: USB OTG mode controller at fa0ab000 using DMA, IRQ 92
...
[    4.824340] g_ether gadget: using random self ethernet address
[    4.830505] g_ether gadget: using random host ethernet address
[    4.837341] usb0: MAC ba:98:d2:e3:60:36
[    4.841430] usb0: HOST MAC 4a:49:17:92:63:df
[    4.846008] g_ether gadget: Ethernet Gadget, version: Memorial Day 2008
[    4.853027] g_ether gadget: g_ether ready
[    4.857269] musb-hdrc musb-hdrc: MUSB HDRC host driver
[    4.863220] musb-hdrc musb-hdrc: new USB bus registered, assigned bus number 2
[    4.885742] usb usb2: New USB device found, idVendor=1d6b, idProduct=0002
[    4.892913] usb usb2: New USB device strings: Mfr=3, Product=2, SerialNumber=1
[    4.900543] usb usb2: Product: MUSB HDRC host driver
[    4.905792] usb usb2: Manufacturer: Linux 2.6.38 musb-hcd
[    4.911499] usb usb2: SerialNumber: musb-hdrc
...
[    5.383911] g_ether gadget: full speed config #1: CDC Ethernet (ECM)

The musb-hdrc is the controller-chip and the g_ether is the implementation of the USB-client side of the USB-over-Ethernet gadget. On my laptop the BeagleBoard gets detected as a "RNDIS/Ethernet Gadget" product from vendor "Linux 2.6.38 with musb-hdrc":
usb 1-1: new high speed USB device using ehci_hcd and address 66
usb 3-1: new full speed USB device using uhci_hcd and address 45
usb 3-1: not running at top speed; connect to a high speed hub
usb 3-1: New USB device found, idVendor=0525, idProduct=a4a2
usb 3-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
usb 3-1: Product: RNDIS/Ethernet Gadget
usb 3-1: Manufacturer: Linux 2.6.38 with musb-hdrc
cdc_ether 3-1:1.0: usb0: register 'cdc_ether' at usb-0000:00:1a.0-1, CDC Ethernet Device, 4a:49:17:92:63:df
usb0: no IPv6 routers present
device usb0 entered promiscuous mode
virbr0: topology change detected, propagating
virbr0: port 1(usb0) entering forwarding state

The last lines are automatically triggered by my ifplugd-configuration which checks for usb0 devices and on a link, the usb0 is added to the virbr0 from libvirt so that BeagleBoard immediately gets access to the network.

On the side of the BeagleBoard, /etc/sysconfig/network-scripts/ifcfg-usb0 is configured to request an IP-address over DHCP:
DEVICE="usb0"
BOOTPROTO="dhcp"
ONBOOT="yes"
MACADDR="ba:98:d2:e3:60:36"

I prefer to give the BeagleBoard the same MAC-address on every boot, by default it is a random one. Setting MACADDR in ifcfg-usb0 makes this happen. The g_ether kernel-module accepts a MAC-address as parameter, but as the module is builtin, this is not convenient (pass g_ether.dev_addr as kernel parameter, or echo it to /sys/module/g_ether/parameters/dev_addr).

Enabling the network on boot and activating usb0 was the only thing left todo:
# chkconfig network on
# ifup usb0

The compiled kernel, initramfs and modules are available for download and re-use. Please report any issues or success if you try them out.

Now this is all written down, it seems really easy and quick. Keep in mind that compiling a very minimal kernel takes at least 120 minutes on the BeagleBoard, the kernel and modules from the Angstom distribution took much more... The BeagleBoard has since gained the elevated status of a mock-builder and rebuild java-1.5.0-gcj-1.5.0.0-32.fc13.bootstrap.src.rpm in "138 minutes 22 seconds", yay!