EFI/PXE Debugging
These are the steps to diagnosing a problem booting OpenBSD using EFI and PXE.
probing: pc0 com0 mem[636K 1887M 16M 84K 88K 752K 16K 4M 584K 7M 6M 6148M] disk: hd0* hd1* hd2* hd3* hd4 >> OpenBSD/amd64 BOOTX64 3.69 boot> cannot open tftp:/etc/random.seed: No such file or directory booting tftp:/bsd: open tftp:/bsd: No such file or directory failed(2). will try /bsd
Edit/Build/Install
Download and unpack openbsd/src-master, and build/install after each change
cd ~/src/src-master/sys/arch/amd64/stand/efiboot ag -l | entr -s 'make && doas cp ./bootx64/obj/BOOTX64.EFI /tftpboot/efi/BOOTX64.EFI'
Add debug statements to
sys/arch/amd64/stand/efiboot/efipxe.c
/* L144-156 */ status = PXE->Mtftp(PXE, EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE, NULL, FALSE, &size, NULL, &servip, path, NULL, FALSE); printf("status: %d == %d?\n", status, EFI_SUCCESS); printf("PXE: %p\n", PXE); printf("tftp_opcode: %d\n", EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE); printf("servip v4: %d.%d.%d.%d\n", servip.v4.Addr[0], servip.v4.Addr[1], servip.v4.Addr[2], servip.v4.Addr[3]); printf("path: %s\n", path); printf("size: %d\n", size); printf("Mtftp: %p\n", PXE->Mtftp);
Network boot, observe that status is
3.
According to
sys/dev/efi/efi.h
#define EFI_SUCCESS 0 #define EFI_INVALID_PARAMETER EFIERR(2) #define EFI_UNSUPPORTED EFIERR(3)
EDK2 docs for TFTP callback funcions
indicate that
GET_FILE_SIZE
is not supported
/* For MTFTP "get file size" operations, if the MTFTP server does not support the "get file size" option, EFI_UNSUPPORTED will be returned. */
Workaround
diff --git a/sys/arch/amd64/stand/efiboot/efipxe.c b/sys/arch/amd64/stand/efiboot/efipxe.c index 316f2f81d..cb3f79b53 100644 --- a/sys/arch/amd64/stand/efiboot/efipxe.c +++ b/sys/arch/amd64/stand/efiboot/efipxe.c @@ -139,7 +139,10 @@ tftp_open(char *path, struct open_file *f) status = PXE->Mtftp(PXE, EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE, NULL, FALSE, &size, NULL, &servip, path, NULL, FALSE); - if (status != EFI_SUCCESS) { + if (status == EFI_UNSUPPORTED) { + size = 5 * 1024 * 1024; /* actual size unknown, allocate enough space for bsd.rd */ + } + else if (status != EFI_SUCCESS) { free(tftpfile, sizeof(*tftpfile)); return ENOENT; } @@ -158,6 +161,7 @@ tftp_open(char *path, struct open_file *f) status = PXE->Mtftp(PXE, EFI_PXE_BASE_CODE_TFTP_READ_FILE, tftpfile->inbuf, FALSE, &size, NULL, &servip, path, NULL, FALSE); + tftpfile->inbufsize = size; if (status != EFI_SUCCESS) { free(tftpfile, sizeof(*tftpfile)); return ENXIO;
Verify UEFI/TFTP boot with QEMU and iPXE
Configure Network Bridgeip link add br0 type bridge ip address add dev br0 172.16.0.1/24 ip link set dev br0 up ip tuntap add dev tap0 mode tap ip link set tap0 master br0
Install/configure TFTP/DHCP
apt install tftpd-hpa isc-dhcp-server
cat <<EOF >/etc/dhcp/dhcpd.conf
subnet 172.16.0.0 netmask 255.255.255.0 {
next-server 172.16.0.1;
}
host tftptest {
hardware ethernet 00:16:3e:34:bb:5f;
fixed-address 172.16.0.10;
filename "tftptest.efi";
}
EOF
echo 'INTERFACESv4="br0"' > /etc/default/isc-dhcp-server
systemctl restart isc-dhcp-server
Build/test EFI application
sudo apt install gnu-efi build-essential git clone https://github.com/eradman/tftptest.efi.git cd tftptest.efi/ make sudo cp tftptest.efi /srv/tftp/
TFTP boot using QEMU and iPXE
sudo apt install qemu-system-x86
Fetch iPXE Image
cd curl -O https://boot.ipxe.org/ipxe.iso
Start VM
sudo qemu-system-x86_64 \
-nographic \
-bios /usr/share/ovmf/OVMF.fd \
-cdrom ~/ipxe.iso \
-nic tap,ifname=tap0,model=virtio-net-pci,mac=00:16:3e:34:bb:5f
By removing
-cdrom ~/ipxe.iso
we can see that EDK II tools do support this operation.