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;
Root Cause
By modifying
github.com/pief/tftptest.efi
to call
TFTP_GET_FILE_SIZE
we are able to see that this function normally succeeds. It fails when the
caller is iPXE!
#!ipxe imgload tftp://192.168.0.2/tftptest.efi boot
Indeed,
efi_pxe.c
returns
ENOTSUP
for any operation that is not
TFTP_READ_FILE.