Step-by-step NFS-mounted Root File System
This tutorial is for Developers. It is written to work with the odroidu2-ubuntu or odroidu2-debian SD-Card images [is this specific enough?]
It is not for Android developers.
Contents
Introduction
A common technique for embedded development is to NFS-mount your root file system. This means that all files are actually on a host. The host is configured to export the filesystem. The target (odroid) mounts the filesystem at boot time and uses it as its own. All files are visible on the host.
As targets have increased in storage capacity and speed, the need for NFS-mounting root file systems will decrease. The technique is still useful when bringing up a new port or you have a lot of files that need to change together.
It is common to check in a whole root file system into a source control system for quality control.
Prerequisites
Overview
We are going to:
Resources
Since the kernel sources and configuration do change, there is an archived set of files here [1]. At this point, you may not understand what all these files are for, but when you get stuck, a complete solution can be nice to have.
boot-nfs.scr compiled u-boot script that will use u-boot ${bootdev} to mount NFS root file system boot-nfs.txt u-boot script source boot-sdcard.scr compiled u-boot script boot-sdcard.txt u-boot script source. Compare to boot-nfs.txt odroid-3.0.62-snapshot.zip kernel source used in the tutorial odroidu2_ubuntu_defconfig configuration at the time of the snapshot odroidu2_ubuntu_nfs_defconfig configuration needed to boot odroidu2_ubuntu_nfs_defconfig.patch Patch to take the original configuration to odroidu2_ubuntu_nfs_defconfig zImage.nfs Kernel compiled with odroidu2_ubuntu_nfs_defconfig, ready to run
Add U-boot Environment Variables
Power-up the odroid and abort the boot at u-boot console
Exynos4412 #
Replace 10.4.124.93 value of nfsserverip with the ip address below with the ip address of the host you want to NFS-mount. This address must be on the same subnet as your odroid -- no routes are in place so early in the boot, and neither is DNS
Replace home/karlo/targetrfs value of rfspath with the host absolute path of the directory you mean to use for the odroid root file system. This can be a symlink, but NFS must be able to resolve it (it must be on the same filesystem)
The setnfs macro may be used as 'run setnfs' at the u-boot prompt to turn on NFS mounting
The unsetnfs macro may be used as 'run unsetnfs' at the u-boot prompt to turn off NFS mounting
saveenv saves the u-boot environment variables we just set
Copy/paste the following text to a text editor. You need to make changes as explained above. After making the changes, you can paste the text into u-boot console. Of course, you could just type the individual lines on the u-boot console.
set nfsserverip 10.4.124.93 set rfspath home/karlo/targetrfs set setnfs 'set bootdev root=/dev/nfs rw nfsroot=${nfsserverip}:/${rfspath}; saveenv;' set unsetnfs 'set bootdev root=/dev/mmcblk0p2 ro rootwait; saveenv ' saveenv
Now boot the odroid, nothing we did so far is going to change the boot.
run bootcmd
Mounting the Boot Partition
Mount the boot partition read-write, if it is not already mounted. The Debian images do not mount the boot partition (at this time)
mount /dev/mmcblkp1 /boot cd /boot
Compiling Custom U-boot Script
This is the current boot.scr (yours may be different):
setenv initrd_high "0xffffffff" setenv fdt_high "0xffffffff" setenv bootcmd "fatload mmc 0:1 0x40008000 zImage; fatload mmc 0:1 0x42000000 uInitrd; bootm 0x40008000 0x42000000" setenv bootargs "console=tty1 console=ttySAC1,115200n8 root=/dev/mmcblk0p2 rootwait ro mem=2047M" boot
Copy the existing boot script:
cp boot.txt boot-nfs.txt
Edit boot-nfs.txt. Change the bootargs line to give the following: (Adding ${bootdev} and ip=dhcp are key)
setenv initrd_high "0xffffffff" setenv fdt_high "0xffffffff" setenv bootcmd "fatload mmc 0:1 0x40008000 zImage; fatload mmc 0:1 0x42000000 uInitrd; bootm 0x40008000" setenv bootargs "${bootdev} console=tty1 console=ttySAC1,115200n8 rootwait ip=dhcp mem=2047M" boot
You will need the mkimage app from the uboot-mkimage package. Install it like this (Debian-based distros)
sudo apt-get install u-boot-tools
Compile to a u-boot script like this:
mkimage -T script -A arm -C none -n 'odroid-u2.Boot NFS-mounted RFS' -d boot-nfs.txt boot-nfs.scr
If that works, replace your existing script with the one we just made. If not, you do not have the prerequisites to build a kernel. mkimage comes from a u-boot package, listed in prerequisites for kernel building.
mv boot.scr boot.scr.orig cp boot-nfs.scr boot.scr
Custom Kernel
Now we need a kernel configured to be able to NFS-mount the root file system and the network driver needs to be built-in, not a kernel module. Maybe it is easiest to just pick up the configuration I used... Or you could look at the patch. Browse here: Example files
You need to somehow get the configuration to the area you are building the kernel. If it is on the target, it would be /usr/src/linux.
cd /usr/src/linux wget http://odroid.us/odroid/users/osterluk/nfs-mounting/odroidu2_ubuntu_nfs_defconfig mv odroidu2_ubuntu_nfs_defconfig arch/arm/configs # now use the new configuration make odroidu2_ubuntu_nfs_defconfig # build the kernel make -j8 zImage # copy it out to the boot partition cp arch/arm/boot/zImage /boot
To keep in sync with the released kernel versions, it may be better to just patch the released configuration -- this step is an alternative to just copying one that may not have your favorite kernel modules selected. This example is based on the default config, you would patch your own selections to add NFS mounted root file system capability.
# In the kernel source directory, get the NFS-mounting root file system configuration patch wget http://odroid.us/odroid/users/osterluk/nfs-mounting/odroidu2_ubuntu_nfs_defconfig.patch # Set up to build the kernel make odroidu2_ubuntu_defconfig # now our .config file matches the default configuration selected above. Apply the patch patch < odroidu2_ubuntu_nfs_defconfig.patch # Save this new configuration for future use. cp .config arch/arm/configs/odroidu2_ubuntu_nfs_defconfig
At this point, you can still boot normally. The capability to NFS mount the kernel will not stop you from mounting the flash-located root file system.
Setting up Target Root File System
# go home cd ~ # make a place to hold the target root file system mkdir targetrfs chmod 777 targetrfs cd targetrfs # You need to expand the RFS image as root, or you will lose the required device nodes sudo tar -xvzf ../odroidu2_20130104-debian-wheezy-2-rootfs.tgz cd ..
Setting up NFS export
# configure to export the target root file system with no restrictions sudo echo "/home/$USER/targetrfs *(rw,no_root_squash,no_subtree_check)" >> /etc/exports # On Debian/Ubuntu host: sudo /etc/init.d/nfs-kernel-server restart # On a SuSE 11.4 host, it looks like this: # sudo /etc/init.d/nfsserver restart
Testing NFS Export
# go home cd ~ # create a mount point and set permissions mkdir mnt chmod 777 mnt sudo mount -t nfs localhost:/home/$USER/targetrfs mnt # test to make sure we have write access echo xyx > mnt/test.txt sudo umount mnt
Selecting NFS-mount
Abort booting at the u-boot console
# select the nfs-mounted RFS configuration. You would use run unsetnfs to go back to normal mount run setnfs <pre> === Testing NFS-mounted Root File System === Reboot the target and watch the boot progress. You can power-cycle or do 'run bootcmd' at the u-boot prompt. Once you see the IP-Config lines, you know you succeeded. <pre> Begin: Loading essential drivers ... done. Begin: Running /scripts/init-premount ... done. Begin: Mounting root file system ... Begin: Running /scripts/nfs-top ... done. [ 5.399441] ADDRCONF(NETDEV_UP): eth0: link is not ready [ 6.975337] ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready [ 6.976319] smsc95xx 1-2:1.0: eth0: link up, 100Mbps, full-duplex, lpa 0xC5E1 IP-Config: eth0 hardware address ce:dd:54:19:96:0b mtu 1488 DHCP RARP IP-Config: no response after 2 secs - giving up IP-Config: eth0 hardware address ce:dd:54:19:96:0b mtu 1488 DHCP RARP IP-Config: eth0 guessed broadcast address 10.4.127.255 IP-Config: eth0 complete (dhcp from 10.1.0.219): address: 10.4.124.209 broadcast: 10.4.127.255 netmask: 255.255.128.0 gateway: 10.4.0.1 dns0 : 10.1.0.83 dns1 : 10.1.0.84 domain : mydomain.com rootserver: 10.1.0.41 rootpath: filename : k2000.0 Begin: Running /scripts/nfs-premount ... done. Begin: Running /scripts/nfs-bottom ... done. done. Begin: Running /scripts/init-bottom ... done. INIT: version 2.88 booting
Here is more proof:
root@odroidu2-1:~# mount sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime) proc on /proc type proc (rw,nosuid,nodev,noexec,relatime) udev on /dev type devtmpfs (rw,relatime,size=10240k,nr_inodes=168964,mode=755) devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620) tmpfs on /run type tmpfs (rw,nosuid,noexec,relatime,size=203124k,mode=755) '''10.4.124.93:/home/karlo/targetrfs on / type nfs (rw,relatime,vers=3,rsize=1048576,wsize=1048576,namlen=255,hard,nolock,proto=tcp,port=2049)''' tmpfs on /run/lock type tmpfs (rw,nosuid,nodev,noexec,relatime,size=5120k) tmpfs on /run/shm type tmpfs (rw,nosuid,nodev,noexec,relatime,size=406240k) root@odroidu2-1:~#
Nice to have a lot of disk space:
root@odroidu2-1:~# df -h Filesystem Size Used Avail Use% Mounted on rootfs 1.9T 713G 1.1T 41% / udev 10M 0 10M 0% /dev tmpfs 199M 204K 199M 1% /run 10.4.124.93:/home/karlo/targetrfs 1.9T 713G 1.1T 41% / tmpfs 5.0M 0 5.0M 0% /run/lock tmpfs 397M 0 397M 0% /run/shm root@odroidu2-1:~#