Commit Graph

7210 Commits

Author SHA1 Message Date
Michael Brown
5b19ddbb3c [riscv] Return virtual address offset from enable_paging()
Once paging has been enabled, there is no direct way to determine the
virtual address offset without external knowledge.  (The paging mode,
if needed, can be read directly from the SATP CSR.)

Change the return value from enable_paging() to provide the virtual
address offset.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-08 14:37:30 +01:00
Michael Brown
5e518c744e [riscv] Restore temporarily modified PTE within 32-bit transition code
If the virtual address offset is precisely one page (i.e. each virtual
address maps to a physical address one page higher), and if the 32-bit
transition code happens to end up at the end of a page (which would
require an unrealistic 2MB of content in .prefix), then it would be
possible for the program counter to cross into the portion of the
virtual address space still borrowed for use as the temporary physical
map.

Avoid this remote possibility by moving the restoration of the
temporarily modified PTE within the transition code block (which is
guaranteed to remain within a single page since it is aligned on its
own size).

This unfortunately requires increasing the alignment of the transition
code (and hence the maximum number of NOPs inserted).  The assembler
syntax theoretically allows us to avoid inserting any NOPs via a
directive such as:

   .balign PAGE_SIZE, , enable_paging_32_max_len

(i.e. relying on the fact that if the transition code is already
sufficiently far away from the end of a page, then no padding needs to
be inserted).  However, alignment on RISC-V is implemented using the
R_RISCV_ALIGN relaxing relocation, which doesn't encode any concept of
a maximum padding length, and so the maximum padding length value is
effectively ignored.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-08 12:45:37 +01:00
Michael Brown
0279015d09 [uaccess] Generalise librm's virt_offset mechanism for RISC-V
The virtual offset memory model used for i386-pcbios and x86_64-pcbios
can be generalised to also cover riscv32-sbi and riscv64-sbi.  In both
architectures, the 32-bit builds will use a circular map of the 32-bit
address space, and the 64-bit builds will use an identity map for the
relevant portion of the physical address space, with iPXE itself
placed in the negative (kernel) address space.

Generalise and document the virt_offset mechanism, and set it as the
default for both PCBIOS and SBI platforms.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-08 00:12:33 +01:00
Michael Brown
e8a6c26571 [build] Constrain PHYS_CODE() and REAL_CODE() to use i386 registers
Inline assembly using PHYS_CODE() or REAL_CODE() must use the "R"
constraint rather than the "r" constraint to ensure that the compiler
chooses registers that will be valid for the 32-bit or 16-bit assembly
code fragment.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-07 23:03:02 +01:00
Michael Brown
12dee2dab2 [riscv] Add debug printing of hexadecimal values in libprefix.S
Add millicode routines to print hexadecimal values (with any number of
digits), and macros to print register contents or symbol addresses.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-07 14:23:56 +01:00
Michael Brown
72c81419b1 [riscv] Move prefix system reset code to libprefix.S
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-07 13:10:40 +01:00
Michael Brown
764183504c [riscv] Add basic debug progress messages in libprefix.S
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-07 13:08:49 +01:00
Michael Brown
9445a9ff40 [riscv] Provide a millicode variant of print_message()
RISC-V has a millicode calling convention that allows for the use of
an alternative link register x5/t0.  With sufficient care, this allows
for two levels of subroutine call even when no stack is available.

