Commit Graph

165 Commits

Author SHA1 Message Date
Michael Brown 301b1ecf2b [build] Mark compressed image tools as permitted for UEFI Secure Boot
Some older distributions (such as RHEL 8) provide their AArch64
kernels as gzip-compressed EFI binaries (with no self-decompressing
EFI stub present).  We therefore enable support for gzip images by
default for arm64 EFI builds.

Review the files used to implement the gzip (and zlib) formats and
mark these as permitted for UEFI Secure Boot.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2026-01-28 16:34:57 +00:00
Michael Brown 40c2db9d67 [build] Mark direct kernel loading as forbidden for UEFI Secure Boot
Our long-standing policy for EFI platforms is that we support invoking
binary executables only via the LoadImage() and StartImage() boot
services calls, so that all security policy decisions are delegated to
the platform firmware.

Most binary executable formats that we support are BIOS-only and
cannot in any case be linked in to an EFI executable.  The only
cross-platform format is the generic Linux kernel image format as used
for RISC-V (and potentially also for AArch64).

Mark all files associated with direct loading of a kernel binary as
explicitly forbidden for UEFI Secure Boot.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2026-01-28 13:38:20 +00:00
Michael Brown adcaaf9b93 [build] Mark known reviewed files as permitted for UEFI Secure Boot
Some past security reviews carried out for UEFI Secure Boot signing
submissions have covered specific drivers or functional areas of iPXE.
Mark all of the files comprising these areas as permitted for UEFI
Secure Boot.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2026-01-14 16:10:29 +00:00
Michael Brown 6cccb3bdc0 [build] Mark core files as permitted for UEFI Secure Boot
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>
2026-01-14 13:25:34 +00:00
Michael Brown 9d4a2ee353 [cmdline] Show commands in alphabetical order
Commands were originally ordered by functional group (e.g. keeping the
image management commands together), with arrays used to impose a
functionally meaningful order within the group.

As the number of commands and functional groups has expanded over the
years, this has become essentially useless as an organising principle.
Switch to sorting commands alphabetically (using the linker table
mechanism).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-08-06 16:34:45 +01:00
Michael Brown 1e3fb1b37e [init] Show initialisation function names in debug messages
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-07-15 14:10:33 +01:00
Michael Brown 192cfc3cc5 [image] Use image name rather than pointer value in all debug messages
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-26 18:22:07 +01:00
Michael Brown 09140ab2c1 [memmap] Allow explicit colour selection for memory map debug messages
Provide DBGC_MEMMAP() as a replacement for memmap_dump(), allowing the
colour used to match other messages within the same message group.

Retain a dedicated colour for output from memmap_dump_all(), on the
basis that it is generally most useful to visually compare full memory
dumps against previous full memory dumps.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-25 12:06:53 +01:00
Michael Brown 036e43334a [memmap] Rename addr/last fields to min/max for clarity
Use the terminology "min" and "max" for addresses covered by a memory
region descriptor, since this is sufficiently intuitive to generally
not require further explanation.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-23 16:55:42 +01:00
Michael Brown cd38ed4fab [lkrn] Support initrd construction for RISC-V bare-metal kernels
Use the shared initrd reshuffling and CPIO header construction code
for RISC-V bare-metal kernels.  This allows for files to be injected
into the constructed ("magic") initrd image in exactly the same way as
is done for bzImage and UEFI kernels.

We append a dummy image encompassing the FDT to the end of the
reshuffle list, so that it ends up directly following the constructed
initrd in memory (but excluded from the initrd length, which was
recorded before constructing the FDT).

We also temporarily prepend the kernel binary itself to the reshuffle
list.  This is guaranteed to be safe (since reshuffling is designed to
be unable to fail), and avoids the requirement for the kernel segment
to be available before reshuffling.  This is useful since current
RISC-V bare-metal kernels tend to be distributed as EFI zboot images,
which require large temporary allocations from the external heap for
the intermediate images created during archive extraction.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-23 16:14:45 +01:00
Michael Brown c713ce5c7b [initrd] Squash and shuffle only initrds within the external heap
Any initrd images that are not within the external heap (e.g. embedded
images) do not need to be copied to the external heap for reshuffling,
and can just be left in their original locations.

