If your device has a network interface, it is best to mount the root filesystem over the network during development. It gives you access to almost unlimited storage so you can add in debug tools and executables with large symbol tables. As an added bonus, updates made to the root filesystem hosted on the development machine are made available on the target immediately. You also have a copy of log files.
For this to work, your kernel has to be configured with CONFIG_ROOT_NFS
. Then, you can configure Linux to do the mount at boot time by adding the following to the kernel command line:
root=/dev/nfs
Give the details of the NFS export as follows:
nfsroot=<host-ip>:<root-dir>
Configure the network interface that connects to the NFS server so that it is available at boot time, before the init
program runs by using this command:
ip=<target-ip>
There is more information about NFS root mounts in the kernel source in Documentation/filesystems/nfs/nfsroot.txt
.
You also need to install and configure an NFS server on your host which, for Ubuntu, you can do with this command:
$ sudo apt-get install nfs-kernel-server
The NFS server needs to be told which directories are being exported to the network, which is controlled by /etc/exports
. Add a line like this one to that file:
/<path to staging> *(rw,sync,no_subtree_check,no_root_squash)
Then, restart the server to pick up the change which, for Ubuntu, is:
$ sudo /etc/init.d/nfs-kernel-server restart
The following script creates a virtual network between the network device tap0
on the host and eth0
on the target using a pair of static IPv4 addresses and then launches QEMU with the parameters to use tap0
as the emulated interface. You will need to change the path to the root filesystem to be the full path to your staging directory, and maybe the IP addresses if they conflict with your network configuration:
#!/bin/bash KERNEL=zImage DTB=vexpress-v2p-ca9.dtb ROOTDIR=/home/chris/rootfs HOST_IP=192.168.1.1 TARGET_IP=192.168.1.101 NET_NUMBER=192.168.1.0 NET_MASK=255.255.255.0 sudo tunctl -u $(whoami) -t tap0 sudo ifconfig tap0 ${HOST_IP} sudo route add -net ${NET_NUMBER} netmask ${NET_MASK} dev tap0 sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward" QEMU_AUDIO_DRV=none \ qemu-system-arm -m 256M -nographic -M vexpress-a9 -kernel $KERNEL -append "console=ttyAMA0 root=/dev/nfs rw nfsroot=${HOST_IP}:${ROOTDIR} ip=${TARGET_IP}" -dtb ${DTB} -net nic -net tap,ifname=tap0,script=no
The script is available as run-qemu-nfs.sh
.
It should boot up as before, but now using the staging directory directly via the NFS export. Any files that you create in that directory will be immediately visible to the target device and any files created in the device will be visible to the development PC.
In a similar way, you can enter these commands at the U-Boot prompt of the BeagleBone Black:
setenv serverip 192.168.1.1 setenv ipaddr 192.168.1.101 setenv npath [path to staging directory] setenv bootargs console=ttyO0,115200 root=/dev/nfs rw nfsroot=${serverip}:${npath} ip=${ipaddr}
Then; to boot it, load the kernel and dtb
from sdcard,
as before:
fatload mmc 0:1 0x80200000 zImage fatload mmc 0:1 0x80f00000 am335x-boneblack.dtb bootz 0x80200000 - 0x80f00000
The files that were already in the staging directory are owned by you and will show up on the target when you run ls -l
with whatever your UID is, typically 1,000. Any files created by the target device will be owned by root. The whole thing is a mess.
Unfortunately, there is no simple way out. The best advice is to make a copy of the staging directory and change ownership to root:root
(using sudo chown -R 0:0 *
) and export this directory as the NFS mount. It reduces the inconvenience of having just one copy of the root filesystem shared between development and target systems.