Provide both standard and millicode entry points for print_message(),
and use the millicode entry point to allow for printing debug messages
from libprefix.S itself.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-07 13:08:49 +01:00
Michael Brown
dc9e6f0edf [riscv] Move prefix debug message printing to libprefix.S
Create a prefix library function print_message() to print text to the
SBI debug console.  Use the "write byte" SBI call (rather than "write
string") so that the function remains usable even after enabling
paging.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-06 17:28:14 +01:00
Michael Brown
b3cbdc86fc [riscv] Place prefix debug strings in .rodata
The GNU assembler does not seem to automatically assume alignment to
an instruction boundary for sections containing assembled code.

Place the prefix debug strings (if present) in .rodata rather than in
.prefix, to avoid potentially creating misaligned code sections.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-06 15:51:39 +01:00
Michael Brown
4bef4c8069 [riscv] Use compressed relocation records
Use compressed relocation records instead of raw Elf_Rela records.
This saves around 15% of the total binary size for the all-drivers
image bin-riscv64/ipxe.sbi.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-06 15:01:45 +01:00
Michael Brown
8f7aa292aa [riscv] Place .got and .got.plt in .data
Even though we build with -mno-plt, redundant .got and .got.plt
sections are still generated.

Include these redundant sections within .data (which has identical
section attributes) to simplify the section list.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-06 13:58:38 +01:00
Michael Brown
e37e3f17e5 [riscv] Discard ELF hash tables
The ELF hash table is generated when building a position-independent
executable even though it is not required (since we have no dynamic
linker).

Explicitly discard these unneeded sections.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-06 13:44:44 +01:00
Michael Brown
70bb5e5e63 [zbin] Allow for constructing compressed dynamic relocation records
Define a new "ZREL" compressor information block, describing a block
of Elf_Rel or Elf_Rela runtime relocations to be converted to an
iPXE-specific compressed relocation format.

The compressed relocation format is based loosely on the Elf_Relr
bitmap+offset format, with some optimisations for use in iPXE.  In
particular:

  - a relative "skip" value is used instead of an absolute offset

  - the width of the skip value is reduced to 19 bits (when present)

  - an explicit skip value of zero is used to terminate the list

  - unaligned relocations are prohibited

The layout of bits within the compressed relocation record is also
adjusted to make assembly code implementations simpler: the skip flag
bit is placed in the MSB so that it can be tested using "bltz" or
similar instructions, and the skip value is placed above the
relocation flag bits so that a typical shifting implementation will
naturally end up with a zero value in its accumulator if and only if
the record was a terminator.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-06 12:11:56 +01:00
Michael Brown
98646b9f01 [build] Allow for 32-bit and 64-bit versions of util/zbin
Parsing ELF data is simpler if we don't have to build a single binary
to handle both 32-bit and 64-bit ELF formats.

Allow for separate 32-bit and 64-bit binaries built from util/zbin.c
(as is already done for util/elf2efi.c).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-06 12:11:02 +01:00
Michael Brown
4c11737d5d [riscv] Add support for enabling 32-bit paging
Add code to construct a 32-bit page table to map the whole of the
32-bit address space with a fixed offset selected to map iPXE itself
at its link-time address, and to return with paging enabled and the
program counter updated to a virtual address.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-04 21:40:32 +01:00
Michael Brown
a32f3c2bc4 [riscv] Add support for enabling 64-bit paging
Paging provides an alternative to using relocations: instead of
applying relocation fixups to the runtime addresses, we can set up
virtual addressing so that the runtime addresses match the link-time
addresses.

This opens up the possibility of running portions of iPXE directly
from read-only memory (such as a memory-mapped flash device), subject
to the caveats that .data is not yet writable and .bss is not yet
zeroed.  This should allow us to run enough code to parse the memory
map from the FDT, identify a suitable RAM block, and physically
relocate ourselves there.

Add code to construct a 64-bit page table (in a single 4kB buffer) to
identity-map as much of the physical address space as possible, to map
iPXE itself at its link-time address, and to return with paging
enabled and the program counter updated to a virtual address.  We use
the highest paging level supported by the CPU, to maximise the amount
of the physical address space covered by the identity map.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-02 14:33:43 +01:00
Michael Brown
dad2060260 [riscv] Allow for a non-zero link-time address
Using paging (rather than relocation records) will be easier on 64-bit
RISC-V if we place iPXE within the negative (kernel) virtual address
space.

Allow the link-time address to be non-zero and to vary between 32-bit
and 64-bit builds.  Choose addresses that are expected to be amenable
to the use of paging.

There is no particular need to use a non-zero address in the 32-bit
builds, but doing so allows us to validate that the relocation code is
handling this case correctly.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-01 14:49:53 +01:00
Michael Brown
a4b5dd63c5 [riscv] Split out runtime relocator to libprefix.S
Split out the runtime relocation logic from sbiprefix.S to a new
library libprefix.S.

Since this logically decouples the process of runtime relocation from
the _sbi_start symbol (currently used to determine the base address
for applying relocations), provide an alternative mechanism for the
relocator to determine the base address.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-01 14:36:26 +01:00
Michael Brown
1534b0a6e9 [uaccess] Remove redundant virt_to_user() and userptr_t
Remove the last remaining traces of the concept of a user pointer,
leaving iPXE with a simpler and cleaner memory model that implicitly
assumes that all memory locations can be reached through pointer
dereferences.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-30 16:26:16 +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
2d9a6369dd [test] Separate read-only and writable CMS test images
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
a69c42dd9f [image] Clear recorded replacement image immediately after consuming
If an embedded script uses "chain --replace", the embedded image will
retain a reference to the replacement image in perpetuity.

Fix by clearing any recorded replacement image immediately in
image_exec(), instead of relying upon image_free() to drop the
reference.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-29 16:32:01 +01:00
Michael Brown
9962c0a58f [bofm] Remove userptr_t from BOFM table parsing and updating
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-29 13:42:42 +01:00
Michael Brown
0800723845 [bofm] Allow BOFM tests to be run without a BOFM-capable device driver
The BOFM tests are not part of the standard unit test suite, since
they are designed to allow for exercising real BOFM driver code
outside of the context of a real IBM blade server.

Allow for the BOFM tests to be run without a real BOFM driver, by
providing a dummy driver for the specified PCI test device.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-29 13:39:12 +01:00
Michael Brown
4e909cc2b0 [build] Remove some long-obsolete unused header files
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-29 12:17:16 +01:00
Michael Brown
6c9dc063f6 [peerdist] Remove never-used peerdist_msg_blk() macro
The peerdist_msg_blk() macro seems to have been introduced in the
original commit that added pccrr.h, but this macro was never used by
the version of the code present in that commit.

Remove this unused macro and the corresponding nonexistent external
function declaration.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-29 12:08:33 +01:00
Michael Brown
54c4217bdd [peerdist] Remove userptr_t from PeerDist content information parsing
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-29 11:28:45 +01:00
Michael Brown
837b77293b [xferbuf] Simplify and generalise data transfer buffers
Since all data transfer buffer contents are now accessible via direct
pointer dereferences, remove the unnecessary abstractions for read and
write operations and create two new data transfer buffer types: a
fixed-size buffer, and a void buffer that records its size but can
never receive non-zero lengths of data.  These replace the custom data
buffer types currently implemented for EFI PXE TFTP downloads and for
block device translations.

A new operation xferbuf_detach() is required to take ownership of the
data accumulated in the data transfer buffer, since we no longer rely
on the existence of an independently owned external data pointer for
data transfer buffers allocated via umalloc().

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-29 11:27:22 +01:00
Michael Brown
43fc516298 [prefix] Remove userptr_t from command line image construction
Simplify cmdline_init() by assuming that the externally provided
command line is directly accessible via pointer dereferences.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-29 00:30:34 +01:00
Michael Brown
c9fb94dbaa [comboot] Remove userptr_t from COM32 API implementation
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-29 00:24:55 +01:00
Michael Brown
f001e61a68 [comboot] Remove userptr_t from COMBOOT API implementation
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-28 22:50:23 +01:00
Michael Brown
ef97119589 [comboot] Remove userptr_t from COMBOOT image parsing
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-28 22:31:18 +01:00
Michael Brown
0b45db3972 [uaccess] Remove redundant UNULL definition
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-28 17:36:18 +01:00
Michael Brown
6ccb6bcfc8 [bzimage] Remove userptr_t from bzImage parsing
Simplify bzImage parsing by assuming that the various headers are
directly accessible via pointer dereferences.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-28 16:30:35 +01:00
Michael Brown
412ad56012 [initrd] Use physical addresses for calculations on initrd locations
Commit ef03849 ("[uaccess] Remove redundant userptr_add() and
userptr_diff()") exposed a signedness bug in the comparison of initrd
locations, since the expression (initrd->data - current) was
effectively no longer coerced to a signed type.

In particular, the common case will be that the top of the initrd
region is the start of the iPXE .textdata region, which has virtual
address zero.  This causes initrd->data to compare as being above the
top of the initrd region for all images, when this bug would
previously have been limited to affecting only initrds placed 2GB or
more below the start of .textdata.

Fix by using physical addresses for all comparisons on initrd
locations.

Reported-by: Sven Dreyer <sven@dreyer-net.de>
Reported-by: Harald Jensås <hjensas@redhat.com>
Reported-by: Jan ONDREJ (SAL) <ondrejj@salstar.sk>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-28 15:35:55 +01:00
Michael Brown
ef3827cf14 [bzimage] Use image name in debug messages
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-28 14:43:19 +01:00
Michael Brown
083e273bbc [efi] Add ability to reboot to firmware setup menu
Add the ability to reboot to the firmware setup menu (if supported) by
setting the relevant value in the OsIndications variable.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-28 14:01:17 +01:00
Michael Brown
7eaa2daf6f [reboot] Generalise warm reboot indicator to a flags bitmask
Allow for the possibility of additional reboot types by extending the
reboot() function to use a flags bitmask rather than a single flag.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-28 13:44:53 +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
3befb5eb57 [linux] Enable compiler warnings when building the linux_api.o object
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-27 23:36:34 +01:00
Michael Brown
024439f339 [linux] Add missing return statement to linux_poll()
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-27 23:28:51 +01:00
Michael Brown
bd4ca67cf4 [build] Disable gcc unterminated-string-initializer warnings
GCC 15 generates a warning when a string initializer is too large to
allow for a trailing NUL terminator byte.  This type of initializer is
fairly common in signature strings such as ACPI table identifiers.

Fix by disabling the warning.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-27 18:40:52 +01:00
Michael Brown
15c1111c78 [build] Remove unsafe disable function wrapper from legacy NIC drivers
The legacy NIC drivers do not consistently take a second parameter in
their disable function.  We currently use an unsafe function wrapper
that declares no parameters, and rely on the ABI allowing a second
parameter to be silently ignored if not expected by the caller.  As of
GCC 15, this hack results in an incompatible pointer type warning.

Fix by removing the hack, and instead updating all relevant legacy NIC
drivers to take an unused second parameter in their disable function.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-27 18:40:52 +01:00
Miao Wang
7741756afc [build] Prevent the use of reserved words in C23
GCC 15 defaults to C23, which reserves bool, true, and false as
keywords.  Avoid using these as parameter or variable names.

Modified-by: Michael Brown <mcb30@ipxe.org>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-27 18:40:33 +01:00