Ignore any images that are not already within the external heap (or,
more precisely, that are wholly outside of the reshuffle region within
the external heap) when squashing and swapping images.

This reduces the maximum additional storage required by squashing and
swapping to zero, and so ensures that the reshuffling step is
guaranteed to succeed under all circumstances.  (This is unrelated to
the post-reshuffle load region check, which is still required.)

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-23 14:39:17 +01:00
Michael Brown 4a39b877dd [initrd] Split out initrd construction from bzimage.c
Provide a reusable function initrd_load_all() to load all initrds
(including any constructed CPIO headers) into a contiguous memory
region, and support functions to find the constructed total length and
permissible post-reshuffling load address range.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-23 12:31:46 +01:00
Michael Brown 11929389e4 [initrd] Allow for images straddling the top of the reshuffle region
It is hypothetically possible for external heap memory allocated
during driver startup to have been freed before an image was
downloaded, which could therefore leave an image straddling the
address recorded as the top of the reshuffle region.

Allow for this possibility by skipping squashing for any images
already straddling (or touching) the top of the reshuffle region.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-22 16:28:15 +01:00
Michael Brown 029c7c4178 [initrd] Rename bzimage_align() to initrd_align()
Alignment of initrd lengths is applicable to all Linux kernels, not
just those in the x86 bzImage format.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-22 16:28:15 +01:00
Michael Brown 9231d8c952 [initrd] Swap initrds entirely in-place via triple reversal
Eliminate the requirement for free space when reshuffling initrds by
swapping adjacent initrds using an in-place triple reversal.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-22 16:28:15 +01:00
Michael Brown 11e01f0652 [uheap] Expose external heap region directly
We currently rely on implicit detection of the external heap region.
The INT 15 memory map mangler relies on examining the corresponding
in-use memory region, and the initrd reshuffler relies on performing a
separate detection of the largest free memory block after startup has
completed.

Replace these with explicit public symbols to describe the external
heap region.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-22 16:28:15 +01:00
Michael Brown 20d2c0f787 [lkrn] Shut down devices before jumping to kernel entry point
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-21 15:07:55 +01:00
Michael Brown 969e8b5462 [lkrn] Allow a single initrd to be passed to the booted kernel
Allow a single initrd image to be passed verbatim to the booted RISC-V
kernel, as a proof of concept.

We do not yet support reshuffling to make optimal use of available
memory, or dynamic construction of CPIO headers, but this is
sufficient to allow iPXE to start up the Fedora 42 kernel with its
matching initrd image.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-21 14:56:10 +01:00
Michael Brown 9bc559850c [fdt] Allow an initrd to be specified when creating a device tree
Allow an initrd location to be specified in our constructed device
tree via the "linux,initrd-start" and "linux,initrd-end" properties.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-21 14:31:18 +01:00
Michael Brown c1cd54ad74 [initrd] Move initrd reshuffling to be architecture-independent code
There is nothing x86-specific in initrd.c, and a variant of the
reshuffling logic will be required for executing bare-metal kernels on
RISC-V and AArch64.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-21 12:12:16 +01:00
Michael Brown e2f4dba2b7 [lkrn] Add support for EFI zboot compressed kernel images
Current RISC-V and AArch64 kernels found in the wild tend not to be in
the documented kernel format, but are instead "EFI zboot" kernels
comprising a small EFI executable that decompresses and executes the
inner payload (which is a kernel in the expected format).

The EFI zboot header includes a recognisable magic value "zimg" along
with two fields describing the offset and length of the compressed
payload.  We can therefore treat this as an archive image format,
extracting the payload as-is and then relying on our existing ability
to execute compressed images.

This is sufficient to allow iPXE to execute the Fedora 42 RISC-V
kernel binary as currently published.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-20 14:29:57 +01:00
Michael Brown ecac4a34c7 [lkrn] Add basic support for the RISC-V Linux kernel image format
The RISC-V and AArch64 bare-metal kernel images share a common header
format, and require essentially the same execution environment: loaded
close to the start of RAM, entered with paging disabled, and passed a
pointer to a flattened device tree that describes the hardware and any
boot arguments.

