Using pxeboot to install FreeBSD 5.3 on a laptop without bootable CDROM drive

This month I had to install FreeBSD 5.3 on a laptop that lacked a bootable CDROM (a Toshiba Portege R100). Rather than launch the installation from floppies, I decided to explore the use of pxeboot (supported by the R100’s BIOS) to enable the laptop to boot the FreeBSD 5.3 Installation CDROM over my local LAN.

What is pxeboot?

A quick summary – when your BIOS is set to perform a “LAN boot” it pulls boot information (a pxeboot executable, boot-time configuration details and an operational kernel) from another host on the local LAN. The process requires your on-LAN DHCP server to co-operate by handing back pxeboot-specific optional parameters – the booting machine uses DHCP to query for both an IP address and the on-LAN location of the boot time configuration files and kernel.

What I wanted to do is use pxeboot to force my laptop to boot from the FreeBSD 5.3 installation CDROM, in the absence of a bootable CDROM drive on the laptop itself.

Some more info on pxeboot can be found in the FreeBSD manpage or an article on the FreeBSD website.

An overview of the solution

There are three main components required on your local network:

  • DHCP server
  • TFTP server
  • NFS server

When a client begins to boot over the local LAN, it queries the DHCP server and expects to get back not only a valid IP address but also pointers to where it can find a functional pxeboot executable. The client then initiates a TFTP transfer of the nominated pxeboot executable into local memory, and begins executing pxeboot in place of the more usual boot loader. pxeboot then attempts to NFS-mount a nominated file system that is assumed to contain /boot, the location (under FreeBSD 5.3 at least) of a bootable kernel and various boot-time configuration files.

I chose to create an NFS-exported file system under /cdroms/fb53pxe/ which contained only one directory – /boot/ – copied from the FreeBSD 5.3 installation CDROM. The TFTP server pointed to a copy of pxeboot located at /cdroms/fb53pxe/boot/pxeboot and the NFS server exported /cdroms/fb53pxe/. (It was important to have a modifiable copy of /boot, rather than exporting the FreeBSD 5.3 installation CDROM directly, because /boot/loader.conf needs an extra line to make pxebooting work properly for my needs.)

Creating the pxe-bootable version of the FreeBSD 5.3 Installer file system

As root I first created a minimal, bootable file system from the FreeBSD 5.3 installation CROM using the following steps (…assuming the FreeBSD 5.3 installation CDROM is in the drive):

mount /cdrom 
mkdir -p /cdroms/fb53pxe
cp -Rp /cdrom/boot /cdroms/fb53pxe
umount /cdrom

The main reason we create a separate copy of /boot on regular disk is to edit /cdroms/fb53pxe/boot/loader.conf by adding the following line:

vfs.root.mountfrom="ufs:/dev/md0c"

(This line forces the kernel to use memory mapped disk at /dev/md0c as the root partition, despite the fact that pxeboot normally expects to use an NFS-mounted root partition. The importance of this change will become clearer below.)

DHCP Server configuration

I already had a DHCP server installed on my central machine (easily installed with ‘pkg_add -r isc-dhcp3-server’ and adding ‘dhcpd_enable=”YES”‘ to /etc/rc.conf). The IP to MAC address mappings are defined in /usr/local/etc/dhcpd.conf. In my case, my laptop machine (r100, at 192.168.10.40) already had a special entry that looked like this:

host r100 {
hardware ethernet 00:08:0d:88:c4:33; [This uniquely identifies the client]
fixed-address 192.168.10.40;         [DHCP assigns this IP address to the client]
}

This entry was augmented with three additional lines to support pxeboot, and now looked like:

host r100 {
hardware ethernet 00:08:0d:88:c4:33;
fixed-address 192.168.10.40;
next-server 192.168.10.1;            [Client will do TFTP and NFS transfers from 192.168.10.1]
filename "fb53pxe/boot/pxeboot";     [Grabbed via TFTP, executed in place of the client host's boot loader]
option root-path "/cdroms/fb53pxe/"; [pxeboot will look for /boot/kernel relative to this NFS-mounted directory]
}

TFTP Server configuration

TFTP was easily enabled by editting /etc/inetd.conf to have the following line:

tftp dgram udp wait root /usr/libexec/tftpd tftpd -s /cdroms/

The line above means that all TFTP requests will be resolved relative to /cdroms on my server host (the “-s” forces tftpd to perform a chroot to /cdroms/ after starting up). Recall that I placed a copy of the installation CDROM’s /boot directory tree under /cdroms/fb53pxe/boot. The path specified under filename in the DHCP server’s configuration file (above) thus results in the client requesting the file/cdroms/fb53pxe/boot/pxeboot using TFTP, as required.

Run kill -HUP `cat /var/run/inetd.pid` after editting /etc/inetd.conf to ensure inetd is re-initialised correctly.

NFS Server configuration

I already had NFS running, so the only additional step was to add /cdroms/fb53pxe in the list of exported filesystems. The following line was added to /etc/exports:

/cdroms/fb53pxe -network 192.168.10 -mask 255.255.255.0

This export matches the option root-path in the DHCP server’s configuration file (above), the path that the pxeboot client will automount and use as the intial root directory during the early stage of booting.

Run kill -HUP `cat /var/run/mountd.pid` after editting /etc/exports to ensure the NFS server is re-initialised correctly.

What happens during boot now?

Assuming everything’s working okay, a typical boot sequence is now:

  • Client issues DHCP request, and is handed back an IP address along with next-server, filename and root-path information.
  • Client initiates a TFTP request to 192.168.10.1 for filename, “fb53pxe/boot/pxeboot”, which is assumed to point to a valid pxeboot executable. This results in “/cdroms/fb53pxe/boot/pxeboot” being copied over to the client.
  • pxeboot begins executing, and NFS-mounts 192.168.10.1:/cdroms/fb53pxe/ as its temporary root partition. pxeboot then begins a regular boot loader behaviour – reading /boot/loader.conf (residing at 192.168.10.1:/cdroms/fb53pxe/boot/loader.conf), etc, and ultimately loading and booting a running kernel (which it will pull from 192.168.10.1:/cdroms/fb53pxe/kernel/kernel).
  • 192.168.10.1:/cdroms/fb53pxe/boot/mfsroot.gz will be unpacked and used to create a RAM disk on /dev/md0c (this is standard for the Installation CDROM, because naturally we don’t want to touch the client’s hard drive just yet). The mfsroot.gz-derived RAM disk contains a sufficient root partition (with /sbin, etc) for the Installer to function.
  • The newly booted kernel will use /dev/md0c as its root partition (as a consequence of the line we added to loader.conf above – if we had not done so the kernel would have defaulted to continuing to use 192.168.10.1:/cdroms/fb53pxe/ as the root partition, which would then have failed because it lacks the required /sbin, /etc, and related directories).

Once the client is booted in this fashion it continues into the standard FreeBSD 5.3 Installer, and from this point functions just the same as if we’d booted from CDROM or floppies. One advantage of this approach is that you can add multiple hosts in the DHCP server’s configuration if you need to run the FreeBSD 5.3 installer on numerous machines that support pxeboot but lack bootable CDROM drives.

(In my case I continued on to doing the actual Installation over NFS, since I was also exporting the entire FreeBSD 5.3 CDROM image via NFS using the technique described here.)

Historical note: This blog entry was actually made on June 12th 2012, to archive a web page I wrote in December 2004. Although largely for my own benefit, I’ve archived it in the hope it will be useful to others (like you, if you’re reading this page and you aren’t me).

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: