aboutsummaryrefslogtreecommitdiff
path: root/src/arch/x86
AgeCommit message (Collapse)AuthorFilesLines
2022-02-02[prefix] Fix use of writable code segment on 486 and earlier CPUsfix486Michael Brown1-4/+10
In real mode, code segments are always writable. In protected mode, code segments can never be writable. The precise implementation of this attribute differs between CPU generations, with subtly different behaviour arising on the transitions from protected mode to real mode. At the point of transition (when the PE bit is cleared in CR0) the hidden portion of the %cs descriptor will retain whatever attributes were in place for the protected-mode code segment, including the fact that the segment is not writable. The immediately following code will perform a far control flow transfer (such as ljmp or lret) in order to load a real-mode value into %cs. On the Pentium and later CPUs, the retained protected-mode attributes will be ignored for any accesses via %cs while the CPU is in real mode. A write via %cs will therefore be allowed even though the hidden portion of the %cs descriptor still describes a non-writable segment. On the 486 and earlier CPUs, the retained protected-mode attributes will not be ignored for accesses via %cs. A write via %cs will therefore cause a CPU fault. To obtain normal real-mode behaviour (i.e. a writable %cs descriptor), special logic is added to the ljmp instruction that populates the hidden portion of the %cs descriptor with real-mode attributes when a far jump is executed in real mode. The result is that writes via %cs will cause a CPU fault until the first ljmp instruction is executed, after which writes via %cs will be allowed as expected in real mode. The transition code in libprefix.S currently uses lret to load a real-mode value into %cs after clearing the PE bit. Experimentation shows that only the ljmp instruction will work to load real-mode attributes into the hidden portion of the %cs descriptor: other far control flow transfers (such as lret, lcall, or int) do not do so. When running on a 486 or earlier CPU, this results in code within libprefix.S running with a non-writable code segment after a mode transition, which in turn results in a CPU fault when real-mode code in liba20.S attempts to write to %cs:enable_a20_method. Fix by constructing and executing an ljmp instruction, to trigger the relevant descriptor population logic on 486 and earlier CPUs. This ljmp instruction is constructed on the stack, since the .prefix section may be executing directly from ROM (or from memory that the BIOS has write-protected in order to emulate an ISA ROM region) and so cannot be modified. Reported-by: Nikolai Zhubr <n-a-zhubr@yandex.ru> Signed-off-by: Michael Brown <mcb30@ipxe.org>
2022-01-13[efi] Include Secure Boot Advanced Targeting (SBAT) metadatasbatMichael Brown2-0/+4
SBAT defines an encoding for security generation numbers stored as a CSV file within a special ".sbat" section in the signed binary. If a Secure Boot exploit is discovered then the generation number will be incremented alongside the corresponding fix. Platforms may then record the minimum generation number required for any given product. This allows for an efficient revocation mechanism that consumes minimal flash storage space (in contrast to the DBX mechanism, which allows for only a single-digit number of revocation events to ever take place across all possible signed binaries). Add SBAT metadata to iPXE EFI binaries to support this mechanism. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2022-01-13[doc] Update user-visible ipxe.org URIs to use HTTPSMichael Brown2-3/+3
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2021-09-08[acpi] Generalise DSDT/SSDT data extraction logicMichael Brown1-4/+66
Allow for the DSDT/SSDT signature-scanning and value extraction code to be reused for extracting a pass-through MAC address. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2021-07-27[efi] Record cached ProxyDHCPOFFER and PXEBSACK, if presentMichael Brown1-1/+2
Commit cd3de55 ("[efi] Record cached DHCPACK from loaded image's device handle, if present") added the ability for a chainloaded UEFI iPXE to reuse an IPv4 address and DHCP options previously obtained by a built-in PXE stack, without needing to perform a second DHCP request. Extend this to also record the cached ProxyDHCPOFFER and PXEBSACK obtained from the EFI_PXE_BASE_CODE_PROTOCOL instance installed on the loaded image's device handle, if present. This allows a chainloaded UEFI iPXE to reuse a boot filename or other options that were provided via a ProxyDHCP or PXE boot server mechanism, rather than by standard DHCP. Tested-by: Andreas Hammarskjöld <junior@2PintSoftware.com> Signed-off-by: Michael Brown <mcb30@ipxe.org>
2021-06-03[crypto] Add memory output constraints for big-integer inline assemblybigint_output_constraintsMichael Brown2-22/+43
The ARM versions of the big-integer inline assembly functions include constraints to indicate that the output value is modified by the assembly code. These constraints are not present in the equivalent code for the x86 versions. As of GCC 11, this results in the compiler reporting that the output values may be uninitialized. Fix by including the relevant memory output constraints. Reported-by: Christian Hesse <mail@eworm.de> Signed-off-by: Michael Brown <mcb30@ipxe.org>
2021-05-21[cpio] Split out bzImage initrd CPIO header constructionMichael Brown3-56/+4
iPXE will construct CPIO headers for images that have a non-empty command line, thereby allowing raw images (without CPIO headers) to be injected into a dynamically constructed initrd. This feature is currently implemented within the BIOS-only bzImage format support. Split out the CPIO header construction logic to allow for reuse in other contexts such as in a UEFI build. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2021-05-12[undi] Read TSC only when profilingMichael Brown1-2/+9
Avoid using the "rdtsc" instruction unless profiling is enabled. This allows the non-debug build of the UNDI driver to be used on a CPU such as a 486 that does not support the TSC. Reported-by: Nikolai Zhubr <n-a-zhubr@yandex.ru> Signed-off-by: Michael Brown <mcb30@ipxe.org>
2021-05-12[rng] Check for TSC support before using RTC entropy sourceMichael Brown2-0/+14
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2021-05-12[prefix] Specify i486 architecture for LZMA decompressorMichael Brown1-1/+1
The decompressor uses the i486 "bswap" instruction, but does not require any instructions that exist only on i586 or above. Update the ".arch" directive to reflect the requirements of the code as implemented. Reported-by: Martin Habets <habetsm.xilinx@gmail.com> Signed-off-by: Michael Brown <mcb30@ipxe.org>
2021-04-13[int13] Do not report INT 13 extension support for emulated floppiesMichael Brown1-2/+2
The INT 13 extensions provide a mechanism for accessing disks using linear (LBA) rather than C/H/S addressing. SAN protocols such as iSCSI invariably support only linear addresses and so iPXE currently provides LBA access to all SAN disks (with autodetection and emulation of an appropriate geometry for C/H/S accesses). Most BIOSes will not report support for INT 13 extensions for floppy disk drives, and some operating systems may be confused by a floppy drive that claims such support. Minimise surprise by reporting the existence of support for INT 13 extensions only for non-floppy drive numbers. Continue to provide support for all drive numbers, to avoid breaking operating systems that may unconditionally use the INT 13 extensions without first checking for support. Reported-by: Valdo Toost <vtoost@hot.ee> Signed-off-by: Michael Brown <mcb30@ipxe.org>
2021-04-10[pci] Avoid scanning nonexistent buses when using PCIAPI_DIRECTMichael Brown1-2/+2
There is no method for obtaining the number of PCI buses when using PCIAPI_DIRECT, and we therefore currently scan all possible bus numbers. This can cause a several-second startup delay in some virtualised environments, since PCI configuration space access will necessarily require the involvement of the hypervisor. Ameliorate this situation by defaulting to scanning only a single bus, and expanding the number of PCI buses to accommodate any subordinate buses that are detected during enumeration. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2021-03-02[build] Allow __asmcall to be used as a type attributeMichael Brown4-6/+7
The "used" attribute can be applied only to functions or variables, which prevents the use of __asmcall as a type attribute. Fix by removing "used" from the definition of __asmcall for i386 and x86_64 architectures, and adding explicit __used annotations where necessary. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2021-03-01[acpi] Allow for platforms that provide ACPI tables individuallykexec3kexec2kexecMichael Brown2-0/+14
The ACPI API currently expects platforms to provide access to a single contiguous ACPI table. Some platforms (e.g. Linux userspace) do not provide a convenient way to obtain the entire ACPI table, but do provide access to individual tables. All iPXE consumers of the ACPI API require access only to individual tables. Redefine the internal API to make acpi_find() an API method, with all existing implementations delegating to the current RSDT-based implementation. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2021-02-28[linux] Use host glibc system call wrappersMichael Brown4-336/+7
When building as a Linux userspace application, iPXE currently implements its own system calls to the host kernel rather than relying on the host's C library. The output binary is statically linked and has no external dependencies. This matches the general philosophy of other platforms on which iPXE runs, since there are no external libraries available on either BIOS or UEFI bare metal. However, it would be useful for the Linux userspace application to be able to link against host libraries such as libslirp. Modify the build process to perform a two-stage link: first picking out the requested objects in the usual way from blib.a but with relocations left present, then linking again with a helper object to create a standard hosted application. The helper object provides the standard main() entry point and wrappers for the Linux system calls required by the iPXE Linux drivers and interface code. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2021-02-27[linux] Add a prefix to all symbols to avoid future name collisionsMichael Brown1-0/+2
Allow for the possibility of linking to platform libraries for the Linux userspace build by adding an iPXE-specific symbol prefix. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2021-02-27[bitops] Provide an explicit operand size for bit test instructionsMichael Brown1-4/+4
Recent versions of the GNU assembler (observed with GNU as 2.35 on Fedora 33) will produce a warning message Warning: no instruction mnemonic suffix given and no register operands; using default for `bts' The operand size affects only the potential range for the bit number. Since we pass the bit number as an unsigned int, it is already constrained to 32 bits for both i386 and x86_64. Silence the assembler warning by specifying an explicit 32-bit operand size (and thereby matching the choice that the assembler would otherwise make automatically). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2021-02-18[librm] Test for FXSAVE/FXRSTOR instruction supportfxsrMichael Brown3-6/+36
Assume that preservation of the %xmm registers is unnecessary during installation of iPXE into memory, since this is an operation that by its nature substantially disrupts large portions of the system anyway (such as the E820 memory map). This assumption allows us to utilise the existing CPUID code to check that FXSAVE/FXRSTOR are supported. Test for support during the call to init_librm and store the flag for use during subsequent calls to virt_call. Reduce the scope of TIVOLI_VMM_WORKAROUND to affecting only the call to check_fxsr(), to reduce #ifdef pollution in the remaining code. Debugged-by: Johannes Heimansberg <git@jhe.dedyn.io> Signed-off-by: Michael Brown <mcb30@ipxe.org>
2021-02-18[librm] Add missing __asmcall on init_idt()Michael Brown1-1/+1
The __asmcall declaration has no effect on a void function with no parameters, but should be included for completeness since the function is called directly from assembly code. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2021-02-18[prefix] Add a generic raw image prefixrplMichael Brown1-0/+53
Provide a generic raw image prefix, which assumes that the iPXE image has been loaded in its entirety on a paragraph boundary. The resulting .raw image can be loaded via RPL using an rpld.conf file such as: HOST { ethernet = 00:00:00:00:00:00/6; FILE { path="ipxe.raw"; load=0x2000; }; execute=0x2000; }; Debugged-by: Johannes Heimansberg <git@jhe.dedyn.io> Signed-off-by: Michael Brown <mcb30@ipxe.org>
2021-02-18[initrd] Allow for zero-length initrd filesMichael Brown1-6/+6
A zero-length initrd file will currently cause an endless loop during reshuffling as the empty image is repeatedly swapped with itself. Fix by terminating the inner loop before considering an image as a candidate to be swapped with itself. Reported-by: Pico Mitchell <pico@randomapplications.com> Signed-off-by: Michael Brown <mcb30@ipxe.org>
2021-02-17[pxe] Split out platform-independent portions of cachedhcp.cMichael Brown2-179/+76
Split out the portions of cachedhcp.c that can be shared between BIOS and UEFI (both of which can provide a buffer containing a previously obtained DHCP packet, and neither of which provide a means to determine the length of this DHCP packet). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2021-02-15[build] Work around stray sections introduced by some binutils versionsusbdiskMichael Brown2-7/+33
Some versions of GNU ld (observed with binutils 2.36 on Arch Linux) introduce a .note.gnu.property section marked as loadable at a high address and with non-empty contents. This adds approximately 128MB of garbage to the BIOS .usb disk images. Fix by using a custom linker script for the prefix-only binaries such as the USB disk partition table and MBR, in order to allow unwanted sections to be explicitly discarded. Reported-by: Christian Hesse <mail@eworm.de> Tested-by: Christian Hesse <mail@eworm.de> Signed-off-by: Michael Brown <mcb30@ipxe.org>
2021-02-12[build] Use .balign directive instead of .alignMichael Brown10-16/+16
The semantics of the assembler's .align directive vary by CPU architecture. For the ARM builds, it specifies a power of two rather than a number of bytes. This currently leads to the .einfo entries (which do not appear in the final binary) having an alignment of 256 bytes for the ARM builds. Fix by switching to the GNU-specific directive .balign, which is consistent across architectures Signed-off-by: Michael Brown <mcb30@ipxe.org>
2021-01-30[build] Allow BIOS linker script to be used with FreeBSD linkerfreebsdMichael Brown1-13/+13
Add a few more ABSOLUTE() expressions to convince the FreeBSD linker that already-absolute symbols are, in fact, absolute. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2021-01-30[build] Avoid modifying load addresses when stripping .zinfo sectionMichael Brown1-7/+42
Some versions of objcopy will spuriously complain when asked to extract the .zinfo section since doing so will nominally alter the load addresses of the (non-loadable) .bss.* sections. Avoid these warnings by placing the .zinfo section at the very end of the load memory address space. Allocate non-overlapping load memory addresses for the (non-loadable) .bss.* sections, in the hope of avoiding spurious warnings about overlapping load addresses. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2021-01-25[image] Provide image_memory()Michael Brown1-39/+5
Consolidate the remaining logic common to initrd_init() and imgmem() into a shared image_memory() function. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2021-01-22[image] Provide image_set_data()Michael Brown1-12/+9
Extract part of the logic in initrd_init() to a standalone function image_set_data(). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2021-01-13[build] Create util/genfsimg for building filesystem-based imagesMichael Brown1-39/+4
Generalise util/geniso, util/gensdsk, and util/genefidsk to create a single script util/genfsimg that can be used to build either FAT filesystem images or ISO images. Extend the functionality to allow for building multi-architecture UEFI bootable ISO images and combined BIOS+UEFI images. For example: ./util/genfsimg -o combined.iso \ bin-x86_64-efi/ipxe.efi \ bin-arm64-efi/ipxe.efi \ bin/ipxe.lkrn would generate a hybrid image that could be used as a CDROM (or hard disk or USB key) on legacy BIOS, x86_64 UEFI, or ARM64 UEFI. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2020-11-05[malloc] Rename malloc_dma() to malloc_phys()Michael Brown2-8/+8
The malloc_dma() function allocates memory with specified physical alignment, and is typically (though not exclusively) used to allocate memory for DMA. Rename to malloc_phys() to more closely match the functionality, and to create name space for functions that specifically allocate and map DMA-capable buffers. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2020-09-25[pci] Update drivers to use pci_ioremap()Michael Brown2-2/+6
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2020-09-24[pci] Define pci_ioremap() for mapping PCI bus addressesMichael Brown4-0/+28
Define pci_ioremap() as a wrapper around ioremap() that could allow for a non-zero address translation offset. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2020-07-27[comboot] Fix stack pointer retrieval after COM32 binary returnsDentcho Ludmilov Bankov1-1/+1
This change fixes the offset used when retrieving the iPXE stack pointer after a COM32 binary returns. The iPXE stack pointer is saved at the top of the available memory then the the top of the stack for the COM32 binary is set just below it. However seven more items are pushed on the COM32 stack before the entry point is invoked so when the COM32 binary returns the location of the iPXE stack pointer is 28 (and not 24) bytes above the current stack pointer. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2020-07-21[pcbios] Take alignment into account when checking for available spaceDavid Decotigny1-4/+4
Signed-off-by: David Decotigny <ddecotig@gmail.com> Signed-off-by: Michael Brown <mcb30@ipxe.org>
2020-07-21[pcbios] Fix "out of memory" detection when expanding bottom areaDavid Decotigny1-1/+1
This caused iPXE to reject images even when enough memory was available. Signed-off-by: David Decotigny <ddecotig@gmail.com> Signed-off-by: Michael Brown <mcb30@ipxe.org>
2020-07-07[efi] Avoid setting direction flag on EFI platformsMichael Brown1-0/+14
The only remaining use case in iPXE for the CPU direction flag is in __memcpy_reverse() where it is set to allow the use of "rep movsb" to perform the memory copy. This matches the equivalent functionality in the EDK2 codebase, which has functions such as InternalMemCopyMem that also temporarily set the direction flag in order to use "rep movsb". As noted in commit d2fb317 ("[crypto] Avoid temporarily setting direction flag in bigint_is_geq()"), some UEFI implementations are known to have buggy interrupt handlers that may reboot the machine if a timer interrupt happens to occur while the direction flag is set. Work around these buggy UEFI implementations by using the (unoptimised) generic_memcpy_reverse() on i386 or x86_64 UEFI platforms. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2020-07-07[crypto] Avoid temporarily setting direction flag in bigint_is_geq()Michael Brown1-17/+8
The UEFI specification states that the calling convention for IA-32 and x64 includes "Direction flag in EFLAGS is clear". This specification covers only the calling convention used at the point of calling functions annotated with EFIAPI. The specification explicitly states that other functions (such as private functions or static library calls) are not required to follow the UEFI calling conventions. The reference EDK2 implementation follows this specification. In particular, the EDK2 interrupt handlers will clear the direction flag before calling any EFIAPI functions, and will restore the direction flag when returning from the interrupt handler. Some EDK2 private library functions (most notably InternalMemCopyMem) may set the direction flag temporarily in order to make efficient use of CPU string operations. The current implementation of iPXE's bigint_is_geq() for i386 and x86_64 will similarly set the direction flag temporarily in order to make efficient use of CPU string operations. On some UEFI implementations (observed with a Getac RX10 tablet), a timer interrupt that happens to occur while the direction flag is set will reboot the machine. This very strongly indicates that the UEFI timer interrupt handler is failing to clear the direction flag before performing an affected operation (such as copying a block of memory). Work around such buggy UEFI implementations by rewriting bigint_is_geq() to avoid the use of string operations and so obviate the requirement to temporarily set the direction flag. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2020-03-01[int13con] Create log partition only when CONSOLE_INT13 is enabledMichael Brown1-0/+17
Reduce the size of the USB disk image in the common case that CONSOLE_INT13 is not enabled. Originally-implemented-by: Romain Guyard <romain.guyard@mujin.co.jp> Signed-off-by: Michael Brown <mcb30@ipxe.org>
2020-03-01[bios] Define macros for constructing partition table entriesMichael Brown1-10/+37
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2019-01-25[init] Show startup and shutdown function names in debug messagesMichael Brown6-0/+6
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2019-01-15[pci] Correct invalid base-class/sub-class/prog-if order in PCIRPetr Borsodi2-2/+2
PCI Configuration Space contains fields prog-if at the offset 0x09, sub-class at the offset 0x0a and base-class at the offset 0x0b (it respects little endian). PCIR structure uses these fields in the same order. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2018-04-18[undi] Include subsystem IDs in broken interrupt device checkMichael Brown1-6/+27
Allow the subsystem IDs to be used when checking for PXE stacks with broken interrupt support. Suggested-by: Levi Hsieh <Levi.Hsieh@dell.com> Signed-off-by: Michael Brown <mcb30@ipxe.org>
2018-03-21[librm] Ensure that inline code symbols are uniqueMichael Brown6-9/+9
Commit 6149e0a ("[librm] Provide symbols for inline code placed into other sections") may cause build failures due to duplicate label names if the compiler chooses to duplicate inline assembly code. Fix by using the "%=" special format string to include a guaranteed-unique number within the label name. The "%=" will be expanded only if constraints exist for the inline assembly. This fix therefore requires that all REAL_CODE() fragments use a (possibly empty) constraint list. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2018-03-21[librm] Provide symbols for inline code placed into other sectionsMichael Brown1-0/+5
Provide symbols constructed from the object name and line number for code fragments placed into alternative sections, such as inline REAL_CODE() assembly placed into .text16. This simplifies the debugging task of finding the source code corresponding to a given instruction pointer. Note that we cannot use __FUNCTION__ since it is not a preprocessor macro and so cannot be concatenated with string literals. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2018-03-21[undi] Treat invalid IRQ numbers as non-fatal errorsMichael Brown1-4/+2
If the underlying PXE stack reports an invalid IRQ number (above IRQ_MAX), treat this as equivalent to an empty IRQ number and fall back to using polling mode. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2018-03-20[rng] Use fixed-point calculations for min-entropy quantitiesMichael Brown1-2/+2
We currently perform various min-entropy calculations using build-time floating-point arithmetic. No floating-point code ends up in the final binary, since the results are eventually converted to integers and asserted to be compile-time constants. Though this mechanism is undoubtedly cute, it inhibits us from using "-mno-sse" to prevent the use of SSE registers by the compiler. Fix by using fixed-point arithmetic instead. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2018-03-20[time] Add support for the ACPI power management timerMichael Brown2-0/+137
Allow the ACPI power management timer to be used if enabled via TIMER_ACPI in config/timer.h. This provides an alternative timer on systems where the standard 8254 PIT is unavailable or unreliable. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2018-03-18[librm] Add facility to provide register and stack dump for CPU exceptionsMichael Brown3-7/+162
When DEBUG=librm_mgmt is enabled, intercept CPU exceptions and provide a register and stack dump, then drop to an emergency shell. Exiting from the shell will almost certainly not work, but this provides an opportunity to view the register and stack dump and carry out some basic debugging. Note that we can intercept only the first 8 CPU exceptions, since a PXE ROM is not permitted to rebase the PIC. Signed-off-by: Michael Brown <mcb30@ipxe.org>
2018-01-02[build] Avoid use of "ld --oformat binary"Michael Brown2-4/+5
Using "ld --oformat binary" for mbr.bin and usbdisk.bin seems to cause segmentation faults on some versions of binutils (observed on Fedora 27). Work around this problem by using ld to create an intermediate ELF object, followed by objcopy (via the existing %.tmp -> %.bin rule) to create the final binary. Note that we cannot simply use a single-stage "objcopy -O binary" since this will not process the relocation records for x86_64: see commit 1afcccd ("[build] Do not use "objcopy -O binary" for objects with relocation records"). Reported-by: Brent S <bts@square-r00t.net> Signed-off-by: Michael Brown <mcb30@ipxe.org>
2017-08-30[romprefix] Avoid unaligned accesses within ROM headersMichael Brown2-0/+4
Ensure that all headers (PCI, UNDI, PnP, iPXE) are aligned to at least four bytes, so that all accesses to header fields will be correctly aligned even when reading directly from the expansion ROM BAR. Reported-by: Peter von Konigsmark <peter@exablaze.com> Signed-off-by: Michael Brown <mcb30@ipxe.org>