I've been working on petitboot's netboot code recently. Here's the lowdown on how it all works.

Essentially, everything is intended to be compatible with the de-facto standard pxelinux behaviour. However, there's one major difference, in that we skip the stage where the machine downloads a binary pxelinux loader (because we're already running the loader, right?). This means that you probably don't want to populate the filename field in the DHCP response header. That said, petitboot should work fine with most current pxelinux configurations.

Netboot configuration process

By default, petitboot will send a DHCP request on any interfaces that have an active link (ie, have a network cable plugged-in). The DHCP response will dictate petiboot's behaviour:

Firstly, petitboot will look for a "PXE configuration file" option (DHCP option 209) in the response. If this is specified, then petitboot will download and parse that configuration file. This can be either a full URL, or a file path. See the URLs section below for details on paths and URLs.

If no explicit configuration file is given (ie, there's no option 209 included in the DHCP response), then petitboot will attempt pxelinux-style configuration auto-discovery, using the machine's MAC address, the IP of the DHCP lease, and fall back to a file named default. For example, for a machine with a MAC of 00:01:02:03:04:05, given a lease IP of 192.168.0.10 (C0A8000A in hex), petitboot will request the following files, in order, stopping at the first successful download:

  1. prefix/pxelinux.cfg/01-00-01-02-03-04-05
  2. prefix/pxelinux.cfg/C0A8000A
  3. prefix/pxelinux.cfg/C0A8000
  4. prefix/pxelinux.cfg/C0A800
  5. prefix/pxelinux.cfg/C0A80
  6. prefix/pxelinux.cfg/C0A8
  7. prefix/pxelinux.cfg/C0A
  8. prefix/pxelinux.cfg/C0
  9. prefix/pxelinux.cfg/C
  10. prefix/pxelinux.cfg/default

- where prefix will depend on a few things:

  1. If the DHCP response include a "PXE path prefix" option (DHCP option 210), petitboot will use that value as the prefix. This prefix can be a full URL, or just a path prefix (see the URLs section for details). Note that option 210 should always end with a trailing slash.
  2. Otherwise, TFTP is assumed, the server is determined from the DHCP response, and the files are requested from the top-level directory.

Finally, if there is a "file" parameter present in the DHCP header, then that file is added as a binary boot option, to be executed directly by the machine with no initrd or boot arguments. Don't specify a text config file in this manner, it won't work.

Configuration files

Petitboot supports configuration files based on the syslinux configuration format. However, not all keywords are parsed, as some relate to functionality that isn't relevant in a petitboot environment. Currently, petitboot supports the DEFAULT, KERNEL, INITRD and APPEND keywords. Keywords are case-insensitive.

Here's a typical petitboot configuration file that defines a single, default boot option:

default Linux 3.10.4

label Linux 3.10.4
    kernel tftp://boot-server/powerpc/vmlinux-3.10.4
    initrd tftp://boot-server/powerpc/initrd-3.10.4
    append root=/dev/sda1 console=hvc0

URLs, servers and paths

Remote resources ­— such as configuration files, kernels and initramfs images — can be specified as full URLs (eg. tftp://hostname/path/file) or just paths (eg. /path/file). If a full URL is given, then petitboot will use that as-is. Supported protocols are currently http, ftp, tftp and nfs.

If only a path is given, petitboot will assume the TFTP protocol, and use an appropriate server address based on the DHCP response parameters, in this order:

  1. The "TFTP Server name" option - DCHP option 66
  2. The "Server Identifier" option - DHCP option 54
  3. The "siaddr" field in the DHCP/BOOTP header

Within a configuration file, paths are resolved relative to the location of that file. In keeping with the pxelinux configuration format, absolute paths can be give with a :: prefix - eg. ::/powerpc/vmlinux. Full URLs are always treated as absolute.

DHCP configuration examples

Here are a couple of DHCP server configurations that illustrate how to netboot petitboot machines. These examples are intended for the ISC DHCP server, and only show the configurations relevant to petitboot configuration - you'll need to define the usual subnet, range, etc sections too.

Single, predefined configuration file

This simple example configures all DHCP clients to use a single petitboot configuration file, served over HTTP:

# define a "conf-file" option syntax for the PXE configuration file (opt 209)
option conf-file code 209 = text;

option conf-file "http://boot-server/petitboot.cfg";

Fixed configuration for multiple architectures

This example shows a configuration that will allow petitboot-based POWER machines to work alongside pxelinux-based x86 machines. We use the DHCP architecture identifier 0x0e to dinstinguish the POWER OPAL boot clients.

# define a "conf-file" option syntax for the PXE configuration file (opt 209)
option conf-file code 209 = text;

# define an "arch" option syntax for the DHCP architecture identifier (opt 93)
option arch code 93 = unsigned integer 16;

# specify separate configuration files for powerpc & x86 machines
# and configure x86 machines to use the pxelinux.0 loader.
if option arch = 00:0e {
    option conf-file "powerpc/pxelinux/netboot.cfg";

} else {
    filename "x86/pxelinux/pxelinux.0";
    option conf-file "netboot.cfg";
}

Since we're not specifying full URLs for the configuration files here, petitboot will attempt to download using TFTP, from the same host as the DHCP server.

In the x86 section, note that the config file (netboot.cfg) is specified relative to the pxelinux.0 binary. In this case, pxelinux will request the file from x86/pxelinux/netboot.cfg.

Managed TFTP server

In automated-provisioning environments, a central deployment system may control machine setup and boot. When a newly-racked machine is first booted, we want it to boot to an initial install/provision environment, where it is initialised and registers itself with the provisioning service. Once that registration is complete, we want it to boot to the newly-installed environment.

One way to achieve this is to have the deployment system manage PXE configuration files that are served over TFTP.

For this, we'd rely on the PXE autodiscovery mechanism for any newly-deployed machines (relying on the fallback to the configuration file named 'default'). Once a machine has completed its provisioning process (and registered with the deployment service), a per-machine configuration file can be added to the TFTP server, named after the machine's MAC address. This file will configure the newly-provisioned machine to boot to its standard OS environment, rather than booting through the initial-install process again.

For this scenario, we can use a PXE path prefix parameter to distinguish machines of different architectures:

# define a "path-prefix" option syntax for the PXE path prefix (opt 210)
option path-prefix code 210 = text;

# define an "arch" option syntax for the DHCP architecture identifier (opt 93)
option arch code 93 = unsigned integer 16;

# use 192.168.0.3 as our managed TFTP server
next-server 192.168.0.3;

# provide separate binaries and configuration files depending on
# client architecture
if option arch = 00:0e {
    # POWER OPAL
    option path-prefix "powerpc/";

} else if option arch = 00:07 {
    # x86-64 EFI
    option path-prefix "x86-efi/";
    filename "pxelinux/bootx64.efi";

} else {
    # x86 PC-BIOS
    option path-prefix "x86-pc-bios/";
    filename "pxelinux/pxelinux.0";
}

We could just as easily use HTTP instead of TFTP here, by specifying full HTTP URLs as the configuration files. For the non-petitboot machines, we'd need to use a pxe loader that supports HTTP, like gPXE.

Managed DHCP server

This is similar to the previous example, but rather than using per-machine configuration files (served over TFTP), we can implement per-machine configuration directly in the DHCP server configuration.

If our DHCP configuration is managed by the deployment system, we can use host-specific configurations for machines that have been provisioned, and fall back to a default configuration for newly-racked machines. In this scenario, the deployment system is responsible for managing the DHCP configuration by adding a 'host' stanza for each known machine, after installation.

# define a "conf-file" option syntax for the PXE configuration file (opt 209)
option conf-file code 209 = text;

# define an "arch" option syntax for the DHCP architecture identifier (opt 93)
option arch code 93 = unsigned integer 16;

# configuration for running installers on unknown hosts: provide separate
# binaries and configuration files depending on client architecture
if option arch = 00:0e {
    # POWER OPAL
    option conf-file "pxe-configs/installer-powerpc.conf"

} else if option arch = 00:07 {
    # x86-64 EFI
    option conf-file "pxe-configs/installer-x86-64-efi.conf"
    filename "pxelinux/bootx64.efi";
}

# known host configurations, for which we specify an existing config file. These
# sections are generated and managed by the deployment process, after each
# machine has been provisioned.
host server-001 {
        hardware ethernet 3c:97:0e:3b:85:00;
        option conf-file "pxe-configs/runtime-powerpc.conf";
}

host server-002 {
        hardware ethernet b4:1e:26:c4:a0:be;
        option conf-file "pxe-configs/runtime-x86.conf";
}