aboutsummaryrefslogtreecommitdiff
AgeCommit message (Collapse)AuthorFilesLines
2024-03-27[build] Fix build failures with random versions of gccgcmassertMichael Brown2-15/+18
For unknown reasons, miscellaneous versions of gcc seem to struggle with the static assertions used to ensure the correct layout of the GCM structures. Adjust the assertions to use offsetof() rather than direct pointer comparison, on the basis that offsetof() must be a compile-time constant value. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-03-26[efi] Extract basic network settings from loaded image device pathMichael Brown2-0/+243
The UEFI HTTP boot mechanism is extraordinarily badly designed, even by the standards of the UEFI specification in general. It has the symptoms of a feature that has been designed entirely in terms of user stories, without any consideration at all being given to the underlying technical architecture. It does work, provided that you are doing precisely and only what was envisioned by the product owner. If you want to try anything outside the bounds of the product owner's extremely limited imagination, then you are almost certainly about to enter a world of pain. As one very minor example of this: the cached DHCP packet is not available when using HTTP boot. The UEFI HTTP boot code does perform DHCP, but it pointlessly and unhelpfully throws away the DHCP packet and trashes the network interface configuration before handing over to the downloaded executable. Work around this imbecility by parsing and applying the few network configuration settings that are persisted into the loaded image's device path. This is limited to very basic information such as the IP address, gateway address, and DNS server address, but it does at least provide enough for a functional routing table. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-03-26[efi] Add efi_path_mac() to parse a MAC address from an EFI device pathMichael Brown2-0/+25
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-03-25[efi] Add support for driving EFI_MANAGED_NETWORK_PROTOCOL devicesMichael Brown9-54/+657
We want exclusive access to the network device, both for performance reasons and because we perform operations such as EAPoL that affect the entire link. We currently drive the network card via either a native hardware driver or via the SNP or NII/UNDI interfaces, both of which grant us this exclusive access. Add an alternative driver that drives the network card non-exclusively via the EFI_MANAGED_NETWORK_PROTOCOL interface. This can function as a fallback for situations where neither SNP nor NII/UNDI interfaces are functional, and also opens up the possibility of non-destructively installing a temporary network device over which to download the autoexec.ipxe script. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-03-25[efi] Allow for drivers to be located via child handlesMichael Brown2-2/+10
When using a service binding protocol, CreateChild() will create a new protocol instance (and optionally a new handle). The caller will then typically open this new protocol instance with BY_DRIVER attributes, since the service binding mechanism has no equivalent of the driver binding protocol's Stop() method, and there is therefore no other way for the caller to be informed if the protocol instance is about to become invalid (e.g. because the service driver wants to remove the child). The caller cannot ask CreateChild() to install the new protocol instance on the original handle (i.e. the service binding handle), since the whole point of the service binding protocol is to allow for the existence of multiple children, and UEFI does not permit multiple instances of the same protocol to be installed on a handle. Our current drivers all open the original handle (as passed to our driver binding's Start() method) with BY_DRIVER attributes, and so the same handle will be passed to our Stop() method. This changes when our driver must use a separate handle, as described above. Add an optional "child handle" field to struct efi_device (on the assumption that we will not have any drivers that need to create multiple children), and generalise efidev_find() to match on either the original handle or the child handle. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-03-25[efi] Add helper functions for service binding protocolsMichael Brown4-0/+248
The EFI service binding abstraction is used to add and remove child handles for multiple different protocols. Provide a common interface for doing so. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-03-25[efi] Match chainloaded device by uppermost matching handleMichael Brown1-42/+70
Commit 4c5b794 ("[efi] Use the SNP protocol instance to match the SNP chainloading device") switched the chainloaded device matching logic to use a target protocol instance rather than the loaded image's device handle, on the basis that we want to bind to the parent SNP device rather than to a duplicate SNP protocol instance installed onto an IPv4 or IPv6 child device handle. It is possible that our calls to DisconnectController() and ConnectController() will cause the target protocol instance to be uninstalled and reinstalled, which may change the value of the protocol instance pointer. Allow for this by identifying and matching against the uppermost handle that initially has this target protocol instance installed. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-03-19[efi] Set current working URI from our own device path URI, if presentMichael Brown1-0/+11
When booted via HTTP, our loaded image's device path will include the URI from which we were downloaded. Set this as the current working URI, so that an embedded script may perform subsequent downloads relative to the iPXE binary, or construct explicit relative paths via the ${cwduri} setting. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-03-19[efi] Add efi_path_uri() to parse a URI from an EFI device pathMichael Brown2-0/+41
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-03-19[settings] Expose current working URI and directory URI via settingsMichael Brown2-0/+123
iPXE maintains a concept of a current working URI, which is used when resolving relative URIs and allows scripts to download files using URIs relative to the script itself. There are situations in which it is valuable for a script to be able to access the URI explicitly as a string, not just implicitly as a base URI for subsequent downloads. For example, when booting a Fedora installer, the "inst.repo" command-line parameter may be used to pass the URI of the repository to the installer. Expose the current working URI as ${cwuri}. Since relative URIs may be constructed as strings only from a directory URI (not from a full URI), also expose the current working directory URI as ${cwduri}. This feature may be used as e.g. #!ipxe echo Booting from ${cwuri} prompt -k 0x197e -t 2000 Press F12 to install Fedora... || exit kernel images/pxeboot/vmlinux inst.repo=${cwduri} initrd images/pxeboot/initrd.img boot Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-03-18[efi] Pad transmit buffer length to work around vendor driver bugsMichael Brown2-0/+14
The Mellanox/Nvidia UEFI driver is built from the same codebase as the iPXE driver, and appears to contain the bug that was fixed in commit c11734e ("[golan] Use ETH_HLEN for inline header size"). This results in identical failures when using the SNP or NII interface (via e.g. snponly.efi) to drive a Mellanox card while EAPoL is enabled. Work around the underlying UEFI driver bug by padding transmit I/O buffers to the minimum Ethernet frame length before passing them to the underlying driver's transmit function. This padding is not technically necessary, since almost all modern hardware will insert transmit padding as necessary (and where the hardware does not support doing so, the underlying UEFI driver is responsible for adding any necessary padding). However, it is guaranteed to be harmless (other than a miniscule performance impact): the Ethernet specification requires zero padding up to the minimum frame length for packets that are transmitted onto the wire, and so the receiver will see the same packet whether or not we manually insert this padding in software. The additional padding causes the underlying Mellanox driver to avoid its faulty code path, since it will never be asked to transmit a very short packet. Tested-by: Eric Hagberg <ehagberg@janestreet.com> Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-03-17[golan] Use ETH_HLEN for inline header sizeRabia Manaa1-1/+1
The driver does not correctly handle very short transmitted packets such as EAPoL-Start where the entire DMA content lies within the current send work queue entry inline header length of 18 bytes. Fix by reducing the inline header length to the Ethernet frame header length of 14 bytes. Modified-by: Michael Brown <mcb30@ipxe.org> Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-03-17[build] Fix building on older versions of gccMichael Brown1-0/+1
Older versions of gcc (observed with gcc 4.8.5 on CentOS 7) complain about having the label "err_ioremap" at the end of a compound statement in bios_mp_start_all(). The label is correctly placed, since it immediately follows the iounmap() that would be required to undo a successful ioremap() in the non-error case. Fix by adding an explicit "return" immediately after the label. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-03-16[snp] Allocate additional padding for receive buffersMichael Brown1-1/+14
Some SNP implementations (observed with a wifi adapter in a Dell Latitude 3440 laptop) seem to require additional space in the allocated receive buffers, otherwise full-length packets will be silently dropped. The EDK2 MnpDxe driver happens to allocate an additional 8 bytes of padding (4 for a VLAN tag, 4 for the Ethernet frame checksum). Match this behaviour since drivers are very likely to have been tested against MnpDxe. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-03-15[ucode] Add support for updating x86 microcodeMichael Brown6-0/+1283
Intel and AMD distribute microcode updates, which are typically applied by the BIOS and/or the booted operating system. BIOS updates can be difficult to obtain and cumbersome to apply, and are often neglected. Operating system updates may be subject to strict change control processes, particularly for production workloads. There is therefore value in being able to update the microcode at boot time using a freshly downloaded microcode update file, particularly in scenarios where the physical hardware and the installed operating system are controlled by different parties (such as in a public cloud infrastructure). Add support for parsing Intel and AMD microcode update images, and for applying the updates to all CPUs in the system. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-03-15[bios] Provide a multiprocessor API for BIOSMichael Brown4-1/+207
Provide an implementation of the iPXE multiprocessor API for BIOS, based on sending broadcast INIT and SIPI interprocessor interrupts to start up all application processors. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-03-15[librm] Add support for installing a startup IPI handlerMichael Brown3-0/+113
Application processors are started via INIT and SIPI interprocessor interrupts: the INIT places the processor into a "wait for SIPI" state, and the SIPI then starts the processor in real mode at a page-aligned address derived from the SIPI vector number. Add support for installing a real-mode SIPI handler that will switch the CPU into protected mode with flat physical addressing, load initial register contents, and then jump to the address of a protected-mode SIPI handler. No stack pointer is set up, to avoid the need to allocate stack space for each available processor. We use 32-bit physical addressing in order to minimise the changes required for a 64-bit build. The existing long mode transition code relies on the existence of the stack, so we cannot easily switch the application processor into long mode. We could use 32-bit virtual addressing, but this runtime environment does not currently exist outside of librm.S itself in a 64-bit build, and using it would complicate the implementation of the protected-mode SIPI handler. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-03-15[efi] Provide a multiprocessor API for EFIMichael Brown6-1/+821
Provide an implementation of the iPXE multiprocessor API for EFI, based on using EFI_MP_SERVICES to start up a wrapper function on all application processors. Note that the processor numbers used by EFI_MP_SERVICES are opaque integers that bear no relation to the underlying CPU identity (e.g. the APIC ID), and so we must rely on our own (architecture- specific) implementation to determine the relevant CPU identifiers. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-03-15[mp] Define an API for multiprocessor functionsMichael Brown11-0/+530
Define an API for executing very limited functions on application processors in a multiprocessor system, along with an x86-only implementation. The normal iPXE runtime environment is effectively non-existent on application processors. There is no ability to make firmware calls (e.g. to write to a console), and there may be no stack space available. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-03-13[efi] Update to current EDK2 headersMichael Brown12-11/+421
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-03-07[ci] Update action versions to silence GitHub warningsMichael Brown2-8/+8
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-03-07[efi] Do not report return status from efi_block_local()Michael Brown1-1/+5
The return status from efi_block_local() indicates whether or not the handle is eligible to be assigned a local virtual drive number. There will always be several enumerated EFI_BLOCK_IO_PROTOCOL handles that are not eligible for a local virtual drive number (e.g. the handles corresponding to partitions, rather than to complete disks), and this is not an interesting error to report. Do not report errors from efi_block_local() as the overall error status for a SAN boot, since doing so would be likely to mask a much more relevant error from having previously attempted to scan for a matching filesystem within an eligible block device handle. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-03-07[block] Allow SAN boot device to be identified by filesystem labelMichael Brown3-1/+81
Add a "--label" option that can be used to specify a filesystem label, to be matched against the FAT volume label. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-03-07[block] Allow SAN boot device to be identified by an extra filenameMichael Brown3-28/+68
Add an "--extra" option that can be used to specify an extra (non-boot) filename that must exist within the booted filesystem. Note that only files within the FAT-formatted bootable partition will be visible to this filter. Files within the operating system's root disk (e.g. "/etc/redhat-release") are not generally accessible to the firmware and so cannot be used as the existence check filter filename. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-03-06[block] Allow SAN boot device to be identified by UUIDMichael Brown5-7/+41
Add a "--uuid" option which may be used to specify a boot device UUID, to be matched against the GPT partition GUID. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-03-06[efi] Add efi_path_guid() utility functionMichael Brown3-0/+46
EFI provides no API for determining the partition GUID (if any) for a specified device handle. The partition GUID appears to be exposed only as part of the device path. Add efi_path_guid() to extract the partition GUID (if any) from a device path. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-03-06[block] Allow for additional SAN boot parameters alongside filenameMichael Brown8-23/+45
The drive specification alone does not necessarily contain enough information to perform a SAN boot (or local disk boot) under UEFI. If the next-stage bootloader is installed in the EFI system partition under a non-standard name (e.g. "\EFI\debian\grubx64.efi") then this explicit boot filename must also be specified. Generalise this concept to use a "SAN boot configuration parameters" structure (currently containing only the optional explicit boot filename), to allow for easy expansion to provide other parameters such as the partition UUID or volume label. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-03-05[efi] Allow booting from local disks via the "sanboot" commandMichael Brown3-31/+166
Extend the EFI SAN boot code to allow for booting from a local disk, as is already possible with the BIOS SAN boot code. There is unfortunately no direct UEFI equivalent of the BIOS drive number. The UEFI shell does provide numbered mappings fs0:, blk0:, etc, but these numberings exist only while the UEFI shell is running and are not necessarily stable between shell invocations or across reboots. A substantial amount of existing third-party documentation for iPXE will suggest using "sanboot --drive 0x80" to boot from a local disk (when no SAN drives are present), since this suggestion has been present in the official documentation for the "sanboot" command for almost thirteen years. We therefore aim to ensure that this instruction will also work for UEFI, i.e. that in a situation where there are local disks but no SAN disks, then the first local disk will be treated as being drive 0x80. We therefore assign local disks the virtual drive numbers 0x80, 0x81, etc, matching the numbering typically used in a BIOS environment. Where a SAN disk is already occupying one of these drive numbers, the local disks' virtual drive numbers will be incremented as necessary. This provides a rough approximation of the equivalent functionality under BIOS, where existing local disks' drive numbers are remapped to make way for SAN disks. We do not make any attempt to sort the list of local disks: the order used for allocating virtual drive numbers will be whatever order is returned by LocateHandle(). This will typically match the creation order of the EFI handles, which will typically match the hardware enumeration order of the devices, which will typically match user expectations as to which local disk is first, second, etc. We explicitly do not attempt to match the numbering used by the UEFI shell (which initially sorts in increasing order of device path, but does not renumber when new devices are added or removed). We can never guarantee matching this partly transient UEFI shell numbering, so it is best not to set any expectation that it will be matched. (Using local drive numbers starting at 0x80 helps to avoid setting up this impossible expectation, since the UEFI shell uses local drive numbers starting at zero.) Since floppy disks are essentially non-existent in any plausible UEFI system, overload "--drive 0" to mean "boot from any drive containing the specified (or default) boot filename". Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-03-05[block] Allow for iteration over SAN device list in drive number orderMichael Brown2-2/+24
Maintain the SAN device list in order of drive number, and provide sandev_next() to locate the first SAN device at or above a given drive number. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-03-04[efi] Generalise block device boot to support arbitrary EFI handlesMichael Brown1-47/+66
SAN devices created by iPXE are visible to the firmware, and may be accessed using the firmware's standard block I/O device interface (e.g. INT 13 for BIOS, or EFI_BLOCK_IO_PROTOCOL for UEFI). The iPXE code to perform a SAN boot acts as a client of this standard block I/O device interface, even when the underlying block I/O is being performed by iPXE itself. We rely on this separation to allow the "sanboot" command to be used to boot from a local disk: since the code to perform a SAN boot does not need direct access to an underlying iPXE SAN device, it may be used to boot from any device providing the firmware's standard block I/O device interface. Clean up the EFI SAN boot code to require only a drive number and an EFI_BLOCK_IO_PROTOCOL handle, in preparation for adding support for booting from a local disk under UEFI. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-03-04[efi] Use file system protocol to check for SAN boot filename existenceMichael Brown1-86/+218
The "sanboot" command allows a custom boot filename to be specified via the "--filename" option. We currently rely on LoadImage() to perform both the existence check and to load the image ready for execution. This may give a false negative result if Secure Boot is enabled and the boot file is not correctly signed. Carry out the existence check using EFI_SIMPLE_FILE_SYSTEM_PROTOCOL separately from loading the image via LoadImage(). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-03-04[block] Use drive number as debug message stream IDMichael Brown4-166/+173
We currently use the SAN device pointer as the debug message stream identifier. This pointer is not always available: for example, when booting from a local disk there is no underlying SAN device. Switch to using the drive number as the debug message colour stream identifier, so that all block device debug messages may be colourised consistently. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-03-04[efi] Use long forms of device paths in debug messagesMichael Brown1-1/+1
We currently call ConvertDevicePathToText() with DisplayOnly=TRUE when constructing a device path to appear within a debug message. For ATAPI device paths, this will unfortunately omit some key information: the textual representation will not indicate which ATA bus or drive is represented. This can lead to misleading debug messages that appear to refer to identical devices. Fix by setting DisplayOnly=FALSE to select the long form of device path textual representations. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-02-29[parseopt] Add parse_uuid() for parsing UUID command-line argumentsMichael Brown2-0/+25
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-02-29[settings] Add parsing for UUID and GUID settings typesMichael Brown2-3/+44
The ":uuid" and ":guid" settings types are currently format-only: it is possible to format a setting as a UUID (via e.g. "show foo:uuid") but it is not currently possible to parse a string into a UUID setting (via e.g. "set foo:uuid 406343fe-998b-44be-8a28-44ca38cb202b"). Use uuid_aton() to implement parsing of these settings types, and add appropriate test cases for both. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-02-29[uuid] Add uuid_aton() to parse a UUID from a stringMichael Brown7-2/+203
Add uuid_aton() to parse a UUID value from a string (analogous to inet_aton(), inet6_aton(), sock_aton(), etc), treating it as a 32-digit hex string with optional hyphen separators. The placement of the separators is not checked: each byte within the hex string may be separated by a hyphen, or not separated at all. Add dedicated self-tests for UUID parsing and formatting (already partially covered by the ":uuid" and ":guid" settings self-tests). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-02-27[efi] Work around broken boot services table manipulation by UEFI shimMichael Brown1-49/+43
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>
2024-02-23[eap] Add support for the MS-CHAPv2 authentication methodMichael Brown5-0/+285
Add support for EAP-MSCHAPv2 (note that this is not the same as PEAP-MSCHAPv2), controllable via the build configuration option EAP_METHOD_MSCHAPV2 in config/general.h. Our model for EAP does not encompass mutual authentication: we will starting sending plaintext packets (e.g. DHCP requests) over the link even before EAP completes, and our only use for an EAP success is to mark the link as unblocked. We therefore ignore the content of the EAP-MSCHAPv2 success request (containing the MS-CHAPv2 authenticator response) and just send back an EAP-MSCHAPv2 success response, so that the EAP authenticator will complete the process and send through the real EAP success packet (which will, in turn, cause us to unblock the link). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-02-23[eap] Allow MD5-Challenge authentication method to be disabledMichael Brown6-82/+172
RFC 3748 states that implementations must support the MD5-Challenge method. However, some network environments may wish to disable it as a matter of policy. Allow support for MD5-Challenge to be controllable via the build configuration option EAP_METHOD_MD5 in config/general.h. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-02-23[eap] Add progress debug messagesMichael Brown1-1/+11
Add debug messages for each EAP Request and Response, and to show the list of methods offered when sending a Nak. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-02-22[efi] Ignore new LoongArch PC-relative relocations and relaxationsAlexey Sheplyakov1-0/+20
Several new relocations types have been added in LoongArch ABI version 2.10. In particular: - R_LARCH_B16 (18-bit PC-relative jump) - R_LARCH_B21 (23-bit PC-relative jump) - R_LARCH_PCREL20_S2 (22-bit PC-relative offset) Also relocation relaxations have been introduced. Recent GCC (13.2) and binutils 2.41+ use these types of relocations, which confuses elf2efi tool. As a result, iPXE EFI images for LoongArch fail to build with the following error: Unrecognised relocation type 103 Fix by ignoring R_LARCH_B{16,21} and R_LARCH_PCREL20_S2 (as with other PC-relative relocations), and by ignoring relaxations (R_LARCH_RELAX). Relocation relaxations are basically optimizations: ignoring them results in a correct binary (although it might be suboptimal). Modified-by: Michael Brown <mcb30@ipxe.org> Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-02-22[drivers] Sort PCI_ROM() entries numericallyGeert Stappers21-137/+136
Done with the help of this Perl script: $MARKER = 'PCI_ROM'; # a regex $AB = 1; # At Begin @HEAD = (); @ITEMS = (); @TAIL = (); foreach $fn (@ARGV) { open(IN, $fn) or die "Can't open file '$fn': $!\n"; while (<IN>) { if (/$MARKER/) { push @ITEMS, $_; $AB = 0; # not anymore at begin } else { if ($AB) { push @HEAD, $_; } else { push @TAIL, $_; } } } } continue { close IN; open(OUT, ">$fn") or die "Can't open file '$fn' for output: $!\n"; print OUT @HEAD; print OUT sort @ITEMS; print OUT @TAIL; close OUT; # For a next file $AB = 1; @HEAD = (); @ITEMS = (); @TAIL = (); } Executed that script while src/drivers/ as current working directory, provided '$(grep -rl PCI_ROM)' as argument. Signed-off-by: Geert Stappers <stappers@stappers.it>
2024-02-22[crypto] Force inlining of trivial wrapper functionsMichael Brown1-44/+55
Inspection of the generated assembly shows that gcc will often emit standalone implementations of frequently invoked functions such as digest_update(), which contain no logic and exist only as syntactic sugar. Force inlining of these functions to reduce the overall binary size. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-02-22[crypto] Add implementation of MS-CHAPv2 authenticationmschapv2Michael Brown4-0/+567
Add an implementation of the authentication portions of the MS-CHAPv2 algorithm as defined in RFC 2759, along with the single test vector provided therein. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-02-15[crypto] Allow for multiple cross-signed certificate download attemptsMichael Brown2-100/+249
Certificates issued by Let's Encrypt have two options for their chain of trust: the chain can either terminate in the self-signed ISRG Root X1 root certificate, or in an intermediate ISRG Root X1 certificate that is signed in turn by the self-signed DST Root CA X3 root certificate. This is a historical artifact: when Let's Encrypt first launched as a project, the chain ending in DST Root CA X3 was used since existing clients would not have recognised the ISRG Root X1 certificate as a trusted root certificate. The DST Root CA X3 certificate expired in September 2021, and so is no longer trusted by clients (such as iPXE) that validate the expiry times of all certificates in the certificate chain. In order to maintain usability of certificates on older Android devices, the default certificate chain provided by Let's Encrypt still terminates in DST Root CA X3, even though that certificate has now expired. On newer devices which include ISRG Root X1 as a trusted root certificate, the intermediate version of ISRG Root X1 in the certificate chain is ignored and validation is performed as though the chain had terminated in the self-signed ISRG Root X1 root certificate. On older Android devices which do not include ISRG Root X1 as a trusted root certificate, the validation succeeds since Android chooses to ignore expiry times for root certificates and so continues to trust the DST Root CA X3 root certificate. This backwards compatibility hack unfortunately breaks the cross- signing mechanism used by iPXE, which assumes that the certificate chain will always terminate in a non-expired root certificate. Generalise the validator's cross-signed certificate download mechanism to walk up the certificate chain in the event of a failure, attempting to find a replacement cross-signed certificate chain starting from the next level up. This allows the validator to step over the expired (and hence invalidatable) DST Root CA X3 certificate, and instead download the cross-signed version of the ISRG Root X1 certificate. This generalisation also gives us the ability to handle servers that provide a full certificate chain including their root certificate: iPXE will step over the untrusted public root certificate and attempt to find a cross-signed version of it instead. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-02-15[crypto] Add x509_is_self_signed() helper functionMichael Brown3-1/+15
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-02-14[crypto] Add x509_truncate() to truncate a certificate chainMichael Brown3-9/+37
Downloading a cross-signed certificate chain to partially replace (rather than simply extend) an existing chain will require the ability to discard all certificates after a specified link in the chain. Extract the relevant logic from x509_free_chain() and expose it separately as x509_truncate(). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-02-14[list] Add list_for_each_entry_safe_continue()Michael Brown2-0/+48
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-02-14[list] Add list_is_head_entry()Michael Brown2-0/+27
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-02-10[build] Fix build failures with older versions of gcccentos7Michael Brown2-7/+10
Some versions of gcc (observed with gcc 4.8.5 in CentOS 7) will report spurious build_assert() failures for some assertions about structure layouts. There is no clear pattern as to what causes these spurious failures, and the build assertion does succeed in that no unresolvable symbol reference is generated in the compiled code. Adjust the assertions to work around these apparent compiler issues. Signed-off-by: Michael Brown <mcb30@ipxe.org>