autoexec.ipxe from tftp root not being used due to an erroneously detected zero length autoexec.ipxe on ipxe rom
A zero length autoexec.ipxe is detected on ipxe rom, causing autoexec.ipxe from tftp root not being used.
Changing the definition for EFI_AUTOEXEC_NAME revealed that this behaviour is independent of the actual filename used for autoexec.ipxe.
Current Setup
In my current setup I bootstrap ipxe using an embedded script to chainload custom config from a http server via pxe-boot (or ipxe (if available))
TL;DR: That works as expected! (Apart from the missleading file:autoexec.ipxe... ok)
Details
BdsDxe: failed to load Boot0001 "UEFI QEMU HARDDISK deadbeef " from PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x5,0xFFFF,0x0): Not Found
iPXE 1.0.0+git-20190125.36a4c85-5.1 -- Open Source Network Boot Firmware -- http://ipxe.org
Features: DNS HTTP iSCSI NFS TFTP AoE EFI Menu
net0: 52:54:00:12:34:56 using virtio-net on 0000:01:00.0 (open)
[Link:up, TX:0 TXE:0 RX:5 RXE:0]
Configuring (net0 52:54:00:12:34:56).................. ok
net0: 192.168.0.211/255.255.255.0
net0: fe80::5054:ff:fe12:3456/64
Next server: 192.168.0.1
Filename: uefi/ipxe.efi
tftp://192.168.0.1/uefi/ipxe.efi... ok
ipxe.efi : 1048576 bytes [EFI]
INIT initialising eficonsole...
INIT initialising heap...
INIT initialising timer...
INIT initialising efivars...
INIT initialising efi...
INIT initialising process...
INIT initialising builtin...
INIT initialising smbios...
INIT initialising pci...
INIT initialising embedded...
INIT initialising netX...
iPXE initialising devices...
INIT startup cachedhcp1...
INIT startup efi_tick...
INIT startup devices...
EFI PciRoot(0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/MAC(525400123456,0x1) found SimpleFileSystem on PciRoot(0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/MAC(525400123456,0x1)
file:autoexec.ipxe...LOCAL 0x7e32fee8 using PciRoot(0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/MAC(525400123456,0x1)
LOCAL 0x7e32fee8 using ".\autoexec.ipxe"
ok
EFI PciRoot(0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/MAC(525400123456,0x1) discarding zero-length autoexec.ipxe
INIT startup efi_cmdline...
INIT startup rbg...
INIT startup cachedhcp2...
INIT startup complete
iPXE 1.0.0+ -- Open Source Network Boot Firmware -- https://ipxe.org
Features: DNS HTTP iSCSI TFTP VLAN SRP AoE EFI Menu
Executing embedded script
Waiting for DHCP response ...
Configuring (net0 52:54:00:12:34:56)...... ok
Network configured
Trying to load bootfile from http://192.168.0.1/bootfiles/default.ipxe
http://192.168.0.1/bootfiles/default.ipxe... ok
http://192.168.0.1/bootfiles/vmlinuz... ok
http://192.168.0.1/bootfiles/initrd.img... ok
EFI stub: Loaded initrd from LINUX_EFI_INITRD_MEDIA_GUID device path
EFI stub: Measured initrd data into PCR 9
INIT shutdown cachedhcp2...
INIT shutdown tcp...
INIT shutdown rbg...
INIT shutdown devices...
INIT shutdown efi_tick...
INIT shutdown heap...
INIT shutdown efi_watchdog...
INIT shutdown complete
- The ipxe from the NIC rom is executed
- Configures network via DHCP
- Downloads tftp://192.168.0.1/uefi/ipxe.efi
- Bootstraps into the new ipxe.efi
- Erroneously detects autoexec.ipxe (but ignores it since we have embedded script compiled in)
- Chainloads
http://192.168.0.1/bootfiles/default.ipxeaccording to the embedded script - Loads kernel + initrd
- Boots
The first instance of ipxe (iPXE 1.0.0+git-20190125.36a4c85-5.1) is provided by qemu (
ipxe-qemu).The second instance of ipxe (iPXE 1.0.0+ -- Open Source Network Boot Firmware) is the one I built based on
f7a1e9ef8e1dc22ebded786507b872a45e3fb05dfromgithub.com/ipxe/ipxe.gitwhich got bootstrapped.
Problem
Now I was planning to move from a custom build with embedded script to autoexec.ipxe.
Most probably, due to a bug how access to files is handled by tianocore/EDK II (the uefi firmware deployed). (I could not find the time to debug that yet), this fails on my qemu test setup.
Test setup
I was testing using qemu-system-x86_64 on Debian 12 (bookworm)
qemu-img create -f qcow2 empty.img 10G
OVMF_PATH="/usr/share/OVMF/"
cp "${OVMF_PATH}/OVMF_CODE_4M.fd" fw.image
cp "${OVMF_PATH}/OVMF_VARS_4M.fd" fw.image.vars
Use of pxe to bootstrap self built iPXE ROM from TFTP (autoexec.ipxe not found - correct)
qemu-system-x86_64 -cpu qemu64 -smp 4 -machine q35,accel=kvm:tcg -global ICH9-LPC.noreboot=off -m 16G \
-device ide-hd,serial=deadbeef,drive=storage \
-drive if=pflash,format=raw,unit=0,readonly=on,file=fw.image \
-drive if=pflash,format=raw,file=fw.image.vars \
-drive file=empty.img,if=none,format=qcow2,id=storage \
-netdev tap,id=cloud,ifname=pxe-1-target,script=no,downscript=no \
-device virtio-net-pci,netdev=cloud \
-global virtio-net-pci.romfile= \
-serial mon:stdio
Note the
-global virtio-net-pci.romfile=
Relevant output:
...
INIT startup devices...
EFI PciRoot(0x0)/Pci(0x2,0x0)/MAC(525400123456,0x1)/IPv4(0.0.0.0,0x0,DHCP,0.0.0.0,0.0.0.0,0.0.0.0) found no SimpleFileSystem: Error 0x7f45e08e (https://ipxe.org/7f45e08e)
EFI PciRoot(0x0)/Pci(0x2,0x0)/MAC(525400123456,0x1)/IPv4(0.0.0.0,0x0,DHCP,0.0.0.0,0.0.0.0,0.0.0.0) found ManagedNetworkSb on PciRoot(0x0)/Pci(0x2,0x0)/MAC(525400123456,0x1)
autoexec.ipxe... Not found (https://ipxe.org/2d12618e)
EFI PciRoot(0x0)/Pci(0x2,0x0)/MAC(525400123456,0x1)/IPv4(0.0.0.0,0x0,DHCP,0.0.0.0,0.0.0.0,0.0.0.0) could not download autoexec.ipxe: Not found (https://ipxe.org/2d12618e)
INIT startup efi_cmdline...
...
Use of ipxe to bootstrap self built iPXE ROM from TFTP (autoexec.ipxe erroneously detected - incorrect)
qemu-system-x86_64 -cpu qemu64 -smp 4 -machine q35,accel=kvm:tcg -global ICH9-LPC.noreboot=off -m 16G \
-device ide-hd,serial=deadbeef,drive=storage \
-drive if=pflash,format=raw,unit=0,readonly=on,file=fw.image \
-drive if=pflash,format=raw,file=fw.image.vars \
-drive file=empty.img,if=none,format=qcow2,id=storage \
-netdev tap,id=cloud,ifname=pxe-1-target,script=no,downscript=no \
-device virtio-net-pci,netdev=cloud \
-serial mon:stdio
Relevant output:
...
INIT startup devices...
EFI PciRoot(0x0)/Pci(0x2,0x0)/MAC(525400123456,0x1) found SimpleFileSystem on PciRoot(0x0)/Pci(0x2,0x0)/MAC(525400123456,0x1)
file:autoexec.ipxe...LOCAL 0x7e36bee8 using PciRoot(0x0)/Pci(0x2,0x0)/MAC(525400123456,0x1)
LOCAL 0x7e36bee8 using ".\autoexec.ipxe"
ok
EFI PciRoot(0x0)/Pci(0x2,0x0)/MAC(525400123456,0x1) discarding zero-length autoexec.ipxe
INIT startup efi_cmdline...
...
Versions used
qemu
$ qemu-system-x86_64 -version
QEMU emulator version 7.2.17 (Debian 1:7.2+dfsg-7+deb12u13)
Copyright (c) 2003-2022 Fabrice Bellard and the QEMU Project developers
Firmware
$ apt show -a ovmf
Package: ovmf
Version: 2022.11-6+deb12u2
iPXE ROM
$ apt show ipxe-qemu
Package: ipxe-qemu
Version: 1.0.0+git-20190125.36a4c85-5.1
Proposed Improvement
Independent of the root cause of the issue it makes sense to not abort iteration over autoexec.ipxe providers in case one of them fails.
diff --git a/src/interface/efi/efi_autoexec.c b/src/interface/efi/efi_autoexec.c
index 73ba5df33..a5feca83a 100644
--- a/src/interface/efi/efi_autoexec.c
+++ b/src/interface/efi/efi_autoexec.c
@@ -201,7 +201,7 @@ int efi_autoexec_load ( void ) {
DBGC ( device, "EFI %s discarding zero-length %s\n",
efi_handle_name ( device ), image->name );
unregister_image ( image );
- return -ENOENT;
+ continue;
}
DBGC ( device, "EFI %s loaded %s (%zd bytes)\n",
Depending on discusison, I can provide a pull request.
What do you think, anyone else experiencing similar issues?
Can there ever be multiple providers? autoexec.ipxe should only ever be loaded from the same path as the ipxe binary itself?
In this case is it an old version of iPXE that does provide this file? Can this be reproduced with update versions of qemu using update versions of iPXE as it's firmware, and not something from 2019?
ad multiple providers: Yes, it iterates over multiple providers - https://github.com/ipxe/ipxe/blob/master/src/interface/efi/efi_autoexec.c#L177
See output below, when compiled with the patch from above it iterates uses SimpleFileSystem and ManagedNetworkSb to retrieve autoexec.ipxe
EFI PciRoot(0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/MAC(525400123456,0x1) found SimpleFileSystem on PciRoot(0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/MAC(525400123456,0x1)
file:autoexec.ipxe...LOCAL 0x7e32fee8 using PciRoot(0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/MAC(525400123456,0x1)
LOCAL 0x7e32fee8 using ".\autoexec.ipxe"
ok
EFI PciRoot(0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/MAC(525400123456,0x1) discarding zero-length autoexec.ipxe
EFI PciRoot(0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/MAC(525400123456,0x1) found ManagedNetworkSb on PciRoot(0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/MAC(525400123456,0x1)
autoexec.ipxe... ok
EFI PciRoot(0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/MAC(525400123456,0x1) loaded autoexec.ipxe (206 bytes)
ad current versions: The version bootstrapped from the tftp server - the one checking for autoexec.ipxe - is a current one (f7a1e9ef8e1dc22ebded786507b872a45e3fb05d)
But strangely, when I build my own rom based on that version, bootstrapping ipxe via tftp the system behaves differently:
In that case it does not (erroneously) find an autoexec.ipxe. It is totally unclear to me why this happens, as the bootstrapped version is exactly the same as before.
However, using the outdated rom to bootstrap a modified ipxe.efi that loads autoexec.ipxe-test instead of autoexec.ipxe it reports to find an empty file:
...
tftp://192.168.0.1/uefi/ipxe.efi... ok
ipxe.efi : 1082880 bytes [EFI]
...
INIT startup devices...
EFI PciRoot(0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/MAC(525400123456,0x1) found SimpleFileSystem on PciRoot(0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/MAC(525400123456,0x1)
file:autoexec.ipxe-test...LOCAL 0x7e317ee8 using PciRoot(0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/MAC(525400123456,0x1)
LOCAL 0x7e317ee8 using ".\autoexec.ipxe-test"
ok
EFI PciRoot(0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/MAC(525400123456,0x1) discarding zero-length autoexec.ipxe-test
EFI PciRoot(0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/MAC(525400123456,0x1) found ManagedNetworkSb on PciRoot(0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/MAC(525400123456,0x1)
MNP PciRoot(0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/MAC(525400123456,0x1) registered as net0
autoexec.ipxe-test... Not found (https://ipxe.org/2d12618e)
...
It seems the ipxe provided via rom (the outdated version from 2019) does impact the bootstrapped version. Unfortunately, I don't get how! Any pointers to the right direction?