|
When developing for an Embedded Linux target it is always desirable to shorten your development cycle. The following article explains about how to use an x86 machine (AMD Duron) as a diskless embedded target and use a virtual machine running Linux to setup this development environment. The virtual machine running Linux listens on TFTP and NFS servers to provide a bootable kernel image and a mounted root file system respectively for the diskless client. The development time is reduced as we need not reinstall the kernel and/or root file system every time on the target. We develop device drivers and kernel code on the host and simply reboot the target to load and test.
Components
TARGET @ IP adderess : 192.168.1.109 x86 target machine with : + AMD Duron processor (800 MHz) + 128 MB RAM + Intel Pro100 LAN Card + floppy drive HOST @ IP address : 192.168.1.251 + linux virtual machine running RHEL4 + linux kernel 2.6.26 + grub 0.95 + tftp server + NFS server
|  |
ProcessThe target board is booted via grub floppy, the menu to select the kernel to load will be downloaded via the tftp server on the target. The menu selection provides list of linux kernels to boot which will in turn be downloaded from the same tftp server. Also the root file system for the kernel will be mounted as NFS residing on the host. So lets get started ... As a general convention we need to create a world read/writable directory /tftpboot/<host ip address> which holds the Root file system.
# cd / # mkdir tftpboot # mkdir /tftpboot/192.168.1.109 # mkdir /tftpboot/192.168.1.109/boot GRUBGRUB stands for GRand Unified Boot Loader which is a boot loader used to fetch the linux kernel via the TFTP server running on the host virtual machine.
Download GRUB from ftp://alpha.gnu.org/gnu/grub/ Extract grub for e.g. grub-0.95.tar.gz on the host
# tar zxvf grub-0.95.tar.gz # cd grub-0.95 Have a look at /grub-0.95/netboot/README.netboot to get a list of supported network cards. We need to configure the grub for network booting with the lan card i.e. Intel Pro 100 support in built so that it can transfer files using the LAN card. Also note that we hardcoded the IP addresses of target and host and do not use DHCP in this setup.
# echo "ifconfig --address=192.168.1.109 --server=192.168.1.251" >mypreset # ./configure --enable-eepro100 --enable-preset-menu=mypreset # make Copy the /boot/message and /boot/menu.lst files to target root file system as follows :
# cp -av /boot/message /tftpboot/192.168.1.109/boot/ # cp -av /boot/menu.lst /tftpboot/192.168.1.109/boot/ Edit the target root filesystem menu.lst as follows :
# cat /tftpboot/192.168.1.109/boot/menu.lst
gfxmenu (nd)/boot/message color white/blue black/light-gray default 1 timeout 8 title Linux 2.6.26 test - linux virtual machine root (nd) kernel /boot/linux-2.6.26 rw ip=192.168.1.109 root=/dev/nfs nfsroot=192.168.1.251:/tftpboot/192.168.1.109 This menu.lst file will provide a graphical selection of list of available kernels to boot. Creating GRUB Boot FloppyThe make command above generates stage1 and stage2 file in /stage1 and /stage2 directories respectively. Next put a formatted floppy in to floppy disk drive of the host and run following commands (assuing you are @ ../grub-0.95/)
# cd stage1 # dd if=stage1 of=/dev/fd0 # cd .. # cd stage2 # dd if=stage2 of=/dev/fd0 seek=1 Try the floppy by booting the target with the floppy. If the floppy is OK you should get a grub prompt like :
GNU GRUB version 0.95 (640K lower / 3072K upper memory)
[ Minimal BASH-like line editing is supported. For the first word, TAB lists possible command completions. Anywhere else TAB lists the possible completions of a device/filename. ]
grub> As the name suggests the boot floppy provides initial boot screen and grub prompt which will be used to get the menu.lst file from TFTP server so that we get to select the kernel image to boot.Try 'help' command on the grub> prompt to see the supported commands by grub. Compiling the linux kernel
Next step is preparing the kernel.
Download the linux kernel from http://www.kernel.org for e.g. linux-2.6.26.tar.bz2 and extract it.
# tar zxvf linux-2.6.26.tar.bz2 # cd linux-2.6.26 Configure the kernel using following commands :
# make mrproper # make i386_defconfig # make menuconfig We need to build the kernel with inbuilt support for the ethernet card i.e. Intel Pro 100 and NFS. Select following from the menuconfig and include them as built into (showing *) the kernel rather than as modules (showing M).
Network device support ---> Ethernet (10 or 100Mbit) ---> <*> EtherExpressPro/100 support (eepro100, original Becker driver) <*> Intel(R) PRO/100+ support File systems ---> Network File Systems ---> <*> NFS file system support [*] Provide NFSv3 client support [*] Root file system on NFS
Save the kernel configuration and compile the kernel as follows :
# make all be patient it will take a while....This creates compressed kernel image @ ../linux-2.6.26/arch/x86/boot/bzImage. Copy it to our root file system.
# cp -av arch/x86/boot/bzImage /tftpboot/192.168.1.109/boot/linux-2.6.26 Preparing the root file system
Now as we have the kernel compiled, let's prepare the root file system for the kernel. Create the directories of the root file system :
# mkdir /tftpboot/192.168.1.109/bin # mkdir /tftpboot/192.168.1.109/dev # mkdir /tftpboot/192.168.1.109/etc # mkdir /tftpboot/192.168.1.109/lib # mkdir /tftpboot/192.168.1.109/mnt # mkdir /tftpboot/192.168.1.109/proc # mkdir /tftpboot/192.168.1.109/sbin # mkdir /tftpboot/192.168.1.109/tmp # mkdir /tftpboot/192.168.1.109/usr # mkdir /tftpboot/192.168.1.109/var We are using the host root file system as a base to create root file system for target and thus copy the required minimal set to files to the target root file system from host file system. /devCopy following /dev entries :
# cp -dpRv /dev/fd[01]* /tftpboot/192.168.1.109/dev/ # cp -dpRv /dev/tty[0-6] /tftpboot/192.168.1.109/dev/ # cp -Rv /dev/console /tftpboot/192.168.1.109/dev/ # cp -Rv /dev/kmem /tftpboot/192.168.1.109/dev/ # cp -Rv /dev/mem /tftpboot/192.168.1.109/dev/ # cp -Rv /dev/null /tftpboot/192.168.1.109/dev/ # cp -Rv /dev/ram0 /tftpboot/192.168.1.109/dev/ /etcCopy following /etc entries :
# cp -av /etc/fstab /tftpboot/192.168.1.109/etc/ # cp -av /etc/group /tftpboot/192.168.1.109/etc/ # cp -av /etc/inittab /tftpboot/192.168.1.109/etc/ # cp -av /etc/mtab /tftpboot/192.168.1.109/etc/ # cp -av /etc/nsswitch.conf /tftpboot/192.168.1.109/etc/ # cp -av /etc/passwd /tftpboot/192.168.1.109/etc/ # cp -av /etc/protocols /tftpboot/192.168.1.109/etc/ # cp -av /etc/rc /tftpboot/192.168.1.109/etc/ # cp -av /etc/services /tftpboot/192.168.1.109/etc/ # cp -av /etc/shadow /tftpboot/192.168.1.109/etc/ # cp -av /etc/termcap /tftpboot/192.168.1.109/etc/ # cp -av /etc/fstab /tftpboot/192.168.1.109/etc/ # mkdir /tftpboot/192.168.1.109/etc/rc.d # cp -dpR /etc/rc.d /tftpboot/192.168.1.109/etc/rc.d/ Edit target root file system /etc/fstab as follows :
# cat /tftpboot/192.168.1.109/etc/fstab /dev/ram0 / ext2 defaults 0 0 /dev/fd0 / ext2 defaults 0 0 none /proc proc defaults 0 0 192.168.1.108:/tftpboot/192.168.1.109 / nfs defaults 1 1 This will mount the NFS filesystem as the root filesystem everytime the target is rebooted.Edit target root file system /etc/initab as follows :
# cat /tftpboot/192.168.1.109/etc/inittab id:2:initdefault: si::sysinit:/etc/rc The inittab sets the runlevel to 2 and calls the /etc/rc script to setup the system.Edit target root file system /etc/rc as follows :
# cat /tftpboot/192.168.1.109/etc/rc #! /bin/bash mount -n -t proc /proc /proc [ -d /proc/bus/usb ] && mount -n -t usbfs /proc/bus/usb /proc/bus/usb mount -n -t sysfs /sys /sys >/dev/null 2>&1 /bin/bash This rc srcipt mounts the proc file system to /proc and sets the shell as bash at the end of initialization.Be sure it is executable, be sure it has a "#!" line at the top, and be sure any absolute filenames are correct. Edit target root file system /etc/nsswitch.conf as follows :
# cat /tftpboot/192.168.1.109/etc/nsswitch.conf passwd: files shadow: files group: files hosts: files services: files networks: files protocols: files rpc: files ethers: files netmasks: files bootparams: files automount: files aliases: files netgroup: files publickey: files The file is used to configure which services are to be used to determine information such as hostnames, password files, and group files. /lib
# cp -av /lib/ld* /tftpboot/192.168.1.109/lib/ # cp -av /lib/libc.* /tftpboot/192.168.1.109/lib/ # cp -av /lib/libutil.* /tftpboot/192.168.1.109/lib/ # cp -av /lib/libncurses.* /tftpboot/192.168.1.109/lib/ # cp -av /lib/libdl.* /tftpboot/192.168.1.109/lib/ # cp -av /lib/libnss_dns* /tftpboot/192.168.1.109/lib/ # cp -av /lib/libnss_files* /tftpboot/192.168.1.109/lib/ # cp -av /lib/libresolv* /tftpboot/192.168.1.109/lib/ # cp -av /lib/libproc* /tftpboot/192.168.1.109/lib/ # cp -av /lib/librt* /tftpboot/192.168.1.109/lib/ # cp -av /lib/libpthread* /tftpboot/192.168.1.109/lib/ # cp -av /lib/libm* /tftpboot/192.168.1.109/lib/ # cp -av /lib/libselinux* /tftpboot/192.168.1.109/lib/ # cp -av /lib/libattr* /tftpboot/192.168.1.109/lib/ # cp -av /lib/tls/lib* /tftpboot/192.168.1.109/lib/ ldd command will list the library dependencies for a command
# ldd /bin/ls librt.so.1 => /lib/tls/librt.so.1 (0x0040c000) libacl.so.1 => /lib/libacl.so.1 (0x005f3000) libselinux.so.1 => /lib/libselinux.so.1 (0x00cb9000) libc.so.6 => /lib/tls/libc.so.6 (0x0049b000) libpthread.so.0 => /lib/tls/libpthread.so.0 (0x006f6000) /lib/ld-linux.so.2 (0x0047d000) libattr.so.1 => /lib/libattr.so.1 (0x00cc9000) The libraries on the RHS of => needs to be copied to the host root file system to enable the command to run on the target.
[root@purnendurhel4 lib]# ldd /sbin/mke2fs libext2fs.so.2 => /lib/libext2fs.so.2 (0x00cd9000) libcom_err.so.2 => /lib/libcom_err.so.2 (0x00dd2000) libblkid.so.1 => /lib/libblkid.so.1 (0x005cf000) libuuid.so.1 => /lib/libuuid.so.1 (0x00496000) libe2p.so.2 => /lib/libe2p.so.2 (0x005c8000) libc.so.6 => /lib/tls/libc.so.6 (0x0049b000) /lib/ld-linux.so.2 (0x0047d000) [root@purnendurhel4 lib]# cp -av /lib/libcom* /tftpboot/192.168.1.109/lib/ cp: overwrite `/tftpboot/192.168.1.109/lib/libcom_err.so.2'? n cp: overwrite `/tftpboot/192.168.1.109/lib/libcom_err.so.2.1'? n [root@purnendurhel4 lib]# cp -av /lib/libblk* /tftpboot/192.168.1.109/lib/ `/lib/libblkid.so.1' -> `/tftpboot/192.168.1.109/lib/libblkid.so.1' `/lib/libblkid.so.1.0' -> `/tftpboot/192.168.1.109/lib/libblkid.so.1.0' [root@purnendurhel4 lib]# cp -av /lib/libuuid* /tftpboot/192.168.1.109/lib/ `/lib/libuuid.so.1' -> `/tftpboot/192.168.1.109/lib/libuuid.so.1' `/lib/libuuid.so.1.2' -> `/tftpboot/192.168.1.109/lib/libuuid.so.1.2' [root@purnendurhel4 lib]# cp -av /lib/libe2p* /tftpboot/192.168.1.109/lib/ `/lib/libe2p.so.2' -> `/tftpboot/192.168.1.109/lib/libe2p.so.2' `/lib/libe2p.so.2.3' -> `/tftpboot/192.168.1.109/lib/libe2p.so.2.3' TFTP serverThe TFTP server provides the menu selection and the linux kernel to the target machine. Download and install TFTP server as follows :
# rpm -ivh tftp-server-0.39-3.el4.i386.rpm This will install the TFTP server in /usr/sbin/in.tftpd
we need to run the tftp server in standalone mode using following command.
#/usr/sbin/in.tftpd -l -vv -p -s /tftpboot/192.168.1.109 where, -l standalone mode -vv verbose log messages -p ignore permissions on the file/directory -s start the tftpd @ this directory as rootNFS serverMake sure that NFS server is installed and running by :
# service nfs status Shutting down NFS mountd: rpc.mountd (pid 2628) is running... nfsd (pid 2622 2621 2620 2619 2618 2617 2616 2615) is running... rpc.rquotad (pid 2602) is running... Edit /etc/exports on the host to enable the root file system we created available as an NFS share.
# cat /etc/exports /tftpboot/192.168.1.109 192.168.0.0/255.255.0.0(rw,no_root_squash,sync) Once all the configuration mentioned above is done, now it is time to check the system working.Boot the target using the grub boot floppy we created earlier. On the grub prompt :
grub> configfile (nd)/boot/menu.lst You will get the menu showing the list options. Select the entry you want to boot and press enter !! You should see a bash prompt on the target.
|