22 October 2007 - 17:24pxelinux BSD installs
LUG@GT, my school’s LUG, holds regular “InstallFests,” and for the past few InstallFests, I’ve provided a PXE boot install server with many Linux distros to streamline our installs. For our last event (in September), I also wanted to offer the option of various BSDs to install. It is not as straightforward to offer simultaneous PXE installs of the various BSDs with multiple versions and architectures using pxelinux. I wanted to do this all in a single pxelinux offering, so this post describes how I prepared pxelinux netboot installs for FreeBSD 6.2, OpenBSD 4.1 and NetBSD 3.1 and 4.0RC1 in both 32-bit and 64-bit flavors, all selectable from the same shared install menu (along with the Linux options).
FreeBSD
You’ll need a BSD system to prepare disk images; The instructions here are for FreeBSD and mostly follow this post from the syslinux mailing list, with some slight changes.
- Download a FreeBSD bootonly ISO (for the purposes of this example, 6.2-RELEASE-i386-bootonly.iso)
- Mount the ISO:
mdconfig -a -t vnode -f 6.2-RELEASE-i386-bootonly.iso -u1 ; mount -t cd9660 /dev/md1 /mnt/cdrom - Create a file for a loopback UFS filesystem:
dd if=/dev/zero of=fbsd62_i386.img bs=1k count=32k - Configure a memory disk device:
mdconfig -a -t vnode -f fbsd62_i386.img -u0 - Label the new disk:
bsdlabel -w -B md0 auto; bsdlabel -A md0 - Create a new filesystem:
newfs -b 8192 -f 1024 /dev/md0a - Mount the filesystem:
mount /dev/md0a /mnt/disk - Copy the contents of the boot CD:
cp -R /mnt/cdrom/boot /mnt/disk/ - Unmount the filesystem:
umount /mnt/disk - Clean up:
umount /mnt/cdrom ; mdconfig -d -u0 ; mdconfig -d -u1
At this point you have a file fbsd62_i386.img, which can be gzipped if desired. Add an entry to your pxelinux config similar to the following:
label freebsd6.2_i386 kernel memdiskappend initrd=distros/freebsd/fbsd62_i386.img.gz harddisk noedd
You can perform the same steps and add a similar entry for amd64.
OpenBSD
OpenBSD provides a pxeboot bootloader, but it is hardcoded to request bsd.rd from the tftp server (without manual intervention). This makes it difficult to support multiple architectures, parameters and OpenBSD versions simultaneously. You could simply have users type in the path to the correct image manually, but I wanted an automated process. To work around this problem, I used modified pxeboot and syslinux patches originally provided by ZettaServe. This required building a patched version of OpenBSD’s pxeboot for both architectures (i386 and amd64), as well as rebuilding a patched version of pxelinux.
First, the instructions to build pxeboot, which requires an OpenBSD system (or use my prebuilt images from OpenBSD 4.1):
- Download and unarchive the
/usr/src/syssources fromsys.tar.gz(if necessary) - Download the
pxeboot.patchfor your architecture: i386 patch | amd64 patch (or from the above ZettaServe link) - Apply the patch:
cat pxeboot.patch | patch -l -p0(use -l on the original ZettaServe patch; my patches make it unnecessary for OpenBSD 4.1 sys source) - Make in
stand:cd /usr/src/sys/arch/i386/stand/ ; make(you can simply make instand/pxebootif you already built the dependencies) - Copy modified
pxeboot/pxebootfor use
http://www.thegibson.org/blog/files/openbsd/ contains the prebuilt images and the most current patches (see ftp://ftp.openbsd.org/pub/OpenBSD/4.1/sys.tar.gz for licenses and original source).
Now we need to build a patched pxelinux binary:
- Grab and unpack the syslinux source
- Apply this syslinux patch (applies cleanly on 3.51-3.60pre)
- Build pxelinux.0
Again, my patch is an updated version of the ZettaServe patch, slightly modified in two ways: 1) their patch is for syslinux 3.11 and no longer applies properly without small modifications and; 2) their patch has some extra code for disabling display output on specific embedded hardware. I have removed the screen-related code as I am only interested in the boot parameters.
Now you can simply add pxelinux entries like the following:
label openbsd4.1_i386 kernel distros/openbsd/pxeboot.i386.0 append boot distros/openbsd/bsd.i386.rd label openbsd4.1_amd64 kernel distros/openbsd/pxeboot.amd64.0 append boot distros/openbsd/bsd.amd64.rd
Grab each architecture/version’s bsd.rd and give it a distinct name. pxelinux will now pass the arguments to the modified pxeboot loader which will, in turn, request the correct disk.
NetBSD
NetBSD provides slightly more advanced facilities than OpenBSD’s pxeboot loader, but it still has some issues trying to support multiple architectures and versions. When NetBSD’s pxe bootloader is trying to find a root disk to load, it sends out a DHCP request with a distinguished DHCP Vendor-Class-Identifier NetBSD:i386:libsa. I found two problems, however: 1) the request from the amd64 PXE bootloader also sends the same string as i386, so there is no way to distinguish the two to send different root disks; and 2) I wanted to support two different versions of NetBSD installs (choose to install 3.1 or 4.0RC1).
My solution was fairly low-tech. I simply made two copies of each pxeboot_ia32.bin file (the i386 and amd64 binaries are actually different, despite the name and the fact that both identify as the i386 in the DHCP vendor class identifier – you can’t actually load an amd64 kernel from the i386 loader). I created pxeboot-3.1.amd64.0, pxeboot-3.1.i386.0, pxeboot-4.0rc1.amd64.0, and pxeboot-4.0rc1.i386.0 and hex edited the amd64 binaries to send NetBSD:ix64 rather than NetBSD:i386 (ia64 means Itanium, so I didn’t want to use that). I also edited the 4.0 images to send NetBSD:...:lib40 rather than NetBSD:...:libsa. I then added the following entries to my pxelinux config:
label netbsd3.1_i386 kernel distros/netbsd/pxeboot-3.1.i386.0 label netbsd3.1_amd64 kernel distros/netbsd/pxeboot-3.1.amd64.0 label netbsd4.0rc1_i386 kernel distros/netbsd/pxeboot-4.0rc1.i386.0 label netbsd4.0rc1_amd64 kernel distros/netbsd/pxeboot-4.0rc1.amd64.0
The final piece of the puzzle is how to specify the correct root disks for each installer, which we accomplish by using dhcpd’s ability to distinguish between requests from the different versions. Download netbsd-INSTALL.gz for each architecture and version, and name them uniquely. Then change your dhcpd configuration to send the proper files when the NetBSD vendor class identifiers are encountered:
if substring (option vendor-class-identifier, 0, 18) = "NetBSD:i386:libsa" {
filename "tftp:distros/netbsd/netbsd-INSTALL-3.1.i386.gz";
}
elsif substring (option vendor-class-identifier, 0, 18) = "NetBSD:ix64:libsa" {
filename "tftp:distros/netbsd/netbsd-INSTALL-3.1.amd64.gz";
}
elsif substring (option vendor-class-identifier, 0, 18) = "NetBSD:ix64:lib40" {
filename "tftp:distros/netbsd/netbsd-INSTALL-4.0rc1.amd64.gz";
}
elsif substring (option vendor-class-identifier, 0, 18) = "NetBSD:i386:lib40" {
filename "tftp:distros/netbsd/netbsd-INSTALL-4.0rc1.i386.gz";
}
else {
filename "pxelinux.0";
}
I placed that where normally you’d just have filename "pxelinux.0" in your dhcpd.conf (using ISC’s dhcpd). Anyway, the NetBSD solution isn’t “pretty,” but it works and isn’t too much trouble. It would probably be feasible to patch NetBSD’s pxe boot loader to operate in much the same way as the patched OpenBSD version, but I didn’t want to spent too much time on it.
Epilogue
I also wanted to try to offer DragonFlyBSD and PC-BSD, but I didn’t have enough time to start looking into those. I noticed that DragonFlyBSD offers a PXE boot server option on the install CD, so I could probably use that as a starting point.
Unfortunately, my work didn’t lead to any BSD installs (except my many test installs in VMware virtual machines prior to the event); no one even asked about BSDs. I guess this has to do with the typical demographics of LUG InstallFest attendees. Anyone coming to LUG to get help installing Linux is probably relatively new to the whole non-Windows OS scene, and might not have even heard of the BSDs. Also, people who would be most likely to install one of the BSDs probably wouldn’t need someone else to install it for them.
4 Comments | Tags: PXE-related
26 Oct 2007 - 22:15
Even if no one requests it, it’s still pretty cool to have the infrastructure in place to offer a single netboot server with many operating systems on it. I would say it’d make installing on someone’s bizarre hardware easier. If what they request fails, you can quickly try anything else just to get something installed and working.
27 Oct 2007 - 1:39
Yeah, that has come in handy at the few prior InstallFests where I’ve provided the PXE boot server. Sometimes we did do exactly what you mentioned – start with distro A and ran into issues that we could resolve by switching to distro B (running a newer kernel, perhaps).
The next enhancement I’ve had in mind is EFI netboot support for Intel Macs, which is why I was picking your brain on EFI related issues a while back. Unfortunately, I don’t have any Intel Macs or EFI hardware to test on at the moment. I built Intel’s EFI on BIOS32 thing (DUET from TianoCore’s EDK), but I’m not sure if it can simulate netboot. I successfully booted into the DUET EFI emulation thing on a spare system, but it doesn’t seem to see any network cards to netboot from.
27 Jan 2008 - 15:46
[...] We can network boot installers for all of the different Linux distros we support as well as various BSDs (and a GParted live image). The various Linux net-install images require users to specify a network [...]
19 Mar 2008 - 6:53
[...] # mdconfig -a -t vnode -f 7.0-RELEASE-i386-bootonly.iso -u1 ; mount -t cd9660 /dev/md1 /mnt/cdrom # dd if=/dev/zero of=fbsd7R_i386.img bs=1k count=32k # mdconfig -a -t vnode -f fbsd7R_i386.img -u0 # bsdlabel -w -B md0 auto; bsdlabel -A md0 # newfs -b 8192 -f 1024 /dev/md0a # mount /dev/md0a /mnt/disk # cp -R /mnt/cdrom/boot /mnt/disk/ # umount /mnt/disk # umount /mnt/cdrom ; mdconfig -d -u0 ; mdconfig -d -u1 [nach /dev/rant] [...]