Skip to content

Instantly share code, notes, and snippets.

@Leo-PL
Forked from rikka0w0/ipxe_build.md
Created June 21, 2020 22:22
Show Gist options
  • Save Leo-PL/e24671bfeb4edfb042a44753cc69843a to your computer and use it in GitHub Desktop.
Save Leo-PL/e24671bfeb4edfb042a44753cc69843a to your computer and use it in GitHub Desktop.
Build IPXE

1. Install tools and config IPXE

# Install compiler and dependencies
sudo apt-get install -y git gcc make liblzma-dev

# Grab the source code
git clone https://github.com/ipxe/ipxe.git
cd ipxe/src

# Enable NFS support
sed -i 's/#undef\tDOWNLOAD_PROTO_NFS/#define\tDOWNLOAD_PROTO_NFS/' config/general.h

# Enable Ping support
sed -i 's/\/\/#define\ PING_CMD/#define\ PING_CMD/' config/general.h
sed -i 's/\/\/#define\ IPSTAT_CMD/#define\ IPSTAT_CMD/' config/general.h
sed -i 's/\/\/#define\ REBOOT_CMD/#define\ REBOOT_CMD/' config/general.h
sed -i 's/\/\/#define\ POWEROFF/#define\ POWEROFF/' config/general.h

2. Create the embedded script

Create ipxe/src/embed.ipxe, this script will be embedded into the IPXE binary. It breaks the loop and gives control to main.ipxe. It falls back to IPXE shell if main.ipxe is not found on the tftp server root.

#!ipxe

dhcp
chain tftp://${next-server}/main.ipxe || shell

3. Compile IPXE

make bin/undionly.kpxe EMBED=embed.ipxe and then upload bin/undionly.kpxe to root of TFTP server.

4. Configure DNS server

Assume the DNS server is an OpenWrt box with dnsmasq, add the following to /etc/dnsmasq.conf:

dhcp-match=set:bios,60,PXEClient:Arch:00000
dhcp-boot=tag:bios,undionly.XXXXX,dell,192.168.x.x

dhcp-match=set:efibc,60,PXEClient:Arch:00007
dhcp-boot=tag:efibc,ipxe.efi,XXXXX,192.168.x.x

dhcp-match=set:efi64,60,PXEClient:Arch:00009
dhcp-boot=tag:efi64,ipxe.efi,XXXXX,192.168.x.x

Then execute /etc/init.d/dnsmasq restart to apply the changes.

5. Create main.ipxe on TFTP root

#!ipxe
# dhcp

# Set NFS strings
set nfs-server          ${next-server}
set nfs-mountpt         /srv/nfs
set nfs-root            nfs://${nfs-server}${nfs-mountpt}
set nfs-root-linux      ${nfs-server}:${nfs-mountpt}

# HTTP and iSCSI
set iscsi-server        ${next-server}
set http-root           http://${next-server}:3259

# Some menu defaults
set menu-timeout 5000
set submenu-timeout ${menu-timeout}
set menu-default ubuntu1804_live

:start
menu iPXE boot menu
item --gap --                   ------------------------- Operating systems ------------------------------
item --key l    ubuntu1804_live         Ubuntu 18.04 Live
item --key p    windows10_pe            Windows 10 PE
item            windows10_iscsi         Windows 10 iSCSI
item --gap --                   ---------------------------- Installers ----------------------------------
item --key u    ubuntu1804_inst         Install Ubuntu 18.04
item --key d    debian10_inst           Install Debian 10
item --key w    windows10_inst          Install Windows 10 (WIM)
item --gap --                   ------------------------- Advanced options -------------------------------
item            shell                   Drop to iPXE shell
item            reboot                  Reboot
item
item --key x    exit                    Exit iPXE and continue BIOS boot
choose --timeout ${menu-timeout} --default ${menu-default} selected || goto cancel
set menu-timeout 0
goto ${selected}

:cancel
echo You cancelled the menu, dropping you to a shell

:shell
echo Type 'exit' to get the back to the menu
shell
set menu-timeout 0
set submenu-timeout 0
goto start

:reboot
reboot

:exit
exit

###
### Custom menu entries
###

:ubuntu1804_live
kernel ${nfs-root}/casper/vmlinuz
initrd ${nfs-root}/casper/initrd
imgargs vmlinuz initrd=initrd nfsroot=${nfs-root-linux} netboot=nfs boot=live boot=casper systemd.mask=tmp.mount
boot
goto start

:ubuntu1804_inst
set 210:string tftp://${next-server}/ubuntu/
set 209:string pxelinux.cfg/default
chain tftp://${next-server}/ubuntu/pxelinux.0
goto start

:debian10_inst
set 210:string tftp://${next-server}/debian/
set 209:string pxelinux.cfg/default
chain tftp://${next-server}/debian/pxelinux.0
goto start

:windows10_inst
set keep-san 1
# Has to be 0x80 otherwise installer wont accept the disk
sanhook --drive 0x80 iscsi:${iscsi-server}:tcp:3260:1:net.cszombie.au:windows
kernel wimboot
initrd ${http-root}/win10/boot/bcd         BCD
initrd ${http-root}/win10/boot/boot.sdi    boot.sdi
initrd ${http-root}/win10/sources/boot.wim boot.wim
boot
goto start

:windows10_pe
set keep-san 1
sanhook --drive 0x81 iscsi:${iscsi-server}:tcp:3260:1:net.cszombie.au:windows
echo Cyka
sanboot --no-describe ${http-root}/pe10.iso
goto start

:windows10_iscsi
set keep-san 1
sanboot iscsi:${iscsi-server}:tcp:3260:1:net.cszombie.au:windows
goto start

Add Ubuntu Netboot (BIOS only)

# CD into TFTP root
mkdir ubuntu
cd ubuntu
wget http://archive.ubuntu.com/ubuntu/dists/bionic-updates/main/installer-amd64/current/images/netboot/netboot.tar.gz
tar -xzvf netboot.tar.gz
rm netboot.tar.gz

or add the following to main.ipxe:

kernel http://archive.ubuntu.com/ubuntu/dists/bionic-updates/main/installer-amd64/current/images/netboot/ubuntu-installer/amd64/linux
initrd http://archive.ubuntu.com/ubuntu/dists/bionic-updates/main/installer-amd64/current/images/netboot/ubuntu-installer/amd64/initrd.gz
boot

The above method does not need the ubuntu installer to be downloaded on the TFTP server.

Add Debian Netboot

# CD into TFTP root
mkdir debian
cd debian
wget http://ftp.nl.debian.org/debian/dists/buster/main/installer-amd64/current/images/netboot/netboot.tar.gz
tar -xzvf netboot.tar.gz
rm netboot.tar.gz

References

  1. IPXE download and git repo
  2. lzma.h missing
  3. BootMGR sanboot 0x80 issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment