Commit Graph

2508 Commits

Author SHA1 Message Date
Michael Brown
4224f574da [pci] Map all MSI-X interrupts to a dummy target address by default
Interrupts as such are not used in iPXE, which operates in polling
mode.  However, some network cards (such as the Intel 40GbE and 100GbE
NICs) will defer writing out completions until the point of asserting
an MSI-X interrupt.

From the point of view of the PCI device, asserting an MSI-X interrupt
is just a 32-bit DMA write of an opaque value to an opaque target
address.  The PCI device has no know to know whether or not the target
address corresponds to a real APIC.

We can therefore trick the PCI device into believing that it is
asserting an MSI-X interrupt, by configuring it to write an opaque
32-bit value to a dummy target address in host memory.  This is
sufficient to trigger the associated write of the completions to host
memory.

Allocate a dummy target address when enabling MSI-X on a PCI device,
and map all interrupts to this target address by default.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-10-09 16:29:29 +01:00
Michael Brown
c10da8b53c [efi] Add ability to extract device path from an EFI load option
An EFI boot option (stored in a BootXXXX variable) comprises an
EFI_LOAD_OPTION structure, which includes some undefined number of EFI
device paths.  (The structure is extremely messy and awkward to parse
in C, but that's par for the course with EFI.)

Add a function to extract the first device path from an EFI load
option, along with wrapper functions to read and extract the first
device path from an EFI boot variable.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-08-29 12:34:17 +01:00
Michael Brown
5bec2604a3 [libc] Add wcsnlen()
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-08-28 15:12:41 +01:00
Michael Brown
88ba011764 [fdt] Provide fdt_reg() for unsized single-entry regions
Many region types (e.g. I2C bus addresses) can only ever contain a
single region with no size cells specified.  Provide fdt_reg() to
reduce boilerplate in this common use case.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-08-07 15:49:09 +01: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
f45782f9f3 [digest] Add commands for all enabled digest algorithms
Add "sha256sum", "sha512sum", and similar commands.  Include these new
commands only when DIGEST_CMD is enabled in config/general.h and the
corresponding algorithm is enabled in config/crypto.h.

Leave "mdsum" and "sha1sum" included whenever only DIGEST_CMD is
enabled, to avoid potentially breaking backwards compatibility with
builds that disabled MD5 or SHA-1 as a TLS or X.509 digest algorithm,
but would still have expected those commands to be present.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-08-06 13:17:25 +01:00
Michael Brown
2e4e1f7e9e [dwgpio] Add driver for the DesignWare GPIO controller
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-08-05 14:39:56 +01:00
Michael Brown
90fe3a2924 [gpio] Add a framework for GPIO controllers
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-08-05 13:54:27 +01:00
Michael Brown
5f10b74555 [fdt] Use phandle as device location
Consumption of phandles will be in the form of locating a functional
device (e.g. a GPIO device, or an I2C device, or a reset controller)
by phandle, rather than locating the device tree node to which the
phandle refers.

Repurpose fdt_phandle() to obtain the phandle value (instead of
searching by phandle), and record this value as the bus location
within the generic device structure.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-08-04 14:52:00 +01:00
Michael Brown
fb082bd4cd [fdt] Add ability to locate node by phandle
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-07-22 13:39:13 +01:00
Michael Brown
e01e5ff7c6 [dwusb] Add driver for DesignWare USB3 host controller
Add a basic driver for the DesignWare USB3 host controller as found in
the Lichee Pi 4A.

This driver covers only the DesignWare host controller hardware.  On
the Lichee Pi 4A, this is sufficient to get the single USB root hub
port (exposed internally via the SODIMM connector) up and running.

The driver does not yet handle the various GPIOs that control power
and signal routing for the Lichee Pi 4A's onboard VL817 USB hub and
the four physical USB-A ports.  This therefore leaves the USB hub and
the USB-A ports unpowered, and the USB2 root hub port routed to the
physical USB-C port.  Devices plugged in to the USB-A ports will not
be powered up, and a device plugged in to the USB-C port will
enumerate as a USB2 device.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-07-21 15:55:13 +01:00
Michael Brown
6c42ea1275 [xhci] Allow for non-PCI xHCI host controllers
Allow for the existence of xHCI host controllers where the underlying
hardware is not a PCI device.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-07-21 15:33:58 +01:00
Michael Brown
8701863a17 [efi] Allow compiler to perform type checks on EFI_EVENT
As with EFI_HANDLE, the EFI headers define EFI_EVENT as a void
pointer, rendering EFI_EVENT compatible with a pointer to itself and
hence guaranteeing that pointer type bugs will be introduced.

Redefine EFI_EVENT as a pointer to an anonymous structure (as we
already do for EFI_HANDLE) to allow the compiler to perform type
checking as expected.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-07-15 16:57:25 +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
c3376f8645 [efi] Drop to external TPL for calls to ConnectController()
There is nothing in the current versions of the UEFI specification
that limits the TPL at which we may call ConnectController() or
DisconnectController().  However, at least some platforms (observed
with a Lenovo ThinkPad T14s Gen 5) will occasionally and unpredictably
lock up before returning from ConnectController() if called at a TPL
higher than TPL_APPLICATION.

Work around whatever defect is present on these systems by dropping to
the current external TPL for all calls to ConnectController() or
DisconnectController().

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-07-14 12:19:15 +01:00
Michael Brown
c01c3215dc [efi] Provide efi_tpl_name() for transcribing TPLs in debug messages
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-07-14 12:15:08 +01:00
Michael Brown
c2cdc1d31e [dwmac] Add driver for DesignWare Ethernet MAC
Add a basic driver for the DesignWare Ethernet MAC network interface
as found in the Lichee Pi 4A.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-07-10 14:39:07 +01:00
Michael Brown
bbabde8ff8 [riscv] Invalidate data cache on completed RX DMA buffers
The data cache must be invalidated twice for RX DMA buffers: once
before passing ownership to the DMA device (in case the cache happens
to contain dirty data that will be written back at an undefined future
point), and once after receiving ownership from the DMA device (in
case the CPU happens to have speculatively accessed data in the buffer
while it was owned by the hardware).

Only the used portion of the buffer needs to be invalidated after
completion, since we do not care about data within the unused portion.

Update the DMA API to include the used length as an additional
parameter to dma_unmap(), and add the necessary second cache
invalidation pass to the RISC-V DMA API implementation.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-07-10 14:39:07 +01:00
Michael Brown
101ef74a6e [riscv] Provide a DMA API implementation for RISC-V bare-metal systems
Provide an implementation of dma_map() that performs cache clean or
invalidation as required, and an implementation of dma_alloc() that
returns virtual addresses within the coherent mapping of the 32-bit
physical address space.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-07-09 11:07:37 +01:00
Michael Brown
22de0c4edf [dma] Use virtual addresses for dma_map()
Cache management operations must generally be performed on virtual
addresses rather than physical addresses.

Change the address parameter in dma_map() to be a virtual address, and
make dma() the API-level primitive instead of dma_phys().

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-07-08 15:13:19 +01:00
Michael Brown
19f1407ad9 [iobuf] Ensure I/O buffer data sits within unshared cachelines
On platforms where DMA devices are not in the same coherency domain as
the CPU cache, we must ensure that DMA I/O buffers do not share
cachelines with other data.

Align the start and end of I/O buffers to IOB_ZLEN, which is larger
than any cacheline size we expect to encounter.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-07-07 16:18:04 +01:00
Michael Brown
c21443f0b9 [uaccess] Allow for coherent DMA mapping of the 32-bit address space
On platforms where DMA devices are not in the same coherency domain as
the CPU cache, it is necessary to create page table entries where the
translations are marked as uncacheable.

We choose to place iPXE within the low 4GB of memory (since 32-bit DMA
devices are still reasonably common even on systems with 64-bit CPUs).
We therefore need to cover only the low 4GB of memory with these page
table entries.

Update virt_to_phys() to allow for the existence of such a mapping,
assuming that iPXE itself will always reside within the top 4GB of the
64-bit virtual address space (and therefore that the DMA mapping must
lie somewhere below this in the negative virtual address space).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-07-04 16:10:51 +01:00
Michael Brown
d3e10ebd35 [legacy] Allocate legacy driver .bss-like segments at probe time
Some legacy drivers use large static allocations for transmit and
receive buffers.  To avoid bloating the .bss segment, we currently
implement these as a single common symbol named "_shared_bss" (which
is permissible since only one legacy driver may be active at any one
time).

Switch to dynamic allocation of these .bss-like segments, to avoid the
requirement for using common symbols.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-06-24 13:41:51 +01:00
Michael Brown
6ea800ab54 [legacy] Rename the global legacy NIC to "legacy_nic"
We currently have contexts in which the local variable "nic" is a
pointer to the global variable also called "nic".  This complicates
the creation of macros.

Rename the global variable to "legacy_nic" to reduce pollution of the
global namespace and to allow for the creation of macros referring to
fields within this global variable.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-06-24 13:41:51 +01:00
Michael Brown
9ada09c919 [dwuart] Read input clock frequency from the device tree
The 16550 design includes a programmable 16-bit clock divider for an
arbitrary input clock, requiring knowledge of the input clock
frequency in order to calculate the divider value for a given baud
rate.  The 16550 UARTs in an x86 PC will always have a 1.8432 MHz
input clock.  Non-x86 systems may have other input clock frequencies.

Define the input clock frequency as a property of a 16550 UART, and
read the value from the device tree "clock-frequency" property.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-06-23 22:56:38 +01:00
Michael Brown
2ce1b185b2 [serial] Allow platform to specify mechanism for identifying console
Allow the platform configuration to provide a mechanism for
identifying the serial console UART.  Provide two globally available
mechanisms: "null" (i.e. no serial console), and "fixed" (i.e. use
whatever is specified by COMCONSOLE in config/serial.h).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-06-23 16:53:13 +01:00
Michael Brown
53a3befb69 [dwuart] Add a basic driver for the Synopsys DesignWare UART
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-06-21 23:34:32 +01:00
Michael Brown
cca1cfd49e [uart] Allow for dynamically registered 16550 UARTs
Use the generic UART driver-private data pointer, rather than
embedding the generic UART within the 16550 UART structure.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-06-21 23:34:32 +01:00
Michael Brown
71b4bfb6b2 [uart] Add support for MMIO-accessible 16550 UARTs
16550 UARTs exist on non-x86 platforms but will be accessible via MMIO
rather than port I/O.  It is possible to encounter MMIO-mapped 16550
UARTs on x86 platforms, but there is no real requirement to support
them in iPXE since the standard COM1, COM2, etc ports have been
present on every PC-compatible machine since 1981.

Assume for now that accessing 16550 UART registers requires
inb()/outb() on x86 and readb()/writeb() on other architectures.

Allow for the existence of a register shift on MMIO-mapped 16550
UARTs, since modern SoCs tend to treat register addresses as being
aligned to either 32-bit or 64-bit boundaries.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-06-20 12:52:04 +01:00
Michael Brown
6c8fb4b89d [uart] Allow for the existence of non-16550 UARTs
Remove the assumption that all platforms use a fixed number of 16550
UARTs identifiable by a simple numeric index.  Create an abstraction
allowing for dynamic instantiation and registration of any number of
arbitrary UART models.

The common case of the serial console on x86 uses a single fixed UART
specified at compile time.  Avoid unnecessarily dragging in the
dynamic instantiation code in this use case by allowing COMCONSOLE to
refer to a single static UART object representing the relevant port.

When selecting a UART by command-line argument (as used in the
"gdbstub serial <port>" command), allow the UART to be specified as
either a numeric index (to retain backwards compatiblity) or a
case-insensitive port name such as "COM2".

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-06-20 12:52:04 +01:00
Michael Brown
60e167c00b [uart] Remove ability to use frame formats other than 8n1
In the context of serial consoles, the use of any frame formats other
than the standard 8 data bits, no parity, and one stop bit is so rare
as to be nonexistent.

Remove the almost certainly unused support for custom frame formats.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-06-17 15:44:12 +01:00
Michael Brown
c4a3d438e6 [dt] Allow for creation of standalone devices
We will want to be able to create the console device as early as
possible.  Refactor devicetree probing to remove the assumption that a
devicetree device must have a devicetree parent, and expose functions
to allow a standalone device to be created given only the offset of a
node within the tree.

The full device path is no longer trivial to construct with this
assumption removed.  The full path is currently used only for debug
messages.  Remove the stored full path, use just the node name for
debug messages, and ensure that the topology information previously
visible in the full path is reconstructible from the combined debug
output if needed.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-06-11 13:02:20 +01:00
Michael Brown
b5fb7353fa [ipv4] Add support for classless static routes
Add support for RFC 3442 classless static routes provided via DHCP
option 121.

Originally-implemented-by: Hazel Smith <hazel.smith@leicester.ac.uk>
Originally-implemented-by: Raphael Pour <raphael.pour@hetzner.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-06-10 18:22:32 +01:00
Michael Brown
e648d23fba [ipv4] Extend routing mechanism to handle non-default routes
Extend the definition of an IPv4 routing table entry to allow for the
expression of non-default gateways for specified off-link subnets, and
of on-link secondary subnets (where we can send directly to the
destination address even though our source address is not within the
subnet).

This more precise definition also allows us to correctly handle
routing in the (uncommon for iPXE) case when multiple network
interfaces are open concurrently and more than one interface has a
default gateway.

The common case of a single IPv4 address/netmask and a default gateway
now results in two routing table entries.  To retain backwards
compatibility with existing documentation (and to avoid on-screen
clutter), the "route" command prints default gateways on the same line
as the locally assigned address.  There is therefore no change in
output from the "route" command unless explicit additional (off-link
or on-link) routes are present.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-06-10 13:54:15 +01:00
Michael Brown
96f5864660 [ipv4] Add self-tests for IPv4 routing
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-06-10 13:54:15 +01:00
Michael Brown
bb2011241f [dt] Locate parent node at point of use in dt_ioremap()
We currently rely on the recursive nature of devicetree bus probing to
obtain the region cell size specification from the parent device.
This blocks the possibility of creating a standalone console device
based on /chosen/stdout-path before probing the whole bus.

Fix by using fdt_parent() to locate the parent device at the point of
use within dt_ioremap().

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-30 16:39:10 +01:00
Michael Brown
1762568ec5 [fdt] Provide ability to locate the parent device node
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-30 16:38:39 +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
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
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
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
d0c35b6823 [bios] Use generic external heap based on the system memory map
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-19 20:47:21 +01:00