Implement basic support for executing bare-metal RISC-V and AArch64
kernel images.  The (trivial) AArch64-specific code path is untested
since we do not yet have the ability to build for any bare-metal
AArch64 platforms.  Constructing and passing an initramfs image is not
yet supported.

Rename the IMAGE_BZIMAGE build configuration option to IMAGE_LKRN,
since "bzImage" is specific to x86.  To retain backwards compatibility
with existing local build configurations, we leave IMAGE_BZIMAGE as
the enabled option in config/default/pcbios.h and treat IMAGE_LKRN as
a synonym for IMAGE_BZIMAGE when building for x86 BIOS.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-20 13:08:38 +01:00
Michael Brown 25ab8f4629 [image] Use memmap_describe() to check loadable image segments
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-16 16:55:35 +01:00
Michael Brown 134d76379e [build] Formalise mechanism for accessing absolute symbols
In a position-dependent executable, where all addresses are fixed
at link time, we can use the standard technique as documented by
GNU ld to get the value of an absolute symbol, e.g.:

    extern char _my_symbol[];

    printf ( "Absolute symbol value is %x\n", ( ( int ) _my_symbol ) );

This technique may not work in a position-independent executable.
When dynamic relocations are applied, the runtime addresses will no
longer be equal to the link-time addresses.  If the code to obtain the
address of _my_symbol uses PC-relative addressing, then it will
calculate the runtime "address" of the absolute symbol, which will no
longer be equal the the link-time "address" (i.e. the correct value)
of the absolute symbol.

Define macros ABS_SYMBOL(), ABS_VALUE_INIT(), and ABS_VALUE() that
provide access to the correct values of absolute symbols even in
position-independent code, and use these macros wherever absolute
symbols are accessed.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-09 15:14:03 +01:00
Michael Brown a169d73593 [uaccess] Reduce scope of included uaccess.h header
The uaccess.h header is no longer required for any code that touches
external ("user") memory, since such memory accesses are now performed
through pointer dereferences.  Reduce the number of files including
this header.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-30 16:16:02 +01:00
Michael Brown 05ad7833c5 [image] Make image data read-only to most consumers
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>
2025-04-30 15:38:15 +01:00
Michael Brown cd803ff2e2 [image] Add the concept of a static image
Not all images are allocated via alloc_image().  For example: embedded
images, the static images created to hold a runtime command line, and
the images used by unit tests are all static structures.

Using image_set_cmdline() (via e.g. the "imgargs" command) to set the
command-line arguments of a static image will succeed but will leak
memory, since nothing will ever free the allocated command line.
There are no code paths that can lead to calling image_set_len() on a
static image, but there is no safety check against future code paths
attempting this.

Define a flag IMAGE_STATIC to mark an image as statically allocated,
generalise free_image() to also handle freeing dynamically allocated
portions of static images (such as the command line), and expose
free_image() for use by static images.

Define a related flag IMAGE_STATIC_NAME to mark the name as statically
allocated.  Allow a statically allocated name to be replaced with a
dynamically allocated name since this is a potentially valid use case
(e.g. if "imgdecrypt --name <name>" is used on an embedded image).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-30 15:38:15 +01:00
Michael Brown 3303910010 [image] Move embedded images from .rodata to .data
Decrypting a CMS-encrypted image will overwrite the existing image
data in place, and using an encrypted embedded image is a valid use
case.

