To get nfs mounting to work, following steps are needed:
Under gumstix, this was simply done by the following set of commands:
However, under avr32, this is a little different. Actually, NFS support is built in to the kernel by default. This can be checked by inspecting the .config file in the kernel directory:
The NFS_FS=y and the CONFIG_ROOT_NFS=y imply that this is all setup nice and proper. We can also use the menuconfig method to check if things are setup as we want them:
in the linux-2.6.27.6/ dir above, do
this should bring up the familiar menu. Browse to File Systems | Network File Systems ensure that “NFS Client support (for NFS v3)” and “Root file system on NFS” are built in (denoted by '*'. denotes that they are loaded as modules. We don't want modules, but want built in since at boot up the kernel won't have an opportunity to load modules because no file-system would exist at that point to locate and provide the said modules).
Since the default command contains this, it is good to know and keep around:
Also when booting over TFTP, the kernel image must be provided. Avr32 Buildroot generally produces a kernel image called uImage (same as gumstix). However, this is then copied over to the binaries folder, found at
That this file is the same as uImage produced by the kernel may be verified using the cksum command:
So all that remains now is to set the appropriate commands in u-boot, copy over files to proper places and have this thing going!
Since both the NGW100 and gumstix are buildroot systems they have a lot in common. However, the differences are significant enough to warrant independent and complete documentation.
Firstly, the NGW100's root file system is typically produced as a tar file. Also it's generated root file system is present in a different path as compared with gumstix. In particular, the NGW100's root filesystem is located at:
we copy this over to ~/avr32ngw100/work/nfsroot
Ensure that the target file system has /dev/null and /dev/console. Sometimes, tar does not have the permission to create these nodes.
Ideally /dev/null and /dev/console are character special devices created by mknod
However, this kept giving me problems. Also sometimes i would get a message "could not open initial console" on the serial terminal, so i went back to simply touching the files.
There are some good instructions at:
http://support.atmel.no/knowledgebase/avr32studiohelp/com.atmel.avr32.tool.ngw100/html/filesystem_over_nfs_for_avr32_linux.html
However, once the tftp server is up and serving files, i ran in to an unhandled exception error and an endless loop of the board trying to restart. Turns out that the expanded kernel was trampling over the downloaded data. I computed the appropriate location to download the kernel to so that it won't get trampled over by the expanded kernel.
the second figure is the download location. After doing this, I also ran in to a couple of webpages that indicated success with downloading to an address 0x1040000
We want to leave enough space at the start of the memory section for the kernel to expand. The size computation in perl above helps us determine where to place this. We back-off twice the size of the compressed kernel from the top of the memory. My assumption was to leave the very top alone because some cpus jump to that address during startup. Also placing it close to the end gives more room in the beginning so that the expanded kernel doesn't overwrite the compressed image :)
next we setup the boot args that are passed to the linux kernel. In particular, we need to setup the ethernet interface and indicated that we're booting off nfs. The Uboot interpreter on this board however, can't handle the length of the command. So, we use the askenv command:
syntax of ip command is
Copying and pasting the above might not work, so type away!
Also disable network startup since this is done at boot up
Change /etc/network/interfaces so that no auto setup happens on eth0 that can disrupt the nfs mount.
Change /etc/fstab so that default mounting on / and /usr is disabled:
Ensure that the compiled kernel image is placed in the right location. My tftp root is located at ~/tftpboot. And since it's serving both gumstix and ngw100 uImages, I've modified the tree a little bit so that it is scalabe for other targets / projects:
Ensure that the path above matches the path mentioned in bootcmd on the target.
Change appropriate config files on the server to ensure that the new device has access to these folders:
Change /etc/hosts.allow.
NOTE: /etc/hosts.deny stays the same:
/etc/exports:
Note the rw,no_root_squash options for the development boards. this allows them to mount the paths with root privileges.
Restart tftpd and nfs-servers
PS: there's probably a good reason why i'm running a user space nfs server instead of the usual kernel space version, but it eludes me at the moment. Perhaps I wanted to export heterogeneous filesystems (ntfs + ext3) under one nfs mount point. But since I didn't note my rationale, I have no idea right now. I see no reason for a kernel space nfs server to not work with this setup.
Test the tftp and nfs connections on the server before struggling with the board:
Ironically, it took me half a day to get the setup going and a whole day to blog about it. There's infact more I've already done, just haven't gotten around to bloggin about it :)
- change router / dhcp settings so that board / server can work with each other. In my case, I just chose a static setup because it makes life easy. My server is located at 192.168.1.101 (both tftp and nfs) while the avr device is located at 192.168.1.103. The gumstix stays at 192.168.1.100. Router gateway is at 192.168.1.1. The "static"-ness is achieved by setting appropriate rules on the router's dhcp server.
- expose appropriate root file system from a nfs mountable point on the build-server
- modify avr32ngw100's kernel so that nfs is created as part of the kernel image and not as a module change uboot to boot from tftp instead of on board flash / sd-card
- change uboot arguments to pass root as nfs to linux kernel.
- ensure that root is not mounted on /dev/mtdblock, since it will already have been specified as bootargs to the kernel
- disable any dhcp or other disruptive network setup, since eth0 would already have been setup by uboot
Modifying avr32kernel
Under gumstix, this was simply done by the following set of commands:
cd build_arm_nofpu
cd linux-gum-2.6.21
make ARCH=arm menuconfig
However, under avr32, this is a little different. Actually, NFS support is built in to the kernel by default. This can be checked by inspecting the .config file in the kernel directory:
# grep --ignore-case nfs \
buildroot-avr32-v2.3.0/project_build_avr32/atngw100/linux-2.6.27.6/.config
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
# CONFIG_NFS_V4 is not set
CONFIG_ROOT_NFS=y
CONFIG_NFSD=m
CONFIG_NFSD_V3=y
# CONFIG_NFSD_V3_ACL is not set
# CONFIG_NFSD_V4 is not set
CONFIG_NFS_COMMON=y
The NFS_FS=y and the CONFIG_ROOT_NFS=y imply that this is all setup nice and proper. We can also use the menuconfig method to check if things are setup as we want them:
in the linux-2.6.27.6/ dir above, do
make ARCH=avr32 CROSS_COMPILE=avr32-linux- menuconfig
this should bring up the familiar menu. Browse to File Systems | Network File Systems ensure that “NFS Client support (for NFS v3)” and “Root file system on NFS” are built in (denoted by '*'. denotes that they are loaded as modules. We don't want modules, but want built in since at boot up the kernel won't have an opportunity to load modules because no file-system would exist at that point to locate and provide the said modules).
Since the default command contains this, it is good to know and keep around:
make ARCH=avr32 CROSS_COMPILE=avr32-linux- atngw100_defconfig
Also when booting over TFTP, the kernel image must be provided. Avr32 Buildroot generally produces a kernel image called uImage (same as gumstix). However, this is then copied over to the binaries folder, found at
buildroot-avr32-v2.3.0/binaries/atngw100/atngw100-linux-2.6.27.6.gz
That this file is the same as uImage produced by the kernel may be verified using the cksum command:
cksum $(find ./ -iname uImage -print)
127785873 1252230 ./arch/avr32/boot/images/uImage
cksum ~/work/buildroot-avr32-v2.3.0/binaries/atngw100/atngw100-linux-2.6.27.6.gz
127785873 1252230 ~/work/buildroot-avr32-v2.3.0/binaries/atngw100/atngw100-linux-2.6.27.6.gz
So all that remains now is to set the appropriate commands in u-boot, copy over files to proper places and have this thing going!
Preparing the root-fs
Since both the NGW100 and gumstix are buildroot systems they have a lot in common. However, the differences are significant enough to warrant independent and complete documentation.
Firstly, the NGW100's root file system is typically produced as a tar file. Also it's generated root file system is present in a different path as compared with gumstix. In particular, the NGW100's root filesystem is located at:
/buildroot-avr32-v2.3.0/project_build_avr32/atngw100/root
we copy this over to ~/avr32ngw100/work/nfsroot
cp -a buildroot-avr32-v2.3.0/project_build_avr32/atngw100/root/* ~/avr32ngw100/work/nfsroot
Ensure that the target file system has /dev/null and /dev/console. Sometimes, tar does not have the permission to create these nodes.
touch ~/avr32ngw100/work/nfsroot/dev/null
touch ~/avr32ngw100/work/nfsroot/dev/console
chmod 666 ~/avr32ngw100/work/nfsroot/dev/null ~/avr32ngw100/work/nfsroot/dev/console
Ideally /dev/null and /dev/console are character special devices created by mknod
sudo mknod ~/avr32ngw100/work/nfsroot/dev/console c 5
sudo mknod ~/avr32ngw100/work/nfsroot/dev/null c 1 3
sudo chown hypo ~/avr32ngw100/work/nfsroot/dev/console ~/avr32ngw100/work/nfsroot/dev/null
sudo chmod 666 ~/avr32ngw100/work/nfsroot/dev/console ~/avr32ngw100/work/nfsroot/dev/null
However, this kept giving me problems. Also sometimes i would get a message "could not open initial console" on the serial terminal, so i went back to simply touching the files.
U-boot settings
There are some good instructions at:
http://support.atmel.no/knowledgebase/avr32studiohelp/com.atmel.avr32.tool.ngw100/html/filesystem_over_nfs_for_avr32_linux.html
However, once the tftp server is up and serving files, i ran in to an unhandled exception error and an endless loop of the board trying to restart. Turns out that the expanded kernel was trampling over the downloaded data. I computed the appropriate location to download the kernel to so that it won't get trampled over by the expanded kernel.
perl -e '{my $image = 1.2 * 1024 * 1024; my $top_mem = 0x10000000 + 32 * 1024 * 1024; printf("0x%x 0x%x\n", $image, $top_mem - 2*$image);}'
0x133333 0x11d99999
the second figure is the download location. After doing this, I also ran in to a couple of webpages that indicated success with downloading to an address 0x1040000
We want to leave enough space at the start of the memory section for the kernel to expand. The size computation in perl above helps us determine where to place this. We back-off twice the size of the compressed kernel from the top of the memory. My assumption was to leave the very top alone because some cpus jump to that address during startup. Also placing it close to the end gives more room in the beginning so that the expanded kernel doesn't overwrite the compressed image :)
setenv bootcmd 'set ipaddr 192.168.1.103;tftp 0x10400000 avr32ngw100/uImage-n;bootm'
or
setenv bootcmd 'set ipaddr 192.168.1.103;tftp 0x11d99999 avr32ngw100/uImage-n;bootm'
next we setup the boot args that are passed to the linux kernel. In particular, we need to setup the ethernet interface and indicated that we're booting off nfs. The Uboot interpreter on this board however, can't handle the length of the command. So, we use the askenv command:
syntax of ip command is
ip=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf>
askenv:
/dev/nfs rw nfsroot=192.168.1.101:/home/hypo/avr32ngw100/work/nfsroot,nolock,rsize=1024,wsize=1024 console=ttyS0 ip=192.168.1.103:192.168.1.101:192.168.1.1:::eth0:off
Copying and pasting the above might not work, so type away!
Also disable network startup since this is done at boot up
cd ~/avr32ngw100/work/nfsroot
mv etc/init.d/S20network etc/init.d/s20network
Change /etc/network/interfaces so that no auto setup happens on eth0 that can disrupt the nfs mount.
# Configure Loopback
auto lo
iface lo inet loopback
# Configure Ethernet 0
# commenting out auto setup for eth0 because
# this would already have happened during nfs root
# boot up. Uncomment when not running with root over nfs
# auto eth0
# iface eth0 inet dhcp
# i don't need this just yet, but will enable it later
# Configure Ethernet 1
# auto eth1
# iface eth1 inet static
# address 10.0.0.1
# netmask 255.255.255.0
# network 10.0.0.0
# broadcast 10.0.0.255
Change /etc/fstab so that default mounting on / and /usr is disabled:
# /etc/fstab: static file system information.
#
#
#mtd1 / jffs2 defaults 0 0
# commenting out following because root-fs is now nfs mounted, so /usr is also part of that and not needed anymore
#mtd3 /usr jffs2 defaults 0 0
Server settings
TFTP settings:
Ensure that the compiled kernel image is placed in the right location. My tftp root is located at ~/tftpboot. And since it's serving both gumstix and ngw100 uImages, I've modified the tree a little bit so that it is scalabe for other targets / projects:
cd ~/tftpboot
mkdir gumstix avr32ngw100
cp ~/avr32ngw100/work/nfsroot/boot/uImage ~/tftpboot/avr32ngw100/uImage
cp ~/gumstix/uImage ~/tftpboot/gumstix/uImage
Ensure that the path above matches the path mentioned in bootcmd on the target.
Change appropriate config files on the server to ensure that the new device has access to these folders:
Change /etc/hosts.allow.
portmap: 192.168.1.100 , 192.168.1.101 , 192.168.1.103
lockd: 192.168.1.100 , 192.168.1.101 , 192.168.1.103
mountd: 192.168.1.100 , 192.168.1.101 , 192.168.1.103
statd: 192.168.1.100 , 192.168.1.101 , 192.168.1.103
NOTE: /etc/hosts.deny stays the same:
# ALL: PARANOID
lockd:ALL
mountd:ALL
rquotad:ALL
statd:ALL
/etc/exports:
# Cast of characters
# 192.168.1.100 - gumstix
# 192.168.1.101 - server
# 192.168.1.103 - avr32ngw100
# gumstix tftp boot-point
/home/hypo/gumstix/tftpboot 192.168.1.100(ro,sync) 192.168.1.101(ro,sync) 192.168.1.103(ro,sync)
# avr32ngw100 boot point
/home/hypo/avr32ngw100/work/tftpboot 192.168.1.100(ro,sync) 192.168.1.101(ro,sync) 192.168.1.103(ro,sync)
# gumstix root fs
/home/hypo/gumstix/nfsroot 192.168.1.100(rw,sync,no_root_squash) 192.168.1.101(rw,sync) 192.168.1.103(rw,sync)
# avr32ngw root fs
/home/hypo/avr32ngw100/work/nfsroot 192.168.1.100(rw,sync,no_root_squash) 192.168.1.101(rw,sync) 192.168.1.103(rw,sync,no_root_squash)
Note the rw,no_root_squash options for the development boards. this allows them to mount the paths with root privileges.
Restart tftpd and nfs-servers
sudo /etc/init.d/tftpd restart
sudo /etc/init.d/nfs-user-server restart
PS: there's probably a good reason why i'm running a user space nfs server instead of the usual kernel space version, but it eludes me at the moment. Perhaps I wanted to export heterogeneous filesystems (ntfs + ext3) under one nfs mount point. But since I didn't note my rationale, I have no idea right now. I see no reason for a kernel space nfs server to not work with this setup.
Test the tftp and nfs connections on the server before struggling with the board:
# mkdir ~/temp/test
# cd ~/temp/test
# tftp
tftp> get avr32ngw100/uImage
1 file xxx bytes
tftp> quit
# ls uImage
uImage
# rm *
# cd ../
# sudo mount -t nfs 192.168.1.101:/home/hypo/avr32ngw100/work/nfsroot/ ~/temp/test
# ls
bin etc lost+found proc tmp
boot home media root usr
config lib mnt sbin var
dev linuxrc opt sys www
# umount ~/temp/test
Ironically, it took me half a day to get the setup going and a whole day to blog about it. There's infact more I've already done, just haven't gotten around to bloggin about it :)
No comments:
Post a Comment