Poky NFS Root
HOWTO: Booting poky images on hardware from network
Booting from network is a common practice when developing embedded system on real hardware. It avoids the time consuming process of downloading the kernel and root filesystem to a hard drive or flash to make developer's life easier.
The general idea is to use a bootloader to get the kernel image (using TFTP, mostly) and specifying nfsroot in the kernel command line to mount rootfs via a remote NFS server. In the case of x86 systems, the bootloader is usually PXE (Preboot Execution Environment), either provided by BIOS or other PXE implementations like gPXE.
This HOWTO walks through the process of setting everything for eMenlow, with NFS-root, you can:
- boot a diskless and flashless target
- avoid downloading kernel/rootfs after a rebuild
- change files on the fly even on read-only fs (jffs2, squashfs, etc.)
- boot on different boards or boxen
Target bootloading with gPXE
TODO: integrate gPXE into yocto
The traditional method of bootloading is the PXE stack provided in BIOS. However, that often requires DHCP cooperation, which is not viable in many circumstances. Here we use gPXE, an open-source PXE implementation, to get around this DHCP restriction.
It can function as a standalone bootloader or be chainloaded by grub. Since it's less than 500kB in size, it can fit in a small USB flash drive very well.
First, build it from source. Suppose your development machine has the hostname of <hostname>:
$ git clone git://git.etherboot.org/scm/gpxe.git $ cd gpxe $ cat > chainload.gpxe <<EOF #!gpxe dhcp net0 kernel tftp://<hostname>/boot.gpxe boot EOF $ cd src $ EMBEDDED_IMAGE=../chainload.gpxe make bin/gpxe.usb
The EMBEDDED_IMAGE is the builtin script as gPXE starts. The script above chainloads another gPXE script on the remote tftp server (your development machine) to get actual kernel and rootfs image location.
After that, bin/gpxe.usb can be written to an empty USB stick to bootload the image on any box that has a network connection:
warning: the content of the usb device will be wiped out!
# dd if=bin/gpxe.usb of=</dev/sdX>
Alternatively, there are also other targets available, for example, bin/gpxe.lkrn can be built to be chainloaded by grub, please refer to gPXE docs.
Development box preparation
TODO: integrate nfs server and tftpd into yocto
To set up tftp and nfs server on debian/ubuntu, simply:
# apt-get install nfs-kernel-server atftpd
tftpd-hpa can be used as well instead of atftpd.
Target system changes
There are two additional requirements for the target system, however:
- the kernel needs to have the network driver built in, not as a module
- the network init scripts needs to be disabled or patched to avoid collision with nfsroot
For 1, just change the config file of the target kernel, i.e for qemux86 on eMenlow, change meta/packages/linux/linux-rp-2.6.29/defconfig-qemux86 to add CONFIG_E1000E=y.
(note: status of initramfs is unknown at the moment)
For 2, there are many possible solutions, a relative generic patch can be found here:
Besides, you may also:
- remove /etc/init.d/networking altogether
- remove "auto eth0" in /etc/network/interfaces
Setting up after image build
TODO: avoid using sudo
The following patch provides a script to automatically set up tftp and nfsroot after image build completes.
Simply run the following in the poky build directory, assuming your machine type is qemux86:
$ prepare-nfsroot qemux86 -g
And everything is done. Now just insert the USB stick into the target machine, power it on, and see if the target image is booting.