GRUB PXE network boot
As an alternative way to boot a diskless Media Director the bootloader GRUB can be used.
The bootloader GRUB is able to boot using PXE as well, this can be a great alternative way to boot (diskless) Media Directors for several reasons.
- The machine does not support PXE booting directly (no boot-ROM).
- You can use a GRUB bootmenu to decide wheter you want to boot LMCE or the native OS.
- Booting is a lot faster when you boot the native OS by skipping the network step.
- GRUB allows for easy adjustments of the boot parameters at boottime.
Contents
Prerequisites
- The GRUB sources.
- A development environment capable of building GRUB from source.
- Knowing which (supported) ethernet adapter is in the machine you want to boot.
Getting started
- Untar the GRUB sources somewhere and move into the newly created directory.
- Read The netboot/README.netboot file for additional information on what to specify for which network adapter.
- Configure the GRUB build
- Build GRUB from source.
In a nutshell, using grub-0.97 with my old Realtek 8139 (which you can buy just about anywhere for a few bucks):
tar xvf grub-0.97.tar.gz cd grub-0.97 less netboot/README.netboot # make a note of the option you need for your network interface ./configure --prefix=/usr --enable-diskless --enable-rtl8139 # That's the one I needed make # if this fails see "known problems" below for a possible fix.
WARNING: Do not run make install (as root) unless you want this version to overwrite the existing one on your system.
Installing
You have several options here, basicly this version of GRUB works just like the regular version so it can be put on floppy, USB stick, CDRom, Harddrive, etcertera. Please add other examples as you try them.
Installing on a Floppy using the "extended-2" (ext2fs) filesystem
A better way to do this would be to use the minix-filesystem to save some precious space, one might even be able to squeeze a kernel in, but ext2fs fits my needs as all I want is GRUB so I couldn't be bothered. Before doing this you should have moved to the directory where you built GRUB, obtained root privileges and inserted a writable floppy disk in the drive, WARNING:it's current contents will be lost during this procedure unless you skip the first step.
- format the floppy
- create a directory to mount it on
- mount the floppy
- install GRUB on the floppy directly
- create the boot/grub directory on the floppy
- hard link some files into the boot/grub directory
- copy the example menu.lst
- install GRUB onto the bootsector of the floppy
mkfs.ext2 /dev/fd0 mkdir -pv floppy mount /dev/fd0 floppy make install DESTDIR=`pwd`/floppy mkdir -pv floppy/boot/grub ln -v floppy/usr/lib/grub/i386-pc/{stage1,e2fs_stage1_5,stage2} floppy/boot/grub/ cp -v docs/menu.lst floppy/boot/grub umount floppy grub/grub
GNU GRUB version 0.97 (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> root (fd0) Filesystem type is ext2fs, using whole disk grub> setup (fd0) Checking if "/boot/grub/stage1" exists... yes Checking if "/boot/grub/stage2" exists... yes Checking if "/boot/grub/e2fs_stage1_5" exists... yes Running "embed /boot/grub/e2fs_stage1_5 (fd0)"... failed (this is not fatal) Running "embed /boot/grub/e2fs_stage1_5 (fd0)"... failed (this is not fatal) Running "install /boot/grub/stage1 (fd0) /boot/grub/stage2 p /boot/grub/menu.lst "... succeeded Done. grub> quit
You should be all set now, only thing left is to edit the menu.lst file to your liking.
Configuring GRUB to boot from the network
You will need to edit the boot/grub/menu.lst file for this.
This is an example for adding a new Media Director. First I added this as the top "target":
title New Media Director dhcp root (nd) kernel /tftpboot/default/vmlinuz root=/dev/nfs acpi=off vga=normal ramdisk_size=10240 rw ip=all apicpmtimer initrd /tftpboot/default/initrd
And here is what I added above that for one of my Media Directors (device #100), lateron after it was added to the system:
title moon100 dhcp root (nd) kernel /tftpboot/100/vmlinuz ramdisk=10240 rw root=/dev/nfs boot=nfs nfsroot=192.168.80.1:/usr/pluto/diskless/100 initrd /tftpboot/100/initrd.img
After modifying the boot/grub/menu.lst there is no need to run or install GRUB itself again. This floppy can now be used not only to boot but also to install GRUB on other systems or media.
Known Problems
Building fails with newer version of GCC
When using version 0.97 in combination with a modern version of the Gnu Compiler Collection (GCC) the build is likely to fail, which goes a little like this:
make[2]: Entering directory `/mnt/sda8/usr/src/PMS/Building/grub-0.97/netboot' if gcc -DHAVE_CONFIG_H -I. -I. -I.. -I../stage2 -I../stage1 -Wall -Wmissing-prototypes -Wunused -Wshadow -Wpointer-arith -falign-jumps=1 -falign-loops=1 -falign-functions=1 -Wundef -Os -fno-stack-protector -fno-builtin -nostdinc -DFSYS_TFTP=1 -DINCLUDE_RTL8139=1 -DCONGESTED=1 -DNE_SCAN=0x280,0x300,0x320,0x340 -DWD_DEFAULT_MEM=0xCC000 -g -MT libdrivers_a-main.o -MD -MP -MF ".deps/libdrivers_a-main.Tpo" -c -o libdrivers_a-main.o `test -f 'main.c' || echo './'`main.c; \ then mv -f ".deps/libdrivers_a-main.Tpo" ".deps/libdrivers_a-main.Po"; else rm -f ".deps/libdrivers_a-main.Tpo"; exit 1; fi main.c:57: error: static declaration of 'bootp_data' follows non-static declaration ./etherboot.h:534: error: previous declaration of 'bootp_data' was here main.c:59: error: static declaration of 'end_of_rfc1533' follows non-static declaration ./etherboot.h:536: error: previous declaration of 'end_of_rfc1533' was here main.c: In function 'udp_transmit': main.c:231: warning: pointer targets in passing argument 1 of 'eth_transmit' differ in signedness main.c:276: warning: pointer targets in passing argument 1 of 'eth_transmit' differ in signedness main.c:290: warning: pointer targets in passing argument 1 of 'eth_transmit' differ in signedness main.c: In function 'tftp': main.c:462: warning: pointer targets in passing argument 1 of 'fnc' differ in signedness main.c: In function 'rarp': main.c:509: warning: pointer targets in passing argument 1 of 'eth_transmit' differ in signedness main.c: In function 'udpchksum': main.c:729: warning: dereferencing type-punned pointer will break strict-aliasing rules main.c: In function 'await_reply': main.c:893: warning: pointer targets in passing argument 1 of 'grub_memcmp' differ in signedness main.c:895: warning: pointer targets in passing argument 1 of 'grub_memcmp' differ in signedness main.c:925: warning: pointer targets in passing argument 1 of 'decode_rfc1533' differ in signedness main.c: In function 'decode_rfc1533': main.c:973: warning: pointer targets in passing argument 1 of 'grub_memcmp' differ in signedness main.c:973: warning: pointer targets in passing argument 2 of 'grub_memcmp' differ in signedness main.c:984: warning: pointer targets in passing argument 1 of 'grub_memcmp' differ in signedness main.c:1057: warning: pointer targets in passing argument 1 of 'grub_memcmp' differ in signedness main.c:1057: warning: pointer targets in passing argument 2 of 'grub_memcmp' differ in signedness make[2]: *** [libdrivers_a-main.o] Error 1 make[2]: Leaving directory `/mnt/sda8/usr/src/PMS/Building/grub-0.97/netboot' make[1]: *** [all-recursive] Error 1 make[1]: Leaving directory `/mnt/sda8/usr/src/PMS/Building/grub-0.97' make: *** [all] Error 2
No need to panic, this is basicly just the GCC maintainers letting the GRUB developers know they need to clean up their code. Just throw (copy+paste) this command in the mix in order to fix the collateral damage:
patch -Np1 << EOF --- grub-0.97.orig/netboot/main.c 2004-05-21 00:19:33.000000000 +0200 +++ grub-0.97/netboot/main.c 2007-07-20 02:31:28.000000000 +0200 @@ -54,9 +54,9 @@ static int vendorext_isvalid; static unsigned long netmask; -static struct bootpd_t bootp_data; +struct bootpd_t bootp_data; static unsigned long xid; -static unsigned char *end_of_rfc1533 = NULL; +unsigned char *end_of_rfc1533 = NULL; #ifndef NO_DHCP_SUPPORT #endif /* NO_DHCP_SUPPORT */ EOF
All this does is remove the keyword "static" from 2 lines of code. Now you can continue where it left off by issuing the make command again.
Can't I just use yours?
Sure, you can just download an image of the floppy I just created (whilst verifying these steps) and write it to a floppy:
dd if=grub-0.97--enable-diskless--enable-rtl8139.floppy.img of=/dev/fd0
Or mount it using a loopback device:
modprobe loop mkdir floppy mount grub-0.97--enable-diskless--enable-rtl8139.floppy.img floppy -o loop
Note however that this version will only recognize the Realtek 8139 network interface.