Mount BeagleBoard Root Filesystem over NFS via USB
This page explains how to bridge the usb0 device to eth0 on your Linux host, enabling your Linux host to act as a hub for your BeagleBoard and connecting it to the outside world. As an additional reference, the following article is good at explaining how to create a typical Ethernet bridge on a Linux machine with two Ethernet cards:
Linux Journal: Kernel Korner - Linux as an Ethernet Bridge
Before starting, make sure you have the "bridge-utils" package installed on your Linux host. This gives you the "brctl" command, which you need for creating and using an Ethernet bridge.
Contents
Step 1: Create an Ethernet Bridge from usb0 to eth0 on your Linux Host
The main difference between the scenario in the Linux Journal article mentioned above and the BeagleBoard is that we're creating a bridge from usb0 to eth0 instead of from eth1 to eth0. Also, we have to deal with the fact that "usb0" doesn't exist as a device on our Linux host except when the USB Gadget support is running on the connected Beagleboard, which isn't the case when we're first booting the Linux host.
My Linux host is running Fedora Core 10. I'm sure some of the following network configuration steps are specific to Fedora, but they can probably be easily adapted to other Linux distributions. On Fedora, I edited the network scripts "/etc/sysconfig/network-scripts/ifcfg-eth0" and "/etc/sysconfig/network-scripts/ifcfg-usb0" by hand to make sure those interfaces had no IP or gateway settings, and that they were not controlled by the Fedora network manager by setting NM_CONTROLLED=no.
Contents of /etc/sysconfig/network-scripts/ifcfg-eth0:
DEVICE=eth0 ONBOOT=no BOOTPROTO=none TYPE=Ethernet USERCTL=no PEERDNS=yes IPV6INIT=no NM_CONTROLLED=no
Contents of /etc/sysconfig/network-scripts/ifcfg-usb0:
DEVICE=usb0 ONBOOT=no BOOTPROTO=none TYPE=Ethernet USERCTL=no IPV6INIT=no NM_CONTROLLED=no PEERDNS=yes
Next, I created a new script "/etc/sysconfig/network-scripts/ifcfg-br0" that is going to be the "bridge" interface that connects both usb0 and eth0 to the outside world. This script looks a lot like what "ifcfg-eth0" used to look like.
Contents of /etc/sysconfig/network-scripts/ifcfg-br0:
# Ethernet Bridge DEVICE=br0 ONBOOT=no SEARCH="dmlab" # Replace with your search domains BOOTPROTO=none NETMASK=255.255.255.0 # Replace with your subnet's netmask IPADDR=192.168.198.1 # Replace with your Linux host's IP address USERCTL=no PEERDNS=yes IPV6INIT=no GATEWAY=192.168.198.254 # Replace with your subnet's gateway TYPE=Ethernet DNS1=192.168.198.1 DOMAIN='dmlab' # Replace with your Linux host's domain(s) NM_CONTROLLED=no
Next, I created following init script and placed it in /etc/init.d/br0.
Contents of /etc/init.d/br0:
#!/bin/bash # Source function library. . /etc/rc.d/init.d/functions RETVAL=0 # Check if all what named needs running start() { /usr/sbin/brctl addbr br0 /usr/sbin/brctl addif br0 eth0 /sbin/ifup eth0 /sbin/ifup br0 return 0; } stop() { /sbin/ifdown br0 /sbin/ifdown eth0 /usr/sbin/brctl delbr br0 } restart() { stop start } # See how we were called. case "$1" in start) start ;; stop) stop ;; restart) restart ;; *) echo $"Usage: $0 {start|stop|restart}" exit 3 esac exit $RETVAL
I set the br0 init script to run during bootup by making the following symbolic link:
ln -s /etc/init.d/br0 /etc/rc5.d/S91br0
My system typically runs at runlevel 5 (hence rc5.d), and "S91" on my system runs after the networking scripts, but before critical services like dns, named, dhcp, samba, etc, which need the interface to be up when starting.
The br0 script manually brings up eth0 and br0, which is why it is important that these interfaces are not controlled by Fedora's network manager.
After re-booting the Linux host (without a BeagleBoard attached), the result of "ifconfig" should list "br0", "eth0", and "lo", and if you execute "sudo brctl show" it should list eth0 as being a member of the bridge.
$ ifconfig br0 Link encap:Ethernet HWaddr xx:xx:xx:xx:xx:xx inet addr:192.168.198.1 Bcast:192.168.198.255 Mask:255.255.255.0 inet6 addr: fe80::21a:a0ff:feec:79f1/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:3875507 errors:0 dropped:0 overruns:0 frame:0 TX packets:3351392 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:2798652354 (2.6 GiB) TX bytes:977920512 (932.6 MiB) eth0 Link encap:Ethernet HWaddr xx:xx:xx:xx:xx:xx inet6 addr: fe80::21a:a0ff:feec:79f1/64 Scope:Link UP BROADCAST RUNNING PROMISC MULTICAST MTU:1500 Metric:1 RX packets:2015574 errors:0 dropped:0 overruns:0 frame:0 TX packets:3411988 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:1780819388 (1.6 GiB) TX bytes:972140276 (927.1 MiB) Interrupt:16 lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:236666 errors:0 dropped:0 overruns:0 frame:0 TX packets:236666 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:317726283 (303.0 MiB) TX bytes:317726283 (303.0 MiB)
$ sudo brctl show
bridge name bridge id STP enabled interfaces br0 8000.001aa0ec79f1 no eth0
You should be able to access the external network the same as before on your Linux host at this point.
Step 2: Booting the BeagleBoard
The next step is to boot the BeagleBoard with kernel parameters that tell it to mount its root file system over NFS. Here are the U-Boot settings I used to boot the kernel from an SD card, then boot the rootfs over NFS:
setenv bootargs 'console=ttyS2,115200n8 noinitrd rw ip=192.168.198.24::255.255.255.0 root=/dev/nfs nfsroot=192.168.198.1:/opt/dmsw/OE_BEAGLE_rootfs,nolock,rsize=1024,wsize=1024,rootdelay=2' setenv bootcmd 'mmcinit;fatload mmc 0 80300000 uImage;bootm 80300000'
In the above parameters, replace the following with settings for your network:
Replace This | With This |
ip=192.168.198.24::255.255.255.0 | ip=<BeagleBoard IP Address>::<your subnet mask> |
nfsroot=192.168.198.1:/opt/dmsw/OE_BEAGLE_rootfs | nfsroot=<IP address of your NFS server>:<path to root filesystem on NFS server> |
While the BeagleBoard kernel is booting, the usb0 device will show up on the Linux host. Run "ifconfig" a few times, and when "usb0" is listed, run the following command:
$ sudo brctl addif br0 usb0
This will add "usb0" to the Ethernet bridge, and the Linux host will now act as a hub for the Beagleboard. The Beagleboard will now continue to boot, but the weird thing is I didn't see any of the kernel boot messages scroll by while it's starting up. However, when it's done the "Angstrom" prompt comes up on the serial normally.
If you execute "sudo brctl show" after the BeagleBoard is done booting, it should now should both eth0 and usb0 being on the bridge:
$ sudo brctl show bridge name bridge id STP enabled interfaces br0 8000.001aa0ec79f1 no eth0 usb0
Step 3: Accessing the Outside World from the BeagleBoard
You might want to make sure that any firewall software like iptables is disabled on the Linux host, or at least make sure the firewall settings allow the Linux host to act as a hub for your BeagleBoard. Otherwise, the BeagleBoard will not be able to see the outside world.
On the BeagleBoard, modify "/etc/network/interfaces", and configure the settings for "usb0".
Contents of BeagleBoard's /etc/network/interfaces:
iface usb0 inet static address 192.168.198.24 # Replace with BeagleBoard's IP Address netmask 255.255.255.0 # Replace with your subnet mask network 192.168.198.0 # Replace with your network address gateway 192.168.198.254 # Replace with your subnet gateway
Also, edit the /etc/resolve.conf on the BeagleBoard to point to your DNS server. Here are my settings:
Contents of BeagleBoard's /etc/resolve.conf:
search dmlab # Replace with your domain search path nameserver 192.168.198.1 # Replace with your DNS server
Note that my linux host (192.168.198.1) is running a DNS server. If yours isn't, don't use your Linux host IP here -- set this to the DNS server that your Linux host is using.
Finally, bring up the usb0 interface on the BeagleBoard:
$ ifup usb0
You should now be up and connected as if your beagle board was on the network at the same level as the linux host.
$ ping some.machine.com PING some.machine.com (192.94.93.21): 56 data bytes 64 bytes from 192.94.93.21: seq=0 ttl=247 time=18.005 ms 64 bytes from 192.94.93.21: seq=1 ttl=247 time=10.254 ms ...
Future Considerations
- When the usb0 is detected by the Linux Host during the BeagleBoard boot, how can we automatically add it to the Ethernet bridge?