summaryrefslogtreecommitdiffstats
path: root/src/include/ipxe/base16.h
diff options
context:
space:
mode:
authorMichael Brown2024-02-27 14:34:17 +0100
committerMichael Brown2024-02-27 15:38:41 +0100
commit182ee909313fc60875d3f1741cd4a0bb7dfd15e1 (patch)
tree699730f570dbf392af6f6a4200a759862822bdd9 /src/include/ipxe/base16.h
parent[eap] Add support for the MS-CHAPv2 authentication method (diff)
downloadipxe-182ee909313fc60875d3f1741cd4a0bb7dfd15e1.tar.gz
ipxe-182ee909313fc60875d3f1741cd4a0bb7dfd15e1.tar.xz
ipxe-182ee909313fc60875d3f1741cd4a0bb7dfd15e1.zip
[efi] Work around broken boot services table manipulation by UEFI shim
The UEFI shim installs wrappers around several boot services functions before invoking its next stage bootloader, in an attempt to enforce its desired behaviour upon the aforementioned bootloader. For example, shim checks that the bootloader has either invoked StartImage() or has called into the "shim lock protocol" before allowing an ExitBootServices() call to proceed. When invoking a shim, iPXE will also install boot services function wrappers in order to work around assorted bugs in the UEFI shim code that would otherwise prevent it from being used to boot a kernel. For details on these workarounds, see commits 28184b7 ("[efi] Add support for executing images via a shim") and 5b43181 ("[efi] Support versions of shim that perform SBAT verification"). Using boot services function wrappers in this way is not intrinsically problematic, provided that wrappers are installed before starting the wrapped program, and uninstalled only after the wrapped program exits. This strict ordering requirement ensures that all layers of wrappers are called in the expected order, and that no calls are issued through a no-longer-valid function pointer. Unfortunately, the UEFI shim does not respect this strict ordering requirement, and will instead uninstall (and reinstall) its wrappers midway through the execution of the wrapped program. This leaves the wrapped program with an inconsistent view of the boot services table, leading to incorrect behaviour. This results in a boot failure when a first shim is used to boot iPXE, which then uses a second shim to boot a Linux kernel: - First shim installs StartImage() and ExitBootServices() wrappers - First shim invokes iPXE via its own PE loader - iPXE installs ExitBootServices() wrapper - iPXE invokes second shim via StartImage() At this point, the first shim's StartImage() wrapper will illegally uninstall its ExitBootServices() wrapper, without first checking that nothing else has modified the ExitBootServices function pointer. This effectively bypasses iPXE's own ExitBootServices() wrapper, which causes a boot failure since the code within that wrapper does not get called. A proper fix would be for shim to install its wrappers before starting the image and uninstall its wrappers only after the started image has exited. Instead of repeatedly uninstalling and reinstalling its wrappers while the wrapped program is running, shim should simply use a flag to keep track of whether or not it needs to modify the behaviour of the wrapped calls. Experience shows that there is unfortunately no point in trying to get a fix for this upstreamed into shim. We therefore work around the shim bug by removing our ExitBootServices() wrapper and moving the relevant code into our GetMemoryMap() wrapper. Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/include/ipxe/base16.h')
0 files changed, 0 insertions, 0 deletions