Define a generic system memory map API, based on the abstraction
created for parsing the FDT memory map and adding a concept of hidden
in-use memory regions as required to support patching the BIOS INT 15
memory map.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
The size of accessible physical address space will be required for the
runtime memory map, not just at relocation time. Make this size an
additional parameter to fdt_register() (matching the prototype for
fdt_relocate()), and record the value for future reference.
Note that we cannot simply store the limit in fdt_relocate() since it
is called before .data is writable and before .bss is zeroed.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
We do not currently describe the temporary page table or the temporary
stack as areas to be avoided during relocation of the iPXE image to a
new physical address.
Perform the copy of the iPXE image and zeroing of the .bss within
libprefix.S, after we have no futher use for the temporary page table
or the temporary initial stack. Perform the copy and registration of
the system device tree in C code after relocation is complete and the
new stack (within .bss) has been set up.
This provides a clean separation of responsibilities between the
RISC-V libprefix.S and the architecture-independent fdtmem.c. The
prefix is responsible only for relocating iPXE to the new physical
address returned from fdtmem_relocate(), and doesn't need to know or
care where fdtmem.c is planning to place the copy of the device tree.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
On startup, we may be running from read-only memory. We need to parse
the devicetree to obtain the system memory map, and identify a safe
location to which we can copy our own binary image along with a
stashed copy of the devicetree, and then transfer execution to this
new location.
Parsing the system memory map realistically requires running C code.
This in turn requires a small temporary stack, and some way to ensure
that symbol references are valid.
We first attempt to enable paging, to make the runtime virtual
addresses equal to the link-time virtual addresses. If this fails,
then we attempt to apply the compressed relocation records.
Assuming that one of these has worked (i.e. that either the CPU
supports paging or that our image started execution in writable
memory), then we call fdtmem_relocate() to parse the system memory map
to find a suitable relocation target address.
After the copy we disable paging, jump to the relocated copy,
re-enable paging, and reapply relocation records (if needed). At this
point, we have a full runtime environment, and can transfer control to
normal C code.
Provide this functionality as part of libprefix.S, since it is likely
to be shared by multiple prefixes.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Add code to parse the devicetree memory nodes, memory reservations
block, and reserved memory nodes to construct an ordered and
non-overlapping description of the system memory map, and use this to
identify a suitable address to which iPXE may be relocated at runtime.
We choose to place iPXE on a superpage boundary (as required by the
paging code), and to use the highest available address within
accessible memory. This mirrors the approach taken for x86 BIOS
builds, where we have long assumed that any image format that we might
need to support may require specific fixed addresses towards the
bottom of the memory map, but is very unlikely to require specific
fixed addresses towards the top of the memory map (since those
addresses may not exist, depending on the amount of installed RAM).
Signed-off-by: Michael Brown <mcb30@ipxe.org>
iPXE does not make use of any thread-local storage. Use the otherwise
unused thread pointer register ("tp") to hold the current value of
the virtual address offset, rather than using a global variable.
This ensures that virt_offset can be made valid even during very early
initialisation (when iPXE may be executing directly from read-only
memory and so cannot update a global variable).
Signed-off-by: Michael Brown <mcb30@ipxe.org>
The "reg" property is also used by non-device nodes, such as the nodes
describing the system memory map.
Provide generalised functionality for parsing the "#address-cells",
"#size-cells", and "reg" properties.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
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>
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>
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>
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>
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>
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>
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>
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>
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>
Scrolling currently involves redrawing every character cell, which can
be frustratingly slow on large framebuffer consoles. Accelerate this
operation by skipping the redraw for any unchanged character cells.
In the common case that large areas of the screen contain whitespace,
this optimises away the vast majority of the redrawing operations.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Simplify the framebuffer console drivers by assuming that the raw
framebuffer, character cell array, background picture, and glyph data
are all directly accessible via pointer dereferences.
In particular, this avoids the need to copy each glyph during drawing:
the VESA framebuffer driver can simply return a pointer to the glyph
data stored in the video ROM.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Simplify the block device code by assuming that all read/write buffers
are directly accessible via pointer dereferences.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Use standard void pointers for umalloc(), urealloc(), and ufree(),
with the "u" prefix retained to indicate that these allocations are
made from external ("user") memory rather than from the internal heap.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Simplify the ACPI table parsing code by assuming that all table
content is fully accessible via pointer dereferences.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
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>
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>
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>
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>
For platforms with no real-time clock (such as RISC-V SBI) we use the
null time source, which currently just returns a constant zero.
Switch to using currticks() to provide a clock that does not represent
the real current time, but does at least advance at approximately the
correct rate. In conjunction with the "ntp" command, this allows
these platforms to use time-dependent features such as X.509
certificate verification for HTTPS connections.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Add fdt_cells() to read scalar values encoded within a cell array,
reimplement fdt_u64() as a wrapper around this, and add fdt_u32() for
completeness.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Refactor device tree traversal to operate on the basis of describing
the token at a given offset, with no separate notion of a device tree
cursor.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Using fdt_path() to find the root node "/" currently fails, since it
will attempt to find a child node with the empty name "" within the
root node.
Fix by changing fdt_path() to ignore any trailing slashes in a device
tree path.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
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>
Without any explicit alignment requirement, we will currently allocate
I/O buffers on their own size rounded up to the nearest power of two.
This is done to simplify driver transmit code paths, which can assume
that a standard Ethernet frame lies within a single physical page and
therefore does not need to be split even for devices with DMA engines
that cannot cross page boundaries.
Limit this automatic alignment to a maximum of the page size, to avoid
requiring excessive alignment for unusually large buffers (such as a
buffer allocated for an HTTP POST with a large parameter list).
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Provide fdt_create() to create a device tree to be passed to a booted
operating system. The device tree will be created from the FDT image
(if present), falling back to the system device tree (if present).
Signed-off-by: Michael Brown <mcb30@ipxe.org>
EFI configuration tables may be freed at any time, and there is no way
to be notified when the table becomes invalidated. Create a copy of
the system flattened device tree (if present), so that we do not risk
being left with an invalid pointer.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Allow for parsing device trees where an external factor (such as a
downloaded image length) determines the maximum length, which must be
validated against the length within the device tree header.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
When running on a platform that uses FDT as its hardware description
mechanism, we are likely to have multiple device tree structures. At
a minimum, there will be the device tree passed to us from the
previous boot stage (e.g. OpenSBI), and the device tree that we
construct to be passed to the booted operating system.
Update the internal FDT API to include an FDT pointer in all function
parameter lists.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Define the concept of an "FDT" image, representing a Flattened Device
Tree blob that has been downloaded in order to be provided to a kernel
or other executable image. FDT images are represented using an image
tag (as with other special-purpose images such as the UEFI shim), and
are similarly marked as hidden so that they will not be included in a
generated magic initrd or show up in a virtual filesystem directory
listing.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Allow for the possibility of creating empty directories (without
having to include a dummy file inside the directory) using a
zero-length image and a CPIO filename with a trailing slash, such as:
initrd emptyfile /usr/share/oem/
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Commit 12ea8c4 ("[cpio] Allow for construction of parent directories
as needed") introduced a regression in constructing CPIO archive
headers for relative paths (e.g. simple filenames with no leading
slash).
Fix by counting the number of path components rather than the number
of path separators, and add some test cases to cover CPIO header
construction.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
iPXE allows individual raw files to be automatically wrapped with
suitable CPIO headers and injected into the magic initrd image as
exposed to a booted Linux kernel. This feature is currently limited
to placing files within directories that already exist in the initrd
filesystem.
Remove this limitation by adding the ability for iPXE to construct
CPIO headers for parent directories as needed, under control of the
"mkdir=<n>" command-line argument. For example:
initrd config.ign /usr/share/oem/config.ign mkdir=1
will create CPIO headers for the "/usr/share/oem" directory as well as
for the "/usr/share/oem/config.ign" file itself.
This simplifies the process of booting operating systems such as
Flatcar Linux, which otherwise require the single "config.ign" file to
be manually wrapped up as a CPIO archive solely in order to create the
relevant parent directory entries.
The value <n> may be used to control the number of parent directory
entries that are created. For example, "mkdir=2" would cause up to
two parent directories to be created (i.e. "/usr/share" and
"/usr/share/oem" in the above example). A negative value such as
"mkdir=-1" may be used to create all parent directories up to the root
of the tree.
Do not create any parent directory entries by default, since doing so
would potentially cause the modes and ownership information for
existing directories to be overwritten.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
When allocating memory with a non-zero alignment offset, the free
memory block structure following the allocation may end up improperly
aligned.
Ensure that free memory blocks always remain aligned to the size of
the free memory block structure.
Ensure that the initial heap is also correctly aligned, thereby
allowing the logic for leaking undersized free memory blocks to be
omitted.
Signed-off-by: Michael Brown <mcb30@ipxe.org>