What iPXE can do
We can boot from an iPXE image of various kinds (e.g. ISO image, USB
stick, .efi
executable) or get a bootable image over the network by
the system’s native PXE booting method.
The iPXE image can have embedded in it a script that tells it where to go and get and display a menu of installation options. It then has the ability to pull in the installation files by http and boot and complete the installation.
Example iPXE setup
Building an iPXE image
Get the source:
git clone git://git.ipxe.org/ipxe.git
In the directory ipxe/src
create an iPXE script that will get
embedded in your images - this can go out and chainload another iPXE
script (which is our installation menu) via http.
Contents of file ipxe/src/chain.ipxe
:
#!ipxe
dhcp
chain http://192.168.1.25/install.ipxe
Build the image with the script chain.ipxe
embedded in it.
For an ISO image, in the directory ipxe/src
:
make bin/ipxe.iso EMBED=chain.ipxe
For a standard USB stick image:
make bin/ipxe.usb EMBED=chain.ipxe
For an image to get by standard PXE by network boot:
make bin/undionly.kpxe EMBED=chain.ipxe
This will require setting up DHCP and TFTP server in an appropriate
way to serve the file undionly.kpxe
. See
http://ipxe.org/howto/chainloading
However, to boot EFI systems by PXE you will need to serve ipxe.efi
.
This means that if you want a setup that works with legacy and EFI systems, the DHCP server needs to be able to detect the type of system that is connecting and specify which file they get (see below).
For an EFI executable:
make bin-x86_64-efi/ipxe.efi EMBED=chain.ipxe
[Note: this last failed for me with recent source (November 2015) but worked fine with an earlier version (June 2015). I’m not sure if this is a problem with the source or with the tool chain.]
[Note: it’s also possible to use the on-line build setup at https://rom-o-matic.eu/, which is capable of embedding scripts. Choose the "Advanced" menu and "EFI PXE bootstrap 64-bit (.efi)"]
Installation menu
The file install.ipxe
in this case is in the root of the web server
at 192.168.1.25
and can look something like this:
#!ipxe
:start
menu Please choose an operating system to install
item --gap openSUSE
item 42.1 openSUSE Leap
item tumbleweed.20151022 tumbleweed.20151022
item 13.2-64-bit openSUSE 13.2 64-bit
item --gap SLES 12
item sles12-ga SLES 12 GA 64-bit
item --gap ipxe shell
item shell Drop to iPXE shell
choose target && goto ${target}
:failed
echo Booting failed, dropping to shell
goto shell
:shell
echo Type 'exit' to get the back to the menu
shell
set menu-timeout 0
set submenu-timeout 0
goto start
:42.1
kernel http://192.168.1.25/42.1/boot/x86_64/loader/linux initrd=initrd install=http://192.168.1.25/42.1/
initrd http://192.168.1.25/42.1/boot/x86_64/loader/initrd
boot || goto failed
:tumbleweed.20151022
kernel http://192.168.1.25/tumbleweed.20151022/boot/x86_64/loader/linux initrd=initrd install=http://192.168.1.25/tumbleweed.20151022/
initrd http://192.168.1.25/tumbleweed.20151022/boot/x86_64/loader/initrd
boot || goto failed
:13.2-64-bit
kernel http://192.168.1.25/13.2/x86_64/boot/x86_64/loader/linux initrd=initrd install=http://192.168.1.25/13.2/x86_64/
initrd http://192.168.1.25/13.2/x86_64/boot/x86_64/loader/initrd
boot || goto failed
:sles12-ga
kernel http://192.168.1.25/12ga/x86_64/boot/x86_64/loader/linux initrd=initrd install=http://192.168.1.25/12ga/x86_64/
initrd http://192.168.1.25/12ga/x86_64/boot/x86_64/loader/initrd
This produces a menu that looks something like:
Selecting a menu item should set off the install.
(Note: for EFI systems you need initrd=initrd
in the kernel line
or booting the installer will fail. It does no harm for legacy
systems.)
Serving the right files for legacy and EFI clients
Some conditional logic is needed in /etc/dhcpd.conf
on the DHCP
server to make this work. Also, the file undionly.kpxe
is
apparently too large to be loaded initially by legacy PXE boot. So it
needs to be chainloaded by pxelinux.0
.
The conditional setup in /etc/dhcpd.conf
looks like this:
next-server 192.168.1.254;
option arch code 93 = unsigned integer 16;
if option arch = 00:07 or option arch = 00:09 {
filename "ipxe.efi";
} else {
filename "pxelinux.0";
}
On the TFTP server we now need to have the following setup:
# ls -l /srv/tftpboot/
total 924
-rw-r--r-- 1 root root 845888 Nov 27 11:38 ipxe.efi
-rw-r--r-- 1 root root 26744 Nov 27 13:58 pxelinux.0
drwxr-xr-x 1 root root 14 Nov 27 15:18 pxelinux.cfg
lrwxrwxrwx 1 root root 13 Nov 27 14:00 undionly.0 -> undionly.kpxe
-rw-r--r-- 1 root root 63437 Nov 27 14:30 undionly.kpxe
The file undionly.0
is a symbolic link to undionly.kpxe
.
Then in the directory pxelinux.cfg
is one file default
with contents:
DEFAULT iPXE-legacy
LABEL iPXE-legacy
KERNEL undionly.0
Booting ipxe.efi
directly from the EFI shell
On an EFI system you may be able to choose an EFI shell as a startup
option. In that shell you can find and directly execute ipxe.efi
from the command line if it is on a FAT formatted USB stick which is
connected when the system is switched on.
Making an EFI-bootable USB stick for iPXE
Assuming here that the USB stick is /dev/sdc
.
Use fdisk
to make it contain a single partition of type b
.
Format as VFAT:
mkfs -t vfat /dev/sdc1
Mount it and create a directory structure as follows:
mount /dev/sdc1 /mnt
mkdir -p /mnt/EFI/BOOT/
Copy ipxe.efi
into that directory with the name bootx64.efi
cp ipxe.efi /mnt/EFI/BOOT/bootx64.efi
Unmount:
umount /mnt
Write the gptmbr.bin
from the syslinux package to the start of the disk:
dd if=/usr/share/syslinux/gptmbr.bin of=/dev/sdc
It is now an EFI-bootable USB stick and when booted will run the iPXE boot and retrieve the chainloaded menu.