Testing bootloaders
How to test different bootloaders without using MAAS.
Setup
Install LXD
sudo snap install lxdand initialize it
lxd init --autocreate a new network
lxc network create net-test --type=bridge ipv4.address=10.0.1.1/24 ipv4.dhcp=false ipv4.nat=true ipv6.dhcp=false ipv6.address=nonestart a new container
lxc launch ubuntu:24.04 pxe-serverattach the network to the container
lxc config device add pxe-server eth0 nic network=net-test name=eth0Now get a shell in the container with
lxc shell pxe-serverCreate the netplan configuration file:
sudo tee /etc/netplan/99-static.yaml > /dev/null << 'EOF'
network:
version: 2
ethernets:
eth0:
addresses:
- 10.0.1.2/24
nameservers:
addresses:
- 8.8.8.8
routes:
- to: default
via: 10.0.1.1
EOFApply the changes
sudo netplan applyAlways inside the container, install
sudo apt-get update
sudo apt install -y isc-dhcp-server tftpd-hpaCreate the DHCP server configuration:
sudo tee /etc/dhcp/dhcpd.conf > /dev/null << 'EOF'
default-lease-time 600;
max-lease-time 7200;
authoritative;
option arch code 93 = unsigned integer 16; # RFC4578
subnet 10.0.1.0 netmask 255.255.255.0 {
range 10.0.2.50 10.0.1.200;
option routers 10.0.1.1;
option domain-name-servers 10.0.1.1;
next-server 10.0.1.2;
if option arch = 00:0B {
filename "bootaa64.efi";
}
}
EOFCreate the TFTP server configuration:
sudo tee /etc/default/tftpd-hpa > /dev/null << 'EOF'
# /etc/default/tftpd-hpa
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/srv/tftp"
TFTP_ADDRESS=":69"
TFTP_OPTIONS="--secure --verbose"
EOFRestart the services
sudo systemctl restart tftpd-hpa.service
sudo systemctl restart isc-dhcp-serverNow create a folder where you’ll serve the kernel, initrd and squashfs
mkdir ~/images
cd ~/imagesand create a couple of folders
mkdir ~/images/noble
mkdir ~/images/xenialPlace the images for xenial
wget https://images.maas.io/ephemeral-v3/stable/xenial/arm64/20210928/squashfs -O ~/images/xenial/squashfs
wget https://images.maas.io/ephemeral-v3/stable/xenial/arm64/20210928/ga-16.04/generic/boot-initrd -O ~/images/xenial/boot-initrd
wget https://images.maas.io/ephemeral-v3/stable/xenial/arm64/20210928/ga-16.04/generic/boot-kernel -O ~/images/xenial/boot-kerneland for noble
wget https://images.maas.io/ephemeral-v3/stable/noble/arm64/20250921/squashfs -O ~/images/noble/squashfs
wget https://images.maas.io/ephemeral-v3/stable/noble/arm64/20250921/ga-24.04/generic/boot-initrd -O ~/images/noble/boot-initrd
wget https://images.maas.io/ephemeral-v3/stable/noble/arm64/20250921/ga-24.04/generic/boot-kernel -O ~/images/noble/boot-kerneland put the bootloaders in the tftp root
sudo mkdir -p /srv/tftp
sudo mkdir -p /srv/tftp/jammy
cd /tmp
# noble bootloaders
wget https://images.maas.io/ephemeral-v3/candidate/bootloaders/uefi/arm64/20250715.0/grub2-signed.tar.xz
tar -xvf grub2-signed.tar.xz
wget https://images.maas.io/ephemeral-v3/candidate/bootloaders/uefi/arm64/20250715.0/shim-signed.tar.xz
tar -xvf shim-signed.tar.xz
sudo mv grubaa64.efi /srv/tftp
sudo mv mmaa64.efi /srv/tftp
sudo mv bootaa64.efi /srv/tftp
rm shim-signed.tar.xz
rm grub2-signed.tar.xz
# jammy bootloaders
wget https://images.maas.io/ephemeral-v3/candidate/bootloaders/uefi/arm64/20250821.0/grub2-signed.tar.xz
tar -xvf grub2-signed.tar.xz
wget https://images.maas.io/ephemeral-v3/candidate/bootloaders/uefi/arm64/20250821.0/shim-signed.tar.xz
tar -xvf shim-signed.tar.xz
sudo mv grubaa64.efi /srv/tftp/jammy
sudo mv mmaa64.efi /srv/tftp/jammy
sudo mv bootaa64.efi /srv/tftp/jammy
rm shim-signed.tar.xz
rm grub2-signed.tar.xzNow, create the grub configs
sudo mkdir -p /srv/tftp/grub/Create the main grub configuration:
sudo tee /srv/tftp/grub/grub.cfg > /dev/null << 'EOF'
# MAAS GRUB2 pre-loader configuration file
# Load based on MAC address first.
configfile /grub/grub.cfg-${net_default_mac}
# Failed to load based on MAC address. Load based on the CPU
# architecture.
configfile /grub/grub.cfg-default-${grub_cpu}
EOFCreate the default ARM64 grub configuration:
sudo tee /srv/tftp/grub/grub.cfg-default-arm64 > /dev/null << 'EOF'
set default="0"
set timeout=0
menuentry 'Ephemeral' {
echo 'Booting under MAAS direction...'
linux (http,10.0.1.2:8080)/boot-kernel nomodeset root=squash:http://10.0.1.2:8080/squashfs ip=::::maas-enlist:BOOTIF ip6=off cc:\{'datasource_list': ['MAAS']\}end_cc cloud-config-url=http://10.0.1.2:8080/get_enlist_preseed ro overlayroot=tmpfs overlayroot_cfgdisk=disabled BOOTIF=01-${net_default_mac}
initrd (http,10.0.1.2:8080)/boot-initrd
}
EOFChange permissions of the tftp directory
sudo chmod -R 755 /srv/tftpAnd finally start an http server for the images
cd ~/images/xenial/
python3 -m http.server 8080Create a disk and start the machine
In another shell, go back to the host.
Install qemu
sudo apt install qemu-system-arm -y Configure qemu bridge:
sudo mkdir -p /etc/qemu
echo "allow net-test" | sudo tee /etc/qemu/bridge.conf > /dev/nullfinally
qemu-img create -f qcow2 disk.qcow2 20G
sudo qemu-system-aarch64 -machine virt -cpu cortex-a57 -m 4096 -bios /usr/share/qemu-efi-aarch64/QEMU_EFI.fd -boot order=n -drive file=./disk.qcow2,format=qcow2 -netdev bridge,id=net0,br=net-test -device virtio-net-device,netdev=net0,mac=52:54:00:00:00:02 -nographicIn the terminal you should see the machine getting an IP and “booting under MAAS”. And it should fail. Then, you can go back to the container
lxc shell pxe-server
cd /srv/ftfp
sudo cp jammy/* .
sudo chmod -R 755 /srv/tftpand in the host
sudo pkill qemuand restart the emulator. This time, it should succeed. I.e.
- xenial kernel/initrd/squashfs works with jammy bootloaders
- xenial kernel/initrd/squashfs does not work with noble bootloaders.