summaryrefslogtreecommitdiffstats
path: root/src/image/efi_image.c
Commit message (Collapse)AuthorAgeFilesLines
* [build] Mark core files as permitted for UEFI Secure BootMichael Brown2026-01-141-0/+1
| | | | | | | | | | | | Mark all files used in a standard build of bin-x86_64-efi/snponly.efi as permitted for UEFI Secure Boot. These files represent the core functionality of iPXE that is guaranteed to have been included in every binary that was previously subject to a security review and signed by Microsoft. It is therefore legitimate to assume that at least these files have already been reviewed to the required standard multiple times. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [image] Make image data read-only to most consumersMichael Brown2025-04-301-4/+14
| | | | | | | | | | | | | | | | | | | | Almost all image consumers do not need to modify the content of the image. Now that the image data is a pointer type (rather than the opaque userptr_t type), we can rely on the compiler to enforce this at build time. Change the .data field to be a const pointer, so that the compiler can verify that image consumers do not modify the image content. Provide a transparent .rwdata field for consumers who have a legitimate (and now explicit) reason to modify the image content. We do not attempt to impose any runtime restriction on checking whether or not an image is writable. The only existing instances of genuinely read-only images are the various unit test images, and it is acceptable for defective test cases to result in a segfault rather than a runtime error. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [uaccess] Remove redundant copy_from_user() and copy_to_user()Michael Brown2025-04-301-0/+1
| | | | | | | Remove the now-redundant copy_from_user() and copy_to_user() wrapper functions. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Remove userptr_t from EFI PE image parsingMichael Brown2025-04-251-13/+11Star
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [uaccess] Remove redundant user_to_virt()Michael Brown2025-04-211-4/+4
| | | | | | | | | The user_to_virt() function is now a straightforward wrapper around addition, with the addend almost invariably being zero. Remove this redundant wrapper. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [fdt] Populate boot arguments in constructed device treeMichael Brown2025-04-011-2/+3
| | | | | | | | When creating a device tree to pass to a booted operating system, ensure that the "chosen" node exists, and populate the "bootargs" property with the image command line. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Allow for fact that SNP device may be removed by executed imageMichael Brown2025-03-291-10/+14
| | | | | | | | | | | | | | | | | | | | | | | | The executed image may call DisconnectController() to remove our network device. This will leave the net device unregistered but not yet freed (since our installed PXE base code protocol retains a reference to the net device). Unregistration will cause the network upper-layer driver removal functions to be called, which will free the SNP device structure. When the image returns from StartImage(), the snpdev pointer may therefore no longer be valid. The SNP device structure is not reference counted, and so we cannot simply take out a reference to ensure that it remains valid across the call to StartImage(). However, the code path following the call to StartImage() doesn't actually require the SNP device pointer, only the EFI device handle. Store the device handle in a local variable and ensure that snpdev is invalidated before the call to StartImage() so that future code cannot accidentally reintroduce this issue. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Install a device tree for the booted OS, if availableMichael Brown2025-03-281-0/+28
| | | | | | | | | | | | | If we have a device tree available (e.g. because the user has explicitly downloaded a device tree using the "fdt" command), then provide it to the booted operating system as an EFI configuration table. Since x86 does not typically use device trees, we create weak symbols for efi_fdt_install() and efi_fdt_uninstall() to avoid dragging FDT support into all x86 UEFI binaries. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Allow use of typed pointers for efi_open() et alMichael Brown2025-03-241-14/+11Star
| | | | | | | | | Provide wrapper macros to allow efi_open() and related functions to accept a pointer to any pointer type as the "interface" argument, in order to allow a substantial amount of type adjustment boilerplate to be removed. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Use efi_open() for all ephemeral protocol opensMichael Brown2025-03-241-5/+2Star
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Allow wrapping the global boot services table in situMichael Brown2025-03-201-1/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | When DEBUG=efi_wrap is enabled, we construct a patched copy of the boot services table and patch the global system table to point to this copy. This ensures that any subsequently loaded EFI binaries will call our wrappers. Previously loaded EFI binaries will typically have cached the boot services table pointer (in the gBS variable used by EDK2 code), and therefore will not pick up the updated pointer and so will not call our wrappers. In most cases, this is what we want to happen: we are interested in tracing the calls issued by the newly loaded binary and we do not want to be distracted by the high volume of boot services calls issued by existing UEFI drivers. In some circumstances (such as when a badly behaved OEM driver is causing the system to lock up during the ExitBootServices() call), it can be very useful to be able to patch the global boot services table in situ, so that we can trace calls issued by existing drivers. Restructure the wrapping code to allow wrapping to be enabled or disabled at any time, and to allow for patching the global boot services table in situ. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Add support for executing images via a shimMichael Brown2023-05-221-3/+28
| | | | | | | | | | | | | | | | | | | | | | | Add support for using a shim as a helper to execute an EFI image. When a shim has been specified via shim(), the shim image will be passed to LoadImage() instead of the selected EFI image and the command line will be prepended with the name of the selected EFI image. The selected EFI image will be accessible to the shim via the virtual filesystem as a hidden file. Reduce the Secure Boot attack surface by removing, where possible, the spurious requirement for a third party second stage loader binary such as GRUB to be used solely in order to call the "shim lock protocol" entry point. Do not install the EFI PXE APIs when using a shim, since if shim finds EFI_PXE_BASE_CODE_PROTOCOL on the loaded image's device handle then it will attempt to download files afresh instead of using the files already downloaded by iPXE and exposed via the EFI_SIMPLE_FILE_SYSTEM protocol. (Experience shows that there is no point in trying to get a fix for this upstreamed into shim.) Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Add efi_asprintf() and efi_vasprintf()Michael Brown2023-05-221-10/+6Star
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Attempt to detect EFI images that fail Secure Boot verificationMichael Brown2023-05-171-5/+71
| | | | | | | | | | | | An EFI image that is rejected by LoadImage() due to failing Secure Boot verification is still an EFI image. Unfortunately, the extremely broken UEFI Secure Boot model provides no way for us to unambiguously determine that a valid EFI executable image was rejected only because it failed signature verification. We must therefore use heuristics to guess whether not an image that was rejected by LoadImage() could still be loaded via a separate PE loader such as the UEFI shim. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Allow currently executing image to be opened via virtual filesystemMichael Brown2023-05-051-0/+10
| | | | | | | | | | | | | When invoking a kernel via the UEFI shim, the kernel image must be accessible via EFI_SIMPLE_FILE_SYSTEM_PROTOCOL but must not be present in the magic initrd constructed from all registered images. Re-register a currently executing EFI image and mark it as hidden, thereby allowing it to be accessed via the virtual filesystem exposed via EFI_SIMPLE_FILE_SYSTEM_PROTOCOL without appearing in the magic initrd contents. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Use image name instead of pointer value in debug messagesMichael Brown2023-03-071-21/+21
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Add efi_path_terminate() utility functionMichael Brown2023-01-231-3/+1Star
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Split device path functions out to efi_path.cMichael Brown2020-10-161-2/+2
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Connect controllers after loading an EFI driverMichael Brown2020-10-021-0/+11
| | | | | | | | | | | | iPXE is already capable of loading EFI drivers on demand (via e.g. "chain UsbMassStorageDxe.efi") but there is currently no way to trigger connection of the driver to any preexisting handles. Add an explicit call to (re)connect all drivers after successfully loading an image with a code type that indicates a boot services driver. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Work around UEFI specification bug in LoadImageMichael Brown2020-06-041-2/+18
| | | | | | | | | | | | | | | | | | | | | | | | iPXE currently assumes that any error returned from LoadImage() indicates that the image was not loaded. This assumption was correct at the time the code was written and remained correct for UEFI specifications up to and including version 2.1. In version 2.3, the UEFI specification broke API and ABI compatibility by defining that a return value of EFI_SECURITY_VIOLATION would now indicate that the image had been loaded and a valid image handle had been created, but that the image should not be started. The wording in version 2.2 is ambiguous, and does not define whether or not a return value of EFI_SECURITY_VIOLATION indicates that a valid image handle has been created. Attempt to work around all of these incompatible and partially undefined APIs by calling UnloadImage if we get a return value of EFI_SECURITY_VIOLATION. Minimise the risk of passing an uninitialised pointer to UnloadImage by setting ImageHandle to NULL prior to calling LoadImage. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Add support for EFI_GRAPHICS_OUTPUT_PROTOCOL frame buffer consolesMichael Brown2015-10-161-0/+4
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Provide efi_devpath_len()Michael Brown2015-09-131-2/+1Star
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Implement the EFI_PXE_BASE_CODE_PROTOCOLMichael Brown2015-09-021-0/+10
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Many UEFI NBPs expect to find an EFI_PXE_BASE_CODE_PROTOCOL installed in addition to the EFI_SIMPLE_NETWORK_PROTOCOL. Most NBPs use the EFI_PXE_BASE_CODE_PROTOCOL only to retrieve the cached DHCP packets. This implementation has been tested with grub.efi, shim.efi, syslinux.efi, and wdsmgfw.efi. Some methods (such as Discover() and Arp()) are not used by any known NBP and so have not (yet) been implemented. Usage notes for the tested bootstraps are: - grub.efi uses EFI_PXE_BASE_CODE_PROTOCOL only to retrieve the cached DHCP packet, and uses no other methods. - shim.efi uses EFI_PXE_BASE_CODE_PROTOCOL to retrieve the cached DHCP packet and to retrieve the next NBP via the Mtftp() method. If shim.efi was downloaded via HTTP (or other non-TFTP protocol) then shim.efi will blindly call Mtftp() with an HTTP URI as the filename: this allows the next NBP (e.g. grubx64.efi) to also be transparently retrieved by HTTP. shim.efi can also use the EFI_SIMPLE_FILE_SYSTEM_PROTOCOL to retrieve files previously loaded by "imgfetch" or similar commands in iPXE. The current implementation of shim.efi will use the EFI_SIMPLE_FILE_SYSTEM_PROTOCOL only if it does not find an EFI_PXE_BASE_CODE_PROTOCOL; this patch therefore prevents this usage of our EFI_SIMPLE_FILE_SYSTEM_PROTOCOL. This logic could be trivially reversed in shim.efi if needed. - syslinux.efi uses EFI_PXE_BASE_CODE_PROTOCOL only to retrieve the cached DHCP packet. Versions 6.03 and earlier have a bug which may cause syslinux.efi to attach to the wrong NIC if there are multiple NICs in the system (or if the UEFI firmware supports IPv6). - wdsmgfw.efi (ab)uses EFI_PXE_BASE_CODE_PROTOCOL to retrieve the cached DHCP packets, and to send and retrieve UDP packets via the UdpWrite() and UdpRead() methods. (This was presumably done in order to minimise the amount of benefit obtainable by switching to UEFI, by replicating all of the design mistakes present in the original PXE specification.) The EFI_DOWNGRADE_UX configuration option remains available for now, until this implementation has received more widespread testing. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Provide dummy device path in efi_image_probe()Michael Brown2014-09-191-1/+6
| | | | | | | | | | | | | | | | | Some UEFI platforms will fail the call to LoadImage() with EFI_INVALID_PARAMETER if we do not provide a device path (even though we are providing a non-NULL SourceBuffer). Fix by providing an empty device path for the call to LoadImage() in efi_image_probe(). The call to LoadImage() in efi_image_exec() already constructs and provides a device path (based on the most recently opened SNP device), and so does not require this fix. Reported-by: NICOLAS CATTIE <nicolas.cattie@mpsa.com> Tested-by: NICOLAS CATTIE <nicolas.cattie@mpsa.com> Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Wrap any images loaded by our wrapped imageMichael Brown2014-08-291-1/+1
| | | | | | | | | | | | Propagate our modified EFI system table to any images loaded by the image that we wrap, thereby allowing us to observe boot services calls made by all subsequent EFI images. Also show details of intercepted ExitBootServices() calls. When wrapping is used, exiting boot services will almost certainly fail, but this at least allows us to see when it happens. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Move abstract device path and handle functions to efi_utils.cMichael Brown2014-08-061-1/+1
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Open device path protocol only at point of useMichael Brown2014-08-061-1/+1
| | | | | | | | | | | | Some EFI 1.10 systems (observed on an Apple iMac) do not allow us to open the device path protocol with an attribute of EFI_OPEN_PROTOCOL_BY_DRIVER and so we cannot maintain a safe, long-lived pointer to the device path. Work around this by instead opening the device path protocol with an attribute of EFI_OPEN_PROTOCOL_GET_PROTOCOL whenever we need to use it. Debugged-by: Curtis Larsen <larsen@dixie.edu> Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Provide centralised definitions of commonly-used GUIDsMichael Brown2014-08-061-4/+0Star
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Avoid unnecessarily passing pointers to EFI_HANDLEsMichael Brown2014-07-311-2/+2
| | | | | | | | | | | | efi_file_install() and efi_download_install() are both used to install onto existing handles. There is therefore no need to allow for each of their calls to InstallMultipleProtocolInterfaces() to create a new handle. By passing the handle directly (rather than a pointer to the handle), we avoid potential confusion (and erroneous debug message colours). Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Fill in loaded image's DeviceHandle if firmware fails to do soMichael Brown2014-07-301-0/+7
| | | | | | | | | | | | | | | | | | | Some EFI 1.10 implementations (observed with a mid-2011 iMac) seem to fail to fill in the DeviceHandle for our loaded images. It is plausible that these implementations fill in the DeviceHandle only if loading the image from a device path (rather than directly from a memory buffer). Work around this problem by filling in DeviceHandle if the firmware leaves it empty. We cannot sensibly fill in FilePath, because we have no way of knowing whether or not the firmware will treat this as a pointer to be freed when the image returns. Reported-by: Curtis Larsen <larsen@dixie.edu> Tested-by: Curtis Larsen <larsen@dixie.edu> Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Unload started images only on failureMichael Brown2014-07-301-9/+17
| | | | | | | | | | | | | | | | | If the StartImage() call returns with no error, then the image must have been started and returned successfully. It either unloaded itself, or it intended to remain loaded (e.g. it was a driver). We therefore do not unload successful images. If there was an error, we attempt to unload the image. This may not work. In particular, there is no way to tell whether an error returned from StartImage() was due to being unable to start the image (in which case we probably should call UnloadImage()), or due to the image itself returning an error (in which case we probably should not call UnloadImage()). We therefore ignore any failures from the UnloadImage() call itself. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Allow for interception of boot services calls by loaded imageMichael Brown2014-07-161-0/+4
| | | | | | | When building with DEBUG=efi_wrap, print details of calls made by the loaded image to selected boot services functions. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Disable SNP devices when running iPXE as the applicationMichael Brown2014-03-141-0/+4
| | | | | | | | | | | | | Some UEFI builds will set up a timer to continuously poll any SNP devices. This can drain packets from the network device's receive queue before iPXE gets a chance to process them. Use netdev_rx_[un]freeze() to explicitly indicate when we expect our network devices to be driven via the external SNP API (as we do with the UNDI API on the standard BIOS build), and disable the SNP API except when receive queue processing is frozen. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Add sample platform-generated error disambiguationsMichael Brown2013-04-191-3/+19
| | | | | | | | Add disambiguated errors for LoadImage() and StartImage(), primarily to demonstrate how to use __einfo_uniqify() and __einfo_platformify() in the context of EFI platform errors. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Perform meaningful error code conversionsMichael Brown2013-04-191-8/+11
| | | | | | | | Exploit the redefinition of iPXE error codes to include a "platform error code" to allow for meaningful conversion of EFI_STATUS values to iPXE errors and vice versa. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Fix minor typos in efi_image.cMichael Brown2013-03-201-3/+3
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Expose downloaded images via EFI_SIMPLE_FILE_SYSTEM_PROTOCOLMichael Brown2013-03-131-92/+139
| | | | | | | | | | | | | | | | | Expose iPXE's images as a UEFI file system, allowing the booted image to access all images downloaded by iPXE. This functionality is complementary to the custom iPXE download protocol. The iPXE download protocol allows a booted image to utilise iPXE to download arbitrary URIs, but requires the booted image to specifically support the custom iPXE download protocol. The new functionality limits the booted image to accessing only files that were already downloaded by iPXE (e.g. as part of a script), but can work with any generic UEFI image (e.g. the UEFI shell). Both protocols are provided simultaneously, and are attached to the SNP device handle. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [legal] Update FSF mailing address in GPL licence textsMichael Brown2012-07-201-1/+2
| | | | | Suggested-by: Daniel P. Berrange <berrange@redhat.com> Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Add iPXE download protocolJarrod Johnson2012-02-151-2/+124
| | | | | | | | | | | | | iPXE exposes some extended capabilities via the PXE FILE API to allow NBPs such as pxelinux to use protocols other than TFTP. Provide an equivalent interface as a UEFI protocol so that EFI binaries may also take advantage of iPXE's extended capabilities. This can be used with a patched version of elilo, for example: http://comments.gmane.org/gmane.comp.boot-loaders.elilo.general/147 Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Ensure that all drivers are shut down before the OS bootsMichael Brown2011-03-291-30/+0Star
| | | | | | Reported-by: Itay Gazit <itayg@mellanox.co.il> Suggested-by: Michael R Turner <mikeyt@us.ibm.com> Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [image] Simplify image managementMichael Brown2011-03-071-9/+3Star
| | | | | | | | | | | Refactor the {load,exec} image operations as {probe,exec}. This makes the probe mechanism cleaner, eliminates some forward declarations, avoids holding magic state in image->priv, eliminates the possibility of screwing up between the "load" and "exec" stages, and makes the documentation simpler since the concept of "loading" (as distinct from "executing") no longer needs to be explained. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [init] Remove concept of "shutdown exit flags"Michael Brown2011-01-271-1/+1
| | | | | | | | Remove the concept of shutdown exit flags, and replace it with a counter used to keep track of exposed interfaces that require devices to remain active. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Add the "snpnet" driverGeoff Lywood2010-06-021-3/+34
| | | | | | | | | Add a new network driver that consumes the EFI Simple Network Protocol. Also add a bus driver that can find the Simple Network Protocol that iPXE was loaded from; the resulting behavior is similar to the "undionly" driver for BIOS systems. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [build] Rename gPXE to iPXEMichael Brown2010-04-201-3/+3
| | | | | | | | | | | Access to the gpxe.org and etherboot.org domains and associated resources has been revoked by the registrant of the domain. Work around this problem by renaming project from gPXE to iPXE, and updating URLs to match. Also update README, LOG and COPYRIGHTS to remove obsolete information. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [legal] Add a selection of FILE_LICENCE declarationsMichael Brown2009-05-181-0/+2
| | | | | Add FILE_LICENCE declarations to almost all files that make up the various standard builds of gPXE.
* [efi] Add efi_strerror()Michael Brown2008-11-191-6/+6
| | | | | | | | | EFI_STATUS is defined as an INTN, which maps to UINT32 (i.e. unsigned int) on i386 and UINT64 (i.e. unsigned long) on x86_64. This would require a cast each time the error status is printed. Add efi_strerror() to avoid this ickiness and simultaneously enable prettier reporting of EFI status codes.
* [i386] Change [u]int32_t to [unsigned] int, rather than [unsigned] longMichael Brown2008-11-191-3/+3
| | | | | | This brings us in to line with Linux definitions, and also simplifies adding x86_64 support since both platforms have 2-byte shorts, 4-byte ints and 8-byte long longs.
* [efi] Add EFI image format and basic runtime environmentMichael Brown2008-10-131-0/+106
We have EFI APIs for CPU I/O, PCI I/O, timers, console I/O, user access and user memory allocation. EFI executables are created using the vanilla GNU toolchain, with the EXE header handcrafted in assembly and relocations generated by a custom efilink utility.