Move embedded images from .rodata to .data to reflect the fact that
they are intended to be writable.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-30 15:38:15 +01:00
Michael Brown b6f9e4bab0 [uaccess] Remove redundant copy_from_user() and copy_to_user()
Remove the now-redundant copy_from_user() and copy_to_user() wrapper
functions.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-30 15:32:03 +01:00
Michael Brown ba2135d0fd [multiboot] Remove userptr_t from Multiboot and ELF image parsing
Simplify Multiboot and ELF image parsing by assuming that the
Multiboot and ELF headers are directly accessible via pointer
dereferences, and add some missing header validations.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-28 13:06:18 +01:00
Michael Brown c8c5cd685f [multiboot] Use image name in Multiboot and ELF debug messages
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-28 12:59:25 +01:00
Michael Brown 4c8bf666f4 [pnm] Remove userptr_t from PNM image parsing
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-25 17:23:37 +01:00
Michael Brown d29651ddec [png] Remove userptr_t from PNG image parsing
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-25 16:43:11 +01:00
Michael Brown 4cca1cadf8 [efi] Remove userptr_t from EFI PE image parsing
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-25 00:49:27 +01:00
Michael Brown 4f4f6c33ec [script] Remove userptr_t from script image parsing
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-24 16:28:32 +01:00
Michael Brown e8ffe2cd64 [uaccess] Remove trivial uses of userptr_t
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-24 01:40:05 +01:00
Michael Brown c059b34170 [deflate] Remove userptr_t from decompression code
Simplify the deflate, zlib, and gzip decompression code by assuming
that all content is fully accessible via pointer dereferences.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-22 12:32:12 +01:00
Michael Brown 3f8937d2f3 [crypto] Remove userptr_t from ASN.1 parsers
Simplify the ASN.1 code by assuming that all objects are fully
accessible via pointer dereferences.  This allows the concept of
"additional data beyond the end of the cursor" to be removed, and
simplifies parsing of all ASN.1 image formats.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-21 23:30:13 +01:00
Michael Brown 8c31270a21 [uaccess] Remove user_to_phys() and phys_to_user()
Remove the intermediate concept of a user pointer from physical
address conversions, leaving virt_to_phys() and phys_to_virt() as the
directly implemented functions.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-21 16:17:19 +01:00
Michael Brown 4535548cba [uaccess] Remove redundant user_to_virt()
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>
2025-04-21 00:15:52 +01:00
Michael Brown 89fe788689 [uaccess] Remove redundant memcpy_user() and related string functions
The memcpy_user(), memmove_user(), memcmp_user(), memset_user(), and
strlen_user() functions are now just straightforward wrappers around
the corresponding standard library functions.

Remove these redundant wrappers.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-20 23:00:13 +01:00
Michael Brown ef03849185 [uaccess] Remove redundant userptr_add() and userptr_diff()
The userptr_add() and userptr_diff() functions are now just
straightforward wrappers around addition and subtraction.

Remove these redundant wrappers.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-20 22:31:29 +01:00
Michael Brown 7e64e9b670 [fdt] Populate boot arguments in constructed device tree
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>
2025-04-01 16:55:28 +01:00
Michael Brown 4a7f64bf4f [efi] Allow for fact that SNP device may be removed by executed image
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>
2025-03-29 22:07:13 +00:00
Michael Brown b20f506a72 [efi] Install a device tree for the booted OS, if available
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>
2025-03-28 15:29:53 +00:00
Michael Brown 32a9408217 [efi] Allow use of typed pointers for efi_open() et al
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>
2025-03-24 15:43:56 +00:00
Michael Brown bac3187439 [efi] Use efi_open() for all ephemeral protocol opens
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-24 13:19:26 +00:00
Michael Brown 1a602c92ac [efi] Allow wrapping the global boot services table in situ
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>
2025-03-20 12:35:42 +00:00
Michael Brown 5f3ecbde5a [crypto] Support extracting certificates from EFI signature list images
Add support for the EFI signature list image format (as produced by
tools such as efisecdb).

The parsing code does not require any EFI boot services functions and
so may be enabled even in non-EFI builds.  We default to enabling it
only for EFI builds.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-11 12:58:19 +00:00
Michael Brown 26a8fed710 [crypto] Allow for parsing of DER data separate from DER images
We currently provide pem_asn1() to allow for parsing of PEM data that
is not necessarily contained in an image.  Provide an equivalent
function der_asn1() to allow for similar parsing of DER data.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-11 12:36:23 +00:00