summaryrefslogtreecommitdiffstats
path: root/src/interface/efi
Commit message (Collapse)AuthorAgeFilesLines
...
| * [efi] Add various well-known GUIDs encountered in WiFi bootMichael Brown2025-03-281-0/+36
| | | | | | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [efi] Install a device tree for the booted OS, if availableMichael Brown2025-03-281-0/+82
| | | | | | | | | | | | | | | | | | | | | | | | | | 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] Create a copy of the system flattened device tree, if presentMichael Brown2025-03-281-0/+11
| | | | | | | | | | | | | | | | | | EFI configuration tables may be freed at any time, and there is no way to be notified when the table becomes invalidated. Create a copy of the system flattened device tree (if present), so that we do not risk being left with an invalid pointer. Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [fdt] Allow for parsing device trees where the length is known in advanceMichael Brown2025-03-281-1/+1
| | | | | | | | | | | | | | | | Allow for parsing device trees where an external factor (such as a downloaded image length) determines the maximum length, which must be validated against the length within the device tree header. Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [fdt] Allow for the existence of multiple device treesMichael Brown2025-03-281-3/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | When running on a platform that uses FDT as its hardware description mechanism, we are likely to have multiple device tree structures. At a minimum, there will be the device tree passed to us from the previous boot stage (e.g. OpenSBI), and the device tree that we construct to be passed to the booted operating system. Update the internal FDT API to include an FDT pointer in all function parameter lists. Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [efi] Add support for installing EFI configuration tablesMichael Brown2025-03-272-18/+179
| | | | | | | | | | | | | | Add the ability to install and uninstall arbitrary EFI configuration tables. Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [efi] Add flattened device tree header and GUID definitionsMichael Brown2025-03-272-6/+10
| | | | | | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [efi] Add ACPI and SMBIOS tables as well-known GUIDsMichael Brown2025-03-271-0/+26
| | | | | | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [efi] Allow use of typed pointers for efi_open() et alMichael Brown2025-03-2417-211/+113Star
| | | | | | | | | | | | | | | | | | 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] Eliminate uses of HandleProtocol()Michael Brown2025-03-242-9/+3Star
| | | | | | | | | | | | | | | | It is now simpler to use efi_open() than to use HandleProtocol() to obtain an ephemeral protocol instance. Remove all remaining uses of HandleProtocol() to simplify the code. Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [efi] Use efi_open() for all ephemeral protocol opensMichael Brown2025-03-2413-352/+104Star
| | | | | | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [efi] Use efi_open_unsafe() for all explicitly unsafe protocol opensMichael Brown2025-03-243-20/+15Star
| | | | | | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [efi] Use efi_open_by_driver() for all by-driver protocol opensMichael Brown2025-03-243-42/+19Star
| | | | | | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [efi] Use efi_open_by_child() for all by-child protocol opensMichael Brown2025-03-241-12/+3Star
| | | | | | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [efi] Create safe wrappers for OpenProtocol() and CloseProtocol()Michael Brown2025-03-241-0/+358
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The UEFI model for opening and closing protocols is broken by design and cannot be repaired. Calling OpenProtocol() to obtain a protocol interface pointer does not, in general, provide any guarantees about the lifetime of that pointer. It is theoretically possible that the pointer has already become invalid by the time that OpenProtocol() returns the pointer to its caller. (This can happen when a USB device is physically removed, for example.) Various UEFI design flaws make it occasionally necessary to hold on to a protocol interface pointer despite the total lack of guarantees that the pointer will remain valid. The UEFI driver model overloads the semantics of OpenProtocol() to accommodate the use cases of recording a driver attachment (which is modelled as opening a protocol with EFI_OPEN_PROTOCOL_BY_DRIVER attributes) and recording the existence of a related child controller (which is modelled as opening a protocol with EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER attributes). The parameters defined for CloseProtocol() are not sufficient to allow the implementation to precisely identify the matching call to OpenProtocol(). While the UEFI model appears to allow for matched open and close pairs, this is merely an illusion. Calling CloseProtocol() will delete *all* matching records in the protocol open information tables. Since the parameters defined for CloseProtocol() do not include the attributes passed to OpenProtocol(), this means that a matched open/close pair using EFI_OPEN_PROTOCOL_GET_PROTOCOL can inadvertently end up deleting the record that defines a driver attachment or the existence of a child controller. This in turn can cause some very unexpected side effects, such as allowing other UEFI drivers to start controlling hardware to which iPXE believes it has exclusive access. This rarely ends well. To prevent this kind of inadvertent deletion, we establish a convention for four different types of protocol opening: - ephemeral opens: always opened with ControllerHandle = NULL - unsafe opens: always opened with ControllerHandle = AgentHandle - by-driver opens: always opened with ControllerHandle = Handle - by-child opens: always opened with ControllerHandle != Handle This convention ensures that the four types of open never overlap within the set of parameters defined for CloseProtocol(), and so a close of one type cannot inadvertently delete the record corresponding to a different type. Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [efi] Remove the efipci_open() and efipci_close() wrappersMichael Brown2025-03-242-48/+42Star
| | | | | | | | | | | | | | In preparation for formalising the way that EFI protocols are opened across the codebase, remove the efipci_open() wrapper. Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [efi] Avoid function name near-collisionMichael Brown2025-03-231-3/+3
| | | | | | | | | | | | | | | | We currently have both efipci_info() and efi_pci_info() serving different but related purposes. Rename the latter to reduce confusion. Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [efi] Remove spurious close of SNP device parent's device pathMichael Brown2025-03-231-4/+0Star
| | | | | | | | | | | | | | | | | | | | Commit e727f57 ("[efi] Include a copy of the device path within struct efi_device") neglected to delete the closure of the parent's device path from the success code path in efi_snp_probe(). Reduce confusion by removing this (harmless) additional close. Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [efi] Use driver name only from driver binding handles in debug messagesMichael Brown2025-03-211-6/+0Star
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Some non-driver handles may have an installed component name protocol. In particular, iPXE itself installs these protocols on its SNP device handles, to simplify the process of delegating GetControllerName() from our single-instance driver binding protocol to whatever child controllers the relevant EFI driver may have installed. For non-driver handles, the device path is more useful as debugging information than the driver name. Limit the use of the component name protocols to handles with a driver binding protocol installed, so that we will end up using the device path for non-driver handles such as the SNP device. Continue to prefer the driver name to the device path for handles with a driver binding protocol installed, since these will generally map to things we are likely to conceptualise as drivers rather than as devices. Note that we deliberately do not use GetControllerName() to attempt to get a human-readable name for a controller handle. In the normal course of events, iPXE is likely to disconnect at least some existing drivers from their controller handles. This would cause the name obtained via GetControllerName() to change. By using the device path instead, we ensure that the debug message name remains the same even when the driver controlling the handle is changed. Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [efi] Get veto candidate driver name via either component name protocolMichael Brown2025-03-201-15/+26
| | | | | | | | | | | | | | Attempt to get the veto candidate driver name from both the current and obsolete versions of the component name protocol. Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [efi] Get veto candidate driver name from image handleMichael Brown2025-03-201-5/+5
| | | | | | | | | | | | | | | | Allow for drivers that do not install the driver binding protocol on the image handle by opening the component name protocol on the driver binding's ImageHandle rather than on the driver handle itself. Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [efi] Show image address range in veto debug messagesMichael Brown2025-03-201-3/+3
| | | | | | | | | | | | | | | | When hunting down a misbehaving OEM driver to add it to the veto list, it can be very useful to know the address ranges used by each driver. Add this information to the verbose debug messages. Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [efi] Prefer driver name to device path for debug messagesMichael Brown2025-03-201-3/+3
| | | | | | | | | | | | | | | | The driver name is usually more informative for debug messages than the device path from which a driver was loaded. Try using the various mechanisms for obtaining a driver name before trying the device path. Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [efi] Attempt to retrieve driver name from image handle for debug messagesMichael Brown2025-03-201-0/+91
| | | | | | | | | | | | | | | | | | Not all drivers will install the driver binding protocol on the image handle. Accommodate these drivers by attempting to retrieve the driver name via the component name protocol(s) located on the driver binding's ImageHandle, as well as on the driver handle itself. Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [efi] Allow wrapping the global boot services table in situMichael Brown2025-03-201-63/+123
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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] Fix debug wrappers for CloseEvent() and CheckEvent()Michael Brown2025-03-191-2/+2
| | | | | | | | | | | | | | | | | | | | | | The debug wrappers for CloseEvent() and CheckEvent() are currently both calling SignalEvent() instead (presumably due to copy-paste errors). Astonishingly, this has generally not prevented a successful boot in the (very rare) case that DEBUG=efi_wrap is enabled. Fix the wrappers to call the intended functions. Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [efi] Ignore path separator characters in virtual filenamesMichael Brown2025-03-181-1/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The virtual filesystem that we provide to expose downloaded images will erroneously interpret filenames with redundant path separators such as ".\filename" as an attempt to open the directory, rather than an attempt to open "filename". This shows up most obviously when chainloading from one iPXE into another iPXE, when the inner iPXE may end up attempting to open ".\autoexec.ipxe" from the outer iPXE's virtual filesystem. (The erroneously opened file will have a zero length and will therefore be ignored, but is still confusing.) Fix by discarding any dot or backslash characters after a potential initial backslash. This is very liberal and will accept some syntactically invalid paths, but this is acceptable since our virtual filesystem does not implement directories anyway. Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [efi] Prescroll the display after a failed wrapped ExitBootServices() callMichael Brown2025-03-181-0/+44
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | On some systems (observed with an HP Elitebook 840 G10), writing console output that happens to cause the display to scroll will modify the system memory map. This causes builds with DEBUG=efi_wrap to typically fail to boot, since the debug output from the wrapped ExitBootServices() call itself is sufficient to change the memory map and therefore cause ExitBootServices() to fail due to an invalid memory map key. Work around these UEFI firmware bugs by prescrolling the display after a failed ExitBootServices() attempt, in order to minimise the chance that further scrolling will happen during the subsequent attempt. Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [efi] Add EFI_RNG_PROTOCOL_GUID as a well-known GUIDMichael Brown2025-03-181-0/+7
| | | | | | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [efi] Accept and trust CA certificates in the TlsCaCertificates variableMichael Brown2025-03-131-0/+200
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | UEFI's built-in HTTPS boot mechanism requires the trusted CA certificates to be provided via the TlsCaCertificates variable. (There is no equivalent of the iPXE cross-signing mechanism, so it is not possible for UEFI to automatically use public CA certificates.) Users who have configured UEFI HTTPS boot to use a custom root of trust (e.g. a private CA certificate) may find it useful to have iPXE automatically pick up and use this same root of trust, so that iPXE can seamlessly fetch files via HTTPS from the same servers that were trusted by UEFI HTTPS boot, in addition to servers that iPXE can validate through other means such as cross-signed certificates. Parse the TlsCaCertificates variable at startup, add any certificates to the certificate store, and mark these certificates as trusted. There are no access restrictions on modifying the TlsCaCertificates variable: anybody with access to write UEFI variables is permitted to change the root of trust. The UEFI security model assumes that anyone with access to run code prior to ExitBootServices() or with access to modify UEFI variables from within a loaded operating system is supposed to be able to change the system's root of trust for TLS. Any certificates parsed from TlsCaCertificates will show up in the output of "certstat", and may be discarded using "certfree" if unwanted. Support for parsing TlsCaCertificates is enabled by default in EFI builds, but may be disabled in config/general.h if needed. As with the ${trust} setting, the contents of the TlsCaCertificates variable will be ignored if iPXE has been compiled with an explicit root of trust by specifying TRUST=... on the build command line. Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [efi] Add TLS authentication header and GUID definitionsMichael Brown2025-03-131-0/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | Add the TlsAuthentication.h header from EDK2's NetworkPkg, along with a GUID definition for EFI_TLS_CA_CERTIFICATE_GUID. It is unclear whether or not the TlsCaCertificate variable is intended to be a UEFI standard. Its presence in NetworkPkg (rather than MdePkg) suggests not, but the choice of EFI_TLS_CA_CERTIFICATE_GUID (rather than e.g. EDKII_TLS_CA_CERTIFICATE_GUID) suggests that it is intended to be included in future versions of the standard. Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [efi] Add EFI_GLOBAL_VARIABLE as a well-known GUIDMichael Brown2025-03-131-0/+6
| | | | | | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [efi] Allow efi_guid_ntoa() to be used in non-EFI buildsMichael Brown2025-03-112-236/+236
| | | | | | | | | | | | | | | | | | | | | | The debug message transcription of well-known EFI GUIDs does not require any EFI boot services calls. Move this code from efi_debug.c to efi_guid.c, to allow it to be linked in to non-EFI builds. We continue to rely on linker garbage collection to ensure that the code is omitted completely from any non-debug builds. Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [efi] Add EFI_SIGNATURE_LIST header and GUID definitionsMichael Brown2025-03-102-0/+6
| | | | | | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [cpio] Allow for construction of parent directories as neededMichael Brown2025-02-241-7/+9
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | iPXE allows individual raw files to be automatically wrapped with suitable CPIO headers and injected into the magic initrd image as exposed to a booted Linux kernel. This feature is currently limited to placing files within directories that already exist in the initrd filesystem. Remove this limitation by adding the ability for iPXE to construct CPIO headers for parent directories as needed, under control of the "mkdir=<n>" command-line argument. For example: initrd config.ign /usr/share/oem/config.ign mkdir=1 will create CPIO headers for the "/usr/share/oem" directory as well as for the "/usr/share/oem/config.ign" file itself. This simplifies the process of booting operating systems such as Flatcar Linux, which otherwise require the single "config.ign" file to be manually wrapped up as a CPIO archive solely in order to create the relevant parent directory entries. The value <n> may be used to control the number of parent directory entries that are created. For example, "mkdir=2" would cause up to two parent directories to be created (i.e. "/usr/share" and "/usr/share/oem" in the above example). A negative value such as "mkdir=-1" may be used to create all parent directories up to the root of the tree. Do not create any parent directory entries by default, since doing so would potentially cause the modes and ownership information for existing directories to be overwritten. Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [efi] Increase download timeout for autoexec.ipxeMichael Brown2025-02-171-2/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In almost all cases, the download timeout for autoexec.ipxe is irrelevant: the operation will either succeed or fail relatively quickly (e.g. due to a nonexistent file). The overall download timeout exists only to ensure that an unattended or headless system will not wait indefinitely in the case of a degenerate network response (e.g. an HTTP server that returns an endless trickle of data using chunked transfer encoding without ever reaching the end of the file). The current download timeout is too short if PeerDist content encoding is enabled, since the overall download will abort before the first peer discovery attempt has completed, and without allowing sufficient time for an origin server range request. The single timeout value is currently used for both the download timeout and the sync timeout. The latter timeout exists only to allow network communication to be gracefully quiesced before removing the temporary MNP network device, and may safely be shortened without affecting functionality. Fix by increasing the download timeout from two seconds to 30 seconds, and defining a separate one-second timeout for the sync operation. Reported-by: Michael Niehaus <niehaus@live.com> Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [efi] Add EFI_TCG2_PROTOCOL header and GUID definitionMichael Brown2024-12-172-0/+7
| | | | | | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [efi] Ensure local drives are connected when attempting a SAN bootMichael Brown2024-11-201-0/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | UEFI systems may choose not to connect drivers for local disk drives when the boot policy is set to attempt a network boot. This may cause the "sanboot" command to be unable to boot from a local drive, since the relevant block device and filesystem drivers may not have been connected. Fix by ensuring that all available drivers are connected before attempting to boot from an EFI block device. Reported-by: Andrew Cottrell <andrew.cottrell@xtxmarkets.com> Tested-by: Andrew Cottrell <andrew.cottrell@xtxmarkets.com> Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [uaccess] Rename UACCESS_EFI to UACCESS_FLATMichael Brown2024-10-251-44/+0Star
| | | | | | | | | | | | | | | | | | Running with flat physical addressing is a fairly common early boot environment. Rename UACCESS_EFI to UACCESS_FLAT so that this code may be reused in non-UEFI boot environments that also use flat physical addressing. Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [efi] Use standard va_args macros instead of VA_START() etcMichael Brown2024-09-151-12/+12
| | | | | | | | | | | | | | | | | | | | The EDK2 header macros VA_START(), VA_ARG() etc produce build errors on some CPU architectures (notably on 32-bit RISC-V, which is not yet supported by EDK2). Fix by using the standard variable argument list macros. Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [efi] Centralise definition of efi_cpu_nap()Michael Brown2024-09-131-0/+57
| | | | | | | | | | | | | | | | | | Define a cpu_halt() function which is architecture-specific but platform-independent, and merge the multiple architecture-specific implementations of the EFI cpu_nap() function into a single central efi_cpu_nap() that uses cpu_halt() if applicable. Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [efi] Allow discovery of PCI bus:dev.fn address rangesMichael Brown2024-08-151-64/+176
| | | | | | | | | | | | | | | | | | | | | | Generalise the logic for identifying the matching PCI root bridge I/O protocol to allow for identifying the closest matching PCI bus:dev.fn address range, and use this to provide PCI address range discovery (while continuing to inhibit automatic PCI bus probing). This allows the "pciscan" command to work as expected under UEFI. Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [pci] Separate permission to probe buses from bus:dev.fn range discoveryMichael Brown2024-08-151-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The UEFI device model requires us to not probe the PCI bus directly, but instead to wait to be offered the opportunity to drive devices via our driver service binding handle. We currently inhibit PCI bus probing by having pci_discover() return an empty range when using the EFI PCI I/O API. This has the unwanted side effect that scanning the bus manually using the "pciscan" command will also fail to discover any devices. Separate out the concept of being allowed to probe PCI buses from the mechanism for discovering PCI bus:dev.fn address ranges, so that this limitation may be removed. Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [efi] Veto the Dhcp6Dxe driver on all platformsMichael Brown2024-04-161-0/+30
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The reference implementation of Dhcp6Dxe in EDK2 has a fatal flaw: the code in EfiDhcp6Stop() will poll the network in a tight loop until either a response is received or a timer tick (at TPL_CALLBACK) occurs. When EfiDhcp6Stop() is called at TPL_CALLBACK or higher, this will result in an endless loop and an apparently frozen system. Since this is the reference implementation of Dhcp6Dxe, it is likely that almost all platforms have the same problem. Fix by vetoing the broken driver. If the upstream driver is ever fixed and a new version number issued, then we could plausibly test against the version number exposed via the driver binding protocol. Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [efi] Do not attempt to download autoexec.ipxe without a valid base URIMichael Brown2024-04-151-0/+10
| | | | | | | | | | | | | | | | | | | | | | | | If we do not have a current working URI (after applying the EFI device path settings and any cached DHCP settings), then an attempt to download autoexec.ipxe will fail since there is no base URI from which to resolve the full autoexec.ipxe URI. Avoid this potentially confusing error message by attempting the download only if we have successfully obtained a current working URI. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* | Merge branch 'master' into openslxSimon Rettberg2024-04-127-551/+920
|\|
| * [efi] Restructure handling of autoexec.ipxe scriptMichael Brown2024-04-032-378/+122Star
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | We currently attempt to obtain the autoexec.ipxe script via early use of the EFI_SIMPLE_FILE_SYSTEM_PROTOCOL or EFI_PXE_BASE_CODE_PROTOCOL interfaces to obtain an opaque block of memory, which is then registered as an image at an appropriate point during our startup sequence. The early use of these existent interfaces allows us to obtain the script even if our subsequent actions (e.g. disconnecting drivers in order to connect up our own) may cause the script to become inaccessible. This mirrors the approach used under BIOS, where the autoexec.ipxe script is provided by the prefix (e.g. as an initrd image when using the .lkrn build of iPXE) and so must be copied into a normally allocated image from wherever it happens to previously exist in memory. We do not currently have support for downloading an autoexec.ipxe script if we were ourselves downloaded via UEFI HTTP boot. There is an EFI_HTTP_PROTOCOL defined within the UEFI specification, but it is so poorly designed as to be unusable for the simple purpose of downloading an additional file from the same directory. It provides almost nothing more than a very slim wrapper around EFI_TCP4_PROTOCOL (or EFI_TCP6_PROTOCOL). It will not handle redirection, content encoding, retries, or even fundamentals such as the Content-Length header, leaving all of this up to the caller. The UEFI HTTP Boot driver will install an EFI_LOAD_FILE_PROTOCOL instance on the loaded image's device handle. This looks promising at first since it provides the LoadFile() API call which is specified to accept an arbitrary filename parameter. However, experimentation (and inspection of the code in EDK2) reveals a multitude of problems that prevent this from being usable. Calling LoadFile() will idiotically restart the entire DHCP process (and potentially pop up a UI requiring input from the user for e.g. a wireless network password). The filename provided to LoadFile() will be ignored. Any downloaded file will be rejected unless it happens to match one of the limited set of types expected by the UEFI HTTP Boot driver. The list of design failures and conceptual mismatches is fairly impressive. Choose to bypass every possible aspect of UEFI HTTP support, and instead use our own HTTP client and network stack to download the autoexec.ipxe script over a temporary MNP network device. Since this approach works for TFTP as well as HTTP, drop the direct use of EFI_PXE_BASE_CODE_PROTOCOL. For consistency and simplicity, also drop the direct use of EFI_SIMPLE_FILE_SYSTEM_PROTOCOL and rely upon our existing support to access local files via "file:" URIs. This approach results in console output during the "iPXE initialising devices...ok" message that appears while startup is in progress. Remove the trailing "ok" so that this intermediate output appears at a sensible location on the screen. The welcome banner that will be printed immediately afterwards provides an indication that startup has completed successfully even absent the explicit "ok". Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [efi] Allow for allocating EFI devices from arbitrary handlesMichael Brown2024-03-291-42/+65
| | | | | | | | | | | | | | | | Split out the code that allocates our internal struct efi_device representations, to allow for the creation of temporary MNP devices in order to download the autoexec.ipxe script. Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [efi] Add error table entry for local filesystem EFI_NOT_FOUND errorMichael Brown2024-03-291-1/+18
| | | | | | | | | | | | | | | | | | Add an abbreviated "Not found" error message for an EFI_NOT_FOUND error encountered when attempting to open a file on a local filesystem, so that any automatic attempt to download a non-existent autoexec.ipxe script produces only a minimal error message. Signed-off-by: Michael Brown <mcb30@ipxe.org>
| * [efi] Report local file errors during download, rather than on openingMichael Brown2024-03-291-124/+130
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | iPXE is designed around fully asynchronous I/O, including asynchronous connection opening. Almost all errors are therefore necessarily reported as occurring during an in-progress download, rather than occurring at the time that the URI is opened. Local file access is currently an exception to this: errors such as nonexistent files will be encountered while opening the URI. This results in mildly unexpected error messages of the form "Could not start download", rather than the usual pattern of showing the URI, the initial progress dots, and then the error message. Fix this inconsistency by deferring the local filesystem access until the local file download process is running. Signed-off-by: Michael Brown <mcb30@ipxe.org>