Compare commits

...

498 Commits

Author SHA1 Message Date
fde35ff003 [pci] Disable decoding while setting a BAR value
Setting the base address for a 64-bit BAR requires two separate 32-bit
writes to configuration space, and so will necessarily result in the
BAR temporarily holding an invalid partially written address.

Some hypervisors (observed on an AWS EC2 c7a.medium instance in
eu-west-2) will assume that guests will write BAR values only while
decoding is disabled, and may not rebuild MMIO mappings for the guest
if the BAR registers are written while decoding is enabled.  The
effect of this is that MMIO accesses are not routed through to the
device even though inspection from within the guest shows that every
single PCI configuration register has the correct value.  Writes to
the device will be ignored, and reads will return the all-ones pattern
that typically indicates a nonexistent device.

With the ENA network driver now using low latency transmit queues,
this results in the transmit descriptors being lost (since the MMIO
writes to BAR2 never reach the device), which in turn causes the
device to lock up as soon as the transmit doorbell is rung for the
first time.

Fix by disabling decoding of memory and I/O cycles while setting a BAR
address (as we already do while sizing a BAR), so that the invalid
partial address can never be decoded and so that hypervisors will
rebuild MMIO mappings as expected.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-10-29 23:30:52 +00:00
606e87ec7a [cloud] Display instance type in AWS EC2
Experiments suggest that the instance type is exposed via the SMBIOS
product name.  Include this information within the default output,
since it is often helpful in debugging.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-10-29 13:26:50 +00:00
0336e2987c [ena] Leave queue base address empty when creating a low latency queue
The queue base address is meaningless for a low latency queue, since
the queue entries are written directly to the on-device memory.  Any
non-zero queue base address will be safely ignored by the hardware,
but leaves open the possibility that future revisions could treat it
as an error.

Leave this field as zero, to match the behaviour of the Linux driver.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-10-28 12:27:06 +00:00
0ddd830693 [riscv] Correct page table stride calculation
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-10-27 14:22:16 +00:00
426c721e32 [librm] Correct page table stride calculation
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-10-27 14:22:16 +00:00
c8f088d4e1 [cloud] Display build architecture in AWS EC2
On some newer (7th and 8th generation) instance types, the 32-bit
build of iPXE cannot access PCI configuration space since the ECAM is
placed outside of the 32-bit address space.  The visible symptom is
that iPXE fails to detect any network devices.

The public AMIs are all now built as 64-bit binaries, but there is
nothing that prevents the building and importing of a 32-bit AMI.
There are still potentially valid use cases for 32-bit AMIs (e.g. if
planning to use the AMI only for older instance types), and so we
cannot sensibly prevent this error at build time.

Display the build architecture as part of the AWS EC2 embedded script,
to at least allow for easy identification of this particular failure
mode at run time.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-10-20 12:58:03 +01:00
416a2143af [cloud] Remove AWS public image access block only if not already unblocked
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-10-20 12:58:03 +01:00
ba1846a0d3 [cloud] Remove AWS public image access block automatically if needed
Making images public is blocked by default in new AWS regions.  Remove
this block automatically whenever creating a public image.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-10-17 14:22:21 +01:00
b2e8468219 [ena] Limit receive queue size to work around hardware bugs
Commit a801244 ("[ena] Increase receive ring size to 128 entries")
increased the receive ring size to 128 entries (while leaving the fill
level at 16), since using a smaller receive ring caused unexplained
failures on some instance types.

The original hardware bug that resulted in that commit seems to have
been fixed: experiments suggest that the original failure (observed on
a c6i.large instance in eu-west-2) will no longer reproduce when using
a receive ring containing only 16 entries (as was the case prior to
that commit).

Newer generations of the ENA hardware (observed on an m8i.large
instance in eu-south-2) seem to have a new and exciting hardware bug:
these instance types appear to use a hash of the received packet
header to determine which portion of the (out-of-order) receive ring
to use.  If that portion of the ring happens to be empty (e.g. because
only 32 entries of the 128-entry ring are filled at any one time),
then the packet will be silently dropped.

Work around this new hardware bug by reducing the receive ring size
down to the current fill level of 32 entries.  This appears to work on
all current instance types (but has not been exhaustively tested).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-10-17 13:25:05 +01:00
846c505ae9 [ena] Increase transmit queue size to match receive fill level
Avoid running out of transmit descriptors when sending TCP ACKs by
increasing the transmit queue size to match the increased received
fill level.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-10-17 13:25:05 +01:00
0ae5e25de2 [ena] Add memory barrier after writing to on-device memory
Ensure that writes to on-device memory have taken place before writing
to the doorbell register.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-10-17 12:35:23 +01:00
c296747d0e [ena] Increase receive fill level
Experiments suggest that at least some instance types (observed with
c6i.large in eu-west-2) experience high packet drop rates with only 16
receive buffers allocated.  Increase the fill level to 32 buffers.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-10-16 16:36:29 +01:00
c1badf71ca [ena] Add support for low latency transmit queues
Newer generations of the ENA hardware require the use of low latency
transmit queues, where the submission queues and the initial portion
of the transmitted packet are written to on-device memory via BAR2
instead of being read from host memory.

Detect support for low latency queues and set the placement policy
appropriately.  We attempt the use of low latency queues only if the
device reports that it supports inline headers, 128-byte entries, and
two descriptors prior to the inlined header, on the basis that we
don't care about using low latency queues on older versions of the
hardware since those versions will support normal host memory
submission queues anyway.

We reuse the redundant memory allocated for the submission queue as
the bounce buffer for constructing the descriptors and inlined packet
data, since this avoids needing a separate allocation just for the
bounce buffer.

We construct a metadata submission queue entry prior to the actual
submission queue entry, since experimentation suggests that newer
generations of the hardware require this to be present even though it
conveys no information beyond its own existence.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-10-16 16:36:29 +01:00
0d15d7f0a5 [ena] Record supported device features
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-10-16 16:36:29 +01:00
e5e371f485 [ena] Cancel uncompleted transmit buffers on close
Avoid spurious assertion failures by ensuring that references to
uncompleted transmit buffers are not retained after the device has
been closed.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-10-16 16:36:29 +01:00
dcc5d36ce5 [ena] Map the on-device memory, if present
Newer generations of the ENA hardware require the use of low latency
transmit queues, where the submission queues and the initial portion
of the transmitted packet are written to on-device memory via BAR2
instead of being read from host memory.

Prepare for this by mapping the on-device memory BAR.  As with the
register BAR, we may need to steal a base address from the upstream
PCI bridge since the BIOS on some instance types (observed with an
m8i.metal-48xl instance in eu-south-2) will fail to assign an address
to the device.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-10-15 15:55:57 +01:00
510f3e5e17 [ena] Add descriptive messages for any admin queue command failures
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-10-15 12:00:42 +01:00
3538e9c39a [pci] Record prefetchable memory window for PCI bridges
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-10-14 18:38:08 +01:00
04a61c413d [ena] Use pci_bar_set() to place device within bridge memory window
Use pci_bar_set() when we need to set a device base address (on
instance types such as c6i.metal where the BIOS fails to do so), so
that 64-bit BARs will be handled automatically.

This particular issue has so far been observed only on 6th generation
instances.  These use 32-bit BARs, and so the lack of support for
handling 64-bit BARs has not caused any observable issue.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-10-14 15:57:02 +01:00
94902ae187 [pci] Handle sizing of 64-bit BARs
Provide pci_bar_set() to handle setting the base address for a
potentially 64-bit BAR, and rewrite pci_bar_size() to correctly handle
sizing of 64-bit BARs.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-10-14 14:43:50 +01:00
e80818e4f6 [tls] Disable renegotiation unless extended master secret is used
RFC 7627 states that renegotiation becomes no longer secure under
various circumstances when the non-extended master secret is used.
The description of the precise set of circumstances is spread across
various points within the document and is not entirely clear.

Avoid a superset of the circumstances in which renegotiation
apparently becomes insecure by refusing renegotiation completely
unless the extended master secret is used.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-10-12 23:25:09 +01:00
57504353fe [tls] Refuse to resume sessions with mismatched master secret methods
RFC 7627 section 5.3 states that the client must abort the handshake
if the server attempts to resume a session where the master secret
calculation method stored in the session does not match the method
used for the connection being resumed.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-10-12 23:25:09 +01:00
ab64bc5b8d [tls] Add support for the Extended Master Secret
RFC 7627 defines the Extended Master Secret (EMS) as an alternative
calculation that uses the digest of all handshake messages rather than
just the client and server random bytes.

Add support for negotiating the Extended Master Secret extension and
performing the relevant calculation of the master secret.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-10-12 23:25:04 +01:00
d6656106e9 [tls] Generate master secret only after sending Client Key Exchange
The calculation for the extended master secret as defined in RFC 7627
relies upon the digest of all handshake messages up to and including
the Client Key Exchange.

Facilitate this calculation by generating the master secret only after
sending the Client Key Exchange message.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-10-12 22:20:13 +01:00
4f44f62402 [gve] Rearm interrupts unconditionally on every poll
Experimentation suggests that rearming the interrupt once per observed
completion is not sufficient: we still see occasional delays during
which the hardware fails to write out completions.

As described in commit d2e1e59 ("[gve] Use dummy interrupt to trigger
completion writeback in DQO mode"), there is no documentation around
the precise semantics of the interrupt rearming mechanism, and so
experimentation is the only available guide.  Switch to rearming both
TX and RX interrupts unconditionally on every poll, since this
produces better experimental results.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-10-10 13:12:19 +01:00
f5ca1de738 [gve] Use raw DMA addresses in descriptors in DQO-QPL mode
The DQO-QPL operating mode uses registered queue page lists but still
requires the raw DMA address (rather than the linear offset within the
QPL) to be provided in transmit and receive descriptors.

Set the queue page list base device address appropriately.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-10-10 12:49:26 +01:00
1cc1f1cd4f [gve] Report only packet completions for the transmit ring
The hardware reports descriptor and packet completions separately for
the transmit ring.  We currently ignore descriptor completions (since
we cannot free up the transmit buffers in the queue page list and
advance the consumer counter until the packet has also completed).

Now that transmit completions are written out immediately (instead of
being delayed until 128 bytes of completions are available), there is
no value in retaining the descriptor completions.

Omit descriptor completions entirely, and reduce the transmit fill
level back down to its original value.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-10-09 17:29:20 +01:00
d2e1e591ab [gve] Use dummy interrupt to trigger completion writeback in DQO mode
When operating in the DQO operating mode, the device will defer
writing transmit and receive completions until an entire internal
cacheline (128 bytes) is full, or until an associated interrupt is
asserted.  Since each receive descriptor is 32 bytes, this will cause
received packets to be effectively delayed until up to three further
packets have arrived.  When network traffic volumes are very low (such
as during DHCP, DNS lookups, or TCP handshakes), this typically
induces delays of up to 30 seconds and results in a very poor user
experience.

Work around this hardware problem in the same way as for the Intel
40GbE and 100GbE NICs: by enabling dummy MSI-X interrupts to trick the
hardware into believing that it needs to write out completions to host
memory.

There is no documentation around the interrupt rearming mechanism.
The value written to the interrupt doorbell does not include a
consumer counter value, and so must be relying on some undocumented
ordering constraints.  Comments in the Linux driver source suggest
that the authors believe that the device will automatically and
atomically mask an MSI-X interrupt at the point of asserting it, that
any further interrupts arriving before the doorbell is written will be
recorded in the pending bit array, and that writing the doorbell will
therefore immediately assert a new interrupt if needed.

In the absence of any documentation, choose to rearm the interrupt
once per observed completion.  This is overkill, but is less impactful
than the alternative of rearming the interrupt unconditionally on
every poll.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-10-09 17:12:20 +01:00
c2d7ddd0c2 [gve] Add missing memory barriers
Ensure that remainder of completion records are read only after
verifying the generation bit (or sequence number).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-10-09 16:42:20 +01:00
5438299649 [intelxl] Use default dummy MSI-X target address
Use the default dummy MSI-X target address that is now allocated and
configured automatically by pci_msix_enable().

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-10-09 16:37:14 +01:00
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
ce30ba14fc [gve] Select preferred operating mode
Select a preferred operating mode from those advertised as supported
by the device, falling back to the oldest known mode (GQI-QPL) if
no modes are advertised.

Since there are devices in existence that support only QPL addressing,
and since we want to minimise code size, we choose to always use a
single fixed ring buffer even when using raw DMA addressing.  Having
paid this penalty, we therefore choose to prefer QPL over RDA since
this allows the (virtual) hardware to minimise the number of page
table manipulations required.  We similarly prefer GQI over DQO since
this minimises the amount of work we have to do: in particular, the RX
descriptor ring contents can remain untouched for the lifetime of the
device and refills require only a doorbell write.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-10-06 14:04:18 +01:00
74c9fd72cf [gve] Add support for out-of-order queues
Add support for the "DQO" out-of-order transmit and receive queue
formats.  These are almost entirely different in format and usage (and
even endianness) from the original "GQI" in-order transmit and receive
queues, and arguably should belong to a completely different device
with a different PCI ID.  However, Google chose to essentially crowbar
two unrelated device models into the same virtual hardware, and so we
must handle both of these device models within the same driver.

Most of the new code exists solely to handle the differences in
descriptor sizes and formats.  Out-of-order completions are handled
via a buffer ID ring (as with other devices supporting out-of-order
completions, such as the Xen, Hyper-V, and Amazon virtual NICs).  A
slight twist is that on the transmit datapath (but not the receive
datapath) the Google NIC provides only one completion per packet
instead of one completion per descriptor, and so we must record the
list of chained buffer IDs in a separate array at the time of
transmission.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-10-06 14:04:12 +01:00
0d1ddfe42c [gve] Cancel pending transmissions when closing device
We cancel any pending transmissions when (re)starting the device since
any transmissions that were initiated before the admin queue reset
will not complete.

The network device core will also cancel any pending transmissions
after the device is closed.  If the device is closed with some
transmissions still pending and is then reopened, this will therefore
result in a stale I/O buffer being passed to netdev_tx_complete_err()
when the device is restarted.

This error has not been observed in practice since transmissions
generally complete almost immediately and it is therefore unlikely
that the device will ever be closed with transmissions still pending.
With out-of-order queues, the device seems to delay transmit
completions (with no upper time limit) until a complete batch is
available to be written out as a block of 128 bytes.  It is therefore
very likely that the device will be closed with transmissions still
pending.

Fix by ensuring that we have dropped all references to transmit I/O
buffers before returning from gve_close().

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-10-06 13:16:22 +01:00
cf53497541 [bnxt] Handle link related async events
Handle async events related to link speed change, link speed config
change, and port phy config changes.

Signed-off-by: Joseph Wong <joseph.wong@broadcom.com>
2025-10-01 16:20:23 +01:00
4508e10233 [gve] Allow for descriptor and completion lengths to vary by mode
The descriptors and completions in the DQO operating mode are not the
same sizes as the equivalent structures in the GQI operating mode.
Allow the queue stride size to vary by operating mode (and therefore
to be known only after reading the device descriptor and selecting the
operating mode).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-09-30 12:17:22 +01:00
20a489253c [gve] Rename GQI-specific data structures and constants
Rename data structures and constants that are specific to the GQI
operating mode, to allow for a cleaner separation from other operating
modes.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-09-30 11:10:20 +01:00
86b322d999 [gve] Allow for out-of-order buffer consumption
We currently assume that the buffer index is equal to the descriptor
ring index, which is correct only for in-order queues.

Out-of-order queues will include a buffer tag value that is copied
from the descriptor to the completion.  Redefine the data buffers as
being indexed by this tag value (rather than by the descriptor ring
index), and add a circular ring buffer to allow for tags to be reused
in whatever order they are released by the hardware.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-09-30 11:09:45 +01:00
b8dd3c384b [gve] Add support for raw DMA addressing
Raw DMA addressing allows the transmit and receive descriptors to
provide the DMA address of the data buffer directly, without requiring
the use of a pre-registered queue page list.  It is modelled in the
device as a magic "raw DMA" queue page list (with QPL ID 0xffffffff)
covering the whole of the DMA address space.

When using raw DMA addressing, the transmit and receive datapaths
could use the normal pattern of mapping I/O buffers directly, and
avoid copying packet data into and out of the fixed queue page list
ring buffer.  However, since we must retain support for queue page
list addressing (which requires this additional copying), we choose to
minimise code size by continuing to use the fixed ring buffer even
when using raw DMA addressing.

Add support for using raw DMA addressing by setting the queue page
list base device address appropriately, omitting the commands to
register and unregister the queue page lists, and specifying the raw
DMA QPL ID when creating the TX and RX queues.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-09-29 15:13:55 +01:00
9f554ec9d0 [gve] Add concept of a queue page list base device address
Allow for the existence of a queue page list where the base device
address is non-zero, as will be the case for the raw DMA addressing
(RDA) operating mode.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-09-29 15:13:55 +01:00
91db5b68ff [gve] Set descriptor and completion ring sizes when creating queues
The "create TX queue" and "create RX queue" commands have fields for
the descriptor and completion ring sizes, which are currently left
unpopulated since they are not required for the original GQI-QPL
operating mode.

Populate these fields, and allow for the possibility that a transmit
completion ring exists (which will be the case when using the DQO
operating mode).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-09-29 15:13:55 +01:00
048a346705 [gve] Add concept of operating mode
The GVE family supports two incompatible descriptor queue formats:

  * GQI: in-order descriptor queues
  * DQO: out-of-order descriptor queues

and two addressing modes:

  * QPL: pre-registered queue page list addressing
  * RDA: raw DMA addressing

All four combinations (GQI-QPL, GQI-RDA, DQO-QPL, and DQO-RDA) are
theoretically supported by the Linux driver, which is essentially the
only public reference provided by Google.  The original versions of
the GVE NIC supported only GQI-QPL mode, and so the iPXE driver is
written to target this mode, on the assumption that it would continue
to be supported by all models of the GVE NIC.

This assumption turns out to be incorrect: Google does not deem it
necessary to retain backwards compatibility.  Some newer machine types
(such as a4-highgpu-8g) support only the DQO-RDA operating mode.

Add a definition of operating mode, and pass this as an explicit
parameter to the "configure device resources" admin queue command.  We
choose a representation that subtracts one from the value passed in
this command, since this happens to allow us to decompose the mode
into two independent bits (one representing the use of DQO descriptor
format, one representing the use of QPL addressing).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-09-29 15:13:55 +01:00
610089b98e [gve] Remove separate concept of "packet descriptor"
The Linux driver occasionally uses the terminology "packet descriptor"
to refer to the portion of the descriptor excluding the buffer
address.  This is not a helpful separation, and merely adds
complexity.

Simplify the code by removing this artifical separation.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-09-29 15:12:54 +01:00
ee9aea7893 [gve] Parse option list returned in device descriptor
Provide space for the device to return its list of supported options.
Parse the option list and record the existence of each option in a
support bitmask.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-09-26 12:02:03 +01:00
6464f2edb8 [bnxt] Add error recovery support
Add support to advertise adapter error recovery support to the
firmware.  Implement error recovery operations if adapter fault is
detected.  Refactor memory allocation to better align with probe and
open functions.

Signed-off-by: Joseph Wong <joseph.wong@broadcom.com>
2025-09-18 13:25:07 +01:00
969ce2c559 [efi] Use current boot option as a fallback for obtaining the boot URI
Some systems (observed with a Lenovo X1) fail to populate the loaded
image device path with a Uri() component when performing a UEFI HTTP
boot, instead creating a broken loaded image device path that
represents a DHCP+TFTP boot that has not actually taken place.

If no URI is found within the loaded image device path, then fall back
to looking for a URI within the current boot option.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-08-29 12:34:17 +01:00
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
5bec2604a3 [libc] Add wcsnlen()
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-08-28 15:12:41 +01:00
61b4585e2a [efi] Drag in MNP driver whenever SNP driver is present
The chainloaded-device-only "snponly" driver already drags in support
for driving SNP, NII, and MNP devices, on the basis that the user
generally doesn't care which UEFI API is used and just wants to boot
from the same network device that was used to load iPXE.

The multi-device "snp" driver already drags in support for driving SNP
and NII devices, but does not drag in support for MNP devices.

There is essentially zero code size overhead to dragging in support
for MNP devices, since this support is always present in any iPXE
application build anyway (as part of the code to download
"autoexec.ipxe" prior to installing our own drivers).

Minimise surprise by dragging in support for MNP devices whenever
using the "snp" driver, following the same reasoning used for the
"snponly" driver.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-08-27 13:12:11 +01:00
a53ec44932 [bnxt] Update CQ doorbell type
Update completion queue doorbell to a non-arming type, since polling
is used.

Signed-off-by: Joseph Wong <joseph.wong@broadcom.com>
2025-08-13 12:36:20 +01:00
8460dc4e8f [dwgpio] Use fdt_reg() to get GPIO port numbers
DesignWare GPIO port numbers are represented as unsized single-entry
regions.  Use fdt_reg() to obtain the GPIO port number, rather than
requiring access to a region cell size specification stored in the
port group structure.

This allows the field name "regs" in the port group structure to be
repurposed to hold the I/O register base address, which then matches
the common usage in other drivers.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-08-07 15:49:12 +01:00
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
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
332241238e [digest] Treat inability to acquire an image as a fatal error
The "md5sum" and "sha1sum" commands were originally intended solely as
debugging utilities, and would return success (with a warning message)
even if the specified images did not exist.

To minimise surprise and to be consistent with other commands, treat
the inability to acquire an image as a fatal error.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-08-06 15:21:14 +01:00
6fa901530a [digest] Add "--set" option to store digest value in a setting
Allow the result of a digest calculation to be stored in a named
setting.  This allows for digest verification in scripts using e.g.:

  set expected:hexraw cb05def203386f2b33685d177d9f04e3e3d70dd4
  sha1sum --set actual 1mb
  iseq ${expected} ${actual} || goto checksum_bad

Note that digest verification alone cannot be used to set the trusted
execution status of an image.  The only way to mark an image as
trusted is to use the "imgverify" command.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-08-06 14:07:00 +01:00
f5467d69db [github] Extend sponsorship link
Add Christian Nilsson <nikize@gmail.com> as a project sponsorship
recipient, to reflect the enormous amount of time invested in
responding to issues and pull requests.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-08-06 13:31:00 +01:00
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
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
90fe3a2924 [gpio] Add a framework for GPIO controllers
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-08-05 13:54:27 +01:00
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
f7a1e9ef8e [dwmac] Show core version in debug messages
Read and display the core version immediately after mapping the MMIO
registers, to provide a basic sanity check that the registers have
been correctly mapped and the core is not held in reset.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-07-30 15:59:38 +01:00
01b1028d4e [bnxt] Remove unnecessary test_if macro
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-07-30 14:08:25 +01:00
6ca7a560a4 [bnxt] Remove unnecessary I/O macros
Remove unnecessary driver specific macros.  Use standard
pci_read_config_xxxx, pci_write_config_xxx, writel/q calls.

Signed-off-by: Joseph Wong <joseph.wong@broadcom.com>
2025-07-30 14:03:51 +01:00
be551d420e [serial] Explicitly initialise serial console UART to NULL
When debugging is enabled for the device tree or memory map parsing
code, the active serial console UART variable will be accessed during
early initialisation, before the .bss section has been zeroed.

Place this variable in the .data section (by providing an explicit
initialiser), so that reading this variable is well defined even
during early initialisation.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-07-30 13:40:36 +01:00
a814c46059 [riscv] Place explicitly zero-initialised variables in the .data section
Variables in the .bss section cannot be relied upon to have zero
values during early initialisation, before we have relocated ourselves
to somewhere suitable in RAM and zeroed the .bss section.

Place any explicitly zero-initialised variables in the .data section
rather than in .bss, so that we can rely on their values even during
this early initialisation stage.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-07-30 13:15:11 +01:00
5bda1727b4 [riscv] Allow for poisoning .bss section before early initialisation
On startup, we may be running from read-only memory, and therefore
cannot zero the .bss section (or write to the .data section) until we
have parsed the system memory map and relocated ourselves to somewhere
suitable in RAM.  The code that runs during this early initialisation
stage must be carefully written to avoid writing to the .data section
and to avoid reading from or writing to the .bss section.

Detecting code that erroneously writes to the .data or .bss sections
is relatively easy since running from read-only memory (e.g. via
QEMU's -pflash option) will immediately reveal the bug.  Detecting
code that erroneously reads from the .bss section is harder, since in
a freshly powered-on machine (or in a virtual machine) there is a high
probability that the contents of the memory will be zero even before
we explicitly zero out the section.

Add the ability to fill the .bss section with an invalid non-zero
value to expose bugs in early initialisation code that erroneously
relies upon variables in .bss before the section has been zeroed.  We
use the value 0xeb55eb55eb55eb55 ("EBSS") since this is immediately
recognisable as a value in a crash dump, and will trigger a page fault
if dereferenced since the address is in a non-canonical form.

Poisoning the .bss can be done only when the image is known to already
reside in writable memory.  It will overwrite the relocation records,
and so can be done only on a system where relocation is known to be
unnecessary (e.g. because paging is supported).  We therefore do not
enable this behaviour by default, but leave it as a configurable
option via the config/fault.h header.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-07-30 12:31:15 +01:00
e3a6e9230c [undi] Assume that legacy interrupts are broken for any PCIe device
PCI Express devices do not have physical INTx output signals, and on
modern motherboards there is unlikely to be any interrupt controller
with physical interrupt input signals.  There are multiple levels of
abstraction involved in emulating the legacy INTx interrupt mechanism:
the PCIe device sends Assert_INTx and Deassert_INTx messages, PCIe
bridges and switches must collate these virtual wires, and the root
complex must map the virtual wires into messages that can be
understood by the host's emulated 8259 PIC.

This complex chain of emulations is rarely tested on modern hardware,
since operating systems will invariably use MSI-X for PCI devices and
the I/O APIC for non-PCI devices such as the real-time clock.  Since
the legacy interrupt emulation mechanism is rarely tested, it is
frequently unreliable.  We have encountered many issues over the years
in which legacy interrupts are simply not raised as expected, even
when inspection shows that the device believes it is asserting an
interrupt and the controller believes that the interrupt is enabled.

We already maintain a list of devices that are known to fail to
generate legacy interrupts correctly.  This list is based on the PCI
vendor and device IDs, which is not necessarily a fair test since the
root cause may be a board-level misconfiguration rather than a
device-level fault.

Assume that any PCI Express device has a high chance of not being able
to raise legacy interrupts reliably.  This is a relatively intrusive
change since it will affect essentially all modern network devices,
but should hopefully fix all future issues with non-functional legacy
interrupts, without needing to constantly grow the list of known
broken devices.

If some PCI Express devices are found to fail when operated in polling
mode, then this change will need to be revisited.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-07-24 14:14:41 +01:00
65b8a6e459 [pxeprefix] Display PCI vendor and device ID in PXE startup banner
In the case of a misbehaving PXE stack, it is often useful to know the
PCI vendor and device IDs (e.g. for adding the device to the list of
devices with known broken support for generating interrupts).

The PCI vendor and device ID is already available to the prefix code,
and so can trivially be printed out.  Add this information to the PXE
prefix startup banner.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-07-23 16:11:09 +01:00
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
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
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
eca97c2ee2 [xhci] Use root hub port number to determine slot type
We currently use the downstream hub's port number to determine the
xHCI slot type for a newly connected USB device.  The downstream hub
port number is irrelevant to the xHCI controller's supported protocols
table: the relevant value is the number of the root hub port through
which the device is attached.

Fix by using the root hub port number instead of the immediate parent
hub's port number.

This bug has not previously been detected since the slot type for the
first N root hub ports will invariably be zero to indicate that these
are USB ports.  For any xHCI controller with a sufficiently large
number of root hub ports, the code would therefore end up happening to
calculate the correct slot type value despite using an incorrect port
number.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-07-18 14:58:56 +01:00
8a8904aadd [efi] Check only the non-extended WaitForKey event
The WaitForKeyEx event in EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL is
redundant: by definition it has to signal under exactly the same
conditions as the WaitForKey event in EFI_SIMPLE_TEXT_INPUT_PROTOCOL
and cannot provide any "extended" information since EFI events do not
convey any information beyond their own occurrence.

UEFI keyboard drivers such as Ps2KeyboardDxe and UsbKbDxe invariably
use a single notification function to implement both events.  The
console multiplexer driver ConSplitterDxe uses a single notification
function for both events, which ends up checking only the WaitForKey
event on the underlying console devices.  (Since all console input is
routed through the console multiplexer, this means that in practice
nothing will ever check the underlying devices' WaitForKeyEx events.)

UEFI console consumers such as the UEFI shell tend to use only the
EFI_SIMPLE_TEXT_INPUT_PROTOCOL instance provided as ConIn in the EFI
system table.  With the exception of the UEFI text editor (the "edit"
command in the UEFI shell), almost nothing bothers to open the
EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance on the same handle.

The Lenovo ThinkPad T14s Gen 5 has a very peculiar firmware bug.
Enabling the "UEFI Wi-Fi Network Boot" feature in the BIOS setup will
cause the completely unrelated WaitForKeyEx event pointer to be
overwritten with a pointer to a FAT_DIRENT structure representing the
"BOOT" directory in the EFI system partition.  This happens with 100%
repeatability.  It is not necessary to attempt to boot from Wi-Fi: it
is only necessary to have the feature enabled.  The root cause is
unknown, but is presumably an uninitialised pointer or similar
memory-related bug in Lenovo's UEFI Wi-Fi driver.

Work around this Lenovo firmware bug by checking only the WaitForKey
event, ignoring the WaitForKeyEx event even if we will subsequently
use ReadKeyStrokeEx() to read the keypress.  Since almost all other
UEFI console consumers use only WaitForKey, this ensures that we will
be using code paths that the firmware vendor is likely to have tested
at least once.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-07-16 13:20:29 +01:00
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
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
7ac4b3c6f1 [efi] Assume that vendor wireless drivers are unusable via SNP
The UEFI model for wireless network boot cannot sensibly be described
without cursing.  Commit 758a504 ("[efi] Inhibit calls to Shutdown()
for wireless SNP devices") attempts to work around some of the known
issues.

Experimentation shows that on at least some platforms (observed with a
Lenovo ThinkPad T14s Gen 5) the vendor SNP driver is broken to the
point of being unusable in anything other than the single use case
envisioned by the firwmare authors.  Doing almost anything directly
via the SNP protocol interface has a greater than 50% chance of
locking up the system.

Assume, in the absence of any evidence to the contrary so far, that
vendor SNP drivers for wireless network devices are so badly written
as to be unusable.  Refuse to even attempt to interact with these
drivers via the SNP or NII protocol interfaces.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-07-15 09:12:54 +01:00
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
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
434462a93e [riscv] Ensure coherent DMA allocations do not cross cacheline boundaries
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-07-11 13:50:41 +01:00
d539a420df [riscv] Support the standard Svpbmt extension for page-based memory types
Set the appropriate Svpbmt type bits within page table entries if the
extension is supported.  Tested only in QEMU so far, due to the lack
of availability of real hardware supporting Svpbmt.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-07-11 12:24:02 +01:00
2aacb346ca [riscv] Create coherent DMA mapping of 32-bit address space on demand
Reuse the code that creates I/O device page mappings to create the
coherent DMA mapping of the 32-bit address space on demand, instead of
constructing this mapping as part of the initial page table.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-07-11 12:23:51 +01:00
0611ddbd12 [riscv] Use 1GB pages for I/O device mappings
All 64-bit paging schemes support at least 1GB "gigapages".  Use these
to map I/O devices instead of 2MB "megapages".  This reduces the
number of consumed page table entries, increases the visual similarity
of I/O remapped addresses to the underlying physical addresses, and
opens up the possibility of reusing the code to create the coherent
DMA map of the 32-bit address space.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-07-11 12:05:52 +01:00
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
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
634d9abefb [riscv] Add optimised TCP/IP checksumming
Add a RISC-V assembly language implementation of TCP/IP checksumming,
which is around 50x faster than the generic algorithm.  The main loop
checksums aligned xlen-bit words, using almost entirely compressible
instructions and accumulating carries in a separate register to allow
folding to be deferred until after all loops have completed.

Experimentation on a C910 CPU suggests that this achieves around four
bytes per clock cycle, which is comparable to the x86 implementation.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-07-10 13:32:45 +01:00
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
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
06083d2676 [build] Handle isohybrid with xorrisofs
Generating an isohybrid image with `xorrisofs` is supposed to happen
with option `-isohybrid-gpt-basdat`, not command `isohybrid`.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-07-08 11:49:16 +01:00
e223b32511 [riscv] Support explicit cache management operations on I/O buffers
On platforms where DMA devices are not in the same coherency domain as
the CPU cache, it is necessary to be able to explicitly clean the
cache (i.e. force data to be written back to main memory) and
invalidate the cache (i.e. discard any cached data and force a
subsequent read from main memory).

Add support for cache management via the standard Zicbom extension or
the T-Head cache management operations extension, with the supported
extension detected on first use.

Support cache management operations only on I/O buffers, since these
are guaranteed to not share cachelines with other data.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-07-07 16:38:23 +01:00
6a75115a74 [riscv] Add support for detecting T-Head vendor extensions
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-07-07 16:38:23 +01:00
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
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
d75d10df16 [riscv] Create coherent DMA mapping for low 4GB of address space
Use PTEs 256-259 to create a mapping of the 32-bit physical address
space with attributes suitable for coherent DMA mappings.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-07-04 16:10:51 +01:00
3fd54e4f3a [riscv] Construct invariant portions of page table outside the loop
The page table entries for the identity map vary according to the
paging level in use, and so must be constructed within the loop used
to detect the maximum supported paging level.  Other page table
entries are invariant between paging levels, and so may be constructed
just once before entering the loop.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-07-04 16:10:51 +01:00
6bc55d65b1 [bnxt] Update supported devices array
Add support for new device IDs. Remove device IDs which were never
in use.

Signed-off-by: Joseph Wong <joseph.wong@broadcom.com>
2025-07-02 16:18:33 -07:00
0020627777 [bnxt] Update device descriptions
Use human readable strings for dev_description in PCI_ROM array.

Signed-off-by:  Joseph Wong <joseph.wong@broadcom.com>
2025-07-01 16:05:34 -07:00
126366ac47 [bnxt] Remove VLAN stripping logic
Remove logic that programs the hardware to strip out VLAN from RX
packets.  Do not drop packets due to VLAN mismatch and allow the upper
layer to decide whether to discard the packets.

Signed-off-by: Joseph Wong <joseph.wong@broadcom.com>
2025-06-29 14:21:51 +01:00
4262328c13 [github] Add sponsorship link
iPXE is released under the GNU GPL and is 100% open source software.
There are no "premium editions", no in-app advertisements, and no
hidden costs.  The fully public version published to GitHub is and
always will be the definitive and only version of iPXE.

Many large features in iPXE have been commercially funded within this
open source model, with features being published upstream as soon as
they are complete and made available for the whole world to use, not
restricted for use only by the customer funding that particular piece
of development work.

There has not to date been any funding model for smaller pieces of
work, such as occasional code review or guaranteed attention to bug
reports.  The overhead of establishing a commercial relationship is
usually too high to be worthwhile for very small units of work.

The GitHub sponsorship mechanism provides a framework for efficiently
handling small commercial requests (or individual tokens of thanks).
Add a FUNDING.yml file to provide a convenient way for anyone who
wants to support the ongoing open source development of iPXE to do so.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-06-26 16:33:58 +01:00
54392f0d70 [bnxt] Increase Tx descriptors
Increase TX and CMP descriptor counts.

Signed-off-by: Joseph Wong <joseph.wong@broadcom.com>
2025-06-25 14:05:33 +01:00
e5953ed7e6 [build] Disable use of common symbols
We no longer have any requirement for common symbols.  Disable common
symbols via the -fno-common compiler option, and simplify the test for
support of -fdata-sections (which can return a false negative when
common symbols are enabled).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-06-24 14:40:57 +01:00
8df3b96402 [build] Allow for the existence of small-data sections
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-06-24 14:40:57 +01:00
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
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
d0c02e0df8 [legacy] Allocate extra padding in receive buffers
Allow for legacy drivers that include VLAN tags or CRCs within their
received packets.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-06-24 13:41:51 +01:00
97f40c5fcc [pxe] Use a weak symbol for isapnp_read_port
Use a weak symbol for isapnp_read_port used in pxe_preboot.c, rather
than relying on a common symbol.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-06-24 13:34:41 +01:00
c33ff76d8d [fdtcon] Add basic support for FDT-based system serial console
Add support for probing a device based on the path or alias found in
the "/chosen/stdout-path" node, and using a consequently instantiated
UART as the default serial console.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-06-23 23:35:27 +01:00
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
0ed1dea7f4 [uart] Wait for 16550 UART to become idle before modifying LCR
Some implementations of 16550-compatible UARTs (e.g. the DesignWare
UART) are known to ignore writes to the line control register while
the transmitter is active.

Wait for the transmitter to become empty before attempting to write to
the line control register.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-06-23 22:56:09 +01:00
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
5d9f20bbd6 [dwuart] Add "ns16550a" compatible device ID
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-06-23 15:10:55 +01:00
d1823eb677 [riscv] Inhibit SBI console when a serial console is active
When a native serial driver is enabled for the system console device
specified via "/chosen/stdout-path", it is very likely that this will
correspond to the same physical serial port used for the SBI debug
console.

Inhibit input and output via the SBI console whenever a serial console
is active, to avoid duplicated output characters and unpredictable
input behaviour.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-06-23 15:07:07 +01:00
25fa01822b [riscv] Serialise MMIO accesses with respect to each other
iPXE drivers have been written with the implicit assumption that MMIO
writes are allowed to be posted but that an MMIO register read or
write after another MMIO register write will always observe the
effects of the first write.

For example: after having written a byte to the transmit holding
register (THR) of a 16550 UART, it is expected that any subsequent
read of the line status register (LSR) will observe a value consistent
with the occurrence of the write.

RISC-V does not seem to provide any ordering guarantees between
accesses to different registers within the same MMIO device.  Add
fences as part of the MMIO accessors to provide the assumed
guarantees.

Use "fence io, io" before each MMIO read or write to enforce full
serialisation of MMIO accesses with respect to each other.  This is
almost certainly more conservative than is strictly necessary.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-06-22 09:45:09 +01:00
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
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
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
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
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
5783a10f72 [riscv] Write SBI console output to early UART, if enabled
The early UART is an optional feature used to obtain debug output from
the prefix before iPXE is able to parse the device tree.

Extend this feature to also cover any console output that iPXE
attempts to send to the SBI console, on the basis that the purpose of
the early UART is to provide an output-only device for situations in
which there is no functional SBI console.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-06-12 12:57:26 +01:00
41e65df19d [riscv] Maximise barrier effects of memory fences
The RISC-V "fence" instruction encoding includes bits for predecessor
and successor input and output operations, separate from read and
write operations.  It is up to the CPU implementation to decide what
counts as I/O space rather than memory space for the purposes of this
instruction.

Since we do not expect fencing to be performance-critical, keep
everything as simple and reliable as possible by using the unadorned
"fence" instruction (equivalent to "fence iorw, iorw").

Add a memory clobber to ensure that the compiler does not reorder the
barrier.  (The volatile qualifier seems to already prevent reordering
in practice, but this is not guaranteed according to the compiler
documentation.)

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-06-12 12:33:46 +01:00
7e96e5f2ef [fdt] Allow paths and aliases to be terminated with separator characters
Non-permitted name characters such as a colon are sometimes used to
separate alias names or paths from additional metadata, such as the
baud rate for a UART in the "/chosen/stdout-path" property.

Support the use of such alias names and paths by allowing any
character not permitted in a property name to terminate a property or
node name match.  (This is a very relaxed matching rule that will
produce false positive matches on invalid input, but this is unlikely
to cause problems in practice.)

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-06-11 16:18:36 +01:00
1de3aef78c [bnxt] Remove TX padding
Remove unnecessary TX padding.

Signed-off-by: Joseph Wong <joseph.wong@broadcom.com>
2025-06-11 15:07:40 +01:00
3e8909cf5f [fdtmem] Limit relocation to 32-bit address space
Devices with only 32-bit DMA addressing are relatively common even on
systems with 64-bit CPUs.  Limit relocation of iPXE to 32-bit address
space so that I/O buffers and other DMA allocations will be accessible
by 32-bit devices.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-06-11 13:49:08 +01:00
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
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
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
96f5864660 [ipv4] Add self-tests for IPv4 routing
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-06-10 13:54:15 +01:00
1ae75a3bde [test] Add infrastructure for test network devices
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-06-10 13:39:57 +01:00
5b3ebf8b24 [riscv] Support T-Head CPUs using non-standard Memory Attribute Extension
Xuantie/T-Head processors such as the C910 (as used in the Sipeed
Lichee Pi 4A) use the high bits of the PTE in a very non-standard way
that is incompatible with the RISC-V specification.

As per the "Memory Attribute Extension (XTheadMae)", bits 62 and 61
represent cacheability and "bufferability" (write-back cacheability)
respectively.  If we do not enable these bits, then the processor gets
incredibly confused at the point that paging is enabled.  The symptom
is that cache lines will occasionally fail to fill, and so reads from
any address may return unrelated data from a previously read cache
line for a different address.

Work around these hardware flaws by detecting T-Head CPUs (via the
"get machine vendor ID" SBI call), then reading the vendor-specific
SXSTATUS register to determine whether or not the vendor-specific
Memory Attribute Extension has been enabled by the M-mode firmware.
If it has, then set bits 61 and 62 in each page table entry that is
used to access normal memory.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-06-02 14:19:15 +01:00
817145fe01 [riscv] Do not set executable bit in early UART page mapping
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-06-02 08:59:54 +01:00
7df005c4c6 [riscv] Add fences around early UART writes
Add a fence between the write to the UART transmit register and the
subsequent read from the transmit status register, to ensure that the
status correctly reflects the occurrence of the write.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-06-02 08:36:22 +01:00
88cffd75a9 [riscv] Zero SATP after any failed attempt to enable paging
The RISC-V specification states that "if SATP is written with an
unsupported mode, the entire write has no effect; no fields in SATP
are modified".  We currently rely on this specified behaviour when
calculating the early UART base address: if SATP has a non-zero value
then we assume that paging must be enabled.

The XuanTie C910 CPU (as used in the Lichee Pi 4A) does not conform to
this specified behaviour.  Writing SATP with an unsupported mode will
leave SATP.MODE as zero (i.e. bare physical addressing) but the write
to SATP.PPN will still take effect, leaving SATP with an illegal
non-zero value.

Work around this misbehaviour by explicitly writing zero to SATP if we
detect that the mode change has not taken effect (e.g. because the CPU
does not support the requested paging mode).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-06-02 08:09:15 +01:00
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
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
d64250918c [fdt] Add tests for device tree creation
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-30 14:21:53 +01:00
3fe321c42a [riscv] Add support for a SiFive-compatible early UART
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-27 17:24:16 +01:00
2e27d772ca [riscv] Support mapping early UARTs outside of the identity map
Some platforms (such as the Sipeed Lichee Pi 4A) choose to make early
debugging entertainingly cumbersome for the programmer.  These
platforms not only fail to provide a functional SBI debug console, but
also choose to place the UART at a physical address that cannot be
identity-mapped under the only paging model supported by the CPU.

Support such platforms by creating a virtual address mapping for the
early UART (in the 2MB megapage immediately below iPXE itself), and
using this as the UART base address whenever paging is enabled.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-27 16:31:51 +01:00
98fdfdd255 [riscv] Add support for writing prefix debug messages direct to a UART
Some platforms (such as the Sipeed Lichee Pi 4A) do not provide a
functional SBI debug console.  We can obtain early debug messages on
these systems by writing directly to the UART used by the vendor
firmware.

There is no viable way to parse the UART address from the device tree,
since the prefix debug messages occur extremely early, before the C
runtime environment is available and therefore before any information
has been parsed from the device tree.  The early UART model and
register addresses must be configured by editing config/serial.h if
needed.  (This is an acceptable limitation, since prefix debugging is
an extremely specialised use case.)

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-27 14:49:18 +01:00
2e8d45aeef [riscv] Create macros for writing characters to the debug console
Abstract out the SBI debug console calls into macros that can be
shared between print_message and print_hex_value.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-26 23:36:02 +01:00
6eb51f1a6a [riscv] Ignore riscv,isa property in favour of direct CSR testing
The riscv,isa devicetree property appears not to be fully populated on
some real-world systems.  For example, the Sipeed Lichee Pi 4A
(running the vendor U-Boot) reports itself as "rv64imafdcvsu", which
does not include the "zicntr" extension even though the time CSR is
present and functional.

Ignore the riscv,isa property and rely solely on CSR testing to
determine whether or not extensions are present.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-26 21:34:11 +01:00
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
eae9a27542 [riscv] Support mapping I/O devices outside of the identity map
With the 64-bit paging schemes (Sv39, Sv48, and Sv57), we identity-map
as much of the physical address space as is possible.  Experimentation
shows that this is not sufficient to provide access to all I/O
devices.  For example: the Sipeed Lichee Pi 4A includes a CPU that
supports only Sv39, but places I/O devices at the top of a 40-bit
address space.

Add support for creating I/O page table entries on demand to map I/O
devices, based on the existing design used for x86_64 BIOS.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-26 17:56:27 +01:00
6af4a022b2 [fdtmem] Ignore reservation regions with no fixed addresses
Do not print an error message for unused reservation regions that have
no fixed reserved address ranges.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-26 00:22:52 +01:00
56f5845b36 [riscv] Include carriage returns in libprefix.S debug messages
Support debug consoles that do not automatically convert LF to CRLF by
including the CR character within the debug message strings.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-26 00:10:30 +01:00
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
8d88870da5 [riscv] Support older SBI implementations
Fall back to attempting the legacy SBI console and shutdown calls if
the standard calls fail.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-25 10:43:39 +01:00
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
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
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
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
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
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
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
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
e056041074 [uheap] Prevent allocation of blocks with zero physical addresses
If the external heap ends up at the top of the system memory map then
leave a gap after the heap to ensure that no block ends up being
allocated with either a start or end address of zero, since this is
frequently confusing to both code and humans.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-22 16:16:14 +01:00
b9095a045a [fdtmem] Allow iPXE to be relocated to the top of the address space
Allow for relocation to a region at the very end of the physical
address space (where the next address wraps to zero).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-22 16:16:14 +01:00
a534563345 [riscv] Speed up memmove() when copying in forwards direction
Use the word-at-a-time variable-length memcpy() implementation when
performing an overlapping copy in the forwards direction, since this
is guaranteed to be safe and likely to be substantially faster than
the existing bytewise copy.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-21 16:12:56 +01:00
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
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
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
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
d15a11f3a4 [image] Use image replacement when executing extracted images
Use image_replace() to transfer execution to the extracted image,
rather than calling image_exec() directly.  This allows the original
archive image to be freed immediately if it was marked as an
automatically freeable image (e.g. via "chain --autofree").

In particular, this ensures that in the case of an archive image
containing another archive image (such as an EFI zboot kernel wrapper
image containing a gzip-compressed kernel image), the intermediate
extracted image will be freed as early as possible, since extracted
images are always marked as automatically freeable.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-20 15:34:49 +01:00
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
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
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
140ceeeb08 [riscv] Use generic external heap based on the system memory map
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-19 19:36:25 +01:00
4d560af2b0 [uheap] Add a generic external heap based on the system memory map
Add an implementation of umalloc() using the generalised model of a
heap, placing the external heap in the largest usable region obtained
from the system memory map.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-19 19:36:25 +01:00
490f1ecad8 [malloc] Allow heap to specify block and pointer alignments
Size-tracked pointers allocated via umalloc() have historically been
aligned to a page boundary, as have the edges of the hidden memory
region covering the external heap.

Allow the block and size-tracked pointer alignments to be specified as
heap configuration parameters.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-19 19:36:23 +01:00
c6ca3d3af8 [malloc] Allow for the existence of multiple heaps
Create a generic model of a heap as a list of free blocks with
optional methods for growing and shrinking the heap.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-19 19:35:56 +01:00
83449702e0 [memmap] Remove now-obsolete get_memmap()
All memory map users have been updated to use the new system memory
map API.  Remove get_memmap() and its associated definitions.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-16 18:16:41 +01:00
624d76e26d [bios] Use memmap_describe() to find an external heap location
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-16 18:04:27 +01:00
79c30b92a3 [settings] Use memmap_describe() to construct memory map settings
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-16 17:39:36 +01:00
c8d64ecd87 [bios] Use memmap_describe() to find a relocation address
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-16 17:39:29 +01:00
dbc86458e5 [comboot] Use memmap_describe() to obtain available memory
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-16 17:02:55 +01:00
d0adf3b4cc [multiboot] Use memmap_describe() to construct Multiboot memory map
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-16 17:02:55 +01:00
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
a353e70800 [memmap] Use memmap_dump_all() to dump debug memory maps
There are several places where get_memmap() is called solely to
produce debug output.  Replace these with calls to memmap_dump_all()
(which will be a no-op unless debugging is enabled).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-16 16:18:36 +01:00
3812860e39 [bios] Describe umalloc() heap as an in-use memory area
Use the concept of an in-use memory region defined as part of the
system memory map API to describe the umalloc() heap.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-16 16:18:36 +01:00
4c4c94ca09 [bios] Update to use the generic system memory map API
Provide an implementation of the system memory map API based on the
assorted BIOS INT 15 calls, and a temporary implementation of the
legacy get_memmap() function using the new API.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-16 16:18:36 +01:00
3f6ee95737 [fdtmem] Update to use the generic system memory map API
Provide an implementation of the system memory map API based on the
system device tree, excluding any memory outside the size of the
accessible physical address space and defining an in-use region to
cover the relocated copy of iPXE and the system device tree.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-16 16:18:36 +01:00
bab3d76717 [memmap] Define an API for managing the system memory map
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>
2025-05-16 16:12:15 +01:00
f6f11c101c [tests] Remove prehistoric umalloc() test code
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-15 15:47:08 +01:00
e0c4cfa81e [fdtmem] Record size of accessible physical address space
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>
2025-05-14 22:09:51 +01:00
64ad1d03c3 [bios] Rename memmap.c to int15.c
Create namespace for an architecture-independent memmap.c by renaming
the BIOS-specific memmap.c to int15.c.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-14 22:02:46 +01:00
1dd9ac13fd [bnxt] Use updated DMA APIs
Replace malloc_phys with dma_alloc, free_phys with dma_free, alloc_iob
with alloc_rx_iob, free_iob with free_rx_iob, virt_to_bus with dma or
iob_dma.  Replace dma_addr_t with physaddr_t.

Signed-off-by: Joseph Wong <joseph.wong@broadcom.com>
2025-05-14 14:21:02 +01:00
08edad7ca3 [bnxt] Return proper error codes in probe
Return the proper error codes in bnxt_init_one, to indicate the
correct return status upon completion.  Failure paths could
incorrectly indicate a success.  Correct assertion condition to check
for non-NULL pointer.

Signed-off-by: Joseph Wong <joseph.wong@broadcom.com>
2025-05-14 14:08:27 +01:00
4d39b2dcc6 [crypto] Remove redundant null pointer check
Coverity reports a spurious potential null pointer dereference in
cms_decrypt(), since the null pointer check takes place after the
pointer has already been dereferenced.  The pointer can never be null,
since it is initialised to point to cipher_null at the point that the
containing structure is allocated.

Remove the redundant null pointer check, and for symmetry ensure that
the digest and public-key algorithm pointers are similarly initialised
at the point of allocation.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-14 12:46:23 +01:00
d1c1e578af [riscv] Add a .pf32 build target for padded parallel flash images
QEMU's -pflash option requires an image that has been padded to the
exact expected size (32MB for all of the supported RISC-V virtual
machines).

Add a .pf32 build target which is simply the equivalent .sbi target
padded to 32MB in size, to simplify testing.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-13 18:25:24 +01:00
6fd927f929 [riscv] Perform a writability test before applying relocations
If paging is not supported, then we will attempt to apply dynamic
relocations to fix up the runtime addresses.  If the image is
currently executing directly from flash memory, this can result in
effectively sending an undefined sequence of commands to the flash
device, which can cause unwanted side effects.

Perform an explicit writability test before applying relocations,
using a write value chosen to be safe for at least any devices
conforming to the JEDEC Common Flash Interface (CFI01).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-13 17:42:53 +01:00
4566f59757 [riscv] Avoid potentially overwriting the scratch area during relocation
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>
2025-05-13 14:00:34 +01:00
8e38af800b [riscv] Add a .lkrn build target resembling a Linux kernel binary
On x86 BIOS, it has been useful to be able to build iPXE to resemble a
Linux kernel, so that it can be loaded by programs such as syslinux
which already know how to handle Linux kernel binaries.

Add an equivalent .lkrn build target for RISC-V SBI, allowing for
build targets such as:

  make bin-riscv64/ipxe.lkrn

  make bin-riscv64/cgem.lkrn

The Linux kernel header format allows us to specify a required length
(including uninitialised-data portions) and defines that the image
will be loaded at a fixed offset from the start of RAM.  We can
therefore use known-safe areas of memory (within our own .bss) for the
initial temporary page table and stack.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-13 13:03:08 +01:00
17fd67ce03 [riscv] Relocate to a safe physical address on startup
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>
2025-05-12 13:59:42 +01:00
3dfc88158c [riscv] Construct page tables based on link-time virtual addresses
Always construct the page tables based on the link-time address values
even if relocations have already been applied, on the assumption that
relocations will be reapplied after paging has been enabled.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-12 13:59:42 +01:00
c45dc4a55d [riscv] Allow apply_relocs() to use non-inline relocation records
The address of the compressed relocation records is currently
calculated implicitly relative to the program counter.  This requires
the relocation records to be copied as part of relocation to a new
physical address, so that they can be reapplied (if needed) after
copying iPXE to the new physical address.

Since the relocation destination will never overlap the original iPXE
image, and since the relocation records will not be needed further
after completing relocation, we can avoid the need to copy the records
by passing in a pointer to the relocation records present in the
original iPXE image.

Pass the compressed relocation record address as an explicit parameter
to apply_relocs(), rather than being implicit in the program counter.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-12 12:23:23 +01:00
420e475b11 [riscv] Return accessible physical address space size from enable_paging()
Relocation requires knowledge of the size of the accessible physical
address space, which for 64-bit CPUs will vary according to the paging
level supported by the processor.

Update enable_paging_64() and enable_paging_32() to calculate and
return the size of the accessible physical address space.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-12 11:47:25 +01:00
6fe9ce66ae [fdtmem] Add ability to parse FDT memory map for a relocation address
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>
2025-05-11 18:23:08 +01:00
2e45106c0a [riscv] Ensure that prefix_virt is aligned on an xlen boundary
Ensure that the prefix_virt dynamic relocation ends up on a suitably
aligned boundary for a compressed relocation.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-11 14:17:39 +01:00
95ede670bc [riscv] Hold virtual address offset in the thread pointer register
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>
2025-05-11 13:46:21 +01:00
f988ec09e0 [fdt] Generalise access to "reg" property
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>
2025-05-09 19:09:57 +01:00
3027864f13 [riscv] Use load and store pseudo-instructions where possible
The pattern of "load address to register" followed by "load value from
address in register" generally results in three instructions: two to
load the address and one to load the value.

This can be reduced to two instructions by allowing the assembler to
incorporate the low bits of the address within the load (or store)
instruction itself.  In the case of a store, this requires specifying
a second register that can be temporarily used to hold the high bits
of the address.  (In the case of a load, the destination register is
reused for this purpose.)

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-09 15:23:41 +01:00
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
1d58d928fe [libc] Display assertion failure message before incrementing counter
During early initialisation on some platforms, the .data and .bss
sections may not yet be writable.

Display the assertion message before attempting to increment the
assertion failure counter, since writing to the assertion counter may
trigger a CPU exception that ends up resetting the system.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-09 14:36:00 +01:00
8fe3c68b31 [riscv] Add support for disabling 64-bit and 32-bit paging
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-05-08 16:17:21 +01:00
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
0b45db3972 [uaccess] Remove redundant UNULL definition
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-28 17:36:18 +01:00
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
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
ef3827cf14 [bzimage] Use image name in debug messages
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-28 14:43:19 +01:00
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
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
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
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
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
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
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
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
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
b816b816ab [build] Fix old-style function definition
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-27 18:40:03 +01:00
58e6729cb6 [build] Fix typo in xenver.h header guard
GCC 15 helpfully reports mismatched #ifdef and #define lines in header
guards.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-27 18:40:03 +01:00
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
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
76a17b0986 [fbcon] Avoid redrawing unchanged characters when scrolling
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>
2025-04-25 13:44:18 +01:00
aa3cc56ab2 [fbcon] Remove userptr_t from framebuffer console drivers
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>
2025-04-25 12:44:28 +01:00
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
338cebfeef [pxe] Remove userptr_t from PXE file API implementation
Simplify the PXE file API implementation by assuming that all string
buffers are directly accessible via pointer dereferences.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-25 00:43:30 +01:00
8b3b4f2454 [pxe] Remove userptr_t from PXE API call dispatcher
Simplify the PXE API call dispatcher code by assuming that the PXE
parameter block is accessible via a direct pointer dereference.  This
avoids the need for the API call dispatcher to know the size of the
parameter block.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-24 23:38:50 +01:00
c1b558f59e [cmdline] Remove userptr_t from "digest" command
Simplify the implementation of the "digest" command by assuming that
the entire image data can be passed directly to digest_update().

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-24 23:24:29 +01:00
0edbc4c082 [nbi] Remove userptr_t from NBI image parsing
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-24 23:17:16 +01:00
3cb33435f5 [sdi] Remove userptr_t from SDI image parsing
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-24 23:01:25 +01:00
d7c94c4aa5 [pxe] Remove userptr_t from PXE NBP image parsing
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-24 22:46:50 +01:00
2f11f466e6 [block] Remove userptr_t from block device abstraction
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>
2025-04-24 17:11:30 +01:00
2742ed5d77 [uaccess] Remove now-obsolete memchr_user()
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-24 16:35:49 +01:00
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
8923a216b0 [ucode] Remove userptr_t from microcode image parsing
Simplify microcode image parsing by assuming that all image content is
directly accessible via pointer dereferences.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-24 14:25:00 +01:00
605cff4c84 [ucode] Remove userptr_t from microcode update mechanism
Simplify the microcode update mechanism by assuming that status
reports are accessible via direct pointer dereferences.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-24 13:48:57 +01:00
f18c1472e3 [thunderx] Replace uses of userptr_t with direct pointer dereferences
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-24 13:16:50 +01:00
8ac03b4a73 [exanic] Replace uses of userptr_t with direct pointer dereferences
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-24 10:56:21 +01:00
e8ffe2cd64 [uaccess] Remove trivial uses of userptr_t
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-24 01:40:05 +01:00
945df9b429 [gve] Replace uses of userptr_t with direct pointer dereferences
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-23 23:12:50 +01:00
839540cb95 [umalloc] Remove userptr_t from user memory allocations
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>
2025-04-23 14:43:04 +01:00
0bf0f8716a [smbios] Remove userptr_t from SMBIOS structure parsing
Simplify the SMBIOS structure parsing code by assuming that all
structure content is fully accessible via pointer dereferences.

In particular, this allows the convoluted find_smbios_structure() and
read_smbios_structure() to be combined into a single function
smbios_structure() that just returns a direct pointer to the SMBIOS
structure, with smbios_string() similarly now returning a direct
pointer to the relevant string.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-23 10:08:16 +01:00
0b3fc48fef [acpi] Remove userptr_t from ACPI table parsing
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>
2025-04-22 14:21:06 +01:00
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
b89a34b07f [image] Remove userptr_t from image definition
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-22 12:21:26 +01:00
e98b84f1b9 [crypto] Remove userptr_t from CMS verification and decryption
Simplify the CMS code by assuming that all content is fully accessible
via pointer dereferences.  This avoids the need to use fragment loops
for calculating digests and decrypting (or reencrypting) data.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-22 00:28:07 +01:00
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
04d0b2fdf9 [uaccess] Remove redundant read_user()
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-21 18:55:30 +01:00
050df80bbc [uaccess] Replace real_to_user() with real_to_virt()
Remove the intermediate concept of a user pointer from real address
conversion, leaving real_to_virt() as the directly implemented
function.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-21 18:28:56 +01:00
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
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
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
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
b65f67d443 [uaccess] Change userptr_t to be a pointer type
The original motivation for the userptr_t type was to be able to
support a pure 16-bit real-mode memory model in which a segment:offset
value could be encoded as an unsigned long, with corresponding
copy_from_user() and copy_to_user() functions used to perform
real-mode segmented memory accesses.

Since this memory model was first created almost twenty years ago, no
serious effort has been made to support a pure 16-bit mode of
operation for iPXE.  The constraints imposed by the memory model are
becoming increasingly cumbersome to work within: for example, the
parsing of devicetree structures is hugely simplified by being able to
use and return direct pointers to the names and property values.  The
devicetree code therefore relies upon virt_to_user(), which is
nominally illegal under the userptr_t memory model.

Drop support for the concept of a memory location that cannot be
reached through a straightforward pointer dereference, by redefining
userptr_t to be a simple pointer type.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-20 17:28:33 +01:00
71174e19d8 [uaccess] Add explicit casts to and from userptr_t where needed
Allow for the possibility of userptr_t becoming a pointer type by
adding explicit casts where necessary.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-20 17:21:53 +01:00
63d27c6311 [uaccess] Rename userptr_sub() to userptr_diff()
Clarify the intended usage of userptr_sub() by renaming it to
userptr_diff() (to avoid confusion with userptr_add()), and fix the
existing call sites that erroneously use userptr_sub() to subtract an
offset from a userptr_t value.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-20 17:20:30 +01:00
453acba7dc [time] Use currticks() to provide the null system time
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>
2025-04-19 13:35:23 +01:00
423cdbeb39 [riscv] Map DEL to backspace on the SBI debug console
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-19 12:20:59 +01:00
1291dc39fd [cgem] Add a driver for the Cadence GEM NIC
Add a basic driver for the Cadence GEM network interface as emulated
by QEMU when using the RISC-V "sifive_u" machine type.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-19 11:54:08 +01:00
0c482060d5 [undi] Work around broken ASUSTeK KNPA-U16 server PXE ROM
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-17 15:53:28 +01:00
758a504860 [efi] Inhibit calls to Shutdown() for wireless SNP devices
The UEFI model for wireless network configuration is somewhat
underdefined.  At the time of writing, the EDK2 "UEFI WiFi Connection
Manager" driver provides only one way to configure wireless network
credentials, which is to enter them interactively via an HII form.
Credentials are not stored (or exposed via any protocol interface),
and so any temporary disconnection from the wireless network will
inevitably leave the interface in an unusable state that cannot be
recovered without user intervention.

Experimentation shows that at least some wireless network drivers
(observed with an HP Elitebook 840 G10) will disconnect from the
wireless network when the SNP Shutdown() method is called, or if the
device is not polled sufficiently frequently to maintain its
association to the network.  We therefore inhibit calls to Shutdown()
and Stop() for any such SNP protocol interfaces, and mark our network
device as insomniac so that it will be polled even when closed.

Note that we need to inhibit not only our own calls to Shutdown() and
Stop(), but also those that will be attempted by MnpDxe when we
disconnect it from the SNP handle.  We do this by patching the
installed SNP protocol interface structure to modify the Shutdown()
and Stop() method pointers, which is ugly but unavoidable.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-17 14:42:18 +01:00
b07cc851f0 [netdevice] Add the concept of an insomniac network device
Some network devices (observed with the SNP interface to the wireless
network card on an HP Elitebook 840 G10) will stop working if they are
left for too long without being polled.

Add the concept of an insomniac network device, that must continue to
be polled even when closed.

Note that drivers are already permitted to call netdev_rx() et al even
when closed: this will already be happening for USB devices since
polling operates at the level of the whole USB bus, rather than at the
level of individual USB devices.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-17 10:42:22 +01:00
c88ebf2ac6 [efi] Allow for custom methods for disconnecting existing drivers
Allow for greater control over the process used to disconnect existing
drivers from a device handle, by converting the "exclude" field from a
simple protocol GUID to a per-driver method.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-17 10:08:54 +01:00
eeec6442d9 [dt] Provide dt_ioremap() to map device registers
Devicetree devices encode register address ranges within the "reg"
property, with the number of cells used for addresses and for sizes
determined by the #address-cells and #size-cells properties of the
immediate parent device.

Record the number of address and size cells for each device, and
provide a dt_ioremap() function to allow drivers to map a specified
range without having to directly handle the "reg" property.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-15 20:39:28 +01:00
99322fd3b3 [fdt] Add fdt_cells() to read cell-based properties such as "reg"
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>
2025-04-15 20:24:19 +01:00
2c406ec0b1 [netdevice] Add missing bus type identifier for devicetree devices
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-15 14:02:14 +01:00
424839c58a [crypto] Allow for explicit control of external trust sources
We currently disable all external trust sources (such as the UEFI
TlsCaCertificate variable) if an explicit TRUST=... parameter is
provided on the build command line.

Define an explicit TRUST_EXT build parameter that can be used to
explicitly disable external trust sources even if no TRUST=...
parameter is provided, or to explicitly enable external trust sources
even if an explicit TRUST=... parameter is provided.  For example:

   # Default trusted root certificate, disable external sources
   make TRUST_EXT=0

   # Explicit trusted root certificate, enable external sources
   make TRUST=custom.crt TRUST_EXT=1

If no TRUST_EXT parameter is specified, then continue to default to
disabling external trust sources if an explicit TRUST=... parameter is
provided, to maintain backwards compatibility with existing build
command lines.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-15 13:22:00 +01:00
37e9f785ba [dt] Add basic concept of a devicetree bus
Add a basic model for devices instantiated by parsing the system
flattened device tree, with drivers matched via the "compatible"
property for any non-root node.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-14 14:52:51 +01:00
d462aeb0ca [fdt] Remove concept of a device tree cursor
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>
2025-04-14 14:38:40 +01:00
b1125007ca [fdt] Add basic tests for reading values from a flattened device tree
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-14 14:20:31 +01:00
db49346177 [fdt] Avoid temporarily modifying path during path lookup
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-14 13:53:09 +01:00
c887de208f [fdt] Provide fdt_strings() to read string list properties
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-14 11:32:17 +01:00
69af6f0c30 [fdt] Allow for trailing slashes in path lookups
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>
2025-04-14 11:26:49 +01:00
96dfaa7e7a [crypto] Switch to using python-asn1crypto instead of python-asn1
Version 3.0.0 of python-asn1 has a serious defect that causes it to
generate invalid DER.

Fix by switching to the asn1crypto module, which also allows for
simpler code to be used.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-11 12:40:22 +01:00
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
d853448887 [fdt] Identify free space (if any) at end of parsed tree
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-04-01 13:08:41 +01:00
0a48bb3214 [x509] Ensure certificate remains valid during x509_append()
The allocation of memory for the certificate chain link may cause the
certificate itself to be freed by the cache discarder, if the only
current reference to the certificate is held by the certificate store
and the system runs out of memory during the call to malloc().

Ensure that this cannot happen by taking out a temporary additional
reference to the certificate within x509_append(), rather than
requiring the caller to do so.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-31 18:05:11 +01:00
a289b4b8c2 [tls] Support fragmentation of transmitted records
Large transmitted records may arise if we have long client certificate
chains or if a client sends a large block of data (such as a large
HTTP POST payload).  Fragment records as needed to comply with the
value that we advertise via the max_fragment_length extension.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-31 16:36:33 +01:00
f115cfcf99 [tls] Send an empty client certificate chain if we have no certificate
RFC5246 states that "a client MAY send no certificates if it does not
have an appropriate certificate to send in response to the server's
authentication request".  This use case may arise when the server is
using optional client certificate verification and iPXE has not been
provided with a client certificate to use.

Treat the absence of a suitable client certificate as a non-fatal
condition and send a Certificate message containing no certificates as
permitted by RFC5246.

Reported-by: Alexandre Ravey <alexandre@voilab.ch>
Originally-implemented-by: Alexandre Ravey <alexandre@voilab.ch>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-31 14:33:16 +01:00
5818529f39 [iobuf] Limit automatic I/O buffer alignment to page size
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>
2025-03-31 13:39:58 +01:00
7fe467a46d [tls] Encrypt data in place to reduce memory usage
Provide a custom xfer_alloc_iob() handler to ensure that transmit I/O
buffers contain sufficient headroom for the TLS record header and
record initialisation vector, and sufficient tailroom for the MAC,
block cipher padding, and authentication tag.  This allows us to use
in-place encryption for the actual data within the I/O buffer, which
essentially halves the amount of memory that needs to be allocated for
a TLS data transmission.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-31 12:42:07 +01:00
d92551a320 [xfer] Use xfer_alloc_iob() for transmit I/O buffers on stream sockets
Datagram sockets such as UDP, ICMP, and fibre channel tend to provide
a custom xfer_alloc_iob() handler to ensure that transmit I/O buffers
contain sufficient headroom to accommodate any required protocol
headers.

Stream sockets such as TCP and TLS do not typically provide a custom
xfer_alloc_iob() handler at present.  The default handler simply calls
alloc_iob(), and so stream socket consumers can therefore get away
with using alloc_iob() rather than xfer_alloc_iob().

Fix the HTTP and ONC RPC protocols to use xfer_alloc_iob() where
relevant, in order to operate correctly if the underlying stream
socket chooses to provide a custom xfer_alloc_iob() handler.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-30 21:47:34 +01:00
3937c893ae [isa] Disable legacy ISA device probing by default
Legacy ISA device probing involves poking at various I/O addresses to
guess whether or not a particular device is present.

Actual legacy ISA cards are essentially nonexistent by now, but the
probed I/O addresses have a habit of being reused for various
OEM-specific functions.  This can cause some very undesirable side
effects.  For example, probing for the "ne2k_isa" driver on an HP
Elitebook 840 G10 will cause the system to lock up in a way that
requires two cold reboots to recover.

Enable ISA_PROBE_ONLY in config/isa.h by default.  This limits ISA
probing to use only the addresses specified in ISA_PROBE_ADDRS, which
is empty by default, and so effectively disables ISA probing.  The
vanishingly small number of users who require ISA probing can simply
adjust this configuration in config/local/isa.h.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-29 23:01:21 +00:00
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
18dbd05ed5 [efi] Check correct return value from efi_pxe_find()
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-29 22:03:32 +00:00
4bcaa3d380 [efi] Disconnect existing drivers on a per-protocol basis
UEFI does not provide a direct method to disconnect the existing
driver of a specific protocol from a handle.  We currently use
DisconnectController() to remove all drivers from a handle that we
want to drive ourselves, and then rely on recursion in the call to
ConnectController() to reconnect any drivers that did not need to be
disconnected in the first place.

Experience shows that OEMs tend not to ever test the disconnection
code paths in their UEFI drivers, and it is common to find drivers
that refuse to disconnect, fail to close opened handles, fail to
function correctly after reconnection, or lock up the entire system.

Implement a more selective form of disconnection, in which we use
OpenProtocolInformation() to identify the driver associated with a
specific protocol, and then disconnect only that driver.

Perform disconnections in reverse order of attachment priority, since
this is the order likely to minimise the number of cascaded implicit
disconnections.

This allows our MNP driver to avoid performing any disconnections at
all, since it does not require exclusive access to the MNP protocol.
It also avoids performing unnecessary disconnections and reconnections
of unrelated drivers such as the "UEFI WiFi Connection Manager" that
attaches to wireless network interfaces in order to manage wireless
network associations.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-29 20:26:06 +00:00
7737fec5c6 [efi] Define an attachment priority order for EFI drivers
Define an ordering for internal EFI drivers on the basis of how close
the driver is to the hardware, and attempt to start drivers in this
order.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-29 18:44:34 +00:00
be33224754 [efi] Show all drivers claiming support for a handle in debug messages
UEFI assumes in several places that an image installs only a single
driver binding protocol instance, and that this is installed on the
image handle itself.  We therefore provide a single driver binding
protocol instance, which delegates to the various internal drivers
(for EFI_PCI_IO_PROTOCOL, EFI_USB_IO_PROTOCOL, etc) as appropriate.

The debug messages produced by our Supported() method can end up
slightly misleading, since they will report only the first internal
driver that claims support for a device.  In the common case of the
all-drivers build, there may be multiple drivers that claim support
for the same handle: for example, the PCI, NII, SNP, and MNP drivers
are all likely to initially find the protocols that they need on the
same device handle.

Report all internal drivers that claim support for a device, to avoid
confusing debug messages.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-29 18:44:34 +00:00
ea5762d9d0 [efi] Return success from Stop() if driver is already stopped
Return success if asked to stop driving a device that we are not
currently driving.  This avoids propagating spurious errors to an
external caller of DisconnectController().

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-29 18:44:34 +00:00
7adce3a13e [efi] Add various well-known GUIDs encountered in WiFi boot
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-28 21:01:42 +00:00
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
761f43ce12 [fdt] Provide the ability to create a device tree for a booted OS
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>
2025-03-28 15:29:51 +00:00
666929e311 [efi] Create a copy of the system flattened device tree, if present
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>
2025-03-28 15:29:20 +00:00
3860313dd5 [fdt] Allow for parsing device trees where the length is known in advance
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>
2025-03-28 15:11:39 +00:00
2399c79980 [fdt] Allow for the existence of multiple device trees
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>
2025-03-28 14:14:32 +00:00
09fbebc084 [fdt] Add the "fdt" command
Allow a Flattened Device Tree blob (DTB) to be provided to a booted
operating system using a script such as:

  #!ipxe
  kernel /images/vmlinuz console=ttyAMA0
  initrd /images/initrd.img
  fdt /images/rk3566-radxa-zero-3e.dtb
  boot

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-27 15:36:39 +00:00
cfd93465ec [fdt] Add the concept of an FDT image
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>
2025-03-27 15:36:39 +00:00
98f86b4d0a [efi] Add support for installing EFI configuration tables
Add the ability to install and uninstall arbitrary EFI configuration
tables.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-27 15:36:39 +00:00
f0caf90a72 [efi] Add flattened device tree header and GUID definitions
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-27 14:48:04 +00:00
ec8c5a5fbb [efi] Add ACPI and SMBIOS tables as well-known GUIDs
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-27 14:48:04 +00:00
0b606221cb [undi] Ensure forward progress is made even if UNDI IRQ is stuck
If the UNDI interrupt remains constantly asserted (e.g. because the
BIOS has enabled interrupts for an unrelated device sharing the same
IRQ, or because of bugs in the OEM UNDI driver), then we may get stuck
in an interrupt storm.

We cannot safely chain to the previous interrupt handler (which could
plausibly handle an unrelated device interrupt) since there is no
well-defined behaviour for previous interrupt handlers.  We have
observed BIOSes to provide default interrupt handlers that variously
do nothing, send EOI, disable the IRQ, or crash the system.

Fix by disabling the UNDI interrupt whenever our handler is triggered,
and rearm it as needed when polling the network device.  This ensures
that forward progress continues to be made even if something causes
the interrupt to be constantly asserted.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-26 14:56:20 +00:00
4134280bcd [pxeprefix] Ensure that UNDI IRQ is disabled before starting iPXE
When using the undionly.kkpxe binary (which is never recommended), the
UNDI interrupt may still be enabled when iPXE starts up.  If the PXE
base code interrupt handler is not well-behaved, this can result in
undefined behaviour when interrupts are first enabled (e.g. for
entropy gathering, or for allowing the timer tick to occur).

Fix by detecting and disabling the UNDI interrupt during the prefix
code.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-26 14:56:13 +00:00
e8365f7a51 [pxeprefix] Work around missing type values from PXENV_UNDI_GET_NIC_TYPE
The implementation of PXENV_UNDI_GET_NIC_TYPE in some PXE ROMs
(observed with an Intel X710 ROM in a Dell PowerEdge R6515) will fail
to write the NicType byte, leaving it uninitialised.

Prepopulate the NicType byte with a highly unlikely value as a
sentinel to allow us to detect this, and assume that any such devices
are overwhelmingly likely to be PCI devices.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-26 12:02:27 +00:00
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
37897fbd40 [efi] Eliminate uses of HandleProtocol()
It is now simpler to use efi_open() than to use HandleProtocol() to
obtain an ephemeral protocol instance.  Remove all remaining uses of
HandleProtocol() to simplify the code.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-24 14:25:10 +00:00
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
5a5e2a1dae [efi] Use efi_open_unsafe() for all explicitly unsafe protocol opens
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-24 13:19:26 +00:00
9dd30f11f7 [efi] Use efi_open_by_driver() for all by-driver protocol opens
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-24 13:19:26 +00:00
4561a03766 [efi] Use efi_open_by_child() for all by-child protocol opens
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-24 13:19:26 +00:00
358db15612 [efi] Create safe wrappers for OpenProtocol() and CloseProtocol()
The UEFI model for opening and closing protocols is broken by design
and cannot be repaired.

Calling OpenProtocol() to obtain a protocol interface pointer does
not, in general, provide any guarantees about the lifetime of that
pointer.  It is theoretically possible that the pointer has already
become invalid by the time that OpenProtocol() returns the pointer to
its caller.  (This can happen when a USB device is physically removed,
for example.)

Various UEFI design flaws make it occasionally necessary to hold on to
a protocol interface pointer despite the total lack of guarantees that
the pointer will remain valid.

The UEFI driver model overloads the semantics of OpenProtocol() to
accommodate the use cases of recording a driver attachment (which is
modelled as opening a protocol with EFI_OPEN_PROTOCOL_BY_DRIVER
attributes) and recording the existence of a related child controller
(which is modelled as opening a protocol with
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER attributes).

The parameters defined for CloseProtocol() are not sufficient to allow
the implementation to precisely identify the matching call to
OpenProtocol().  While the UEFI model appears to allow for matched
open and close pairs, this is merely an illusion.  Calling
CloseProtocol() will delete *all* matching records in the protocol
open information tables.

Since the parameters defined for CloseProtocol() do not include the
attributes passed to OpenProtocol(), this means that a matched
open/close pair using EFI_OPEN_PROTOCOL_GET_PROTOCOL can inadvertently
end up deleting the record that defines a driver attachment or the
existence of a child controller.  This in turn can cause some very
unexpected side effects, such as allowing other UEFI drivers to start
controlling hardware to which iPXE believes it has exclusive access.
This rarely ends well.

To prevent this kind of inadvertent deletion, we establish a
convention for four different types of protocol opening:

- ephemeral opens: always opened with ControllerHandle = NULL

- unsafe opens: always opened with ControllerHandle = AgentHandle

- by-driver opens: always opened with ControllerHandle = Handle

- by-child opens: always opened with ControllerHandle != Handle

This convention ensures that the four types of open never overlap
within the set of parameters defined for CloseProtocol(), and so a
close of one type cannot inadvertently delete the record corresponding
to a different type.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-24 13:19:23 +00:00
48d1680127 [efi] Remove the efipci_open() and efipci_close() wrappers
In preparation for formalising the way that EFI protocols are opened
across the codebase, remove the efipci_open() wrapper.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-24 12:05:30 +00:00
3283885326 [efi] Avoid function name near-collision
We currently have both efipci_info() and efi_pci_info() serving
different but related purposes.  Rename the latter to reduce
confusion.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-23 22:29:30 +00:00
331bbf5075 [efi] Remove spurious close of SNP device parent's device path
Commit e727f57 ("[efi] Include a copy of the device path within struct
efi_device") neglected to delete the closure of the parent's device
path from the success code path in efi_snp_probe().

Reduce confusion by removing this (harmless) additional close.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-23 18:24:10 +00:00
8249bbc098 [efi] Use driver name only from driver binding handles in debug messages
Some non-driver handles may have an installed component name protocol.
In particular, iPXE itself installs these protocols on its SNP device
handles, to simplify the process of delegating GetControllerName()
from our single-instance driver binding protocol to whatever child
controllers the relevant EFI driver may have installed.

For non-driver handles, the device path is more useful as debugging
information than the driver name.  Limit the use of the component name
protocols to handles with a driver binding protocol installed, so that
we will end up using the device path for non-driver handles such as
the SNP device.

Continue to prefer the driver name to the device path for handles with
a driver binding protocol installed, since these will generally map to
things we are likely to conceptualise as drivers rather than as
devices.

Note that we deliberately do not use GetControllerName() to attempt to
get a human-readable name for a controller handle.  In the normal
course of events, iPXE is likely to disconnect at least some existing
drivers from their controller handles.  This would cause the name
obtained via GetControllerName() to change.  By using the device path
instead, we ensure that the debug message name remains the same even
when the driver controlling the handle is changed.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-21 17:15:38 +00:00
02ecb23d10 [efi] Get veto candidate driver name via either component name protocol
Attempt to get the veto candidate driver name from both the current
and obsolete versions of the component name protocol.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-20 15:17:08 +00:00
756e3907fd [efi] Get veto candidate driver name from image handle
Allow for drivers that do not install the driver binding protocol on
the image handle by opening the component name protocol on the driver
binding's ImageHandle rather than on the driver handle itself.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-20 14:39:52 +00:00
be5bf0aa7a [efi] Show image address range in veto debug messages
When hunting down a misbehaving OEM driver to add it to the veto list,
it can be very useful to know the address ranges used by each driver.
Add this information to the verbose debug messages.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-20 14:30:34 +00:00
5d64469a9e [efi] Prefer driver name to device path for debug messages
The driver name is usually more informative for debug messages than
the device path from which a driver was loaded.  Try using the various
mechanisms for obtaining a driver name before trying the device path.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-20 14:20:57 +00:00
7cda3dbf94 [efi] Attempt to retrieve driver name from image handle for debug messages
Not all drivers will install the driver binding protocol on the image
handle.  Accommodate these drivers by attempting to retrieve the
driver name via the component name protocol(s) located on the driver
binding's ImageHandle, as well as on the driver handle itself.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-20 14:20:36 +00:00
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
f68c8b09e3 [efi] Fix debug wrappers for CloseEvent() and CheckEvent()
The debug wrappers for CloseEvent() and CheckEvent() are currently
both calling SignalEvent() instead (presumably due to copy-paste
errors).  Astonishingly, this has generally not prevented a successful
boot in the (very rare) case that DEBUG=efi_wrap is enabled.

Fix the wrappers to call the intended functions.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-19 16:20:27 +00:00
37ea181d8b [efi] Ignore path separator characters in virtual filenames
The virtual filesystem that we provide to expose downloaded images
will erroneously interpret filenames with redundant path separators
such as ".\filename" as an attempt to open the directory, rather than
an attempt to open "filename".

This shows up most obviously when chainloading from one iPXE into
another iPXE, when the inner iPXE may end up attempting to open
".\autoexec.ipxe" from the outer iPXE's virtual filesystem.  (The
erroneously opened file will have a zero length and will therefore be
ignored, but is still confusing.)

Fix by discarding any dot or backslash characters after a potential
initial backslash.  This is very liberal and will accept some
syntactically invalid paths, but this is acceptable since our virtual
filesystem does not implement directories anyway.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-18 16:21:10 +00:00
6e4196baff [efi] Prescroll the display after a failed wrapped ExitBootServices() call
On some systems (observed with an HP Elitebook 840 G10), writing
console output that happens to cause the display to scroll will modify
the system memory map.  This causes builds with DEBUG=efi_wrap to
typically fail to boot, since the debug output from the wrapped
ExitBootServices() call itself is sufficient to change the memory map
and therefore cause ExitBootServices() to fail due to an invalid
memory map key.

Work around these UEFI firmware bugs by prescrolling the display after
a failed ExitBootServices() attempt, in order to minimise the chance
that further scrolling will happen during the subsequent attempt.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-18 14:13:56 +00:00
8ea8411f0d [efi] Add EFI_RNG_PROTOCOL_GUID as a well-known GUID
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-18 12:49:19 +00:00
42a29d5681 [crypto] Update cmsdetach to work with python-asn1 version 3.0.0
The python-asn1 documentation indicates that end of file may be
detected either by obtaining a True value from .eof() or by obtaining
a None value from .peek(), but does not mention any way to detect the
end of a constructed tag (rather than the end of the overall file).
We currently use .eof() to detect the end of a constructed tag, based
on the observed behaviour of the library.

The behaviour of .eof() changed between versions 2.8.0 and 3.0.0, such
that .eof() no longer returns True at the end of a constructed tag.

Switch to testing for a None value returned from .peek() to determine
when we have reached the end of a constructed tag, since this works on
both newer and older versions.

Continue to treat .eof() as a necessary but not sufficient condition
for reaching the overall end of file, to maintain compatibility with
older versions.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-17 11:48:06 +00:00
829e2d1f29 [rng] Restore state of IRQ 8 and PIE when disabling entropy gathering
Legacy IRQ 8 appears to be enabled by default on some platforms.  If
iPXE selects the RTC entropy source, this will currently result in the
RTC IRQ 8 being unconditionally disabled.  This can break assumptions
made by BIOSes or subsequent bootloaders: in particular, the FreeBSD
loader may lock up at the point of starting its default 10-second
countdown when it calls INT 15,86.

Fix by restoring the previous state of IRQ 8 instead of disabling it
unconditionally.  Note that we do not need to disable IRQ 8 around the
point of hooking (or unhooking) the ISR, since this code will be
executing in iPXE's normal state of having interrupts disabled anyway.

Also restore the previous state of the RTC periodic interrupt enable,
rather than disabling it unconditionally.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-14 15:08:05 +00:00
8840de4096 [pic8259] Return previous state when enabling or disabling IRQs
Return the previous interrupt enabled state from enable_irq() and
disable_irq(), to allow callers to more easily restore this state.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-14 14:09:26 +00:00
d1133956d1 [contrib] Update bochsrc.txt to work with current versions
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-14 12:46:02 +00:00
ddc2d928d2 [efi] Accept and trust CA certificates in the TlsCaCertificates variable
UEFI's built-in HTTPS boot mechanism requires the trusted CA
certificates to be provided via the TlsCaCertificates variable.
(There is no equivalent of the iPXE cross-signing mechanism, so it is
not possible for UEFI to automatically use public CA certificates.)

Users who have configured UEFI HTTPS boot to use a custom root of
trust (e.g. a private CA certificate) may find it useful to have iPXE
automatically pick up and use this same root of trust, so that iPXE
can seamlessly fetch files via HTTPS from the same servers that were
trusted by UEFI HTTPS boot, in addition to servers that iPXE can
validate through other means such as cross-signed certificates.

Parse the TlsCaCertificates variable at startup, add any certificates
to the certificate store, and mark these certificates as trusted.

There are no access restrictions on modifying the TlsCaCertificates
variable: anybody with access to write UEFI variables is permitted to
change the root of trust.  The UEFI security model assumes that anyone
with access to run code prior to ExitBootServices() or with access to
modify UEFI variables from within a loaded operating system is
supposed to be able to change the system's root of trust for TLS.

Any certificates parsed from TlsCaCertificates will show up in the
output of "certstat", and may be discarded using "certfree" if
unwanted.

Support for parsing TlsCaCertificates is enabled by default in EFI
builds, but may be disabled in config/general.h if needed.

As with the ${trust} setting, the contents of the TlsCaCertificates
variable will be ignored if iPXE has been compiled with an explicit
root of trust by specifying TRUST=... on the build command line.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-13 15:54:43 +00:00
aa49ce5b1d [efi] Add TLS authentication header and GUID definitions
Add the TlsAuthentication.h header from EDK2's NetworkPkg, along with
a GUID definition for EFI_TLS_CA_CERTIFICATE_GUID.

It is unclear whether or not the TlsCaCertificate variable is intended
to be a UEFI standard.  Its presence in NetworkPkg (rather than
MdePkg) suggests not, but the choice of EFI_TLS_CA_CERTIFICATE_GUID
(rather than e.g. EDKII_TLS_CA_CERTIFICATE_GUID) suggests that it is
intended to be included in future versions of the standard.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-13 14:04:41 +00:00
2a901a33df [efi] Add EFI_GLOBAL_VARIABLE as a well-known GUID
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-13 14:04:40 +00:00
da3024d257 [cpio] Allow for the construction of pure directories
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>
2025-03-12 14:32:41 +00:00
d6ee9a9242 [cpio] Fix calculation of name lengths in CPIO headers
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>
2025-03-12 14:27:44 +00:00
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
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
011c778f06 [efi] Allow efi_guid_ntoa() to be used in non-EFI builds
The debug message transcription of well-known EFI GUIDs does not
require any EFI boot services calls.  Move this code from efi_debug.c
to efi_guid.c, to allow it to be linked in to non-EFI builds.

We continue to rely on linker garbage collection to ensure that the
code is omitted completely from any non-debug builds.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-11 11:52:37 +00:00
8706ae36d3 [efi] Add EFI_SIGNATURE_LIST header and GUID definitions
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-10 12:34:35 +00:00
a3ede10788 [efi] Update to current EDK2 headers
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-10 12:34:35 +00:00
32d706a9ff [build] Use -fshort-wchar when building EFI host utilities
The EFI host utilities (such as elf2efi64, efirom, etc) include the
EDK2 headers, which include static assertions to ensure that they are
built with -fshort-wchar enabled.  When building the host utilities,
we currently bypass these assertions by defining MDE_CPU_EBC.  The EBC
compiler apparently does not support static assertions, and defining
MDE_CPU_EBC therefore causes EDK2's Base.h to define STATIC_ASSERT()
as a no-op.

Newer versions of the EDK2 headers omit the check for MDE_CPU_EBC (and
will presumably therefore fail to build with the EBC compiler).  This
causes our host utility builds to fail since the static assertion now
detects that we are building with the host's default ABI (i.e. without
enabling -fshort-wchar).

Fix by enabling -fshort-wchar when building EFI host utilities.  This
produces binaries that are technically incompatible with the host ABI.
However, since our host utilities never handle any wide-character
strings, this nominal ABI incompatiblity has no effect.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-10 12:34:35 +00:00
82fac51626 [efi] Mark UsbHostController.h as a non-imported header
The UsbHostController.h header has been removed from the EDK2 codebase
since it was never defined in a released UEFI specification.  However,
we may still encounter it in the wild and so it is useful to retain
the GUID and the corresponding protocol name for debug messages.

Add an iPXE include guard to this file so that the EDK2 header import
script will no longer attempt to import it from the EDK2 tree.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-03-10 11:15:04 +00:00
be3a78eaf8 [lkrnprefix] Support a longer version string
The bzImage specification allows two bytes for the setup code jump
instruction at offset 0x200, which limits its relative offset to +0x7f
bytes.  This currently imposes an upper limit on the length of the
version string, which currently precedes the setup code.

Fix by moving the version string to the .prefix.data section, so that
it no longer affects the placement of the setup code.

Originally-fixed-by: Miao Wang <shankerwangmiao@gmail.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-02-28 11:32:42 +00:00
12ea8c4074 [cpio] Allow for construction of parent directories as needed
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>
2025-02-24 14:37:26 +00:00
e7595fe88d [menu] Allow a post-activity timeout to be defined
Allow the "--retimeout" option to be used to specify a timeout value
that will be (re)applied after each keypress activity.  This allows
script authors to ensure that a single (potentially accidental)
keypress will not pause the boot process indefinitely.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-02-19 13:12:29 +00:00
ccd6200549 [crypto] Start up RBG on demand if needed
The ANS X9.82 specification implicitly assumes that the RBG_Startup
function will be called before it is needed, and includes checks to
make sure that Generate_function fails if this has not happened.
However, there is no well-defined point at which the RBG_Startup
function is to be called: it's just assumed that this happens as part
of system startup.

We currently call RBG_Startup to instantiate the DRBG as an iPXE
startup function, with the corresponding shutdown function
uninstantiating the DRBG.  This works for most use cases, and avoids
an otherwise unexpected user-visible delay when a caller first
attempts to use the DRBG (e.g. by attempting an HTTPS download).

The download of autoexec.ipxe for UEFI is triggered by the EFI root
bus probe in efi_probe().  Both the root bus probe and the RBG startup
function run at STARTUP_NORMAL, so there is no defined ordering
between them.  If the base URI for autoexec.ipxe uses HTTPS, then this
may cause random bits to be requested before the RBG has been started.

Extend the logic in rbg_generate() to automatically start up the RBG
if startup has not already been attempted.  If startup fails
(e.g. because the entropy source is broken), then do not automatically
retry since this could result in extremely long delays waiting for
entropy that will never arrive.

Reported-by: Michael Niehaus <niehaus@live.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-02-18 15:38:54 +00:00
b35300fc67 [efi] Increase download timeout for autoexec.ipxe
In almost all cases, the download timeout for autoexec.ipxe is
irrelevant: the operation will either succeed or fail relatively
quickly (e.g. due to a nonexistent file).  The overall download
timeout exists only to ensure that an unattended or headless system
will not wait indefinitely in the case of a degenerate network
response (e.g. an HTTP server that returns an endless trickle of data
using chunked transfer encoding without ever reaching the end of the
file).

The current download timeout is too short if PeerDist content encoding
is enabled, since the overall download will abort before the first
peer discovery attempt has completed, and without allowing sufficient
time for an origin server range request.

The single timeout value is currently used for both the download
timeout and the sync timeout.  The latter timeout exists only to allow
network communication to be gracefully quiesced before removing the
temporary MNP network device, and may safely be shortened without
affecting functionality.

Fix by increasing the download timeout from two seconds to 30 seconds,
and defining a separate one-second timeout for the sync operation.

Reported-by: Michael Niehaus <niehaus@live.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-02-17 13:30:27 +00:00
8e6b914c53 [crypto] Support direct reduction only for Montgomery constant R^2 mod N
The only remaining use case for direct reduction (outside of the unit
tests) is in calculating the constant R^2 mod N used during Montgomery
multiplication.

The current implementation of direct reduction requires a writable
copy of the modulus (to allow for shifting), and both the modulus and
the result buffer must be padded to be large enough to hold (R^2 - N),
which is twice the size of the actual values involved.

For the special case of reducing R^2 mod N (or any power of two mod
N), we can run the same algorithm without needing either a writable
copy of the modulus or a padded result buffer.  The working state
required is only two bits larger than the result buffer, and these
additional bits may be held in local variables instead.

Rewrite bigint_reduce() to handle only this use case, and remove the
no longer necessary uses of double-sized big integers.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-02-14 13:03:20 +00:00
5056e8ad93 [crypto] Expose shifted out bit from big integer shifts
Expose the bit shifted out as a result of shifting a big integer left
or right.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-02-13 15:25:35 +00:00
bd90abf487 [bnxt] Allocate TX rings with firmware input
Use queue_id value retrieved from firmware unconditionally when
allocating TX rings.

Signed-off by: Joseph Wong <joseph.wong@broadcom.com>
2025-02-07 09:26:15 +00:00
77cc3ed108 [malloc] Ensure free memory blocks remain aligned
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>
2025-02-03 14:43:03 +00:00
6f076efa65 [malloc] Clean up debug messages
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-02-03 14:41:35 +00:00
c85de315a6 [crypto] Add definitions and tests for the NIST P-384 elliptic curve
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-01-30 15:35:34 +00:00
bc5f3dbe3e [crypto] Add definitions and tests for the NIST P-256 elliptic curve
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-01-28 16:57:40 +00:00
be9ce49076 [crypto] Add support for Weierstrass elliptic curve point multiplication
The NIST elliptic curves are Weierstrass curves and have the form

  y^2 = x^3 + ax + b

with each curve defined by its field prime, the constants "a" and "b",
and a generator base point.

Implement a constant-time algorithm for point addition, based upon
Algorithm 1 from "Complete addition formulas for prime order elliptic
curves" (Joost Renes, Craig Costello, and Lejla Batina), and use this
as a Montgomery ladder commutative operation to perform constant-time
point multiplication.

The code for point addition is implemented using a custom bytecode
interpreter with 16-bit instructions, since this results in
substantially smaller code than compiling the somewhat lengthy
sequence of arithmetic operations directly.  Values are calculated
modulo small multiples of the field prime in order to allow for the
use of relaxed Montgomery reduction.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-01-28 16:32:12 +00:00
66b5d1ec81 [crypto] Add a generic implementation of a Montgomery ladder
The Montgomery ladder may be used to perform any operation that is
isomorphic to exponentiation, i.e. to compute the result

    r = g^e = g * g * g * g * .... * g

for an arbitrary commutative operation "*", base or generator "g", and
exponent "e".

Implement a generic Montgomery ladder for use by both modular
exponentiation and elliptic curve point multiplication (both of which
are isomorphic to exponentiation).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-01-28 14:47:52 +00:00
c2f21a2185 [test] Add generic tests for elliptic curve point multiplication
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-01-22 15:07:02 +00:00
c9291bc5c7 [tls] Allow for NIST elliptic curve point formats
The elliptic curve point representation for the x25519 curve includes
only the X value, since the curve is designed such that the Montgomery
ladder does not need to ever know or calculate a Y value.  There is no
curve point format byte: the public key data is simply the X value.
The pre-master secret is also simply the X value of the shared secret
curve point.

The point representation for the NIST curves includes both X and Y
values, and a single curve point format byte that must indicate that
the format is uncompressed.  The pre-master secret for the NIST curves
does not include both X and Y values: only the X value is used.

Extend the definition of an elliptic curve to allow the point size to
be specified separately from the key size, and extend the definition
of a TLS named curve to include an optional curve point format byte
and a pre-master secret length.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-01-21 15:55:33 +00:00
df7ec31766 [crypto] Generalise elliptic curve key exchange to ecdhe_key()
Split out the portion of tls_send_client_key_exchange_ecdhe() that
actually performs the elliptic curve key exchange into a separate
function ecdhe_key().

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-01-21 15:20:17 +00:00
cc38d7dd3e [crypto] Add bigint_ntoa() for transcribing big integers
In debug messages, big integers are currently printed as hex dumps.
This is quite verbose and cumbersome to check against external
sources.

Add bigint_ntoa() to transcribe big integers into a static buffer
(following the model of inet_ntoa(), eth_ntoa(), uuid_ntoa(), etc).

Abbreviate big integers that will not fit within the static buffer,
showing both the most significant and least significant digits in the
transcription.  This is generally the most useful form when visually
comparing against external sources (such as test vectors, or results
produced by high-level languages).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-01-20 16:00:44 +00:00
d88eb0a193 [crypto] Extract bigint_reduce_supremum() from bigint_mod_exp()
Calculating the Montgomery constant (R^2 mod N) is done in our
implementation by zeroing the double-width representation of N,
subtracting N once to give (R^2 - N) in order to obtain a positive
value, then reducing this value modulo N.

Extract this logic from bigint_mod_exp() to a separate function
bigint_reduce_supremum(), to allow for reuse by other code.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2025-01-10 13:47:25 +00:00
83ba34076a [crypto] Allow for relaxed Montgomery reduction
Classic Montgomery reduction involves a single conditional subtraction
to ensure that the result is strictly less than the modulus.

When performing chains of Montgomery multiplications (potentially
interspersed with additions and subtractions), it can be useful to
work with values that are stored modulo some small multiple of the
modulus, thereby allowing some reductions to be elided.  Each addition
and subtraction stage will increase this running multiple, and the
following multiplication stages can be used to reduce the running
multiple since the reduction carried out for multiplication products
is generally strong enough to absorb some additional bits in the
inputs.  This approach is already used in the x25519 code, where
multiplication takes two 258-bit inputs and produces a 257-bit output.

Split out the conditional subtraction from bigint_montgomery() and
provide a separate bigint_montgomery_relaxed() for callers who do not
require immediate reduction to within the range of the modulus.

Modular exponentiation could potentially make use of relaxed
Montgomery multiplication, but this would require R>4N, i.e. that the
two most significant bits of the modulus be zero.  For both RSA and
DHE, this would necessitate extending the modulus size by one element,
which would negate any speed increase from omitting the conditional
subtractions.  We therefore retain the use of classic Montgomery
reduction for modular exponentiation, apart from the final conversion
out of Montgomery form.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-12-18 14:31:24 +00:00
c0cbe7c2e6 [efi] Add EFI_TCG2_PROTOCOL header and GUID definition
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-12-17 13:52:23 +00:00
8816ddcd96 [efi] Update to current EDK2 headers
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-12-17 13:30:16 +00:00
97079553b6 [crypto] Calculate inverse of modulus on demand in bigint_montgomery()
Reduce the number of parameters passed to bigint_montgomery() by
calculating the inverse of the modulus modulo the element size on
demand.  Cache the result, since Montgomery reduction will be used
repeatedly with the same modulus value.

In all currently supported algorithms, the modulus is a public value
(or a fixed value defined by specification) and so this non-constant
timing does not leak any private information.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-12-16 15:13:37 +00:00
24db39fb29 [gve] Run startup process only while device is open
The startup process is scheduled to run when the device is opened and
terminated (if still running) when the device is closed.  It assumes
that the resource allocation performed in gve_open() has taken place,
and that the admin and transmit/receive data structure pointers are
therefore valid.

The process initialisation in gve_probe() erroneously calls
process_init() rather than process_init_stopped() and will therefore
schedule the startup process immediately, before the relevant
resources have been allocated.

This bug is masked in the typical use case of a Google Cloud instance
with a single NIC built with the config/cloud/gce.ipxe embedded
script, since the embedded script will immediately open the NIC (and
therefore allocate the required resources) before the scheduled
process is allowed to run for the first time.  In a multi-NIC
instance, undefined behaviour will arise as soon as the startup
process for the second NIC is allowed to run.

Fix by using process_init_stopped() to avoid implicitly scheduling the
startup process during gve_probe().

Originally-fixed-by: Kal Cutter Conley <kalcutterc@nvidia.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-12-03 13:57:06 +00:00
5202f83345 [crypto] Remove obsolete bigint_mod_multiply()
There is no further need for a standalone modular multiplication
primitive, since the only consumer is modular exponentiation (which
now uses Montgomery multiplication instead).

Remove the now obsolete bigint_mod_multiply().

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-11-28 15:06:17 +00:00
83ac98ce22 [crypto] Use Montgomery reduction for modular exponentiation
Speed up modular exponentiation by using Montgomery reduction rather
than direct modular reduction.

Montgomery reduction in base 2^n requires the modulus to be coprime to
2^n, which would limit us to requiring that the modulus is an odd
number.  Extend the implementation to include support for
exponentiation with even moduli via Garner's algorithm as described in
"Montgomery reduction with even modulus" (Koç, 1994).

Since almost all use cases for modular exponentation require a large
prime (and hence odd) modulus, the support for even moduli could
potentially be removed in future.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-11-28 15:06:01 +00:00
4f7dd7fbba [crypto] Add bigint_montgomery() to perform Montgomery reduction
Montgomery reduction is substantially faster than direct reduction,
and is better suited for modular exponentiation operations.

Add bigint_montgomery() to perform the Montgomery reduction operation
(often referred to as "REDC"), along with some test vectors.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-11-27 13:25:18 +00:00
96f385d7a4 [crypto] Use inverse size as effective size for bigint_mod_invert()
Montgomery reduction requires only the least significant element of an
inverse modulo 2^k, which in turn depends upon only the least
significant element of the invertend.

Use the inverse size (rather than the invertend size) as the effective
size for bigint_mod_invert().  This eliminates around 97% of the loop
iterations for a typical 2048-bit RSA modulus.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-11-27 13:16:05 +00:00
7c2e68cc87 [crypto] Eliminate temporary working space for bigint_mod_invert()
With a slight modification to the algorithm to ignore bits of the
residue that can never contribute to the result, it is possible to
reuse the as-yet uncalculated portions of the inverse to hold the
residue.  This removes the requirement for additional temporary
working space.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-11-27 13:05:18 +00:00
9cbf5c4f86 [crypto] Eliminate temporary working space for bigint_reduce()
Direct modular reduction is expected to be used in situations where
there is no requirement to retain the original (unreduced) value.

Modify the API for bigint_reduce() to reduce the value in place,
(removing the separate result buffer), impose a constraint that the
modulus and value have the same size, and require the modulus to be
passed in writable memory (to allow for scaling in place).  This
removes the requirement for additional temporary working space.

Reverse the order of arguments so that the constant input is first,
to match the usage pattern for bigint_add() et al.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-11-26 14:45:51 +00:00
167a08f089 [crypto] Expose carry flag from big integer addition and subtraction
Expose the effective carry (or borrow) out flag from big integer
addition and subtraction, and use this to elide an explicit bit test
when performing x25519 reduction.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-11-26 12:55:13 +00:00
da6da6eb3b [crypto] Add bigint_msb_is_set() to clarify code
Add a dedicated bigint_msb_is_set() to reduce the amount of open
coding required in the common case of testing the sign of a two's
complement big integer.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-11-20 14:39:49 +00:00
e9a23a5b39 [efi] Ensure local drives are connected when attempting a SAN boot
UEFI systems may choose not to connect drivers for local disk drives
when the boot policy is set to attempt a network boot.  This may cause
the "sanboot" command to be unable to boot from a local drive, since
the relevant block device and filesystem drivers may not have been
connected.

Fix by ensuring that all available drivers are connected before
attempting to boot from an EFI block device.

Reported-by: Andrew Cottrell <andrew.cottrell@xtxmarkets.com>
Tested-by: Andrew Cottrell <andrew.cottrell@xtxmarkets.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-11-20 14:25:06 +00:00
8fc11d8a4a [build] Allow for per-architecture cross-compilation prefixes
We currently require the variable CROSS (or CROSS_COMPILE) to be set
to specify the global cross-compilation prefix.  This becomes
cumbersome when developing across multiple CPU architectures,
requiring frequent editing of build command lines and preventing
incompatible architectures from being built with a single command.

Allow a default cross-compilation prefix for each architecture to be
specified via the CROSS_COMPILE_<arch> variables.  These may then be
provided as environment variables, e.g. using

  export CROSS_COMPILE_arm32=arm-linux-gnu-
  export CROSS_COMPILE_arm64=aarch64-linux-gnu-
  export CROSS_COMPILE_loong64=loongarch64-linux-gnu-
  export CROSS_COMPILE_riscv32=riscv64-linux-gnu-
  export CROSS_COMPILE_riscv64=riscv64-linux-gnu-

This change requires some portions of the Makefile to be rearranged,
to allow for the fact that $(CROSS_COMPILE) may not have been set
until the build directory has been parsed to determine the CPU
architecture.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-10-29 14:11:08 +00:00
19f44d2998 [riscv] Check if seed CSR is accessible from S-mode
The seed CSR defined by the Zkr extension is accessible only in M-mode
by default.  Older versions of OpenSBI (prior to version 1.4) do not
set mseccfg.sseed, with the result that attempts to access the seed
CSR from S-mode will raise an illegal instruction exception.

Add a facility for testing the accessibility of arbitrary CSRs, and
use it to check that the seed CSR is accessible before reporting the
seed CSR entropy source as being functional.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-10-28 23:07:14 +00:00
e0e102ee24 [sbi] Add support for running as a RISC-V SBI payload
Add basic support for running directly on top of SBI, with no UEFI
firmware present.  Build as e.g.:

  make CROSS=riscv64-linux-gnu- bin-riscv64/ipxe.sbi

The resulting binary can be tested in QEMU using e.g.:

  qemu-system-riscv64 -M virt -cpu max -serial stdio \
                      -kernel bin-riscv64/ipxe.sbi

No drivers or executable binary formats are supported yet, but the
unit test suite may be run successfully.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-10-28 19:20:50 +00:00
7ccd08dbf4 [build] Allow default platform to vary by architecture
Restructure the parsing of the build directory name from

  bin[[-<arch>]-<platform>]

to

  bin[-<arch>[-<platform>]]

and allow for a per-architecture default build platform.

For the sake of backwards compatibility, handle "bin-efi" as a special
case equivalent to "bin-i386-efi".

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-10-28 18:34:55 +00:00
d9c0d26e17 [pci] Provide a null PCI API for platforms with no PCI bus
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-10-28 16:43:43 +00:00
06a9330004 [riscv] Add missing volatile qualifiers on timer and seed CSR accesses
The timer and entropy seed CSRs will, by design, return different
values each time they are read.

Add the missing volatile qualifiers on the inline assembly to prevent
gcc from assuming that repeated invocations may be elided.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-10-28 16:43:43 +00:00
be0c9788a1 [riscv] Add support for the seed CSR as an entropy source
The Zkr entropy source extension defines a potentially unprivileged
seed CSR that can be read to obtain 16 bits of entropy input, with a
mandated requirement that 256 entropy input bits read from the seed
CSR will contain at least 128 bits of min-entropy.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-10-28 15:55:24 +00:00
cd54e7c844 [riscv] Add support for RDTIME as a timer source
The Zicntr extension defines an unprivileged wall-clock time CSR that
roughly matches the behaviour of an invariant TSC on x86.  The nominal
frequency of this timer may be read from the "timebase-frequency"
property of the CPU node in the device tree.

Add a timer source using RDTIME to provide implementations of udelay()
and currticks(), modelled on the existing RDTSC-based timer for x86.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-10-28 13:55:36 +00:00
b0a8eabbf4 [riscv] Add support for checking CPU extensions reported via device tree
RISC-V seems to allow for direct discovery of CPU features only from
M-mode (e.g. by setting up a trap handler and then attempting to
access a CSR), with S-mode code expected to read the resulting
constructed ISA description from the device tree.

Add the ability to check for the presence of named extensions listed
in the "riscv,isa" property of the device tree node corresponding to
the boot hart.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-10-28 13:55:00 +00:00
74710b8316 [fdt] Add ability to parse unsigned integer properties
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-10-28 13:55:00 +00:00
cc45ca372c [pci] Drag in PCI settings mechanism only when PCI support is present
Allow for the existence of platforms with no PCI bus by including the
PCI settings mechanism only if PCI bus support is included.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-10-25 14:40:28 +01:00
abfa7c3ab1 [uaccess] Rename UACCESS_EFI to UACCESS_FLAT
Running with flat physical addressing is a fairly common early boot
environment.  Rename UACCESS_EFI to UACCESS_FLAT so that this code may
be reused in non-UEFI boot environments that also use flat physical
addressing.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-10-25 14:21:27 +01:00
33d80b1cd8 [smbios] Provide a null SMBIOS API for platforms with no concept of SMBIOS
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-10-25 14:05:00 +01:00
21940425c4 [riscv] Add support for reboot and power off via SBI
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-10-22 15:13:59 +01:00
b23204b383 [riscv] Add support for the SBI debug console
Add the ability to issue Supervisor Binary Interface (SBI) calls via
the ECALL instruction, and use the SBI DBCN extension to implement a
debug console.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-10-22 12:51:48 +01:00
fa1c24d14b [crypto] Add bigint_mod_invert() to calculate inverse modulo a power of two
Montgomery multiplication requires calculating the inverse of the
modulus modulo a larger power of two.

Add bigint_mod_invert() to calculate the inverse of any (odd) big
integer modulo an arbitrary power of two, using a lightly modified
version of the algorithm presented in "A New Algorithm for Inversion
mod p^k (Koç, 2017)".

The power of two is taken to be 2^k, where k is the number of bits
available in the big integer representation of the invertend.  The
inverse modulo any smaller power of two may be obtained simply by
masking off the relevant bits in the inverse.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-10-21 17:24:53 +01:00
c69f9589cc [usb] Expose USB device descriptor and strings via settings
Allow scripts to read basic information from USB device descriptors
via the settings mechanism.  For example:

  echo USB vendor ID: ${usb/${busloc}.8.2}
  echo USB device ID: ${usb/${busloc}.10.2}
  echo USB manufacturer name: ${usb/${busloc}.14.0}

The general syntax is

  usb/<bus:dev>.<offset>.<length>

where bus:dev is the USB bus:device address (as obtained via the
"usbscan" command, or from e.g. ${net0/busloc} for a USB network
device), and <offset> and <length> select the required portion of the
USB device descriptor.

Following the usage of SMBIOS settings tags, a <length> of zero may be
used to indicate that the byte at <offset> contains a USB string
descriptor index, and an <offset> of zero may be used to indicate that
the <length> contains a literal USB string descriptor index.

Since the byte at offset zero can never contain a string index, and a
literal string index can never be zero, the combination of both
<length> and <offset> being zero may be used to indicate that the
entire device descriptor is to be read as a raw hex dump.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-10-18 13:13:51 +01:00
c219b5d8a9 [usb] Add "usbscan" command for iterating over USB devices
Implement a "usbscan" command as a direct analogy of the existing
"pciscan" command, allowing scripts to iterate over all detected USB
devices.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-10-17 14:18:22 +01:00
2bf16c6ffc [crypto] Separate out bigint_reduce() from bigint_mod_multiply()
Faster modular multiplication algorithms such as Montgomery
multiplication will still require the ability to perform a single
direct modular reduction.

Neaten up the implementation of direct reduction and split it out into
a separate bigint_reduce() function, complete with its own unit tests.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-10-15 13:50:51 +01:00
f78c5a763c [crypto] Use architecture-independent bigint_is_set()
Every architecture uses the same implementation for bigint_is_set(),
and there is no reason to suspect that a future CPU architecture will
provide a more efficient way to implement this operation.

Simplify the code by providing a single architecture-independent
implementation of bigint_is_set().

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-10-10 15:35:16 +01:00
7e0bf4ec5c [crypto] Rename bigint_rol()/bigint_ror() to bigint_shl()/bigint_shr()
The big integer shift operations are misleadingly described as
rotations since the original x86 implementations are essentially
trivial loops around the relevant rotate-through-carry instruction.

The overall operation performed is a shift rather than a rotation.
Update the function names and descriptions to reflect this.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-10-07 13:13:43 +01:00
3f4f843920 [crypto] Eliminate temporary carry space for big integer multiplication
An n-bit multiplication product may be added to up to two n-bit
integers without exceeding the range of a (2n)-bit integer:

  (2^n - 1)*(2^n - 1) + (2^n - 1) + (2^n - 1) = 2^(2n) - 1

Exploit this to perform big integer multiplication in constant time
without requiring the caller to provide temporary carry space.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-09-27 13:51:24 +01:00
8844a3d546 [arm] Support building as a Linux userspace binary for AArch32
Add support for building as a Linux userspace binary for AArch32.
This allows the self-test suite to be more easily run for the 32-bit
ARM code.  For example:

  make CROSS=arm-linux-gnu- bin-arm32-linux/tests.linux

  qemu-arm -L /usr/arm-linux-gnu/sys-root/ \
           ./bin-arm32-linux/tests.linux

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-09-24 19:17:34 +01:00
e0282688c1 [arm] Check PMCCNTR availability before use for profiling
Reading from PMCCNTR causes an undefined instruction exception when
running in PL0 (e.g. as a Linux userspace binary), unless the
PMUSERENR.EN bit is set.

Restructure profile_timestamp() for 32-bit ARM to perform an
availability check on the first invocation, with subsequent
invocations returning zero if PMCCNTR could not be enabled.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-09-24 16:14:33 +01:00
5f7c6bd95b [profile] Standardise return type of profile_timestamp()
All consumers of profile_timestamp() currently treat the value as an
unsigned long.  Only the elapsed number of ticks is ever relevant: the
absolute value of the timestamp is not used.  Profiling is used to
measure short durations that are generally fewer than a million CPU
cycles, for which an unsigned long is easily large enough.

Standardise the return type of profile_timestamp() as unsigned long
across all CPU architectures.  This allows 32-bit architectures such
as i386 and riscv32 to omit all logic associated with retrieving the
upper 32 bits of the 64-bit hardware counter, which simplifies the
code and allows riscv32 and riscv64 to share the same implementation.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-09-24 15:40:45 +01:00
3def13265d [crypto] Use constant-time big integer multiplication
Big integer multiplication currently performs immediate carry
propagation from each step of the long multiplication, relying on the
fact that the overall result has a known maximum value to minimise the
number of carries performed without ever needing to explicitly check
against the result buffer size.

This is not a constant-time algorithm, since the number of carries
performed will be a function of the input values.  We could make it
constant-time by always continuing to propagate the carry until
reaching the end of the result buffer, but this would introduce a
large number of redundant zero carries.

Require callers of bigint_multiply() to provide a temporary carry
storage buffer, of the same size as the result buffer.  This allows
the carry-out from the accumulation of each double-element product to
be accumulated in the temporary carry space, and then added in via a
single call to bigint_add() after the multiplication is complete.

Since the structure of big integer multiplication is identical across
all current CPU architectures, provide a single shared implementation
of bigint_multiply().  The architecture-specific operation then
becomes the multiplication of two big integer elements and the
accumulation of the double-element product.

Note that any intermediate carry arising from accumulating the lower
half of the double-element product may be added to the upper half of
the double-element product without risk of overflow, since the result
of multiplying two n-bit integers can never have all n bits set in its
upper half.  This simplifies the carry calculations for architectures
such as RISC-V and LoongArch64 that do not have a carry flag.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-09-23 13:19:58 +01:00
59d123658b [gve] Allocate all possible event counters
The admin queue API requires us to tell the device how many event
counters we have provided via the "configure device resources" admin
queue command.  There is, of course, absolutely no documentation
indicating how many event counters actually need to be provided.

We require only two event counters: one for the transmit queue, one
for the receive queue.  (The receive queue doesn't seem to actually
make any use of its event counter, but the "create receive queue"
admin queue command will fail if it doesn't have an available event
counter to choose.)

In the absence of any documentation, we currently make the assumption
that allocating and configuring 16 counters (i.e. one whole cacheline)
will be sufficient to allow for the use of two counters.

This assumption turns out to be incorrect.  On larger instance types
(observed with a c3d-standard-16 instance in europe-west4-a), we find
that creating the transmit or receive queues will each fail with a
probability of around 50% with the "failed precondition" error code.

Experimentation suggests that even though the device has accepted our
"configure device resources" command indicating that we are providing
only 16 event counters, it will attempt to choose any of its potential
32 event counters (and will then fail since the event counter that it
unilaterally chose is outside of the agreed range).

Work around this firmware bug by always allocating the maximum number
of event counters supported by the device.  (This requires deferring
the allocation of the event counters until after issuing the "describe
device" command.)

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-09-17 13:37:20 +01:00
9bb2068636 [efi] Remove redundant EFI_BOOT_FILE definitions
As of commit 79c0173 ("[build] Create util/genfsimg for building
filesystem-based images"), the EFI boot file name for each CPU
architecture is defined within the genfsimg script itself, rather than
being passed in as a Makefile parameter.

Remove the now-redundant Makefile definitions for EFI_BOOT_FILE.

Reported-by: Christian I. Nilsson <nikize@gmail.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-09-16 11:04:52 +01:00
c215048dda [riscv] Add support for the RISC-V CPU architecture
Add support for building iPXE as a 64-bit or 32-bit RISC-V binary, for
either UEFI or Linux userspace platforms.  For example:

  # RISC-V 64-bit UEFI
  make CROSS=riscv64-linux-gnu- bin-riscv64-efi/ipxe.efi

  # RISC-V 32-bit UEFI
  make CROSS=riscv64-linux-gnu- bin-riscv32-efi/ipxe.efi

  # RISC-V 64-bit Linux
  make CROSS=riscv64-linux-gnu- bin-riscv64-linux/tests.linux
  qemu-riscv64 -L /usr/riscv64-linux-gnu/sys-root \
               ./bin-riscv64-linux/tests.linux

  # RISC-V 32-bit Linux
  make CROSS=riscv64-linux-gnu- SYSROOT=/usr/riscv32-linux-gnu/sys-root \
       bin-riscv32-linux/tests.linux
  qemu-riscv32 -L /usr/riscv32-linux-gnu/sys-root \
               ./bin-riscv32-linux/tests.linux

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-09-15 22:34:10 +01:00
68db9a3cb3 [linux] Allow a sysroot to be specified via SYSROOT=...
The cross-compiler will typically use the appropriate sysroot
directory automatically.  This may not work for toolchains where a
single cross-compiler is used to produce output for multiple CPU
variants (e.g. 32-bit and 64-bit RISC-V).

Add a SYSROOT=... parameter that may be used to specify the relevant
sysroot directory, e.g.

 make CROSS=riscv64-linux-gnu- SYSROOT=/usr/riscv32-linux-gnu/sys-root \
      bin-riscv32-linux/tests.linux

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-09-15 10:01:35 +01:00
670810bed8 [efi] Use standard va_args macros instead of VA_START() etc
The EDK2 header macros VA_START(), VA_ARG() etc produce build errors
on some CPU architectures (notably on 32-bit RISC-V, which is not yet
supported by EDK2).

Fix by using the standard variable argument list macros.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-09-15 10:01:35 +01:00
1d43e535fb [test] Add tests for 64-bit logical and arithmetic shifts
For some 32-bit CPUs, we need to provide implementations of 64-bit
shifts as libgcc helper functions.  Add test cases to cover these.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-09-15 10:01:35 +01:00
c85ad12468 [efi] Centralise definition of efi_cpu_nap()
Define a cpu_halt() function which is architecture-specific but
platform-independent, and merge the multiple architecture-specific
implementations of the EFI cpu_nap() function into a single central
efi_cpu_nap() that uses cpu_halt() if applicable.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-09-13 14:38:23 +01:00
5de5d4626e [libc] Centralise architecture-independent portions of setjmp.h
The definitions of the setjmp() and longjmp() functions are common to
all architectures, with only the definition of the jump buffer
structure being architecture-specific.

Move the architecture-specific portions to bits/setjmp.h and provide a
common setjmp.h for the function definitions.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-09-12 15:01:04 +01:00
a1830ff43c [cloud] Add ability to delete old AMI images
Add the "--retain <N>" option to limit the number of retained old AMI
images (within the same family, architecture, and public visibility).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-09-09 15:02:27 +01:00
49f9e036ff [cloud] Add family and architecture tags to AWS snapshots and images
Allow for easier identification of images and snapshots created by the
aws-import script by adding tags for image family (e.g. "iPXE") and
architecture (e.g. "x86_64") to both.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-09-06 15:09:12 +01:00
f88761ef49 [ena] Change reported operating system type to "iPXE"
As described in commit 3b81a4e ("[ena] Provide a host information
page"), we currently report an operating system type of "Linux" in
order to work around broken versions of the ENA firmware that will
fail to create a completion queue if we report the correct operating
system type.

As of September 2024, the ENA team at AWS assures us that the entire
AWS fleet has been upgraded to fix this bug, and that we are now safe
to report the correct operating system type value in the "type" field
of struct ena_host_info.

The ENA team has also clarified that at least some deployed versions
of the ENA firmware still have the defect that requires us to report
an operating system version number of 2 (regardless of operating
system type), and so we continue to report ENA_HOST_INFO_VERSION_WTF
in the "version" field of struct ena_host_info.

Add an explicit warning on the previous known failure path, in case
some deployed versions of the ENA firmware turn out to not have been
upgraded as expected.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-09-05 14:13:16 +01:00
2b82007571 [gdb] Allow CPU architectures to omit support for GDB
Move the <gdbmach.h> file to <bits/gdbmach.h>, and provide a common
dummy implementation for all architectures that have not yet
implemented support for GDB.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-09-05 13:00:39 +01:00
804f35cb5a [build] Centralise dummy architecture-specific headers
Simplify the process of adding a new CPU architecture by providing
common implementations of typically empty architecture-specific header
files.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-09-03 17:32:26 +01:00
c7f2e75519 [aqc1xx] Add support for Marvell AQtion Ethernet controller
This patch adds support for the AQtion Ethernet controller, enabling
iPXE to recognize and utilize the specific models (AQC114, AQC113, and
AQC107).

Tested-by: Animesh Bhatt <animeshb@marvell.com>
Signed-off-by: Animesh Bhatt <animeshb@marvell.com>
2024-09-02 13:45:54 +01:00
7f75d320f6 [etherfabric] Fix use of uninitialised variable in falcon_xaui_link_ok()
The link status check in falcon_xaui_link_ok() reads from the
FCN_XX_CORE_STAT_REG_MAC register only on production hardware (where
the FPGA version reads as zero), but modifies the value and writes
back to this register unconditionally.  This triggers an uninitialised
variable warning on newer versions of gcc.

Fix by assuming that the register exists only on production hardware,
and so moving the "modify-write" portion of the "read-modify-write"
operation to also be covered by the same conditional check.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-09-02 12:24:57 +01:00
301644ab48 [test] Add CMS decryption self-tests
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-08-29 23:36:00 +01:00
5e69cf08d7 [crypto] Allow cms_decrypt() to be called on unregistered images
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-08-29 23:31:10 +01:00
72316b820d [image] Add the "imgdecrypt" command
Add the "imgdecrypt" command that can be used to decrypt a detached
encrypted data image using a cipher key obtained from a separate CMS
envelope image.  For example:

  # Create non-detached encrypted CMS messages
  #
  openssl cms -encrypt -binary -aes-256-gcm -recip client.crt \
              -in vmlinuz -outform DER -out vmlinuz.cms
  openssl cms -encrypt -binary -aes-256-gcm -recip client.crt \
              -in initrd.img -outform DER -out initrd.img.cms

  # Detach data from envelopes (using iPXE's contrib/crypto/cmsdetach)
  #
  cmsdetach vmlinuz.cms -d vmlinuz.dat -e vmlinuz.env
  cmsdetach initrd.img.cms -d initrd.img.dat -e initrd.img.env

and then within iPXE:

  #!ipxe
  imgfetch http://192.168.0.1/vmlinuz.dat
  imgfetch http://192.168.0.1/initrd.img.dat
  imgdecrypt vmlinuz.dat    http://192.168.0.1/vmlinuz.env
  imgdecrypt initrd.img.dat http://192.168.0.1/initrd.img.env
  boot vmlinuz

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-08-29 15:11:30 +01:00
486b15b3c1 [crypto] Support decryption of images via CMS envelopes
Add support for decrypting images containing detached encrypted data
using a cipher key obtained from a separate CMS envelope image (in DER
or PEM format).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-08-29 14:47:13 +01:00
49404bfea9 [image] Split image_strip_suffix() out from image_extract()
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-08-29 13:09:41 +01:00
748cab7745 [crypto] Add cmsdetach script for detaching encrypted data from CMS messages
The openssl toolchain does not currently seem to support creating CMS
envelopedData or authEnvelopedData messages with detached encrypted
data.

Add a standalone tool "cmsdetach" that can be used to detach the
encrypted data from a CMS message.  For example:

  openssl cms -encrypt -binary -aes-256-gcm -recip client.crt \
              -in bootfile -outform DER -out bootfile.cms

  cmsdetach bootfile.cms --data bootfile.dat --envelope bootfile.env

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-08-28 16:17:14 +01:00
b053ba1988 [test] Update CMS self-test terminology
Generalise CMS self-test data structure and macro names to refer to
"messages" rather than "signatures", in preparation for adding image
decryption tests.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-08-28 13:03:55 +01:00
4b4a362f07 [crypto] Allow for extraction of ASN.1 algorithm parameters
Some ASN.1 OID-identified algorithms require additional parameters,
such as an initialisation vector for a block cipher.  The structure of
the parameters is defined by the individual algorithm.

Extend asn1_algorithm() to allow these additional parameters to be
returned via a separate ASN.1 cursor.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-08-28 13:03:55 +01:00
bdb5b4aef4 [crypto] Hold CMS message as a single ASN.1 object
Reduce the number of dynamic allocations required to parse a CMS
message by retaining the ASN.1 cursor returned from image_asn1() for
the lifetime of the CMS message.  This allows embedded ASN.1 cursors
to be used for parsed objects within the message, such as embedded
signatures.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-08-23 13:43:42 +01:00
46937a9df6 [crypto] Remove the concept of a public-key algorithm reusable context
Instances of cipher and digest algorithms tend to get called
repeatedly to process substantial amounts of data.  This is not true
for public-key algorithms, which tend to get called only once or twice
for a given key.

Simplify the public-key algorithm API so that there is no reusable
algorithm context.  In particular, this allows callers to omit the
error handling currently required to handle memory allocation (or key
parsing) errors from pubkey_init(), and to omit the cleanup calls to
pubkey_final().

This change does remove the ability for a caller to distinguish
between a verification failure due to a memory allocation failure and
a verification failure due to a bad signature.  This difference is not
material in practice: in both cases, for whatever reason, the caller
was unable to verify the signature and so cannot proceed further, and
the cause of the error will be visible to the user via the return
status code.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-08-21 21:00:57 +01:00
acbabdb335 [tls] Group client and server state in TLS connection structure
The TLS connection structure has grown to become unmanageably large as
new features and support for new TLS protocol versions have been added
over time.

Split out the portions of struct tls_connection that are specific to
client and server operations into separate structures, and simplify
some structure field names.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-08-21 12:15:24 +01:00
c9cac76a5c [tls] Group transmit and receive state in TLS connection structure
The TLS connection structure has grown to become unmanageably large as
new features and support for new TLS protocol versions have been added
over time.

Split out the portions of struct tls_connection that are specific to
transmit and receive operations into separate structures, and simplify
some structure field names.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-08-21 11:59:43 +01:00
be2784649d [gve] Add missing error codes in EUNIQ() list of potential errors
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-08-20 22:44:15 +01:00
ab5743efc5 [contrib] Remove obsolete rom-o-matic code
The rom-o-matic code does not form part of the iPXE codebase, has not
been maintained for over a decade, and does not appear to still be in
use anywhere in the world.

It does, however, result in a large number of false positive security
vulnerability reports from some low quality automated code analysis
tools such as Fortify SCA.

Remove this unused and obsolete code to reduce the burden of
responding to these false positives.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-08-20 10:22:18 +01:00
633f4f362d [test] Generalise public-key algorithm tests and use okx()
Generalise the existing support for performing RSA public-key
encryption, decryption, signature, and verification tests, and update
the code to use okx() for neater reporting of test results.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-08-18 23:51:43 +01:00
53f089b723 [crypto] Pass asymmetric keys as ASN.1 cursors
Asymmetric keys are invariably encountered within ASN.1 structures
such as X.509 certificates, and the various large integers within an
RSA key are themselves encoded using ASN.1.

Simplify all code handling asymmetric keys by passing keys as a single
ASN.1 cursor, rather than separate data and length pointers.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-08-18 15:44:38 +01:00
950f6b5861 [efi] Allow discovery of PCI bus:dev.fn address ranges
Generalise the logic for identifying the matching PCI root bridge I/O
protocol to allow for identifying the closest matching PCI bus:dev.fn
address range, and use this to provide PCI address range discovery
(while continuing to inhibit automatic PCI bus probing).

This allows the "pciscan" command to work as expected under UEFI.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-08-15 09:39:01 +01:00
7c82ff0b6b [pci] Separate permission to probe buses from bus:dev.fn range discovery
The UEFI device model requires us to not probe the PCI bus directly,
but instead to wait to be offered the opportunity to drive devices via
our driver service binding handle.

We currently inhibit PCI bus probing by having pci_discover() return
an empty range when using the EFI PCI I/O API.  This has the unwanted
side effect that scanning the bus manually using the "pciscan" command
will also fail to discover any devices.

Separate out the concept of being allowed to probe PCI buses from the
mechanism for discovering PCI bus:dev.fn address ranges, so that this
limitation may be removed.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-08-15 09:31:14 +01:00
9d9465b140 [crypto] Fix debug name for empty certificate chain validators
An attempt to use a validator for an empty certificate chain will
correctly fail the overall validation with the "empty certificate
chain" error propagated from x509_auto_append().

In a debug build, the call to validator_name() will attempt to call
x509_name() on a non-existent certificate, resulting in garbage in the
debug message.

Fix by checking for the special case of an empty certificate chain.

This issue does not affect non-debug builds, since validator_name() is
(as per its description) called only for debug messages.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-08-14 14:07:41 +01:00
97635eb71b [crypto] Generalise cms_signature to cms_message
There is some exploitable similarity between the data structures used
for representing CMS signatures and CMS encryption keys.  In both
cases, the CMS message fundamentally encodes a list of participants
(either message signers or message recipients), where each participant
has an associated certificate and an opaque octet string representing
the signature or encrypted cipher key.  The ASN.1 structures are not
identical, but are sufficiently similar to be worth exploiting: for
example, the SignerIdentifier and RecipientIdentifier data structures
are defined identically.

Rename data structures and functions, and add the concept of a CMS
message type.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-08-14 13:04:01 +01:00
998edc6ec5 [crypto] Add OID-identified algorithms for AES ciphers
Extend the definition of an ASN.1 OID-identified algorithm to include
a potential cipher suite, and add identifiers for AES-CBC and AES-GCM.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-08-14 13:04:01 +01:00
3b4d0cb555 [crypto] Pass image as parameter to CMS functions
The cms_signature() and cms_verify() functions currently accept raw
data pointers.  This will not be possible for cms_decrypt(), which
will need the ability to extract fragments of ASN.1 data from a
potentially large image.

Change cms_signature() and cms_verify() to accept an image as an input
parameter, and move the responsibility for setting the image trust
flag within cms_verify() since that now becomes a more natural fit.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-08-13 12:30:51 +01:00
96fb7a0a93 [crypto] Allow passing a NULL certificate store to x509_find() et al
Allow passing a NULL value for the certificate list to all functions
used for identifying an X.509 certificate from an existing set of
certificates, and rename function parameters to indicate that this
certificate list represents an unordered certificate store (rather
than an ordered certificate chain).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-08-13 12:26:31 +01:00
d85590b658 [crypto] Centralise mechanisms for identifying X.509 certificates
Centralise all current mechanisms for identifying an X.509 certificate
(by raw content, by subject, by issuer and serial number, and by
matching public key), and remove the certstore-specific and
CMS-specific variants of these functions.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-08-12 12:38:08 +01:00
59e2b03e6a [crypto] Extend asn1_enter() to handle partial object cursors
Handling large ASN.1 objects such as encrypted CMS files will require
the ability to use the asn1_enter() and asn1_skip() family of
functions on partial object cursors, where a defined additional length
is known to exist after the end of the data buffer pointed to by the
ASN.1 object cursor.

We already have support for partial object cursors in the underlying
asn1_start() operation used by both asn1_enter() and asn1_skip(), and
this is used by the DER image probe routine to check that the
potential DER file comprises a single ASN.1 SEQUENCE object.

Add asn1_enter_partial() to formalise the process of entering an ASN.1
partial object, and refactor the DER image probe routine to use this
instead of open-coding calls to the underlying asn1_start() operation.

There is no need for an equivalent asn1_skip_partial() function, since
only objects that are wholly contained within the partial cursor may
be successfully skipped.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-08-07 16:26:19 +01:00
0e73b48f77 [crypto] Clarify ASN.1 cursor invalidation behaviour
Calling asn1_skip_if_exists() on a malformed ASN.1 object may
currently leave the cursor in a partially-updated state, where the tag
byte and one of the length bytes have been stripped.  The cursor is
left with a valid data pointer and length and so no out-of-bounds
access can arise, but the cursor no longer points to the start of an
ASN.1 object.

Ensure that each ASN.1 cursor manipulation code path leads to the
cursor being either fully updated, left unmodified, or invalidated,
and update the function descriptions to reflect this.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-08-07 16:11:57 +01:00
309ac8fd21 [crypto] Do not return an error when skipping the final ASN.1 object
Successfully reaching the end of a well-formed ASN.1 object list is
arguably not an error, but the current code (dating back to the
original ASN.1 commit in 2007) will explicitly check for and report
this as an error condition.

Remove the explicit check for reaching the end of a well-formed ASN.1
object list, and instead return success along with a zero-length (and
hence implicitly invalidated) cursor.

Almost every existing caller of asn1_skip() or asn1_skip_if_exists()
currently ignores the return value anyway.  Skipped objects are (by
definition) not of interest to the caller, and the invalidation
behaviour of asn1_skip() ensures that any errors will be safely caught
on a subsequent attempt to actually use the ASN.1 object content.
Since these existing callers ignore the return value, they cannot be
affected by this change.

There is one existing caller of asn1_skip_if_exists() that does check
the return value: in asn1_skip() itself, an error returned from
asn1_skip_if_exists() will cause the cursor to be invalidated.  In the
case of an error indicating only that the cursor length is already
zero, invalidation is a no-op, and so this change affects only the
return value propagated from asn1_skip().

This leaves only a single call site within ocsp_request() where the
return value from asn1_skip() is currently checked.  The return status
here is moot since there is no way for the code in question to fail
(absent a bug in the ASN.1 construction or parsing code).

There are therefore no callers of asn1_skip() or asn1_skip_if_exists()
that rely on an error being returned for successfully reaching the end
of a well-formed ASN.1 object list.  Simplify the code by redefining
this as a successful outcome.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-08-07 13:06:23 +01:00
a064d39768 [cpuid] Allow hypervisor CPUID leaves to be accessed as settings
Redefine bit 30 of an SMBIOS numerical setting to be part of the
function number, in order to allow access to hypervisor CPUID leaves.

This technically breaks backwards compatibility with scripts
attempting to read more than 64 consecutive functions.  Since there is
no meaningful block of 64 consecutive related functions, it is
vanishingly unlikely that this capability has ever been used.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-08-01 12:54:49 +01:00
121d96b903 [cpuid] Allow reading hypervisor CPUID leaves
Hypervisors typically intercept CPUID leaves in the range 0x40000000
to 0x400000ff, with leaf 0x40000000 returning the maximum supported
function within this range in register %eax.

iPXE currently masks off bit 30 from the requested CPUID leaf when
checking to see if a function is supported, which causes this check to
read from leaf 0x00000000 instead of 0x40000000.

Fix by including bit 30 within the mask.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-08-01 12:49:48 +01:00
c117e6a481 [smbios] Allow reading an entire SMBIOS data structure as a setting
The general syntax for SMBIOS settings:

  smbios/<instance>.<type>.<offset>.<length>

is currently extended such that a <length> of zero indicates that the
byte at <offset> contains a string index, and an <offset> of zero
indicates that the <length> contains a literal string index.

Since the byte at offset zero can never contain a string index, and a
literal string index can never have a zero value, the combination of
both <length> and <offset> being zero is currently invalid and will
always return "not found".

Extend the syntax such that the combination of both <length> and
<offset> being zero may be used to read the entire data structure.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-07-31 16:26:48 +01:00
60d682409e [smbios] Avoid reading beyond end of constructed SMBIOS setting
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-07-31 16:20:37 +01:00
0dc8933f67 [cloud] Add utility to read INT13CON partition in Google Compute Engine
Following the example of aws-int13con, add a utility that can be used
to read the INT13 console log from a used iPXE boot disk in Google
Compute Engine.

There seems to be no easy way to directly read the contents of either
a disk image or a snapshot in Google Cloud.  Work around this
limitation by creating a snapshot and attaching this snapshot as a
data disk to a temporary Linux instance, which is then used to echo
the INT13 console log to the serial port.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-07-30 16:11:28 +01:00
d2d194bc60 [gve] Increase number of receive buffers to reduce packet loss
Experiments suggest that using fewer than 64 receive buffers leads to
excessive packet drop rates on some instance types (observed with a
c3-standard-4 instance in europe-west4-a).

Fix by increasing the number of receive data buffers (and adjusting
the length of the registrable queue page address list to match).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-07-25 00:13:33 +01:00
c7b76e3adc [gve] Add driver for Google Virtual Ethernet NIC
The Google Virtual Ethernet NIC (GVE or gVNIC) is found only in Google
Cloud instances.  There is essentially zero documentation available
beyond the mostly uncommented source code in the Linux kernel.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-07-24 14:45:46 +01:00
5a9f476d4f [cloud] Add utility for importing images to Google Compute Engine
Following the example of aws-import, add a utility that can be used to
upload an iPXE disk image to Google Compute Engine as a bootable
image.  For example:

  make CONFIG=cloud EMBED=config/cloud/gce.ipxe \
       bin-x86_64-pcbios/ipxe.usb bin-x86_64-efi/ipxe.usb

  make CONFIG=cloud EMBED=config/cloud/gce.ipxe \
       CROSS=aarch64-linux-gnu- bin-arm64-efi/ipxe.usb

  ../contrib/cloud/gce-import -p \
       bin-x86_64-pcbios/ipxe.usb \
       bin-x86_64-efi/ipxe.usb \
       bin-arm64-efi/ipxe.usb

The iPXE disk image is automatically wrapped into a tarball containing
a single file named "disk.raw", uploaded to a temporary bucket in
Google Cloud Storage, and used to create a bootable image.  The
temporary bucket is deleted after use.

An appropriate image family name is identified automatically: "ipxe"
for BIOS images, "ipxe-uefi-x86-64" for x86_64 UEFI images, and
"ipxe-uefi-arm64" for AArch64 UEFI images.  This allows the latest
image within each family to be launched within needing to know the
precise image name.

Google Compute Engine images are globally scoped and are available
(and cached upon first use) in all regions.  The initial placement of
the image may be controlled indirectly by using the "--location"
option to specify the Google Cloud Storage location used for the
temporary upload bucket: the image will then be created in the closest
multi-region to the storage location.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-07-08 13:31:43 +01:00
b66e27d9b2 [ipv6] Expose router address for DHCPv6 leased addresses
The DHCPv6 protocol does not itself provide a router address or a
prefix length.  This information is instead obtained from the router
advertisements.

Our IPv6 minirouting table construction logic will first construct an
entry for each advertised prefix, and later update the entry to
include an address assigned within that prefix via stateful DHCPv6 (if
applicable).

This logic fails if the address assigned via stateful DHCPv6 does not
fall within any of the advertised prefixes (e.g. if the network is
configured to use DHCPv6-assigned /128 addresses with no advertised
on-link prefixes).  We will currently treat this situation as
equivalent to having a manually assigned address with no corresponding
router address or prefix length: the routing table entry will use the
default /64 prefix length and will not include the router address.

DHCPv6 is triggered only in response to a router advertisement with
the "Managed Address Configuration (M)" or "Other Configuration (O)"
flags set, and a router address is therefore available at the point
that we initiate DHCPv6.

Record the router address when initiating DHCPv6, and expose this
router address as part of the DHCPv6 settings block.  This allows the
routing table entry for any address assigned via stateful DHCPv6 to
correctly include the router address, even if the assigned address
does not fall within an advertised prefix.

Also provide a fixed /128 prefix length as part of the DHCPv6 settings
block.  When an address assigned via stateful DHCPv6 does not fall
within an advertised prefix, this will cause the routing table entry
to have a /128 prefix length as expected.  (When such an address does
fall within an advertised prefix, it will continue to use the
advertised prefix length.)

Originally-fixed-by: Guvenc Gulce <guevenc.guelce@sap.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-06-27 13:43:37 +01:00
77acf6b41f [ipv4] Support small subnets with no directed broadcast address
In a small subnet (with a /31 or /32 subnet mask), all addresses
within the subnet are valid host addresses: there is no separate
network address or directed broadcast address.

The logic used in iPXE to determine whether or not to use a link-layer
broadcast address will currently fail in these subnets.  In a /31
subnet, the higher of the two host addresses (i.e. the address with
all host bits set) will be treated as a broadcast address.  In a /32
subnet, the single valid host address will be treated as a broadcast
address.

Fix by adding the concept of a host mask, defined such that an address
in the local subnet with all of the mask bits set to zero represents
the network address, and an address in the local subnet with all of
the mask bits set to one represents the directed broadcast address.
For most subnets, this is simply the inverse of the subnet mask.  For
small subnets (/31 or /32) we can obtain the desired behaviour by
setting the host mask to all ones, so that only the local broadcast
address 255.255.255.255 will be treated as a broadcast address.

Originally-fixed-by: Lukas Stockner <lstockner@genesiscloud.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-06-26 05:01:58 -07:00
821bb326f8 [hci] Remove the generalised widget user interface abstraction
Remove the now-unused generalised text widget user interface, along
with the associated concept of a widget set and the implementation of
a read-only label widget.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-06-21 09:57:03 -07:00
162cc51b6d [form] Reimplement the "login" user interface
Rewrite the code implementing the "login" user interface to use a
predefined interactive form.  The command "login" then becomes roughly
equivalent to:

  #!ipxe

  form
  item          username   Username
  item --secret password   Password
  present

with the result that login form customisations (e.g. to add a Windows
domain name) may be implemented within the scripting language.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-06-21 09:45:44 -07:00
f417f0b6a5 [form] Add support for dynamically created interactive forms
Add support for presenting a dynamic user interface as an interactive
form, alongside the existing support for presenting a dynamic user
interface as a menu.

An interactive form may be used to allow a user to input (or edit)
values for multiple settings on a single screen, as a user-friendly
alternative to prompting for setting values via the "read" command.

In the present implementation, all input fields must fit on a single
screen (with no scrolling), and the only supported widget type is an
editable text box.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-06-20 16:28:46 -07:00
1c3c5e2b22 [dynui] Add concept of a secret user interface item
For interactive forms, the concept of a secret value becomes
meaningful (e.g. for password fields).

Add a flag to indicate that an item represents a secret value, and
allow this flag to be set via the "--secret" option of the "item"
command.

This flag has no meaning for menu items, but is silently accepted
anyway to keep the code size minimal.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-06-20 16:24:38 -07:00
039019039e [dynui] Allow for multiple flags on a user interface item
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-06-20 16:24:38 -07:00
c8e50bb0fd [dynui] Generalise mechanisms for looking up user interface items
Generalise the ability to look up a dynamic user interface item by
index or by shortcut key, to allow for reuse of this code for
interactive forms.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-06-20 14:51:28 -07:00
5719cde838 [dynui] Generalise the concept of a menu to a dynamic user interface
We currently have an abstract model of a dynamic menu as a list of
items, each of which has a name, a description, and assorted metadata
such as a shortcut key.  The "menu" and "item" commands construct
representations in this abstract model, and the "choose" command then
presents the items as a single-choice menu, with the selected item's
name used as the output value.

This same abstraction may be used to model a dynamic form as a list of
editable items, each of which has a corresponding setting name, an
optional description label, and assorted metadata such as a shortcut
key.  By defining a "form" command as an alias for the "menu" command,
we could construct and present forms using commands such as:

  #!ipxe
  form                     Login to ${url}
  item          username   Username or email address
  item --secret password   Password
  present

or

  #!ipxe
  form                Configure IPv4 networking for ${netX/ifname}
  item netX/ip        IPv4 address
  item netX/netmask   Subnet mask
  item netX/gateway   Gateway address
  item netX/dns       DNS server address
  present

Reusing the same abstract model for both menus and forms allows us to
minimise the increase in code size, since the implementation of the
"form" and "item" commands is essentially zero-cost.

Rename everything within the abstract data model from "menu" to
"dynamic user interface" to reflect this generalisation.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-06-20 14:26:06 -07:00
122777f789 [hci] Allow tab key to be used to cycle through UI elements
Add support for wraparound scrolling and allow the tab key to be used
to move forward through a list of elements, wrapping back around to
the beginning of the list on overflow.

This is mildly useful for a menu, and likely to be a strong user
expectation for an interactive form.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-06-20 13:14:35 -07:00
76e0933d78 [hci] Rename "item" command's first parameter from "label" to "name"
Switch terminology for the "item" command from "item <label> <text>"
to "item <name> <text>", in preparation for repurposing the "item"
command to cover interactive forms as well as menus.

Since this renaming affects only a positional parameter, it does not
break compatibility with any existing scripts.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-06-18 15:17:03 -07:00
bf98eae5da [hci] Split out msg() and alert() from settings UI code
The msg() and alert() functions currently defined in settings_ui.c
provide a general-purpose facility for printing messages centred on
the screen.

Split this out to a separate file to allow for reuse by the form
presentation code.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-06-18 15:08:01 -07:00
bb4a10696f [hci] Draw all widgets on the standard screen
The curses concept of a window has been supported but never actively
used in iPXE since the mucurses library was first implemented in 2006.

Simplify the code by removing the ability to place a widget set in a
specified window, and instead use the standard screen for all drawing
operations.

This simplification allows the widget set parameter to be omitted for
the draw_widget() and edit_widget() operations, since the only reason
for its inclusion was to provide access to the specified window.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-06-18 14:46:31 -07:00
e965f179e1 [libc] Add stpcpy()
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-05-31 10:11:22 +01:00
dc118c5369 [hci] Provide a general concept of a text widget set
Create a generic abstraction of a text widget, refactor the existing
editable text box widget to use this abstraction, add an
implementation of a non-editable text label widget, and generalise the
login user interface to use this generic widget abstraction.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-05-15 14:22:01 +01:00
846 changed files with 44080 additions and 14553 deletions

1
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1 @@
github: [mcb30, NiKiZe]

View File

@ -22,11 +22,12 @@ def detect_architecture(image):
return 'x86_64'
def create_snapshot(region, description, image):
def create_snapshot(region, description, image, tags):
"""Create an EBS snapshot"""
client = boto3.client('ebs', region_name=region)
snapshot = client.start_snapshot(VolumeSize=1,
Description=description)
Description=description,
Tags=tags)
snapshot_id = snapshot['SnapshotId']
with open(image, 'rb') as fh:
for block in count():
@ -46,21 +47,42 @@ def create_snapshot(region, description, image):
return snapshot_id
def import_image(region, name, architecture, image, public, overwrite):
def delete_images(region, filters, retain):
client = boto3.client('ec2', region_name=region)
resource = boto3.resource('ec2', region_name=region)
images = client.describe_images(Owners=['self'], Filters=filters)
old_images = sorted(images['Images'], key=lambda x: x['CreationDate'])
if retain > 0:
old_images = old_images[:-retain]
for image in old_images:
image_id = image['ImageId']
snapshot_id = image['BlockDeviceMappings'][0]['Ebs']['SnapshotId']
resource.Image(image_id).deregister()
resource.Snapshot(snapshot_id).delete()
def import_image(region, name, family, architecture, image, public, overwrite,
retain):
"""Import an AMI image"""
client = boto3.client('ec2', region_name=region)
resource = boto3.resource('ec2', region_name=region)
description = '%s (%s)' % (name, architecture)
images = client.describe_images(Filters=[{'Name': 'name',
'Values': [description]}])
if overwrite and images['Images']:
images = images['Images'][0]
image_id = images['ImageId']
snapshot_id = images['BlockDeviceMappings'][0]['Ebs']['SnapshotId']
resource.Image(image_id).deregister()
resource.Snapshot(snapshot_id).delete()
tags = [
{'Key': 'family', 'Value': family},
{'Key': 'architecture', 'Value': architecture},
]
if overwrite:
filters = [{'Name': 'name', 'Values': [description]}]
delete_images(region=region, filters=filters, retain=0)
if retain is not None:
filters = [
{'Name': 'tag:family', 'Values': [family]},
{'Name': 'tag:architecture', 'Values': [architecture]},
{'Name': 'is-public', 'Values': [str(public).lower()]},
]
delete_images(region=region, filters=filters, retain=retain)
snapshot_id = create_snapshot(region=region, description=description,
image=image)
image=image, tags=tags)
client.get_waiter('snapshot_completed').wait(SnapshotIds=[snapshot_id])
image = client.register_image(Architecture=architecture,
BlockDeviceMappings=[{
@ -72,12 +94,19 @@ def import_image(region, name, architecture, image, public, overwrite):
}],
EnaSupport=True,
Name=description,
TagSpecifications=[{
'ResourceType': 'image',
'Tags': tags,
}],
RootDeviceName='/dev/sda1',
SriovNetSupport='simple',
VirtualizationType='hvm')
image_id = image['ImageId']
client.get_waiter('image_available').wait(ImageIds=[image_id])
if public:
image_block = client.get_image_block_public_access_state()
if image_block['ImageBlockPublicAccessState'] != 'unblocked':
client.disable_image_block_public_access()
resource.Image(image_id).modify_attribute(Attribute='launchPermission',
OperationType='add',
UserGroups=['all'])
@ -94,10 +123,14 @@ def launch_link(region, image_id):
parser = argparse.ArgumentParser(description="Import AWS EC2 image (AMI)")
parser.add_argument('--name', '-n',
help="Image name")
parser.add_argument('--family', '-f',
help="Image family name")
parser.add_argument('--public', '-p', action='store_true',
help="Make image public")
parser.add_argument('--overwrite', action='store_true',
help="Overwrite any existing image with same name")
parser.add_argument('--retain', type=int, metavar='NUM',
help="Retain at most <NUM> old images")
parser.add_argument('--region', '-r', action='append',
help="AWS region(s)")
parser.add_argument('--wiki', '-w', metavar='FILE',
@ -108,9 +141,13 @@ args = parser.parse_args()
# Detect CPU architectures
architectures = {image: detect_architecture(image) for image in args.image}
# Use default family name if none specified
if not args.family:
args.family = 'iPXE'
# Use default name if none specified
if not args.name:
args.name = 'iPXE (%s)' % date.today().strftime('%Y-%m-%d')
args.name = '%s (%s)' % (args.family, date.today().strftime('%Y-%m-%d'))
# Use all regions if none specified
if not args.region:
@ -123,10 +160,12 @@ with ThreadPoolExecutor(max_workers=len(imports)) as executor:
futures = {executor.submit(import_image,
region=region,
name=args.name,
family=args.family,
architecture=architectures[image],
image=image,
public=args.public,
overwrite=args.overwrite): (region, image)
overwrite=args.overwrite,
retain=args.retain): (region, image)
for region, image in imports}
results = {futures[future]: future.result()
for future in as_completed(futures)}

167
contrib/cloud/gce-import Executable file
View File

@ -0,0 +1,167 @@
#!/usr/bin/env python3
import argparse
from concurrent.futures import ThreadPoolExecutor, as_completed
from datetime import date
import io
import subprocess
import tarfile
from uuid import uuid4
from google.cloud import compute
from google.cloud import exceptions
from google.cloud import storage
IPXE_STORAGE_PREFIX = 'ipxe-upload-temp-'
FEATURE_GVNIC = compute.GuestOsFeature(type_="GVNIC")
FEATURE_IDPF = compute.GuestOsFeature(type_="IDPF")
FEATURE_UEFI = compute.GuestOsFeature(type_="UEFI_COMPATIBLE")
POLICY_PUBLIC = compute.Policy(bindings=[{
"role": "roles/compute.imageUser",
"members": ["allAuthenticatedUsers"],
}])
def delete_temp_bucket(bucket):
"""Remove temporary bucket"""
assert bucket.name.startswith(IPXE_STORAGE_PREFIX)
for blob in bucket.list_blobs(prefix=IPXE_STORAGE_PREFIX):
assert blob.name.startswith(IPXE_STORAGE_PREFIX)
blob.delete()
if not list(bucket.list_blobs()):
bucket.delete()
def create_temp_bucket(location):
"""Create temporary bucket (and remove any stale temporary buckets)"""
client = storage.Client()
for bucket in client.list_buckets(prefix=IPXE_STORAGE_PREFIX):
delete_temp_bucket(bucket)
name = '%s%s' % (IPXE_STORAGE_PREFIX, uuid4())
return client.create_bucket(name, location=location)
def create_tarball(image):
"""Create raw disk image tarball"""
tarball = io.BytesIO()
with tarfile.open(fileobj=tarball, mode='w:gz',
format=tarfile.GNU_FORMAT) as tar:
tar.add(image, arcname='disk.raw')
tarball.seek(0)
return tarball
def upload_blob(bucket, image):
"""Upload raw disk image blob"""
blob = bucket.blob('%s%s.tar.gz' % (IPXE_STORAGE_PREFIX, uuid4()))
tarball = create_tarball(image)
blob.upload_from_file(tarball)
return blob
def detect_uefi(image):
"""Identify UEFI CPU architecture(s)"""
mdir = subprocess.run(['mdir', '-b', '-i', image, '::/EFI/BOOT'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
check=False)
mapping = {
b'BOOTX64.EFI': 'x86_64',
b'BOOTAA64.EFI': 'arm64',
}
uefi = [
arch
for filename, arch in mapping.items()
if filename in mdir.stdout
]
return uefi
def image_architecture(uefi):
"""Get image architecture"""
return uefi[0] if len(uefi) == 1 else None if uefi else 'x86_64'
def image_features(uefi):
"""Get image feature list"""
features = [FEATURE_GVNIC, FEATURE_IDPF]
if uefi:
features.append(FEATURE_UEFI)
return features
def image_name(base, uefi):
"""Calculate image name or family name"""
suffix = ('-uefi-%s' % uefi[0].replace('_', '-') if len(uefi) == 1 else
'-uefi-multi' if uefi else '')
return '%s%s' % (base, suffix)
def create_image(project, basename, basefamily, overwrite, public, bucket,
image):
"""Create image"""
client = compute.ImagesClient()
uefi = detect_uefi(image)
architecture = image_architecture(uefi)
features = image_features(uefi)
name = image_name(basename, uefi)
family = image_name(basefamily, uefi)
if overwrite:
try:
client.delete(project=project, image=name).result()
except exceptions.NotFound:
pass
blob = upload_blob(bucket, image)
disk = compute.RawDisk(source=blob.public_url)
image = compute.Image(name=name, family=family, architecture=architecture,
guest_os_features=features, raw_disk=disk)
client.insert(project=project, image_resource=image).result()
if public:
request = compute.GlobalSetPolicyRequest(policy=POLICY_PUBLIC)
client.set_iam_policy(project=project, resource=name,
global_set_policy_request_resource=request)
image = client.get(project=project, image=name)
return image
# Parse command-line arguments
#
parser = argparse.ArgumentParser(description="Import Google Cloud image")
parser.add_argument('--name', '-n',
help="Base image name")
parser.add_argument('--family', '-f',
help="Base family name")
parser.add_argument('--public', '-p', action='store_true',
help="Make image public")
parser.add_argument('--overwrite', action='store_true',
help="Overwrite any existing image with same name")
parser.add_argument('--project', '-j', default="ipxe-images",
help="Google Cloud project")
parser.add_argument('--location', '-l',
help="Google Cloud Storage initial location")
parser.add_argument('image', nargs='+', help="iPXE disk image")
args = parser.parse_args()
# Use default family name if none specified
if not args.family:
args.family = 'ipxe'
# Use default name if none specified
if not args.name:
args.name = '%s-%s' % (args.family, date.today().strftime('%Y%m%d'))
# Create temporary upload bucket
bucket = create_temp_bucket(args.location)
# Use one thread per image to maximise parallelism
with ThreadPoolExecutor(max_workers=len(args.image)) as executor:
futures = {executor.submit(create_image,
project=args.project,
basename=args.name,
basefamily=args.family,
overwrite=args.overwrite,
public=args.public,
bucket=bucket,
image=image): image
for image in args.image}
results = {futures[future]: future.result()
for future in as_completed(futures)}
# Delete temporary upload bucket
delete_temp_bucket(bucket)
# Show created images
for image in args.image:
result = results[image]
print("%s (%s) %s" % (result.name, result.family, result.status))

146
contrib/cloud/gce-int13con Executable file
View File

@ -0,0 +1,146 @@
#!/usr/bin/env python3
import argparse
import textwrap
import time
from uuid import uuid4
from google.cloud import compute
IPXE_LOG_PREFIX = 'ipxe-log-temp-'
IPXE_LOG_MAGIC = 'iPXE LOG'
IPXE_LOG_END = '----- END OF iPXE LOG -----'
def get_log_disk(instances, project, zone, name):
"""Get log disk source URL"""
instance = instances.get(project=project, zone=zone, instance=name)
disk = next(x for x in instance.disks if x.boot)
return disk.source
def delete_temp_snapshot(snapshots, project, name):
"""Delete temporary snapshot"""
assert name.startswith(IPXE_LOG_PREFIX)
snapshots.delete(project=project, snapshot=name)
def delete_temp_snapshots(snapshots, project):
"""Delete all old temporary snapshots"""
filter = "name eq %s.+" % IPXE_LOG_PREFIX
request = compute.ListSnapshotsRequest(project=project, filter=filter)
for snapshot in snapshots.list(request=request):
delete_temp_snapshot(snapshots, project, snapshot.name)
def create_temp_snapshot(snapshots, project, source):
"""Create temporary snapshot"""
name = '%s%s' % (IPXE_LOG_PREFIX, uuid4())
snapshot = compute.Snapshot(name=name, source_disk=source)
snapshots.insert(project=project, snapshot_resource=snapshot).result()
return name
def delete_temp_instance(instances, project, zone, name):
"""Delete log dumper temporary instance"""
assert name.startswith(IPXE_LOG_PREFIX)
instances.delete(project=project, zone=zone, instance=name)
def delete_temp_instances(instances, project, zone):
"""Delete all old log dumper temporary instances"""
filter = "name eq %s.+" % IPXE_LOG_PREFIX
request = compute.ListInstancesRequest(project=project, zone=zone,
filter=filter)
for instance in instances.list(request=request):
delete_temp_instance(instances, project, zone, instance.name)
def create_temp_instance(instances, project, zone, family, image, machine,
snapshot):
"""Create log dumper temporary instance"""
image = "projects/%s/global/images/family/%s" % (family, image)
machine_type = "zones/%s/machineTypes/%s" % (zone, machine)
logsource = "global/snapshots/%s" % snapshot
bootparams = compute.AttachedDiskInitializeParams(source_image=image)
bootdisk = compute.AttachedDisk(boot=True, auto_delete=True,
initialize_params=bootparams)
logparams = compute.AttachedDiskInitializeParams(source_snapshot=logsource)
logdisk = compute.AttachedDisk(boot=False, auto_delete=True,
initialize_params=logparams,
device_name="ipxelog")
nic = compute.NetworkInterface()
name = '%s%s' % (IPXE_LOG_PREFIX, uuid4())
script = textwrap.dedent(f"""
#!/bin/sh
tr -d '\\000' < /dev/disk/by-id/google-ipxelog-part3 > /dev/ttyS3
echo "{IPXE_LOG_END}" > /dev/ttyS3
""").strip()
items = compute.Items(key="startup-script", value=script)
metadata = compute.Metadata(items=[items])
instance = compute.Instance(name=name, machine_type=machine_type,
network_interfaces=[nic], metadata=metadata,
disks=[bootdisk, logdisk])
instances.insert(project=project, zone=zone,
instance_resource=instance).result()
return name
def get_log_output(instances, project, zone, name):
"""Get iPXE log output"""
request = compute.GetSerialPortOutputInstanceRequest(project=project,
zone=zone, port=4,
instance=name)
while True:
log = instances.get_serial_port_output(request=request).contents.strip()
if log.endswith(IPXE_LOG_END):
if log.startswith(IPXE_LOG_MAGIC):
return log[len(IPXE_LOG_MAGIC):-len(IPXE_LOG_END)]
else:
return log[:-len(IPXE_LOG_END)]
time.sleep(1)
# Parse command-line arguments
#
parser = argparse.ArgumentParser(description="Import Google Cloud image")
parser.add_argument('--project', '-j', default="ipxe-images",
help="Google Cloud project")
parser.add_argument('--zone', '-z', required=True,
help="Google Cloud zone")
parser.add_argument('--family', '-f', default="debian-cloud",
help="Helper OS image family")
parser.add_argument('--image', '-i', default="debian-12",
help="Helper OS image")
parser.add_argument('--machine', '-m', default="e2-micro",
help="Helper machine type")
parser.add_argument('instance', help="Instance name")
args = parser.parse_args()
# Construct client objects
#
instances = compute.InstancesClient()
snapshots = compute.SnapshotsClient()
# Clean up old temporary objects
#
delete_temp_instances(instances, project=args.project, zone=args.zone)
delete_temp_snapshots(snapshots, project=args.project)
# Create log disk snapshot
#
logdisk = get_log_disk(instances, project=args.project, zone=args.zone,
name=args.instance)
logsnap = create_temp_snapshot(snapshots, project=args.project, source=logdisk)
# Create log dumper instance
#
dumper = create_temp_instance(instances, project=args.project, zone=args.zone,
family=args.family, image=args.image,
machine=args.machine, snapshot=logsnap)
# Wait for log output
#
output = get_log_output(instances, project=args.project, zone=args.zone,
name=dumper)
# Print log output
#
print(output)
# Clean up
#
delete_temp_instance(instances, project=args.project, zone=args.zone,
name=dumper)
delete_temp_snapshot(snapshots, project=args.project, name=logsnap)

61
contrib/crypto/cmsdetach Executable file
View File

@ -0,0 +1,61 @@
#!/usr/bin/env python3
"""Detach CMS encrypted data.
Detach encrypted data from a CMS envelopedData or authEnvelopedData
message into a separate file.
"""
import argparse
from pathlib import Path
from asn1crypto.cms import ContentInfo, AuthEnvelopedData, EnvelopedData
# Parse command-line arguments
#
parser = argparse.ArgumentParser(
description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter,
)
parser.add_argument("-d", "--data", metavar="FILE", type=Path,
help="Write detached data (without envelope) to FILE")
parser.add_argument("-e", "--envelope", metavar="FILE", type=Path,
help="Write envelope (without data) to FILE")
parser.add_argument("-o", "--overwrite", action="store_true",
help="Overwrite output files")
parser.add_argument("file", type=Path, help="Input envelope file")
args = parser.parse_args()
if args.data is None and args.envelope is None:
parser.error("at least one of --data and --envelope is required")
outmode = "wb" if args.overwrite else "xb"
# Read input envelope
#
envelope = ContentInfo.load(args.file.read_bytes())
# Locate encrypted content info
#
content = envelope["content"]
if type(content) is AuthEnvelopedData:
encinfo = content["auth_encrypted_content_info"]
elif type(content) is EnvelopedData:
encinfo = content["encrypted_content_info"]
else:
parser.error("Input file does not contain any encrypted data")
# Detach encrypted content data
#
data = encinfo["encrypted_content"]
del encinfo["encrypted_content"]
# Write envelope (without data), if applicable
#
if args.envelope:
with args.envelope.open(mode=outmode) as fh:
fh.write(envelope.dump())
# Write data (without envelope), if applicable
#
if args.data:
with args.data.open(mode=outmode) as fh:
fh.write(data.contents)

View File

@ -1,62 +0,0 @@
ROM-o-matic web interface for building iPXE ROMs
------------------------------------------------
This web application generates iPXE images and sends them to a web
browser.
Available as part of the iPXE source code distribution, which can be
downlaoded from http://etherboot.org/
Author: Marty Connor <mdc@etherboot.org>
License: GPLv2
Support: http://etherboot.org/mailman/listinfo/ipxe
Please send support questions to the iPXE mailing list
System Requirements
-------------------
- Apache web server
- PHP 4+
- Tools required to build iPXE installed on the server
- gcc, mtools, syslinux, perl, etc.
Setup
-----
As distributed, it is expected that the rom-o-matic source code
directory is in the contrib directory of a iPXE source distribution.
The easiest way to do this is to simply put a iPXE source distribution
in a web server accessible directory.
If this is not the case, you will need to either edit the file
"globals.php"
or create a file called
"local-config.php"
containing the following lines:
<?php
$src_dir = "../../src";
?>
Then change the line beginning "$src_dir = " to the path of your iPXE
source code tree.
To make build times shorter, before you run rom-o-matic for the first time
you should cd to the ipxe "src" directory and enter the following
commands:
$ make
$ make bin/NIC
This will pro-compile most object files and will make your rom-o-matic
builds much faster.
Running rom-o-matic from a web browser
--------------------------------------
Enter a URL like:
http://example.com/ipxe-1.x.x/contrib/rom-o-matic

View File

@ -1,62 +0,0 @@
<?php
/**
* Copyright (C) 2009 Marty Connor <mdc@etherboot.org>.
* Copyright (C) 2009 Entity Cyber, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
?>
<hr>
<h4>
Resources:
</h4>
<ul>
<li>
Source code for iPXE images is available at
<a href="http://www.ipxe.org/download" target="_blank">
http://www.ipxe.org/download</a>
<br><br>
</li>
<li>
For general information about using iPXE, please visit the
<a href="http://www.ipxe.org/" target="_blank">
iPXE Project Home Page</a>
<br><br>
</li>
<li>
For Email-based support for iPXE please join
<a href="http://www.ipxe.org/contact" target="_blank">
iPXE Project mailing lists.</a>
<br><br>
</li>
<li>
For real-time online iPXE support via IRC please visit the
<a href="irc://irc.freenode.net/%23ipxe"> #ipxe channel
of irc.freenode.net</a>.
<br><br>
</li>
</ul>
<hr>
<font size="-1">
<br>
Please email <a href="mailto:<?php echo "${webmaster_email}" ?>"><?php echo "${webmaster_email}"?></a>
with questions or comments about this website.
</font>
<br><br>
<hr>
</body>
</html>

View File

@ -1,311 +0,0 @@
<?php // -*- Mode: PHP; -*-
/**
* Copyright (C) 2009 Marty Connor <mdc@etherboot.org>.
* Copyright (C) 2009 Entity Cyber, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
// Get utility functions and set globals
require_once "utils.php";
// Make sure at least $A (action) was supplied
if ( ! isset ( $_POST['A'] ) ) {
// Present user with form to customize build options
require_once "customize-flags.php";
exit ();
// If user chose "Customize" option on form
} else if ( $_POST['A'] == "Customize" ) {
// Present user with form to customize build options
require_once "customize-flags.php";
exit ();
// The following conditional includes all other cases except "Get Image"
// particularly the explicit ($A == "Start Over") case
} else if ( $_POST['A'] != "Get Image" ) {
// Note that this method of redirections discards all the
// configuration flags, which is intentional in this case.
$dest = curDirURL ();
header ( "Location: $dest" );
// This next "echo" should normally not be seen, because
// the "header" statement above should cause immediate
// redirection but just in case...
echo "Try this link: <a href=\"$dest\">$dest</a>";
exit ();
}
// OK, we're going to try to use whatever options have been set
// to build an image.
// Make sure at least $nic was supplied
if ( ! isset ( $_POST['nic'] ) ) {
die ( "No NIC supplied!" );
}
if ( isset ( $nics[$_POST['nic']] ) ) {
$nic = $nics[$_POST['nic']];
} else {
die ( "Invalid NIC \"${_POST['nic']}\" supplied!" );
}
// Fetch flags
$flags = get_flags ();
// Get requested format
$ofmt = isset ( $_POST['ofmt'] ) ? $_POST['ofmt'] : "";
$fmt_extension = isset ( $ofmts[$ofmt] ) ? $ofmts[$ofmt] : 'dsk';
// Handle some special cases
$pci_vendor_code = "";
$pci_device_code = "";
if ( $nic == 'undionly' && $fmt_extension == "pxe" ) {
// undionly.pxe can't work because it unloads the PXE stack
// that it needs to communicate with, so we set the extension
// to .kpxe, which has a chance of working. The extension
// .kkpxe is another option.
$fmt_extension = "kpxe";
} else if ( $fmt_extension == "rom" ) {
if ( ! isset ( $_POST['pci_vendor_code'] )
|| ! isset ( $_POST['pci_device_code'] ) ) {
die ( "rom output format selected but PCI code(s) missing!" );
}
$pci_vendor_code = $_POST['pci_vendor_code'];
$pci_device_code = $_POST['pci_device_code'];
if ( $pci_vendor_code == ""
|| $pci_device_code == "" ) {
die ( "rom output format selected but PCI code(s) missing!" );
}
// Try to be forgiving of 0xAAAA format
if ( strtolower ( substr ( $pci_vendor_code, 0, 2 ) ) == "0x"
&& strlen ( $pci_vendor_code ) == 6 ) {
$pci_vendor_code = substr ( $pci_vendor_code, 2, 4 );
}
if ( strtolower ( substr ( $pci_device_code, 0, 2 ) ) == "0x"
&& strlen ( $pci_device_code ) == 6 ) {
$pci_device_code = substr ( $pci_device_code, 2, 4 );
}
// concatenate the pci codes to get the $nic part of the
// Make target
$pci_codes = strtolower ( $pci_vendor_code . $pci_device_code );
$nic = $pci_codes;
if ( ! isset ( $roms[$pci_codes] ) ) {
die ( "Sorry, no network driver supports PCI codes<br>"
. "${_POST['pci_vendor_code']}:"
. "${_POST['pci_device_code']}" );
}
} else if ( $fmt_extension != "rom"
&& ( $pci_vendor_code != "" || $pci_device_code != "" ) ) {
die ( "'$fmt_extension' format was selected but PCI IDs were"
. " also entered.<br>Did you mean to select 'rom' output format"
. " instead?" );
}
/**
* remove temporary build directory
*
* @return bool true if removal is successful, false otherwise
*/
function rm_build_dir ()
{
global $build_dir;
global $keep_build_dir;
if ( $keep_build_dir !== true ) {
rm_file_or_dir ( $build_dir );
}
}
// Arrange for the build directory to always be removed on exit.
$build_dir = "";
$keep_build_dir = false;
register_shutdown_function ( 'rm_build_dir' );
// Make temporary copy of src directory
$build_dir = mktempcopy ( "$src_dir", "/tmp", "MDCROM" );
$config_dir = $build_dir . "/config";
// Write config files with supplied flags
write_ipxe_config_files ( $config_dir, $flags );
// Handle a possible embedded script
$emb_script_cmd = "";
$embedded_script = isset ( $_POST['embedded_script'] ) ? $_POST['embedded_script'] : "";
if ( $embedded_script != "" ) {
$emb_script_path = "$build_dir" . "/script0.ipxe";
if ( substr ( $embedded_script, 0, 5 ) != "#!ipxe" ) {
$embedded_script = "#!ipxe\n" . $embedded_script;
}
// iPXE 0.9.7 doesn't like '\r\n" in the shebang...
$embedded_script = str_replace ( "\r\n", "\n", $embedded_script );
write_file_from_string ( $emb_script_path, $embedded_script );
$emb_script_cmd = "EMBEDDED_IMAGE=${emb_script_path}";
}
// Make the requested image. $status is set to 0 on success
$make_target = "bin/${nic}.${fmt_extension}";
$gitversion = exec('git describe --always --abbrev=1 --match "" 2>/dev/null');
if ($gitversion) {
$gitversion = "GITVERSION=$gitversion";
}
$make_cmd = "make -C '$build_dir' '$make_target' $gitversion $emb_script_cmd 2>&1";
exec ( $make_cmd, $maketxt, $status );
// Uncomment the following section for debugging
/**
echo "<h2>build.php:</h2>";
echo "<h3>Begin debugging output</h3>";
//echo "<h3>\$_POST variables</h3>";
//echo "<pre>"; var_dump ( $_POST ); echo "</pre>";
echo "<h3>Build options:</h3>";
echo "<strong>Build directory is:</strong> $build_dir" . "<br><br>";
echo "\$_POST['ofmt'] = " . "\"${_POST['ofmt']}\"" . "<br>";
echo "\$_POST['nic'] = " . "\"${_POST['nic']}\"" . "<br>";
echo "\$_POST['pci_vendor_code'] = " . "\"${_POST['pci_vendor_code']}\"" . "<br>";
echo "\$_POST['pci_device_code'] = " . "\"${_POST['pci_device_code']}\"" . "<br>";
echo "<h3>Flags:</h3>";
show_flags ( $flags );
if ( $embedded_script != "" ) {
echo "<h3>Embedded script:</h3>";
echo "<blockquote>"."<pre>";
echo $embedded_script;
echo "</pre>"."</blockquote>";
}
echo "<h3>Make output:</h3>";
echo "Make command: " . $make_cmd . "<br>";
echo "Build status = <? echo $status ?>" . "<br>";
echo "<blockquote>"."<pre>";
echo htmlentities ( implode ("\n", $maketxt ) );
echo "</pre>"."</blockquote>";
// Uncomment the next line if you want to keep the
// build directory around for inspection after building.
$keep_build_dir = true;
die ( "<h3>End debugging output</h3>" );
**/ // End debugging section
// Send ROM to browser (with extreme prejudice)
if ( $status == 0 ) {
$fp = fopen("${build_dir}/${make_target}", "rb" );
if ( $fp > 0 ) {
$len = filesize ( "${build_dir}/${make_target}" );
if ( $len > 0 ) {
$buf = fread ( $fp, $len );
fclose ( $fp );
// Delete build directory as soon as it is not needed
rm_build_dir ();
$output_filename = preg_replace('/[^a-z0-9\+\.\-]/i', '', "ipxe-${version}-${nic}.${fmt_extension}");
// Try to force IE to handle downloading right.
Header ( "Cache-control: private");
Header ( "Content-Type: application/x-octet-stream; " .
"name=$output_filename");
Header ( "Content-Disposition: attachment; " .
"Filename=$output_filename");
Header ( "Content-Location: $output_filename");
Header ( "Content-Length: $len");
echo $buf;
exit ();
}
}
}
/*
* If we reach this point, the build has failed, and we provide
* debugging information for a potential bug report
*
*/
// Remove build directory
rm_build_dir ();
// Announce failure if $status from make was non-zero
echo "<h2>Build failed. Status = " . $status . "</h2>";
echo "<h2>build.php:</h2>";
echo "<h3>Build options:</h3>";
echo "<strong>Build directory is:</strong> $build_dir" . "<br><br>";
echo "\$_POST['ofmt'] = " . "\"${_POST['ofmt']}\"" . "<br>";
echo "\$_POST['nic'] = " . "\"${_POST['nic']}\"" . "<br>";
echo "\$_POST['pci_vendor_code'] = " . "\"${_POST['pci_vendor_code']}\"" . "<br>";
echo "\$_POST['pci_device_code'] = " . "\"${_POST['pci_device_code']}\"" . "<br>";
echo "<h3>Flags:</h3>";
show_flags ( $flags );
if ( $embedded_script != "" ) {
echo "<h3>Embedded script:</h3>";
echo "<blockquote>"."<pre>";
echo $embedded_script;
echo "</pre>"."</blockquote>";
}
echo "<h3>Make output:</h3>";
echo "Make command: " . $make_cmd . "<br>";
echo "<blockquote>"."<pre>";
echo htmlentities ( implode ("\n", $maketxt ) );
echo "</pre>"."</blockquote>";
echo "Please let us know that this happened, and paste the above output into your email message.<br>";
include_once $bottom_inc;
// For emacs:
// Local variables:
// c-basic-offset: 4
// c-indent-level: 4
// tab-width: 4
// End:
?>

View File

@ -1,69 +0,0 @@
<?php // -*- Mode: PHP; -*-
/**
* Copyright (C) 2009 Marty Connor <mdc@etherboot.org>.
* Copyright (C) 2009 Entity Cyber, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
// Get utility functions and set globals
require_once "utils.php";
// Prepare settable compile options for presentation to user
$flags = default_flags ();
$build = "<input type=\"submit\" name=\"A\" value=\"Get Image\">";
$restart = "<input type=\"submit\" name=\"A\" value=\"Start Over\">";
// Begin html output
include_once $top_inc;
?>
<form action="build.php" method=POST>
<input type="hidden" name="version" value = "<?php echo $version ?>">
<input type="hidden" name="use_flags" value="1">
<h3>
Make changes below and press <?php echo $build ?> to create an image, <br>
Or press <?php echo $restart ?> to return to the main page.
</h3>
<hr>
<ul>
<?php require ( "directions.php" ); ?>
</ul>
<hr>
<?php echo_flags( $flags ); ?>
<hr>
<h3>Embedded Script:</h3>
<?php echo textarea ( "embedded_script", "", "10", "50" ); ?>
<br><br>
<hr>
<center><table width="35%"><tr>
<td align="left"> <?php echo $build; ?> </td>
<td align="right"> <?php echo $restart ?></td>
</tr></table></center>
</form>
<?php include_once $bottom_inc; ?>
<?
// For emacs:
//
// Local variables:
// c-basic-offset: 4
// c-indent-level: 4
// tab-width: 4
// End:
?>

View File

@ -1,63 +0,0 @@
<?php
/**
* Copyright (C) 2009 Marty Connor <mdc@etherboot.org>.
* Copyright (C) 2009 Entity Cyber, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
?>
<li>
Choose an output format: <?php echo keys_menubox ( "ofmt", $ofmts,
isset ( $_POST['ofmt'] ) ? $_POST['ofmt'] : "") ?>
<br><br>
</li>
<li>
Choose a NIC type: <?php echo keys_menubox ( "nic", $nics,
isset ( $_POST['nic'] ) ? $_POST['nic'] : "" ) ?>
<br><br>
</li>
<li>
<strong>( optional &mdash; for binary ROM image format only )</strong> <br><br>
If you choose <em>Binary ROM image</em> as your output format, you must<br>
enter <strong>4 hex digits</strong> below for
<em>PCI VENDOR CODE</em> and <em>PCI DEVICE CODE</em> <br>
that match the NIC device for which you are making this image.<br><br>
Information on how to determine NIC PCI IDs may be found
<a href="http://www.ipxe.org/howto/romburning"
target="_blank">here</a>.
<br><br>
PCI VENDOR CODE: <?php echo textbox ( "pci_vendor_code",
isset ( $_POST['pci_vendor_code'] ) ? $_POST['pci_vendor_code']
: "", 6 ); ?>
&nbsp;&nbsp;
PCI DEVICE CODE: <?php echo textbox ( "pci_device_code",
isset ( $_POST['pci_device_code'] ) ? $_POST['pci_device_code']
: "", 6 ); ?>
<h4>Please note for ROM images:</h4>
<ul>
<li>
If you enter PCI IDs, we will attempt to determine the correct<br>
driver to support them, and will ignore any NIC type entered
above.<br><br>
</li>
<li>
iPXE does not support all possible PCI IDs for supported
NICs.
<br><br>
</li>
</ul>
</li>

View File

@ -1 +0,0 @@
Automatic booting

View File

@ -1 +0,0 @@
Tenths of a second for which the shell banner should appear

View File

@ -1,3 +0,0 @@
Serial Console I/O port address. Common addresses are:<br>
COM1 => 0x3f8, COM2 => 0x2f8, COM3 => 0x3e8, COM4 => 0x2e8

View File

@ -1 +0,0 @@
Serial Console Data bits

View File

@ -1 +0,0 @@
Serial Console Parity: 0=None, 1=Odd, 2=Even

View File

@ -1 +0,0 @@
Keep settings from a previous user of the serial port

View File

@ -1 +0,0 @@
Serial Console Baud rate

View File

@ -1 +0,0 @@
Serial Console Stop bits

View File

@ -1 +0,0 @@
Option configuration console

View File

@ -1 +0,0 @@
Enable Default BIOS console

View File

@ -1 +0,0 @@
Enable Serial port console

View File

@ -1 +0,0 @@
Wireless WEP encryption support

View File

@ -1 +0,0 @@
Wireless WPA encryption support

View File

@ -1 +0,0 @@
Wireless WPA2 encryption support

View File

@ -1 +0,0 @@
DHCP management commands

View File

@ -1 +0,0 @@
DNS resolver

View File

@ -1 +0,0 @@
File Transfer Protocol

View File

@ -1 +0,0 @@
Hypertext Transfer Protocol

View File

@ -1 +0,0 @@
Trivial File Transfer Protocol

View File

@ -1 +0,0 @@
Interface management commands

View File

@ -1 +0,0 @@
Linux bzImage image support

View File

@ -1 +0,0 @@
Image management commands

View File

@ -1 +0,0 @@
ELF image support

View File

@ -1 +0,0 @@
MultiBoot image support

View File

@ -1 +0,0 @@
NBI image support

View File

@ -1 +0,0 @@
PXE image support

View File

@ -1 +0,0 @@
iPXE script image support

View File

@ -1 +0,0 @@
Wireless interface management commands

View File

@ -1 +0,0 @@
NMB resolver

View File

@ -1 +0,0 @@
Non-volatile option storage commands

View File

@ -1 +0,0 @@
Routing table management commands

View File

@ -1 +0,0 @@
SAN boot commands

View File

@ -1,531 +0,0 @@
<?php // -*- Mode: PHP; -*-
/**
* Copyright (C) 2009 Marty Connor <mdc@etherboot.org>.
* Copyright (C) 2009 Entity Cyber, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
$ofmts = array
( "Floppy bootable image (.dsk)" => "dsk",
"SYSLINUX-based bootable floppy image (.sdsk)" => "sdsk",
"ISO bootable image (.iso)" => "iso",
"ISO bootable image with legacy floppy emulation (.liso)" => "liso",
"Linux kernel (SYSLINUX/GRUB/LILO) loadable image (.lkrn)" => "lkrn",
"USB Keychain disk image (.usb)" => "usb",
"ROM binary (flashable) image (.rom)" => "rom",
"ROM binary (flashable) for problem PMM BIOSES (.hrom)" => "hrom",
"PXE bootstrap loader image [Unload PXE stack] (.pxe)" => "pxe",
"PXE bootstrap loader keep [Keep PXE stack method 1] (.kpxe)" => "kpxe",
"PXE bootstrap loader keep [Keep PXE stack method 2] (.kkpxe)" => "kkpxe",
);
$flag_table = array (
// Begin General Options:
"HDR_MISC_OPTIONS"
=> array (
"flag" => "HDR_MISC_OPTIONS",
"hide_from_user" => "yes", // Hide even the header
"type" => "header",
"label" => "Miscellaneous Options"
),
"PRODUCT_NAME"
=> array (
"flag" => "PRODUCT_NAME",
"hide_from_user" => "yes",
"type" => "string",
"value" => "",
"cfgsec" => "general"
),
"PRODUCT_SHORT_NAME"
=> array (
"flag" => "PRODUCT_SHORT_NAME",
"hide_from_user" => "yes",
"type" => "string",
"value" => "iPXE",
"cfgsec" => "general"
),
// End General Options:
// Begin Console Options:
"HDR_CONSOLE_OPTIONS"
=> array (
"flag" => "HDR_CONSOLE_OPTIONS",
"type" => "header",
"label" => "Console Options"
),
"CONSOLE_PCBIOS"
=> array (
"flag" => "CONSOLE_PCBIOS",
"type" => "on/off",
"value" => "on",
"cfgsec" => "console"
),
"CONSOLE_SERIAL"
=> array (
"flag" => "CONSOLE_SERIAL",
"type" => "on/off",
"value" => "off",
"cfgsec" => "console"
),
"BANNER_TIMEOUT"
=> array (
"flag" => "BANNER_TIMEOUT",
"type" => "integer",
"value" => "20",
"cfgsec" => "general"
),
"KEYBOARD_MAP"
=> array (
"flag" => "KEYBOARD_MAP",
"type" => "choice",
"options" => array("al","az","bg","by","cf","cz","de","dk","es","et","fi","fr",
"gr","hu","il","it","lt","mk","mt","nl","no","pl","pt","ro","ru","sg","sr",
"th","ua","uk","us","wo"),
"value" => "us",
"cfgsec" => "console"
),
"LOG_LEVEL"
=> array (
"flag" => "LOG_LEVEL",
"type" => "choice",
"options" => array("LOG_NONE","LOG_EMERG","LOG_ALERT","LOG_CRIT","LOG_ERR",
"LOG_WARNING","LOG_NOTICE","LOG_INFO","LOG_DEBUG","LOG_ALL"),
"value" => "LOG_NONE",
"cfgsec" => "console"
),
// End Console Options
// Begin Network Protocol Options:
"HDR_NETWORK_PROTOCOL_OPTIONS"
=> array (
"flag" => "HDR_NETWORK_PROTOCOL_OPTIONS",
"hide_from_user" => "yes", // Hide even the header
"type" => "header",
"label" => "Network Protocol Options"
),
"NET_PROTO_IPV4"
=> array (
"flag" => "NET_PROTO_IPV4",
"type" => "on/off",
"value" => "on",
"hide_from_user" => "yes",
"cfgsec" => "general"
),
// End Network Protocol Options
// Begin Serial Port configuration
"HDR_SERIAL_PORT_OPTIONS"
=> array (
"flag" => "HDR_SERIAL_PORT_OPTIONS",
"type" => "header",
"label" => "Serial Port Options"
),
"COMCONSOLE"
=> array (
"flag" => "COMCONSOLE",
"type" => "integer-hex", // e.g. 0x378
"value" => "0x3F8",
"cfgsec" => "serial"
),
"COMPRESERVE"
=> array (
"flag" => "COMPRESERVE",
"type" => "on/off",
"value" => "off",
"cfgsec" => "serial"
),
"COMSPEED"
=> array (
"flag" => "COMSPEED",
"type" => "integer",
"value" => "115200",
"cfgsec" => "serial"
),
"COMDATA"
=> array (
"flag" => "COMDATA",
"type" => "integer",
"value" => "8",
"cfgsec" => "serial"
),
"COMPARITY"
=> array (
"flag" => "COMPARITY",
"type" => "integer",
"value" => "0",
"cfgsec" => "serial"
),
"COMSTOP"
=> array (
"flag" => "COMSTOP",
"type" => "integer",
"value" => "1",
"cfgsec" => "serial"
),
// End Serial Options
// Begin Download Protocols
"HDR_DOWNLOAD_PROTOCOLS"
=> array (
"flag" => "HDR_DOWNLOAD_PROTOCOLS",
"type" => "header",
"label" => "Download Protocols"
),
"DOWNLOAD_PROTO_TFTP"
=> array (
"flag" => "DOWNLOAD_PROTO_TFTP",
"type" => "on/off",
"value" => "on",
"cfgsec" => "general"
),
"DOWNLOAD_PROTO_HTTP"
=> array (
"flag" => "DOWNLOAD_PROTO_HTTP",
"type" => "on/off",
"value" => "on",
"cfgsec" => "general"
),
"DOWNLOAD_PROTO_HTTPS"
=> array (
"flag" => "DOWNLOAD_PROTO_HTTPS",
"type" => "on/off",
"value" => "off",
"cfgsec" => "general"
),
"DOWNLOAD_PROTO_FTP"
=> array (
"flag" => "DOWNLOAD_PROTO_FTP",
"type" => "on/off",
"value" => "off",
"cfgsec" => "general"
),
// End Download Protocols
// Begin SAN boot protocols
"HDR_SANBOOT_PROTOCOLS"
=> array (
"flag" => "HDR_SANBOOT_PROTOCOLS",
"type" => "header",
"label" => "SAN Boot Protocols"
),
"SANBOOT_PROTO_ISCSI"
=> array (
"flag" => "SANBOOT_PROTO_ISCSI",
"type" => "on/off",
"value" => "on",
"cfgsec" => "general"
),
"SANBOOT_PROTO_AOE"
=> array (
"flag" => "SANBOOT_PROTO_AOE",
"type" => "on/off",
"value" => "on",
"cfgsec" => "general"
),
// End SAN boot protocols
// Begin Name resolution modules
"HDR_NAME_RESOLUTION_MODULES"
=> array (
"flag" => "HDR_NAME_RESOLUTION_MODULES",
"type" => "header",
"label" => "Name Resolution Modules"
),
"DNS_RESOLVER"
=> array (
"flag" => "DNS_RESOLVER",
"type" => "on/off",
"value" => "on",
"cfgsec" => "general"
),
"NMB_RESOLVER"
=> array (
"flag" => "NMB_RESOLVER",
"type" => "on/off",
"value" => "off",
"hide_from_user" => "yes",
"cfgsec" => "general"
),
// End Name resolution modules
// Begin Image types
"HDR_IMAGE_TYPES"
=> array (
"flag" => "HDR_IMAGE_TYPES",
"type" => "header",
"label" => "Image Types",
),
"IMAGE_ELF"
=> array (
"flag" => "IMAGE_ELF",
"type" => "on/off",
"value" => "on",
"cfgsec" => "general"
),
"IMAGE_NBI"
=> array (
"flag" => "IMAGE_NBI",
"type" => "on/off",
"value" => "on",
"cfgsec" => "general"
),
"IMAGE_MULTIBOOT"
=> array (
"flag" => "IMAGE_MULTIBOOT",
"type" => "on/off",
"value" => "on",
"cfgsec" => "general"
),
"IMAGE_PXE"
=> array (
"flag" => "IMAGE_PXE",
"type" => "on/off",
"value" => "on",
"cfgsec" => "general"
),
"IMAGE_SCRIPT"
=> array (
"flag" => "IMAGE_SCRIPT",
"type" => "on/off",
"value" => "on",
"cfgsec" => "general"
),
"IMAGE_BZIMAGE"
=> array (
"flag" => "IMAGE_BZIMAGE",
"type" => "on/off",
"value" => "on",
"cfgsec" => "general"
),
"IMAGE_COMBOOT"
=> array (
"flag" => "IMAGE_COMBOOT",
"type" => "on/off",
"value" => "on",
"cfgsec" => "general"
),
// End Image types
// Begin Command-line commands to include
"HDR_COMMAND_LINE_OPTIONS"
=> array (
"flag" => "HDR_COMMAND_LINE_OPTIONS",
"type" => "header",
"label" => "Command Line Options",
),
"AUTOBOOT_CMD"
=> array (
"flag" => "AUTOBOOT_CMD",
"type" => "on/off",
"value" => "on",
"cfgsec" => "general"
),
"NVO_CMD"
=> array (
"flag" => "NVO_CMD",
"type" => "on/off",
"value" => "on",
"cfgsec" => "general"
),
"CONFIG_CMD"
=> array (
"flag" => "CONFIG_CMD",
"type" => "on/off",
"value" => "on",
"cfgsec" => "general"
),
"IFMGMT_CMD"
=> array (
"flag" => "IFMGMT_CMD",
"type" => "on/off",
"value" => "on",
"cfgsec" => "general"
),
"IWMGMT_CMD"
=> array (
"flag" => "IWMGMT_CMD",
"type" => "on/off",
"value" => "on",
"cfgsec" => "general"
),
"ROUTE_CMD"
=> array (
"flag" => "ROUTE_CMD",
"type" => "on/off",
"value" => "on",
"cfgsec" => "general"
),
"IMAGE_CMD"
=> array (
"flag" => "IMAGE_CMD",
"type" => "on/off",
"value" => "on",
"cfgsec" => "general"
),
"DHCP_CMD"
=> array (
"flag" => "DHCP_CMD",
"type" => "on/off",
"value" => "on",
"cfgsec" => "general"
),
"SANBOOT_CMD"
=> array (
"flag" => "SANBOOT_CMD",
"type" => "on/off",
"value" => "on",
"cfgsec" => "general"
),
"LOGIN_CMD"
=> array (
"flag" => "LOGIN_CMD",
"type" => "on/off",
"value" => "on",
"cfgsec" => "general"
),
"TIME_CMD"
=> array (
"flag" => "TIME_CMD",
"type" => "on/off",
"value" => "off",
"cfgsec" => "general"
),
"DIGEST_CMD"
=> array (
"flag" => "DIGEST_CMD",
"type" => "on/off",
"value" => "off",
"cfgsec" => "general"
),
// End Command-line commands to include
// Begin Wireless options
"HDR_WIRELESS_OPTIONS"
=> array (
"flag" => "HDR_WIRELESS_OPTIONS",
"type" => "header",
"label" => "Wireless Interface Options",
),
"CRYPTO_80211_WEP"
=> array (
"flag" => "CRYPTO_80211_WEP",
"type" => "on/off",
"value" => "on",
"cfgsec" => "general"
),
"CRYPTO_80211_WPA"
=> array (
"flag" => "CRYPTO_80211_WPA",
"type" => "on/off",
"value" => "on",
"cfgsec" => "general"
),
"CRYPTO_80211_WPA2"
=> array (
"flag" => "CRYPTO_80211_WPA2",
"type" => "on/off",
"value" => "on",
"cfgsec" => "general"
),
// End Wireless options
// Obscure options required to compile
"NETDEV_DISCARD_RATE"
=> array (
"flag" => "NETDEV_DISCARD_RATE",
"type" => "integer",
"value" => "0",
"cfgsec" => "general",
"hide_from_user" => true
)
// End Obscure options
);
// For emacs:
// Local variables:
// c-basic-offset: 4
// c-indent-level: 4
// tab-width: 4
// End:
?>

View File

@ -1,51 +0,0 @@
<?php // -*- Mode: PHP; -*-
/**
* Copyright (C) 2009 Marty Connor <mdc@etherboot.org>.
* Copyright (C) 2009 Entity Cyber, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
// Directory containing iPXE source code tree
$src_dir = "../../src";
// Compute iPXE version based on source tree
exec ( "make -C '$src_dir' version 2>&1", $make_output, $status );
$version = ( $status == 0 && count ( $make_output ) > 1 )
? trim ( $make_output[count ( $make_output ) - 2] )
: "";
// Email address of person responsible for this website
$webmaster_email = "webmaster@example.com";
// Files that header and footer text
$top_inc = "top.php";
$bottom_inc = "bottom.php";
// Descriptive strings
$header_title = "ROM-o-matic for iPXE $version";
$html_tagline = "ROM-o-matic dynamically generates iPXE images";
$html_title = "ROM-o-matic for iPXE $version";
$description = "a dynamic iPXE image generator";
// For emacs:
// Local variables:
// c-basic-offset: 4
// c-indent-level: 4
// tab-width: 4
// End:
?>

View File

@ -1,47 +0,0 @@
<?php // -*- Mode: PHP; -*-
/**
* Copyright (C) 2009 Marty Connor <mdc@etherboot.org>.
* Copyright (C) 2009 Entity Cyber, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
// Get utility functions and set globals
require_once "utils.php";
// Begin html output
include_once $top_inc;
?>
<form action="build.php" method=POST>
<input type="hidden" name="version" value = "<?php echo $version ?>">
<h3>To create an image:</h3>
<ol>
<?php require ( "directions.php" ); ?>
<li>
Generate and download an image:
<input type="submit" name="A" value="Get Image">
<br><br>
</li>
<li>
(optional) Customize image configuration options:
<input type="submit" name="A" value="Customize">
<br><br>
</li>
</ol>
</form>
<?php include_once $bottom_inc ?>

View File

@ -1,41 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<?php
/**
* Copyright (C) 2009 Marty Connor <mdc@etherboot.org>.
* Copyright (C) 2009 Entity Cyber, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
?>
<html>
<head>
<link rev="made" href="mailto:<?php echo "${webmaster_email}" ?>">
<meta name="keywords" content="rom, etherboot, ipxe, open source, rom-o-matic.net">
<title><?php echo $header_title ?></title>
<meta name="description" content="<?php echo $description ?>">
</head>
<h1>
<?php echo "$html_title" ?>&nbsp;
</h1>
<hr>
<h2>
<?php echo "$html_tagline" ?>
</h2>
</form>
<hr>

View File

@ -1,684 +0,0 @@
<?php // -*- Mode: PHP; -*-
/**
* Copyright (C) 2009 Marty Connor <mdc@etherboot.org>.
* Copyright (C) 2009 Entity Cyber, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
// Include table of user-configurable iPXE options
require_once "flag-table.php";
// Include user-shadowable globals
require_once "globals.php";
// Allow user to shadow globals
if ( is_file ( 'local-config.php' ) ) {
include_once "local-config.php";
}
////
// General utility functions
////
/**
* Remove undesirable characters from a given string
*
* Certain characters have the potential to be used for
* malicious purposes by web-based attackers. This routine
* filters out such characters.
*
* @param string $s supplied string
*
* @return string returned string with unwanted characters
* removed
*/
function cleanstring ( $s )
{
$len = strlen ( $s );
if ( $len > 80 ) {
$s = substr ( $s, 0, 80 );
}
$s = trim ( $s );
$pos = 0;
$result = "";
while ( $pos < $len ) {
$ltr = ord ( ucfirst ( $s[$pos] ) );
if ( ( $ltr >= ord ( "A" ) ) && ( $ltr <= ord ( "Z" ) ) ||
( $ltr >= ord ( "0" ) ) && ( $ltr <= ord ( "9" ) ) ||
( $ltr == ord ( "." ) ) && ( strlen ( $result ) > 0 ) ||
( $ltr == ord ( "_" ) ) ||
( $ltr == ord ( "+" ) ) ||
( $ltr == ord ( ":" ) ) ||
( $ltr == ord ( "/" ) ) ||
( $ltr == ord ( "-" ) ) ) {
$result .= $s[$pos];
}
$pos++;
}
return $result;
}
/**
* Return URL of the currently running script, minus the filename
*
* @return string the URL of the currently running script, minus the filename
*/
function curDirURL ()
{
$dir = dirname ( $_SERVER['PHP_SELF'] );
if ( $dir == "." || $dir == "/" ) {
$dir = "";
}
$isHTTPS = ( isset ( $_SERVER["HTTPS"] ) && $_SERVER["HTTPS"] == "on" );
$port = ( isset($_SERVER["SERVER_PORT"] ) &&
( ( !$isHTTPS && $_SERVER["SERVER_PORT"] != "80" ) ||
( $isHTTPS && $_SERVER["SERVER_PORT"] != "443" ) ) );
$port = ( $port ) ? ':' . $_SERVER["SERVER_PORT"] : '';
$dest = ( $isHTTPS ? 'https://' : 'http://' ) .
$_SERVER["SERVER_NAME"] . $dir . "/";
return $dest;
}
/**
* Extract NIC families and associated ROM PCI IDs from the src/bin/NIC file.
*
* $src_dir must contain the path of the iPXE src directory for this build
*
* @return array[0] array $new_nics
* @return array[1] array $roms
*/
function parse_nic_file ()
{
global $src_dir;
$fd = fopen ( "$src_dir/bin/NIC", "r" );
if ( ! $fd ) {
die ( "Missing src/bin/NIC file. 'make bin/NIC'" );
}
$nics = array ();
$roms = array ();
$nic = "";
while ( !feof ( $fd ) ) {
$line = trim ( fgets ( $fd, 200 ) );
$first_eight_chars = substr ( $line, 0, 8 );
settype ( $first_eight_chars, "string" );
if ( strpos ( $first_eight_chars, "family" ) === 0 ) {
// get pathname of NIC driver
#list ( $dummy, $nic ) = split( "[ \t]+", $line );
list ( $dummy, $nic ) = explode("\t", $line);
settype ( $nic, "string" );
// extract filename name of driver from pathname
$nic = substr ( $nic, strrpos ( $nic, "/" ) + 1,
strlen ( $nic ) - strrpos ( $nic, "/" ) + 1 );
$nics[$nic] = $nic;
// For each ISA NIC, there can only be one ROM variant
$roms[$nic] = $nic;
}
// If the first 8 digits of the line are hex digits
// add this rom to the current nic family.
if ( ( strlen ( $first_eight_chars ) == 8 )
&& ( ctype_xdigit ( $first_eight_chars ) )
&& ( $nic != "" ) ) {
$roms[$first_eight_chars] = $nic;
}
}
fclose ( $fd );
// put most NICs in nice alpha order for menu
ksort ( $nics );
// add special cases to the top
$new_nics = array ( "all-drivers" => "ipxe",
"undionly" => "undionly",
"undi" => "undi",
);
foreach ( $nics as $key => $value ) {
// skip the undi driver
if ( $key != "undi" ) {
$new_nics[$key] = $value;
}
}
return array ( $new_nics, $roms );
}
////
// HTML form utility functions
////
/**
* Return html code to create hidden form input fields
*
* @param string $flag name of form variable to set
* @param string $value value to give form variable
*
* @return string html code for given hidden form input field
*/
function hidden ( $flag, $value )
{
$value = htmlentities ( $value );
return "<input type=\"hidden\" value=\"$value\" name=\"$flag\"></input>";
}
/**
* Return html code to create checkbox form input fields
*
* @param string $flag name of form variable to set
* @param string $value "on" means box should be checked
*
* @return string html code for given hidden form input field
*/
function checkbox ( $flag, $value )
{
return "<input type=\"checkbox\" value=\"on\" name=\"$flag\"" .
($value == "on" ? " checked>" : ">" );
}
/**
* Return html code to create text form input fields
*
* @param string $flag name of form variable to set
* @param string $value initial contents of field
* @param string $size size in characters of text box
*
* @return string html code for given text input field
*/
function textbox ( $flag, $value, $size )
{
$value = htmlentities ( $value );
return "<input type=\"text\" size=\"$size\" value=\"$value\" name=\"$flag\">";
}
/**
* Return html code to create textarea form fields
*
* @param string $flag name of form variable to set
* @param string $value initial contents of textarea
* @param string $rows height of text area in rows
* @param string $cols width of text area in columns
*
* @return string html code for given textarea input field
*/
function textarea ( $flag, $value, $rows, $cols )
{
$value = htmlentities ( $value );
return "<textarea name=\"$flag\" rows=\"$rows\" cols=\"$cols\">"
. $value . "</textarea>";
}
/**
* Return html code to create select (menu) form fields
*
* Use array of strings as menu choices
*
* @param string $flag name of form variable to set
* @param array $options array of strings representing choices
* @param string $value value of choice to select in menu
*
* @return string html code for given select (menu) input field
*/
function menubox ( $name, $options, $value )
{
$s="<select name=\"$name\">";
foreach ( $options as $ignore => $option ) {
if ( !$value ) $value = $option;
$s .= "<option" . ( $option == $value ? " selected>" : ">" ) .
htmlentities ( $option ) . "</option>";
}
return $s . "</select>";
}
/**
* Return html code to create select (menu) form fields
*
* Use indices of array of strings as menu choices rather than
* the values pointed to by the indicies.
*
* @param string $flag name of form variable to set
* @param array $options array of strings representing choices
* @param string $value value of choice to select in menu
*
* @return string html code for given select (menu) input field
*/
function keys_menubox ( $name, $options, $value )
{
$s="<select name=\"$name\">";
foreach ( $options as $option => $ignore ) {
if ( !$value ) $value = $option;
$s .= "<option" . ( $option == $value ? " selected>" : ">" ) .
htmlentities ( $option ) . "</option>";
}
return $s . "</select>";
}
////
// Flag (compile option) handling functions
////
/**
* Return default compile options (flags)
*
* Initial compile options are in a global called $flag_table.
* Create and return an array containing the ones we want.
*
* @return array default compile options (flags)
*/
function default_flags ()
{
global $flag_table;
$flags = array ();
foreach ( $flag_table as $key => $props ) {
$flag = $props["flag"];
$type = $props["type"];
// Fields like headers have no "value" property
if ( isset ( $props["value"] ) ) {
$flags[$flag] = $props["value"];
}
}
return $flags;
}
/**
* Return combination of default and user compile options (flags)
*
* Initial compile options are in a global called $flag_table.
* Compile options may have been changed via form input. We return
* an array with either the default value of each option or a user
* supplied value from form input.
*
* @return array combined default and user supplied compile options (flags)
*/
function get_flags ()
{
global $flag_table;
$flags = default_flags ();
if ( ! isset ( $_POST["use_flags"] ) )
return $flags;
foreach ( $flag_table as $key => $props ) {
$flag = $props["flag"];
$type = $props["type"];
if ( isset ( $_POST["$flag"] ) ) {
$flags[$flag] = $_POST["$flag"];
if ( $type == "integer-hex" ) {
if ( strtolower ( substr ( $flags[$flag], 0, 2 ) ) != "0x" ) {
$flags[$flag] = "0x" . $flags[$flag];
}
}
} else if ( $type == "on/off" ) {
// Unchecked checkboxes don't pass any POST value
// so we must check for them specially. At this
// point we know that there is no $_POST value set
// for this option. If it is a checkbox, this means
// it is unchecked, so record that in $flags so we
// can later generate an #undef for this option.
$flags[$flag] = "off";
}
}
return $flags;
}
/**
* Output given value in appropriate format for iPXE config file
*
* iPXE config/*.h files use C pre-processor syntax. Output the given
* compile option in a format appropriate to its type
*
* @param string $key index into $flag_table for given compile option
* @param string $value value we wish to set compile option to
*
* @return string code to set compile option to given value
*/
function pprint_flag ( $key, $value )
{
global $flag_table;
// Determine type of given compile option (flag)
$type = $flag_table[$key]["type"];
$s = "";
if ( $type == "on/off" && $value == "on" ) {
$s = "#define $key";
} else if ( $type == "on/off" && $value != "on" ) {
$s = "#undef $key";
} else if ( $type == "string" ) {
$s = ( "#define $key \"" . cleanstring ( $value ) . "\"" );
} else if ($type == "qstring" ) {
$s = ( "#define $key \\\"" . cleanstring ( $value ) . "\\\"" );
} else {
$s = "#define $key " . cleanstring ( $value );
}
return $s;
}
/**
* Output html code to display all compile options as a table
*
* @param array $flags array of compile options
*
* @return void
*/
function echo_flags ( $flags )
{
global $flag_table;
echo "<table>\n";
foreach ( $flag_table as $key => $props ) {
// Hide parameters from users that should not be changed.
$hide_from_user = isset ( $props["hide_from_user"] ) ? $props["hide_from_user"] : "no";
$flag = $props["flag"];
$type = $props["type"];
$value = isset ( $flags[$flag] ) ? $flags[$flag] : '';
if ( $hide_from_user == "yes" ) {
// Hidden flags cannot not be set by the user. We use hidden form
// fields to keep them at their default values.
if ( $type != "header" ) {
echo hidden ( $flag, $value );
}
} else {
// Flag (iPXE compile option) should be displayed to user
if ( $type == "header" ) {
$label = $props["label"];
echo "<td colspan=2><hr><h3>$label</h3><hr></td>";
} else if ($type == "on/off" ) {
echo "<td>", checkbox ( $flag, $value ), "</td><td><strong>$flag</strong></td>";
} else { // don't display checkbox for non-on/off flags
echo "<td>&nbsp;</td><td><strong>$flag: </strong>";
if ($type == "choice" ) {
$options = $props["options"];
echo menubox($flag, $options, $value);
} else {
echo textbox($flag, $value, ($type == "integer" ||
$type == "integer-hex"
? 7 : 25));
}
echo "</td>";
}
echo "</tr>\n";
if ( $type != "header" ) {
echo "<tr><td>&nbsp;</td>";
echo "<td>\n";
if ( is_file ( "doc/$flag.html" ) ) {
include_once "doc/$flag.html";
}
echo "\n</td></tr>\n";
}
}
}
echo "</table>";
}
/**
* Return an array of configuration sections used in all compile options
*
* $flag_table, the global list of compile options contains a 'cfgsec'
* property for each flag we are interested in. We return a list of
* all the unique cfgsec options we find in $flag_table.
*
* @return array an array of strings representing all unique cfgsec values
* found in $flag_table
*/
function get_flag_cfgsecs ()
{
global $flag_table;
$cfgsecs = array ();
foreach ( $flag_table as $key => $props ) {
if ( isset ( $props['cfgsec'] ) ) {
$cfgsec = $props["cfgsec"];
$cfgsecs[$cfgsec] = $cfgsec;
}
}
return $cfgsecs;
}
////
// File and directory handling functions
////
/**
* Create a copy of a given source directory to a given destination
*
* Since we are going to modify the source directory, we create a copy
* of the directory with a unique name in the given destination directory.
* We supply a prefix for the tempnam call to prepend to the random filename
* it generates.
*
* @param string $src source directory
* @param string $dst destination directory
* @param string $prefix string to append to directory created
*
* @return string absolute path to destination directory
*/
function mktempcopy ( $src, $dst, $prefix )
{
if ( $src[0] != "/" ) {
$src = dirname ( $_SERVER['SCRIPT_FILENAME'] ) . "/" . $src;
}
// Create a file in the given destination directory with a unique name
$dir = tempnam ( $dst, $prefix );
// Delete the file just created, since it would interfere with the copy we
// are about to do. We only care that the dir name we copy to is unique.
unlink ( $dir );
exec ( "/bin/cp -a '$src' '$dir' 2>&1", $cpytxt, $status );
if ( $status != 0 ) {
die ( "src directory copy failed!" );
}
return $dir;
}
/**
* Write iPXE config files based on value of given flags
*
* iPXE compile options are stored in src/config/*.h .
* We write out a config file for each set of options.
*
* @param string $config_dir directory to write .h files to
* @param array $flags array of compile options for this build
*
* @return void
*/
function write_ipxe_config_files ( $config_dir, $flags )
{
global $flag_table;
$cfgsecs = get_flag_cfgsecs ();
foreach ( $cfgsecs as $cfgsec ) {
$fname = $config_dir . "/" . $cfgsec . ".h";
$fp = fopen ( $fname, "wb" );
if ( $fp <= 0 ) {
die ( "Unable to open $fname file for output!" );
}
$ifdef_secname = "CONFIG_" . strtoupper ( $cfgsec ) . "_H";
fwrite ( $fp, "#ifndef ${ifdef_secname}\n" );
fwrite ( $fp, "#define ${ifdef_secname}\n" );
fwrite ( $fp, "#include <config/defaults.h>\n" );
foreach ( $flags as $key => $value ) {
// When the flag matches this section name, write it out
if ( $flag_table[$key]["cfgsec"] == $cfgsec ) {
fwrite ( $fp, pprint_flag ( $key, $value ) . "\n" );
}
}
fwrite ( $fp, "#endif /* ${ifdef_secname} */\n" );
fclose ( $fp );
}
}
/**
* Output a string to a file
*
* Output a given string to a given pathname. The file will be created if
* necessary, and the string will replace the file's contents in all cases.
*
* @param string $fname pathname of file to output string to
* @param string $ftext text to output to file
*
* @return void
*/
function write_file_from_string ( $fname, $ftext )
{
$fp = fopen ( $fname, "wb" );
if ( ! $fp ) {
die ( "Unable to open $fname file for output!" );
}
fwrite ( $fp, $ftext );
fclose ( $fp );
}
/**
* Delete a file or recursively delete a directory tree
*
* @param string $file_or_dir_name name of file or directory to delete
* @return bool Returns TRUE on success, FALSE on failure
*/
function rm_file_or_dir ( $file_or_dir_name )
{
if ( ! file_exists ( $file_or_dir_name ) ) {
return false;
}
if ( is_file ( $file_or_dir_name ) || is_link ( $file_or_dir_name ) ) {
return unlink ( $file_or_dir_name );
}
$dir = dir ( $file_or_dir_name );
while ( ( $dir_entry = $dir->read () ) !== false ) {
if ( $dir_entry == '.' || $dir_entry == '..') {
continue;
}
rm_file_or_dir ( $file_or_dir_name . '/' . $dir_entry );
}
$dir->close();
return rmdir ( $file_or_dir_name );
}
////
// Debugging functions
////
/**
* Emit html code to display given array of compile options (flags)
*
* @param array $flags array of compile options for this build
*
* @return void
*/
function show_flags ( $flags )
{
echo ( "\$flags contains " . count ( $flags ) . " elements:" . "<br>" );
foreach ( $flags as $key => $flag ) {
echo ( "\$flags[" . $key . "]=" . "\"$flag\"" . "<br>" );
}
}
/**
* Emit HTML code to display default array of compile options (flags)
*
* $flag_table contains default compile options and properties. This
* routine outputs HTML code to display all properties of $flag_table.
*
* @return void
*/
function dump_flag_table ()
{
global $flag_table;
echo ( "\$flag_table contains " . count ( $flag_table ) . " elements:" . "<br>" );
foreach ( $flag_table as $key => $props ) {
print ( "flag_table[" . $key . "] = " . "<br>" );
foreach ( $props as $key2 => $props2 ) {
print ( "&nbsp;&nbsp;&nbsp;" . $key2 . " = " . $props2 . "<br>" );
}
}
}
// Parse src/bin/NIC file
list ( $nics, $roms ) = parse_nic_file ();
// For emacs:
// Local variables:
// c-basic-offset: 4
// c-indent-level: 4
// tab-width: 4
// End:
?>

View File

@ -25,12 +25,12 @@ plugin_ctrl: unmapped=1, biosdev=1, speaker=1, e1000=1, parallel=1, serial=1
# allows you to change all the settings that control Bochs's behavior.
# Depending on the platform there are up to 3 choices of configuration
# interface: a text mode version called "textconfig" and two graphical versions
# called "win32config" and "wx". The text mode version uses stdin/stdout and
# is always compiled in, unless Bochs is compiled for wx only. The choice
# "win32config" is only available on win32 and it is the default there.
# The choice "wx" is only available when you use "--with-wx" on the configure
# command. If you do not write a config_interface line, Bochs will
# choose a default for you.
# called "win32config" and "wx". The text mode version uses stdin/stdout or
# gui console (if available / runtime config) and is always compiled in, unless
# Bochs is compiled for wx only. The choice "win32config" is only available on
# win32/win64 and it is the default on these platforms. The choice "wx" is only
# available when Bochs is compiled with wxWidgets support. If you do not write
# a config_interface line, Bochs will choose a default for you.
#
# NOTE: if you use the "wx" configuration interface, you must also use
# the "wx" display library.
@ -73,12 +73,14 @@ plugin_ctrl: unmapped=1, biosdev=1, speaker=1, e1000=1, parallel=1, serial=1
# "cmdmode" - call a headerbar button handler after pressing F7 (sdl, sdl2,
# win32, x)
# "fullscreen" - startup in fullscreen mode (sdl, sdl2)
# "gui_debug" - use GTK debugger gui (sdl, sdl2, x) / Win32 debugger gui (sdl,
# sdl2, win32)
# "hideIPS" - disable IPS output in status bar (rfb, sdl, sdl2, term, vncsrv,
# win32, wx, x)
# "nokeyrepeat" - turn off host keyboard repeat (sdl, sdl2, win32, x)
# "no_gui_console" - use system console instead of builtin gui console
# (rfb, sdl, sdl2, vncsrv, x)
# "timeout" - time (in seconds) to wait for client (rfb, vncsrv)
# "gui_debug" - This option is DEPRECATED, use command line option '-dbg_gui'
# instead. It also supports the 'globalini' extension
#
# See the examples below for other currently supported options.
# Setting up options without specifying display library is also supported.
@ -113,9 +115,12 @@ plugin_ctrl: unmapped=1, biosdev=1, speaker=1, e1000=1, parallel=1, serial=1
#
# CPU configurations that can be selected:
# -----------------------------------------------------------------
# i386 Intel 386SX
# i486dx4 Intel 486DX4
# pentium Intel Pentium (P54C)
# pentium_mmx Intel Pentium MMX
# amd_k6_2_chomper AMD-K6(tm) 3D processor (Chomper)
# athlon_xp AMD Athlon(tm) XP Processor
# p2_klamath Intel Pentium II (Klamath)
# p3_katmai Intel Pentium III (Katmai)
# p4_willamette Intel(R) Pentium(R) 4 (Willamette)
@ -136,6 +141,26 @@ plugin_ctrl: unmapped=1, biosdev=1, speaker=1, e1000=1, parallel=1, serial=1
# corei7_ivy_bridge_3770k Intel(R) Core(TM) i7-3770K CPU (Ivy Bridge)
# corei7_haswell_4770 Intel(R) Core(TM) i7-4770 CPU (Haswell)
# broadwell_ult Intel(R) Processor 5Y70 CPU (Broadwell)
# corei7_skylake_x Intel(R) Core(TM) i7-7800X CPU (Skylake)
# corei3_cnl Intel(R) Core(TM) i3-8121U CPU (Cannonlake)
# corei7_icelake_u QuadCore Intel Core i7-1065G7 (IceLake)
# tigerlake 11th Gen Intel(R) Core(TM) i5-1135G7 (TigerLake)
# sapphire_rapids Intel(R) Xeon(R) w9-3475X (Sappire Rapids)
# arrow_lake 15th Gen Intel(R) Core(TM) Ultra 5 245K (ArrowLake)
#
# ADD_FEATURES:
# Enable one of more CPU feature in the CPU configuration selected by MODEL.
# Could be useful for testing CPU with newer imaginary configurations by
# adding a specific feature or set of features to existing MODEL. The list
# of features to add supplied through space or comma separated string.
#
# EXCLUDE_FEATURES:
# Disable one of more CPU feature from CPU configuration selected by MODEL.
# Could be useful for testing CPU without a specific feature or set of
# features. When experiening issues booting a modern OS it could be useful
# to disable CPU features(s) to see if they responsible for the failures.
# The list of features to exclude supplied through space or comma separated
# string.
#
# COUNT:
# Set the number of processors:cores per processor:threads per core when
@ -196,151 +221,6 @@ plugin_ctrl: unmapped=1, biosdev=1, speaker=1, e1000=1, parallel=1, serial=1
cpu: model=core2_penryn_t9600, count=1, ips=50000000, reset_on_triple_fault=1, ignore_bad_msrs=1, msrs="msrs.def"
cpu: cpuid_limit_winnt=0
#=======================================================================
# CPUID:
#
# This defines features and functionality supported by Bochs emulated CPU.
# The option has no offect if CPU model was selected in CPU option.
#
# MMX:
# Select MMX instruction set support.
# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 5.
#
# APIC:
# Select APIC configuration (LEGACY/XAPIC/XAPIC_EXT/X2APIC).
# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 5.
#
# SEP:
# Select SYSENTER/SYSEXIT instruction set support.
# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6.
#
# SIMD:
# Select SIMD instructions support.
# Any of NONE/SSE/SSE2/SSE3/SSSE3/SSE4_1/SSE4_2/AVX/AVX2/AVX512
# could be selected.
#
# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6.
# The AVX choises exists only if Bochs compiled with --enable-avx option.
#
# SSE4A:
# Select AMD SSE4A instructions support.
# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6.
#
# MISALIGNED_SSE:
# Select AMD Misaligned SSE mode support.
# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6.
#
# AES:
# Select AES instruction set support.
# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6.
#
# SHA:
# Select SHA instruction set support.
# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6.
#
# MOVBE:
# Select MOVBE Intel(R) Atom instruction support.
# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6.
#
# ADX:
# Select ADCX/ADOX instructions support.
# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6.
#
# XSAVE:
# Select XSAVE extensions support.
# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6.
#
# XSAVEOPT:
# Select XSAVEOPT instruction support.
# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6.
#
# AVX_F16C:
# Select AVX float16 convert instructions support.
# This option exists only if Bochs compiled with --enable-avx option.
#
# AVX_FMA:
# Select AVX fused multiply add (FMA) instructions support.
# This option exists only if Bochs compiled with --enable-avx option.
#
# BMI:
# Select BMI1/BMI2 instructions support.
# This option exists only if Bochs compiled with --enable-avx option.
#
# XOP:
# Select AMD XOP instructions support.
# This option exists only if Bochs compiled with --enable-avx option.
#
# FMA4:
# Select AMD four operand FMA instructions support.
# This option exists only if Bochs compiled with --enable-avx option.
#
# TBM:
# Select AMD Trailing Bit Manipulation (TBM) instructions support.
# This option exists only if Bochs compiled with --enable-avx option.
#
# X86-64:
# Enable x86-64 and long mode support.
# This option exists only if Bochs compiled with x86-64 support.
#
# 1G_PAGES:
# Enable 1G page size support in long mode.
# This option exists only if Bochs compiled with x86-64 support.
#
# PCID:
# Enable Process-Context Identifiers (PCID) support in long mode.
# This option exists only if Bochs compiled with x86-64 support.
#
# FSGSBASE:
# Enable GS/GS BASE access instructions support in long mode.
# This option exists only if Bochs compiled with x86-64 support.
#
# SMEP:
# Enable Supervisor Mode Execution Protection (SMEP) support.
# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6.
#
# SMAP:
# Enable Supervisor Mode Access Prevention (SMAP) support.
# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6.
#
# MWAIT:
# Select MONITOR/MWAIT instructions support.
# This option exists only if Bochs compiled with --enable-monitor-mwait.
#
# VMX:
# Select VMX extensions emulation support.
# This option exists only if Bochs compiled with --enable-vmx option.
#
# SVM:
# Select AMD SVM (Secure Virtual Machine) extensions emulation support.
# This option exists only if Bochs compiled with --enable-svm option.
#
# VENDOR_STRING:
# Set the CPUID vendor string returned by CPUID(0x0). This should be a
# twelve-character ASCII string.
#
# BRAND_STRING:
# Set the CPUID vendor string returned by CPUID(0x80000002 .. 0x80000004).
# This should be at most a forty-eight-character ASCII string.
#
# LEVEL:
# Set emulated CPU level information returned by CPUID. Default value is
# determined by configure option --enable-cpu-level. Currently supported
# values are 5 (for Pentium and similar processors) and 6 (for P6 and
# later processors).
#
# FAMILY:
# Set model information returned by CPUID. Default family value determined
# by configure option --enable-cpu-level.
#
# MODEL:
# Set model information returned by CPUID. Default model value is 3.
#
# STEPPING:
# Set stepping information returned by CPUID. Default stepping value is 3.
#=======================================================================
#cpuid: x86_64=1, mmx=1, sep=1, simd=sse4_2, apic=xapic, aes=1, movbe=1, xsave=1
#cpuid: family=6, model=0x1a, stepping=5
#=======================================================================
# MEMORY
# Set the amount of physical memory you want to emulate.
@ -357,8 +237,14 @@ cpu: cpuid_limit_winnt=0
# memory pool. You will be warned (by FATAL PANIC) in case guest already
# used all allocated host memory and wants more.
#
# BLOCK_SIZE:
# Memory block size select granularity of host memory allocation. Very
# large memory configurations might requre larger memory blocks which
# configurations with small memory might want memory block smaller.
# Default memory block size is 128K.
#
#=======================================================================
memory: guest=512, host=256
memory: guest=512, host=256, block_size=512
#=======================================================================
# ROMIMAGE:
@ -368,28 +254,50 @@ memory: guest=512, host=256
# starting at address 0xfffe0000, and it is exactly 128k long. The legacy
# version of the Bochs BIOS is usually loaded starting at address 0xffff0000,
# and it is exactly 64k long.
# You can use the environment variable $BXSHARE to specify the location
# of the BIOS.
# The usage of external large BIOS images (up to 512k) at memory top is
# now supported, but we still recommend to use the BIOS distributed with Bochs.
# The start address is optional, since it can be calculated from image size.
# The Bochs BIOS currently supports only the option "fastboot" to skip the
# boot menu delay.
#
# FILE
# Name of the BIOS image file. You can use the environment variable $BXSHARE
# to specify the location of the BIOS.
#
# ADDRESS
# The start address is optional, since it can be calculated from image size.
#
# OPTIONS
# The Bochs BIOS currently only supports the option "fastboot" to skip the
# boot menu delay.
#
# FLASH_DATA
# This parameter defines the file name for the flash BIOS config space loaded
# at startup if existing and saved on exit if modified. The Bochs BIOS doesn't
# use this feature yet.
#
# Please note that if you use the BIOS-bochs-legacy romimage BIOS option,
# you cannot use a PCI enabled VGA ROM BIOS.
# Please note that if you use a SeaBIOS binary in romimage BIOS option,
# you must use a PCI enabled VGA ROM BIOS.
#=======================================================================
#romimage: file=$BXSHARE/BIOS-bochs-latest, options=fastboot
#romimage: file=$BXSHARE/BIOS-bochs-legacy
#romimage: file=$BXSHARE/bios.bin-1.13.0 # http://www.seabios.org/SeaBIOS
#romimage: file=$BXSHARE/i440fx.bin, flash_data=escd.bin
#romimage: file=asus_p6np5.bin, flash_data=escd.bin
#romimage: file=mybios.bin, address=0xfff80000 # 512k at memory top
romimage: file=bochs/bios/BIOS-bochs-latest
#=======================================================================
# VGAROMIMAGE
# You now need to load a VGA ROM BIOS into C0000.
# Please note that if you use the BIOS-bochs-legacy romimage BIOS option,
# you cannot use a PCI enabled VGA ROM BIOS option such as the cirrus
# option shown below.
#=======================================================================
#vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest
#vgaromimage: file=bios/VGABIOS-lgpl-latest-cirrus
#vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest.bin
#vgaromimage: file=bios/VGABIOS-lgpl-latest-cirrus.bin
#vgaromimage: file=$BXSHARE/vgabios-cirrus.bin-1.13.0 # http://www.seabios.org/SeaVGABIOS
#vgaromimage: file=bios/VGABIOS-elpin-2.40
vgaromimage: file=bochs/bios/VGABIOS-lgpl-latest
vgaromimage: file=bochs/bios/VGABIOS-lgpl-latest.bin
#=======================================================================
# OPTROMIMAGE[1-4]:
@ -406,7 +314,7 @@ vgaromimage: file=bochs/bios/VGABIOS-lgpl-latest
#optromimage2: file=optionalrom.bin, address=0xd1000
#optromimage3: file=optionalrom.bin, address=0xd2000
#optromimage4: file=optionalrom.bin, address=0xd3000
optromimage1: file=../../src/bin/intel.rom, address=0xcb000
optromimage1: file=../../src/bin/intel.rom, address=0xc8000
#optramimage1: file=/path/file1.img, address=0x0010000
#optramimage2: file=/path/file2.img, address=0x0020000
@ -426,7 +334,9 @@ optromimage1: file=../../src/bin/intel.rom, address=0xcb000
# UPDATE_FREQ
# This parameter specifies the number of display updates per second.
# The VGA update timer by default uses the realtime engine with a value
# of 5. This parameter can be changed at runtime.
# of 10 (valid: 1 to 75). This parameter can be changed at runtime.
# The special value 0 enables support for using the frame rate of the
# emulated graphics device.
#
# REALTIME
# If set to 1 (default), the VGA timer is based on realtime, otherwise it
@ -440,6 +350,10 @@ optromimage1: file=../../src/bin/intel.rom, address=0xcb000
# the monitor EDID data. By default the 'builtin' values for 'Bochs Screen'
# are used. Other choices are 'disabled' (no DDC emulation) and 'file'
# (read monitor EDID from file / path name separated with a colon).
#
# VBE_MEMSIZE
# With this parameter the size of the memory for the Bochs VBE extension
# can be defined. Valid values are 4, 8, 16 and 32 MB (default is 16 MB).
# Examples:
# vga: extension=cirrus, update_freq=10, ddc=builtin
#=======================================================================
@ -488,6 +402,8 @@ optromimage1: file=../../src/bin/intel.rom, address=0xcb000
# KEYMAP:
# This enables a remap of a physical localized keyboard to a
# virtualized us keyboard, as the PC architecture expects.
# Using a language specifier instead of a file name is also supported.
# A keymap is also required by the paste feature.
#
# USER_SHORTCUT:
# This defines the keyboard shortcut to be sent when you press the "user"
@ -504,7 +420,7 @@ optromimage1: file=../../src/bin/intel.rom, address=0xcb000
# keyboard: keymap=gui/keymaps/x11-pc-de.map
# keyboard: user_shortcut=ctrl-alt-del
#=======================================================================
#keyboard: type=mf, serial_delay=250
#keyboard: type=mf, serial_delay=150
#=======================================================================
# MOUSE:
@ -529,8 +445,8 @@ optromimage1: file=../../src/bin/intel.rom, address=0xcb000
# TOGGLE:
# The default method to toggle the mouse capture at runtime is to press the
# CTRL key and the middle mouse button ('ctrl+mbutton'). This option allows
# to change the method to 'ctrl+f10' (like DOSBox), 'ctrl+alt' (like QEMU)
# or 'f12'.
# to change the method to 'ctrl+f10' (like DOSBox), 'ctrl+alt' (legacy QEMU),
# 'ctrl+alt+g' (QEMU current) or 'f12'.
#
# Examples:
# mouse: enabled=1
@ -567,7 +483,8 @@ mouse: enabled=0
# PCI chipset. These options can be specified as comma-separated values.
# By default the "Bochs i440FX" chipset enables the ACPI and HPET devices, but
# original i440FX doesn't support them. The options 'noacpi' and 'nohpet' make
# it possible to disable them.
# it possible to disable them. The option 'noagp' disables the incomplete AGP
# subsystem of the i440BX chipset.
#
# Example:
# pci: enabled=1, chipset=i440fx, slot1=pcivga, slot2=ne2k, advopts=noacpi
@ -772,10 +689,11 @@ ata3: enabled=0, ioaddr1=0x168, ioaddr2=0x360, irq=9
# This defines the boot sequence. Now you can specify up to 3 boot drives,
# which can be 'floppy', 'disk', 'cdrom' or 'network' (boot ROM).
# Legacy 'a' and 'c' are also supported.
# The new boot choice 'usb' is only supported by the i440fx.bin BIOS.
# Examples:
# boot: floppy
# boot: cdrom, disk
# boot: network, disk
# boot: network, usb, disk
# boot: cdrom, floppy, disk
#=======================================================================
#boot: floppy
@ -929,15 +847,15 @@ parport1: enabled=1, file="parport.out"
# waveoutdrv:
# This defines the driver to be used for the waveout feature.
# Possible values are 'file' (all wave data sent to file), 'dummy' (no
# output) and the platform-dependant drivers 'alsa', 'oss', 'osx', 'sdl'
# and 'win'.
# output), 'pulse', 'sdl' (both cross-platform) and the platform-dependant
# drivers 'alsa', 'oss', 'osx' and 'win'.
# waveout:
# This defines the device to be used for wave output (if necessary) or
# the output file for the 'file' driver.
# waveindrv:
# This defines the driver to be used for the wavein feature.
# Possible values are 'dummy' (recording silence) and platform-dependent
# drivers 'alsa', 'oss', 'sdl' and 'win'.
# Possible values are 'dummy' (recording silence), 'pulse', 'sdl' (both
# cross-platform) and platform-dependent drivers 'alsa', 'oss' and 'win'.
# wavein:
# This defines the device to be used for wave input (if necessary).
# midioutdrv:
@ -967,6 +885,7 @@ parport1: enabled=1, file="parport.out"
# the Beep() function. The 'gui' mode forwards the beep to the related
# gui methods (currently only used by the Carbon gui).
#=======================================================================
#speaker: enabled=1, mode=sound, volume=15
speaker: enabled=1, mode=system
#=======================================================================
@ -1000,14 +919,15 @@ speaker: enabled=1, mode=system
# log: The file to write the sb16 emulator messages to.
# dmatimer:
# microseconds per second for a DMA cycle. Make it smaller to fix
# non-continuous sound. 750000 is usually a good value. This needs a
# reasonably correct setting for the IPS parameter of the CPU option.
# non-continuous sound. 1000000 is usually a good value. This needs a
# reasonably correct setting for the IPS parameter of the CPU option
# and also depends on the clock sync setting.
#
# Examples for output modes:
# sb16: midimode=2, midifile="output.mid", wavemode=1 # MIDI to file
# sb16: midimode=1, wavemode=3, wavefile="output.wav" # wave to file and device
#=======================================================================
#sb16: midimode=1, wavemode=1, loglevel=2, log=sb16.log, dmatimer=600000
#sb16: midimode=1, wavemode=1, loglevel=2, log=sb16.log, dmatimer=900000
#=======================================================================
# ES1370:
@ -1069,7 +989,8 @@ speaker: enabled=1, mode=system
#
# BOOTROM: The bootrom value is optional, and is the name of the ROM image
# to load. Note that this feature is only implemented for the PCI version of
# the NE2000.
# the NE2000. For the ISA version using one of the 'optromimage[1-4]' options
# must be used instead of this one.
#
# If you don't want to make connections to any physical networks,
# you can use the following 'ethmod's to simulate a virtual network.
@ -1137,34 +1058,40 @@ e1000: enabled=1, mac=52:54:00:12:34:56, ethmod=tuntap, ethdev=/dev/net/tun:tap0
# the numeric keypad to the USB device instead of the PS/2 keyboard. If the
# keyboard is selected, all key events are sent to the USB device.
#
# To connect a 'flat' mode image as a USB hardisk you can use the 'disk' device
# with the path to the image separated with a colon. To use other disk image modes
# similar to ATA disks the syntax 'disk:mode:filename' must be used (see below).
# To connect a disk image as a USB hardisk you can use the 'disk' device. Use
# the 'path' option in the optionsX parameter to specify the path to the image
# separated with a colon. To use other disk image modes similar to ATA disks
# the syntax 'path:mode:filename' must be used (see below).
#
# To emulate a USB cdrom you can use the 'cdrom' device name and the path to
# an ISO image or raw device name also separated with a colon. An option to
# insert/eject media is available in the runtime configuration.
# To emulate a USB cdrom you can use the 'cdrom' device and the path to an
# ISO image or raw device name can be set with the 'path' option in the
# optionsX parameter also separated with a colon. An option to insert/eject
# media is available in the runtime configuration.
#
# To emulate a USB floppy you can use the 'floppy' device with the path to the
# image separated with a colon. To use the VVFAT image mode similar to the
# legacy floppy the syntax 'floppy:vvfat:directory' must be used (see below).
# To emulate a USB floppy you can use the 'floppy' device and the path to a
# floppy image can be set with the 'path' option in the optionsX parameter
# separated with a colon. To use the VVFAT image mode similar to the legacy
# floppy the syntax 'path:vvfat:directory' must be used (see below).
# An option to insert/eject media is available in the runtime configuration.
#
# The device name 'hub' connects an external hub with max. 8 ports (default: 4)
# to the root hub. To specify the number of ports you have to add the value
# separated with a colon. Connecting devices to the external hub ports is only
# available in the runtime configuration.
# to the root hub. To specify the number of ports you have to use the 'ports'
# option in the optionsX parameter with the value separated with a colon.
# Connecting devices to the external hub ports is only available in the runtime
# configuration.
#
# The device 'printer' emulates the HP Deskjet 920C printer. The PCL data is
# sent to a file specified in bochsrc.txt. The current code appends the PCL
# code to the file if the file already existed. The output file can be
# changed at runtime.
# sent to a file specified in the 'file' option with the optionsX parameter.
# The current code appends the PCL code to the file if the file already existed.
# The output file can be changed at runtime.
#
# The optionsX parameter can be used to assign specific options to the device
# connected to the corresponding USB port. Currently this feature is used to
# set the speed reported by device ('low', 'full', 'high' or 'super'). The
# available speed choices depend on both HC and device. The option 'debug' turns
# on debug output for the device at connection time.
# connected to the corresponding USB port. The option 'speed' can be used to set
# the speed reported by device ('low', 'full', 'high' or 'super'). The available
# speed choices depend on both HC and device. The option 'debug' turns on debug
# output for the device at connection time. The option 'pcap' turns on packet
# logging in PCAP format.
#
# For the USB 'disk' device the optionsX parameter can be used to specify an
# alternative redolog file (journal) of some image modes. For 'vvfat' mode USB
# disks the optionsX parameter can be used to specify the disk size (range
@ -1174,15 +1101,23 @@ e1000: enabled=1, mac=52:54:00:12:34:56, ethmod=tuntap, ethdev=/dev/net/tun:tap0
# supported (can fix hw detection in some guest OS). The USB floppy also
# accepts the parameter "write_protected" with valid values 0 and 1 to select
# the access mode (default is 0).
#
# For a high- or super-speed USB 'disk' device the optionsX parameter can include
# the 'proto:bbb' or 'proto:uasp' parameter specifying to use either the bulk-only
# Protocol (default) or the USB Attached SCSI Protocol. If no such parameter
# is given, the 'bbb' protocol is used. A Guest that doesn't support UASP
# should revert to bbb even if the 'uasp' attribute is given. See the usb_ehci:
# or usb_xhci: section below for an example. (Only 1 LUN is available at this time)
#=======================================================================
#usb_uhci: enabled=1
#usb_uhci: enabled=1, port1=mouse, port2=disk:usbstick.img
#usb_uhci: enabled=1, port1=hub:7, port2=disk:growing:usbdisk.img
#usb_uhci: enabled=1, port2=disk:undoable:usbdisk.img, options2=journal:redo.log
#usb_uhci: enabled=1, port2=disk:usbdisk2.img, options2=sect_size:1024
#usb_uhci: enabled=1, port2=disk:vvfat:vvfat, options2="debug,speed:full"
#usb_uhci: enabled=1, port1=printer:printdata.bin, port2=cdrom:image.iso
#usb_uhci: enabled=1, port2=floppy:vvfat:diskette, options2="model:teac"
#usb_uhci: port1=mouse, port2=disk, options2="path:usbstick.img"
#usb_uhci: port1=hub, options1="ports:6, pcap:outfile.pcap"
#usb_uhci: port2=disk, options2="path:undoable:usbdisk.img, journal:u.redolog"
#usb_uhci: port2=disk, options2=""path:usbdisk2.img, sect_size:1024"
#usb_uhci: port2=disk, options2="path:vvfat:vvfat, debug, speed:full"
#usb_uhci: port2=cdrom, options2="path:image.iso"
#usb_uhci: port1=printer, options1="file:printdata.bin"
#usb_uhci: port2=floppy, options2="path:vvfat:diskette, model:teac"
#=======================================================================
# USB_OHCI:
@ -1200,19 +1135,61 @@ e1000: enabled=1, mac=52:54:00:12:34:56, ethmod=tuntap, ethdev=/dev/net/tun:tap0
# 6-port hub. The portX parameter accepts the same device types with the
# same syntax as the UHCI controller (see above). The optionsX parameter is
# also available on EHCI.
# The HC will default to three UHCI companion controllers, but you can specify
# either UHCI or OHCI. Each companion controller will be evenly divided
# with 2 ports each, the first 2 on the first companion, and so on.
#=======================================================================
#usb_ehci: enabled=1
#usb_ehci: enabled=1, companion=uhci
#usb_ehci: enabled=1, companion=ohci
#usb_ehci: port1=disk, options1="speed:high, path:hdd.img, proto:bbb"
#usb_ehci: port1=disk, options1="speed:high, path:hdd.img, proto:uasp"
#=======================================================================
# USB_XHCI:
# This option controls the presence of the USB xHCI host controller with a
# 4-port hub. The portX parameter accepts the same device types with the
# same syntax as the UHCI controller (see above). The optionsX parameter is
# also available on xHCI. NOTE: port 1 and 2 are USB3 and only support
# super-speed devices, but port 3 and 4 are USB2 and support speed settings
# low, full and high.
# default 4-port hub. The portX parameter accepts the same device types
# with the same syntax as the UHCI controller (see above). The optionsX
# parameter is also available on xHCI.
#
# The xHCI emulation allows you to set the number of ports used with a range
# of 2 to 10, requiring an even numbered count.
#
# NOTE: The first half of the ports, (ports 1 and 2 on a 4-port hub) are
# USB3 only and support super-speed devices. The second half ports (ports
# 3 and 4) are USB2 and support speed settings of low, full, or high.
# The xHCI also allows for different host controllers using the model=
# parameter. Currently, the two allowed options are "uPD720202" and
# "uPD720201". The first defaults to 2 sockets (4 ports) and the later
# defaults to 4 sockets (8 ports).
#=======================================================================
#usb_xhci: enabled=1
#usb_xhci: enabled=1 # defaults to the uPD720202 w/4 ports
#usb_xhci: enabled=1, n_ports=6 # defaults to the uPD720202 w/6 ports
#usb_xhci: enabled=1, model=uPD720202 # defaults to 4 ports
#usb_xhci: enabled=1, model=uPD720202, n_ports=6 # change to 6 ports
#usb_xhci: enabled=1, model=uPD720201 # defaults to 8 ports
#usb_xhci: enabled=1, model=uPD720201, n_ports=10 # change to 10 ports
#usb_xhci: port1=disk, options1="speed:super, path:hdd.img, proto:bbb"
#usb_xhci: port1=disk, options1="speed:super, path:hdd.img, proto:uasp"
#usb_xhci: port3=disk, options3="speed:high, path:hdd.img, proto:uasp"
#=======================================================================
# USB Debugger:
# This is the experimental USB Debugger for the Windows Platform.
# Specify a type (none, uhci, ohci, ehci, xhci) and one or more triggers.
# (Currently, only xhci is supported, with some uhci in the process)
# Triggers:
# reset: will break and load the debugger on a port reset
# enable: will break and load the debugger on a port enable
# doorbell: will break and load the debugger a xHCI Command Ring addition
# event: will break and load the debugger on a xHCI Event Ring addition
# data: will break and load the debugger on a xHCI Data Ring addition
# start_frame: will break and load the debugger on start of frame
# (this is different for each controller type)
# non_exist: will break and load the debugger on a non-existant port access
# (experimental and is under development)
#=======================================================================
#usb_debug: type=xhci, reset=1, enable=1, start_frame=1, doorbell=1, event=1, data=1, non_exist=1
#=======================================================================
# PCIDEV:
@ -1232,11 +1209,20 @@ e1000: enabled=1, mac=52:54:00:12:34:56, ethmod=tuntap, ethdev=/dev/net/tun:tap0
#=======================================================================
# MAGIC_BREAK:
# This enables the "magic breakpoint" feature when using the debugger.
# The useless cpu instruction XCHG BX, BX causes Bochs to enter the
# The useless cpu instructions XCHG %REGW, %REGW causes Bochs to enter the
# debugger mode. This might be useful for software development.
#
# Example:
# You can specify multiple at once:
#
# cx dx bx sp bp si di
#
# Example for breaking on "XCHGW %DI, %DI" or "XCHG %SP, %SP" execution
# magic_break: enabled=1 di sp
#
# If nothing is specified, the default will be used: XCHGW %BX, %BX
# magic_break: enabled=1
#
# Note: Windows XP ntldr can cause problems with XCHGW %BX, %BX
#=======================================================================
magic_break: enabled=1
@ -1262,12 +1248,27 @@ magic_break: enabled=1
# very early when writing BIOS or OS code for example, without having to
# bother with setting up a serial port or etc. Reading from port 0xE9 will
# will return 0xe9 to let you know if the feature is available.
# Leave this 0 unless you have a reason to use it.
# Leave this 0 unless you have a reason to use it. By enabling the
# 'all_rings' option, you can utilize the port e9 hack from ring3.
#
# Example:
# port_e9_hack: enabled=1
# port_e9_hack: enabled=1, all_rings=1
#=======================================================================
port_e9_hack: enabled=1
port_e9_hack: enabled=1, all_rings=1
#=======================================================================
# IODEBUG:
# I/O Interface to Bochs Debugger plugin allows the code running inside
# Bochs to monitor memory ranges, trace individual instructions, and
# observe register values during execution. By enabling the 'all_rings'
# option, you can utilize the iodebug ports from ring3. For more
# information, refer to "Advanced debugger usage" documentation.
#
# Example:
# iodebug: all_rings=1
#=======================================================================
#iodebug: all_rings=1
#=======================================================================
# fullscreen: ONLY IMPLEMENTED ON AMIGA

View File

@ -26,16 +26,17 @@ PRINTF := printf
PERL := perl
PYTHON := python
TRUE := true
CC := $(CROSS_COMPILE)gcc
CPP := $(CC) -E
AS := $(CROSS_COMPILE)as
LD := $(CROSS_COMPILE)ld
SIZE := $(CROSS_COMPILE)size
AR := $(CROSS_COMPILE)ar
RANLIB := $(CROSS_COMPILE)ranlib
OBJCOPY := $(CROSS_COMPILE)objcopy
NM := $(CROSS_COMPILE)nm
OBJDUMP := $(CROSS_COMPILE)objdump
TRUNCATE := truncate
CC = $(CROSS_COMPILE)gcc
CPP = $(CC) -E
AS = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
SIZE = $(CROSS_COMPILE)size
AR = $(CROSS_COMPILE)ar
RANLIB = $(CROSS_COMPILE)ranlib
OBJCOPY = $(CROSS_COMPILE)objcopy
NM = $(CROSS_COMPILE)nm
OBJDUMP = $(CROSS_COMPILE)objdump
OPENSSL := openssl
CSPLIT := csplit
PARSEROM := ./util/parserom.pl
@ -45,7 +46,8 @@ SORTOBJDUMP := ./util/sortobjdump.pl
PADIMG := ./util/padimg.pl
LICENCE := ./util/licence.pl
NRV2B := ./util/nrv2b
ZBIN := ./util/zbin
ZBIN32 := ./util/zbin32
ZBIN64 := ./util/zbin64
ELF2EFI32 := ./util/elf2efi32
ELF2EFI64 := ./util/elf2efi64
EFIROM := ./util/efirom
@ -77,9 +79,11 @@ SRCDIRS += drivers/net/efi
SRCDIRS += drivers/net/tg3
SRCDIRS += drivers/net/bnxt
SRCDIRS += drivers/net/sfc
SRCDIRS += drivers/net/marvell
SRCDIRS += drivers/block
SRCDIRS += drivers/nvs
SRCDIRS += drivers/bitbash
SRCDIRS += drivers/gpio
SRCDIRS += drivers/infiniband
SRCDIRS += drivers/infiniband/mlx_utils_flexboot/src
SRCDIRS += drivers/infiniband/mlx_utils/src/public
@ -91,6 +95,7 @@ SRCDIRS += drivers/infiniband/mlx_utils/mlx_lib/mlx_link_speed
SRCDIRS += drivers/infiniband/mlx_utils/mlx_lib/mlx_mtu
SRCDIRS += drivers/infiniband/mlx_nodnic/src
SRCDIRS += drivers/usb
SRCDIRS += drivers/uart
SRCDIRS += interface/pxe interface/efi interface/smbios
SRCDIRS += interface/bofm
SRCDIRS += interface/xen

View File

@ -3,6 +3,20 @@
# This file contains various boring housekeeping functions that would
# otherwise seriously clutter up the main Makefile.
###############################################################################
#
# Make syntax does not allow use of comma or space in certain places.
# This ugly workaround is suggested in the manual.
#
COMMA := ,
EMPTY :=
SPACE := $(EMPTY) $(EMPTY)
HASH := \#
define NEWLINE
endef
###############################################################################
#
# Find a usable "echo -e" substitute.
@ -68,56 +82,6 @@ HOST_OS := $(shell uname -s)
hostos :
@$(ECHO) $(HOST_OS)
###############################################################################
#
# Determine compiler
CCDEFS := $(shell $(CC) -E -x c -c /dev/null -dM | cut -d" " -f2)
ccdefs:
@$(ECHO) $(CCDEFS)
ifeq ($(filter __GNUC__,$(CCDEFS)),__GNUC__)
CCTYPE := gcc
endif
cctype:
@$(ECHO) $(CCTYPE)
###############################################################################
#
# Check for tools that can cause failed builds
#
ifeq ($(CCTYPE),gcc)
GCC_2_96_BANNER := $(shell $(CC) -v 2>&1 | grep -is 'gcc version 2\.96')
ifneq ($(GCC_2_96_BANNER),)
$(warning gcc 2.96 is unsuitable for compiling iPXE)
$(warning Use gcc 2.95 or a newer version instead)
$(error Unsuitable build environment found)
endif
endif
PERL_UNICODE_CHECK := $(shell $(PERL) -e 'use bytes; print chr(255)' | wc -c)
ifeq ($(PERL_UNICODE_CHECK),2)
$(warning Your Perl version has a Unicode handling bug)
$(warning Execute this command before building iPXE:)
$(warning export LANG=$${LANG%.UTF-8})
$(error Unsuitable build environment found)
endif
LD_GOLD_BANNER := $(shell $(LD) -v 2>&1 | grep 'GNU gold')
ifneq ($(LD_GOLD_BANNER),)
$(warning GNU gold is unsuitable for building iPXE)
$(warning Use GNU ld instead)
$(error Unsuitable build environment found)
endif
OBJCOPY_ETC_BANNER := $(shell $(OBJCOPY) --version | grep 'elftoolchain')
ifneq ($(OBJCOPY_ETC_BANNER),)
$(warning The elftoolchain objcopy is unsuitable for building iPXE)
$(warning Use binutils objcopy instead)
$(error Unsuitable build environment found)
endif
###############################################################################
#
# Check if $(eval ...) is available to use
@ -130,74 +94,6 @@ endif
eval :
@$(ECHO) $(HAVE_EVAL)
###############################################################################
#
# Check for various tool workarounds
#
WORKAROUND_CFLAGS :=
WORKAROUND_ASFLAGS :=
WORKAROUND_LDFLAGS :=
# Make syntax does not allow use of comma or space in certain places.
# This ugly workaround is suggested in the manual.
#
COMMA := ,
EMPTY :=
SPACE := $(EMPTY) $(EMPTY)
HASH := \#
define NEWLINE
endef
# gcc 4.4 generates .eh_frame sections by default, which distort the
# output of "size". Inhibit this.
#
ifeq ($(CCTYPE),gcc)
CFI_TEST = $(CC) -fno-dwarf2-cfi-asm -fno-exceptions -fno-unwind-tables \
-fno-asynchronous-unwind-tables -x c -c /dev/null \
-o /dev/null >/dev/null 2>&1
CFI_FLAGS := $(shell $(CFI_TEST) && \
$(ECHO) '-fno-dwarf2-cfi-asm -fno-exceptions ' \
'-fno-unwind-tables -fno-asynchronous-unwind-tables')
WORKAROUND_CFLAGS += $(CFI_FLAGS)
endif
# gcc 4.6 generates spurious warnings if -Waddress is in force.
# Inhibit this.
#
ifeq ($(CCTYPE),gcc)
WNA_TEST = $(CC) -Waddress -x c -c /dev/null -o /dev/null >/dev/null 2>&1
WNA_FLAGS := $(shell $(WNA_TEST) && $(ECHO) '-Wno-address')
WORKAROUND_CFLAGS += $(WNA_FLAGS)
# gcc 8.0 generates warnings for certain suspect string operations. Our
# sources have been vetted for correct usage. Turn off these warnings.
#
WNST_TEST = $(CC) -Wstringop-truncation -x c -c /dev/null -o /dev/null \
>/dev/null 2>&1
WNST_FLAGS := $(shell $(WNST_TEST) && $(ECHO) '-Wno-stringop-truncation')
WORKAROUND_CFLAGS += $(WNST_FLAGS)
# gcc 9.1 generates warnings for taking address of packed member which
# may result in an unaligned pointer value. Inhibit the warnings.
#
WNAPM_TEST = $(CC) -Wno-address-of-packed-member -x c -c /dev/null \
-o /dev/null >/dev/null 2>&1
WNAPM_FLAGS := $(shell $(WNAPM_TEST) && \
$(ECHO) '-Wno-address-of-packed-member')
WORKAROUND_CFLAGS += $(WNAPM_FLAGS)
endif
# Some versions of gas choke on division operators, treating them as
# comment markers. Specifying --divide will work around this problem,
# but isn't available on older gas versions.
#
DIVIDE_TEST = $(AS) --divide /dev/null -o /dev/null 2>/dev/null
DIVIDE_FLAGS := $(shell $(DIVIDE_TEST) && $(ECHO) '--divide')
WORKAROUND_ASFLAGS += $(DIVIDE_FLAGS)
###############################################################################
#
# Build verbosity
@ -284,7 +180,7 @@ ifeq ($(wildcard $(BIN)),)
$(shell $(MKDIR) -p $(BIN))
endif
# Target to allow e.g. "make bin-efi arch"
# Target to allow e.g. "make bin-x86_64-efi arch"
#
$(BIN) :
@# Do nothing, silently
@ -333,8 +229,13 @@ else
BIN_AP := $(BIN_APS)
BIN_SECUREBOOT := 0
endif
BIN_PLATFORM := $(lastword $(BIN_AP))
BIN_ARCH := $(wordlist 2,$(words $(BIN_AP)),discard $(BIN_AP))
ifeq ($(BIN_AP),efi)
BIN_ARCH := i386
BIN_PLATFORM := efi
else
BIN_ARCH := $(word 1,$(BIN_AP))
BIN_PLATFORM := $(word 2,$(BIN_AP))
endif
# Determine build architecture
DEFAULT_ARCH := i386
@ -345,8 +246,12 @@ arch :
.PHONY : arch
# Determine build platform
DEFAULT_PLATFORM := pcbios
PLATFORM := $(firstword $(BIN_PLATFORM) $(DEFAULT_PLATFORM))
DEFAULT_PLATFORM_i386 := pcbios
DEFAULT_PLATFORM_x86_64 := pcbios
DEFAULT_PLATFORM_riscv32 := sbi
DEFAULT_PLATFORM_riscv64 := sbi
DEFAULT_PLATFORM := $(DEFAULT_PLATFORM_$(ARCH))
PLATFORM := $(firstword $(BIN_PLATFORM) $(DEFAULT_PLATFORM) none)
CFLAGS += -DPLATFORM=$(PLATFORM) -DPLATFORM_$(PLATFORM)
platform :
@$(ECHO) $(PLATFORM)
@ -358,19 +263,138 @@ CFLAGS += -DSECUREBOOT=$(SECUREBOOT)
secureboot :
@$(ECHO) $(SECUREBOOT)
# Set cross-compilation prefix automatically if not specified
ifeq ($(CROSS_COMPILE),)
CROSS_COMPILE := $(CROSS_COMPILE_$(ARCH))
endif
endif # defined(BIN)
###############################################################################
#
# Determine compiler
CCDEFS := $(shell $(CC) -E -x c -c /dev/null -dM | cut -d" " -f2)
ccdefs:
@$(ECHO) $(CCDEFS)
ifeq ($(filter __GNUC__,$(CCDEFS)),__GNUC__)
CCTYPE := gcc
endif
cctype:
@$(ECHO) $(CCTYPE)
###############################################################################
#
# Check for tools that can cause failed builds
#
ifeq ($(CCTYPE),gcc)
GCC_2_96_BANNER := $(shell $(CC) -v 2>&1 | grep -is 'gcc version 2\.96')
ifneq ($(GCC_2_96_BANNER),)
$(warning gcc 2.96 is unsuitable for compiling iPXE)
$(warning Use gcc 2.95 or a newer version instead)
$(error Unsuitable build environment found)
endif
endif
PERL_UNICODE_CHECK := $(shell $(PERL) -e 'use bytes; print chr(255)' | wc -c)
ifeq ($(PERL_UNICODE_CHECK),2)
$(warning Your Perl version has a Unicode handling bug)
$(warning Execute this command before building iPXE:)
$(warning export LANG=$${LANG%.UTF-8})
$(error Unsuitable build environment found)
endif
LD_GOLD_BANNER := $(shell $(LD) -v 2>&1 | grep 'GNU gold')
ifneq ($(LD_GOLD_BANNER),)
$(warning GNU gold is unsuitable for building iPXE)
$(warning Use GNU ld instead)
$(error Unsuitable build environment found)
endif
OBJCOPY_ETC_BANNER := $(shell $(OBJCOPY) --version | grep 'elftoolchain')
ifneq ($(OBJCOPY_ETC_BANNER),)
$(warning The elftoolchain objcopy is unsuitable for building iPXE)
$(warning Use binutils objcopy instead)
$(error Unsuitable build environment found)
endif
###############################################################################
#
# Check for various tool workarounds
#
WORKAROUND_CFLAGS :=
WORKAROUND_ASFLAGS :=
WORKAROUND_LDFLAGS :=
# gcc 4.4 generates .eh_frame sections by default, which distort the
# output of "size". Inhibit this.
#
ifeq ($(CCTYPE),gcc)
CFI_TEST = $(CC) -fno-dwarf2-cfi-asm -fno-exceptions -fno-unwind-tables \
-fno-asynchronous-unwind-tables -x c -c /dev/null \
-o /dev/null >/dev/null 2>&1
CFI_FLAGS := $(shell $(CFI_TEST) && \
$(ECHO) '-fno-dwarf2-cfi-asm -fno-exceptions ' \
'-fno-unwind-tables -fno-asynchronous-unwind-tables')
WORKAROUND_CFLAGS += $(CFI_FLAGS)
endif
# gcc 4.6 generates spurious warnings if -Waddress is in force.
# Inhibit this.
#
ifeq ($(CCTYPE),gcc)
WNA_TEST = $(CC) -Waddress -x c -c /dev/null -o /dev/null >/dev/null 2>&1
WNA_FLAGS := $(shell $(WNA_TEST) && $(ECHO) '-Wno-address')
WORKAROUND_CFLAGS += $(WNA_FLAGS)
# gcc 8.0 generates warnings for certain suspect string operations. Our
# sources have been vetted for correct usage. Turn off these warnings.
#
WNST_TEST = $(CC) -Wstringop-truncation -x c -c /dev/null -o /dev/null \
>/dev/null 2>&1
WNST_FLAGS := $(shell $(WNST_TEST) && $(ECHO) '-Wno-stringop-truncation')
WORKAROUND_CFLAGS += $(WNST_FLAGS)
# gcc 9.1 generates warnings for taking address of packed member which
# may result in an unaligned pointer value. Inhibit the warnings.
#
WNAPM_TEST = $(CC) -Wno-address-of-packed-member -x c -c /dev/null \
-o /dev/null >/dev/null 2>&1
WNAPM_FLAGS := $(shell $(WNAPM_TEST) && \
$(ECHO) '-Wno-address-of-packed-member')
WORKAROUND_CFLAGS += $(WNAPM_FLAGS)
endif
# gcc 15 generates warnings for fixed-length character array
# initializers that lack a terminating NUL. Inhibit the warnings.
#
WNUSI_TEST = $(CC) -Wunterminated-string-initialization -x c -c /dev/null \
-o /dev/null >/dev/null 2>&1
WNUSI_FLAGS := $(shell $(WNUSI_TEST) && \
$(ECHO) '-Wno-unterminated-string-initialization')
WORKAROUND_CFLAGS += $(WNUSI_FLAGS)
# Some versions of gas choke on division operators, treating them as
# comment markers. Specifying --divide will work around this problem,
# but isn't available on older gas versions.
#
DIVIDE_TEST = $(AS) --divide /dev/null -o /dev/null 2>/dev/null
DIVIDE_FLAGS := $(shell $(DIVIDE_TEST) && $(ECHO) '--divide')
WORKAROUND_ASFLAGS += $(DIVIDE_FLAGS)
###############################################################################
#
# Include architecture-specific Makefile
#
ifdef ARCH
MAKEDEPS += arch/$(ARCH)/Makefile
include arch/$(ARCH)/Makefile
endif
# Include architecture-specific include path
ifdef ARCH
INCDIRS += arch/$(ARCH)/include
endif
###############################################################################
#
# Especially ugly workarounds
@ -459,7 +483,7 @@ CFLAGS += -Os
CFLAGS += -g
ifeq ($(CCTYPE),gcc)
CFLAGS += -ffreestanding
CFLAGS += -fcommon
CFLAGS += -fno-common
CFLAGS += -Wall -W -Wformat-nonliteral
CFLAGS += -Wno-array-bounds -Wno-dangling-pointer
HOST_CFLAGS += -Wall -W -Wformat-nonliteral
@ -469,6 +493,7 @@ CFLAGS += $(WORKAROUND_CFLAGS) $(EXTRA_CFLAGS)
ASFLAGS += $(WORKAROUND_ASFLAGS) $(EXTRA_ASFLAGS)
LDFLAGS += $(WORKAROUND_LDFLAGS) $(EXTRA_LDFLAGS)
HOST_CFLAGS += -O2 -g
HOST_EFI_CFLAGS += -fshort-wchar
# Inhibit -Werror if NO_WERROR is specified on make command line
#
@ -478,17 +503,14 @@ ASFLAGS += --fatal-warnings
HOST_CFLAGS += -Werror
endif
# Enable per-item sections and section garbage collection. Note that
# some older versions of gcc support -fdata-sections but treat it as
# implying -fno-common, which would break our build. Some other older
# versions issue a spurious and uninhibitable warning if
# -ffunction-sections is used with -g, which would also break our
# build since we use -Werror.
# Enable per-item sections and section garbage collection. Some older
# versions of gcc issue a spurious and uninhibitable warning if
# -ffunction-sections is used with -g, which would break our build
# since we use -Werror.
#
ifeq ($(CCTYPE),gcc)
DS_TEST = $(ECHO) 'char x;' | \
$(CC) -fdata-sections -S -x c - -o - 2>/dev/null | \
grep -E '\.comm' > /dev/null
DS_TEST = $(CC) -fdata-sections -c -x c /dev/null \
-o /dev/null 2>/dev/null
DS_FLAGS := $(shell $(DS_TEST) && $(ECHO) '-fdata-sections')
FS_TEST = $(CC) -ffunction-sections -g -c -x c /dev/null \
-o /dev/null 2>/dev/null
@ -590,7 +612,7 @@ embedded_DEPS += $(EMBEDDED_FILES) $(EMBEDDED_LIST)
CFLAGS_embedded = -DEMBED_ALL="$(EMBED_ALL)"
# List of trusted root certificates
# List of trusted root certificate configuration
#
TRUSTED_LIST := $(BIN)/.trusted.list
ifeq ($(wildcard $(TRUSTED_LIST)),)
@ -598,8 +620,9 @@ TRUST_OLD := <invalid>
else
TRUST_OLD := $(shell cat $(TRUSTED_LIST))
endif
ifneq ($(TRUST_OLD),$(TRUST))
$(shell $(ECHO) "$(TRUST)" > $(TRUSTED_LIST))
TRUST_CFG := $(TRUST) $(TRUST_EXT)
ifneq ($(TRUST_OLD),$(TRUST_CFG))
$(shell $(ECHO) "$(TRUST_CFG)" > $(TRUSTED_LIST))
endif
$(TRUSTED_LIST) : $(MAKEDEPS)
@ -616,7 +639,8 @@ TRUSTED_FPS := $(foreach CERT,$(TRUSTED_CERTS),\
rootcert_DEPS += $(TRUSTED_FILES) $(TRUSTED_LIST)
CFLAGS_rootcert = $(if $(TRUSTED_FPS),-DTRUSTED="$(TRUSTED_FPS)")
CFLAGS_rootcert += $(if $(TRUST_EXT),-DALLOW_TRUST_OVERRIDE=$(TRUST_EXT))
CFLAGS_rootcert += $(if $(TRUSTED_FPS),-DTRUSTED="$(TRUSTED_FPS)")
# List of embedded certificates
#
@ -1422,10 +1446,15 @@ endif # defined(BIN)
ZBIN_LDFLAGS := -llzma
$(ZBIN) : util/zbin.c $(MAKEDEPS)
$(ZBIN32) : util/zbin.c $(MAKEDEPS)
$(QM)$(ECHO) " [HOSTCC] $@"
$(Q)$(HOST_CC) $(HOST_CFLAGS) $< $(ZBIN_LDFLAGS) -o $@
CLEANUP += $(ZBIN)
$(Q)$(HOST_CC) $(HOST_CFLAGS) $< $(ZBIN_LDFLAGS) -DELF32 -o $@
CLEANUP += $(ZBIN32)
$(ZBIN64) : util/zbin.c $(MAKEDEPS)
$(QM)$(ECHO) " [HOSTCC] $@"
$(Q)$(HOST_CC) $(HOST_CFLAGS) $< $(ZBIN_LDFLAGS) -DELF64 -o $@
CLEANUP += $(ZBIN64)
###############################################################################
#
@ -1434,22 +1463,22 @@ CLEANUP += $(ZBIN)
$(ELF2EFI32) : util/elf2efi.c $(MAKEDEPS)
$(QM)$(ECHO) " [HOSTCC] $@"
$(Q)$(HOST_CC) $(HOST_CFLAGS) -idirafter include -DEFI_TARGET32 $< -o $@
$(Q)$(HOST_CC) $(HOST_CFLAGS) $(HOST_EFI_CFLAGS) -idirafter include -DEFI_TARGET32 $< -o $@
CLEANUP += $(ELF2EFI32)
$(ELF2EFI64) : util/elf2efi.c $(MAKEDEPS)
$(QM)$(ECHO) " [HOSTCC] $@"
$(Q)$(HOST_CC) $(HOST_CFLAGS) -idirafter include -DEFI_TARGET64 $< -o $@
$(Q)$(HOST_CC) $(HOST_CFLAGS) $(HOST_EFI_CFLAGS) -idirafter include -DEFI_TARGET64 $< -o $@
CLEANUP += $(ELF2EFI64)
$(EFIROM) : util/efirom.c util/eficompress.c $(MAKEDEPS)
$(QM)$(ECHO) " [HOSTCC] $@"
$(Q)$(HOST_CC) $(HOST_CFLAGS) -idirafter include -o $@ $<
$(Q)$(HOST_CC) $(HOST_CFLAGS) $(HOST_EFI_CFLAGS) -idirafter include -o $@ $<
CLEANUP += $(EFIROM)
$(EFIFATBIN) : util/efifatbin.c $(MAKEDEPS)
$(QM)$(ECHO) " [HOSTCC] $@"
$(Q)$(HOST_CC) $(HOST_CFLAGS) -idirafter include -o $@ $<
$(Q)$(HOST_CC) $(HOST_CFLAGS) $(HOST_EFI_CFLAGS) -idirafter include -o $@ $<
CLEANUP += $(EFIFATBIN)
###############################################################################

View File

@ -29,6 +29,13 @@ NON_AUTO_MEDIA = linux
# Compiler flags for building host API wrapper
#
LINUX_CFLAGS += -Os -idirafter include -DSYMBOL_PREFIX=$(SYMBOL_PREFIX)
LINUX_CFLAGS += -Wall -W
ifneq ($(SYSROOT),)
LINUX_CFLAGS += --sysroot=$(SYSROOT)
endif
ifneq ($(NO_WERROR),1)
LINUX_CFLAGS += -Werror
endif
# Check for libslirp
#

View File

@ -3,9 +3,9 @@
ASM_TCHAR := %
ASM_TCHAR_OPS := %%
# Include common ARM headers
# Include ARM-specific headers
#
INCDIRS += arch/arm/include
INCDIRS := arch/$(ARCH)/include arch/arm/include $(INCDIRS)
# ARM-specific directories containing source files
#

View File

@ -1,12 +0,0 @@
#ifndef _BITS_ACPI_H
#define _BITS_ACPI_H
/** @file
*
* ARM-specific ACPI API implementations
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#endif /* _BITS_ACPI_H */

View File

@ -1,12 +0,0 @@
#ifndef _BITS_HYPERV_H
#define _BITS_HYPERV_H
/** @file
*
* Hyper-V interface
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#endif /* _BITS_HYPERV_H */

View File

@ -1,12 +0,0 @@
#ifndef _BITS_IOMAP_H
#define _BITS_IOMAP_H
/** @file
*
* ARM-specific I/O mapping API implementations
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#endif /* _BITS_IOMAP_H */

View File

@ -1,12 +0,0 @@
#ifndef _BITS_MP_H
#define _BITS_MP_H
/** @file
*
* ARM-specific multiprocessor API implementation
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#endif /* _BITS_MP_H */

View File

@ -9,6 +9,12 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/efi/efiarm_nap.h>
/**
* Sleep until next CPU interrupt
*
*/
static inline __attribute__ (( always_inline )) void cpu_halt ( void ) {
__asm__ __volatile__ ( "wfi" );
}
#endif /* _BITS_MAP_H */
#endif /* _BITS_NAP_H */

View File

@ -1,12 +0,0 @@
#ifndef _BITS_PCI_IO_H
#define _BITS_PCI_IO_H
/** @file
*
* ARM PCI I/O API implementations
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#endif /* _BITS_PCI_IO_H */

View File

@ -1,12 +0,0 @@
#ifndef _BITS_SANBOOT_H
#define _BITS_SANBOOT_H
/** @file
*
* ARM-specific sanboot API implementations
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#endif /* _BITS_SANBOOT_H */

View File

@ -1,12 +0,0 @@
#ifndef _BITS_SMBIOS_H
#define _BITS_SMBIOS_H
/** @file
*
* ARM-specific SMBIOS API implementations
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#endif /* _BITS_SMBIOS_H */

View File

@ -1,12 +0,0 @@
#ifndef _BITS_TIME_H
#define _BITS_TIME_H
/** @file
*
* ARM-specific time API implementations
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#endif /* _BITS_TIME_H */

View File

@ -1,12 +0,0 @@
#ifndef _BITS_UACCESS_H
#define _BITS_UACCESS_H
/** @file
*
* ARM-specific user access API implementations
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#endif /* _BITS_UACCESS_H */

View File

@ -1,12 +0,0 @@
#ifndef _BITS_UART_H
#define _BITS_UART_H
/** @file
*
* 16550-compatible UART
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#endif /* _BITS_UART_H */

View File

@ -1,12 +0,0 @@
#ifndef _BITS_UMALLOC_H
#define _BITS_UMALLOC_H
/** @file
*
* ARM-specific user memory allocation API implementations
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#endif /* _BITS_UMALLOC_H */

View File

@ -1,18 +0,0 @@
#ifndef _IPXE_EFIARM_NAP_H
#define _IPXE_EFIARM_NAP_H
/** @file
*
* EFI CPU sleeping
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#ifdef NAP_EFIARM
#define NAP_PREFIX_efiarm
#else
#define NAP_PREFIX_efiarm __efiarm_
#endif
#endif /* _IPXE_EFIARM_NAP_H */

View File

@ -1,3 +1,7 @@
# Specify compressor
#
ZBIN = $(ZBIN32)
# ARM32-specific directories containing source files
#
SRCDIRS += arch/arm32/core

View File

@ -8,10 +8,6 @@ CFLAGS += -mfloat-abi=soft
#
ELF2EFI = $(ELF2EFI32)
# Specify EFI boot file
#
EFI_BOOT_FILE = bootarm.efi
# Include generic EFI Makefile
#
MAKEDEPS += arch/arm/Makefile.efi

View File

@ -0,0 +1,25 @@
# -*- makefile -*- : Force emacs to use Makefile mode
# The number of different ABIs for 32-bit ARM is insane. It is
# unclear whether or not unaligned accesses ought to work in a 32-bit
# Linux userspace binary. When running in QEMU, unaligned accesses
# result in a SIGBUS. Since this is likely to be the most common use
# case (for running self-tests on an x86 build machine), and since we
# don't particularly care about performance for Linux userspace
# binaries, force the compiler to never generate an unaligned access.
#
CFLAGS += -mno-unaligned-access
# Inhibit the harmless warning about wchar_t size mismatch between the
# linux_api.o helper object and the rest of iPXE.
#
LINUX_CFLAGS += -Wl,--no-wchar-size-warning
# Starting virtual address
#
LDFLAGS += -Ttext=0x10000
# Include generic Linux Makefile
#
MAKEDEPS += arch/arm/Makefile.linux
include arch/arm/Makefile.linux

View File

@ -1,106 +0,0 @@
/*
* Copyright (C) 2016 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
* You can also choose to distribute this program under the terms of
* the Unmodified Binary Distribution Licence (as given in the file
* COPYING.UBDL), provided that you have satisfied its requirements.
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <string.h>
#include <ipxe/bigint.h>
/** @file
*
* Big integer support
*/
/**
* Multiply big integers
*
* @v multiplicand0 Element 0 of big integer to be multiplied
* @v multiplicand_size Number of elements in multiplicand
* @v multiplier0 Element 0 of big integer to be multiplied
* @v multiplier_size Number of elements in multiplier
* @v result0 Element 0 of big integer to hold result
*/
void bigint_multiply_raw ( const uint32_t *multiplicand0,
unsigned int multiplicand_size,
const uint32_t *multiplier0,
unsigned int multiplier_size,
uint32_t *result0 ) {
unsigned int result_size = ( multiplicand_size + multiplier_size );
const bigint_t ( multiplicand_size ) __attribute__ (( may_alias ))
*multiplicand = ( ( const void * ) multiplicand0 );
const bigint_t ( multiplier_size ) __attribute__ (( may_alias ))
*multiplier = ( ( const void * ) multiplier0 );
bigint_t ( result_size ) __attribute__ (( may_alias ))
*result = ( ( void * ) result0 );
unsigned int i;
unsigned int j;
uint32_t multiplicand_element;
uint32_t multiplier_element;
uint32_t *result_elements;
uint32_t discard_low;
uint32_t discard_high;
uint32_t discard_temp;
/* Zero result */
memset ( result, 0, sizeof ( *result ) );
/* Multiply integers one element at a time */
for ( i = 0 ; i < multiplicand_size ; i++ ) {
multiplicand_element = multiplicand->element[i];
for ( j = 0 ; j < multiplier_size ; j++ ) {
multiplier_element = multiplier->element[j];
result_elements = &result->element[ i + j ];
/* Perform a single multiply, and add the
* resulting double-element into the result,
* carrying as necessary. The carry can
* never overflow beyond the end of the
* result, since:
*
* a < 2^{n}, b < 2^{m} => ab < 2^{n+m}
*/
__asm__ __volatile__ ( "umull %1, %2, %5, %6\n\t"
"ldr %3, [%0]\n\t"
"adds %3, %1\n\t"
"stmia %0!, {%3}\n\t"
"ldr %3, [%0]\n\t"
"adcs %3, %2\n\t"
"stmia %0!, {%3}\n\t"
"bcc 2f\n\t"
"\n1:\n\t"
"ldr %3, [%0]\n\t"
"adcs %3, #0\n\t"
"stmia %0!, {%3}\n\t"
"bcs 1b\n\t"
"\n2:\n\t"
: "+l" ( result_elements ),
"=l" ( discard_low ),
"=l" ( discard_high ),
"=l" ( discard_temp ),
"+m" ( *result )
: "l" ( multiplicand_element ),
"l" ( multiplier_element )
: "cc" );
}
}
}

View File

@ -0,0 +1,85 @@
/*
* Copyright (C) 2024 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
* You can also choose to distribute this program under the terms of
* the Unmodified Binary Distribution Licence (as given in the file
* COPYING.UBDL), provided that you have satisfied its requirements.
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
/** @file
*
* Performance Monitor Cycle Counter (PMCCNTR)
*
*/
.section ".note.GNU-stack", "", %progbits
.text
.arm
/*
* PMCCNTR status
*
* bit 31 set if PMCCNTR availability is not yet determined
* bit 0 set if PMCCNTR is available
*
*/
.section ".data.pmccntr_status", "aw", %progbits
.globl pmccntr_status
pmccntr_status:
.word 0x80000000
/*
* Check PMCCNTR availability
*
* Must preserve all registers, and return with either PMCCNTR enabled
* or the Z flag set to indicate unavailability.
*
*/
.section ".text.pmccntr_check", "ax", %progbits
.globl pmccntr_check
.type pmccntr_check, %function
pmccntr_check:
/* Save registers */
stmfd sp!, { r0, r1 }
/* Read CPSR.M (bits 3:0, always permitted in PL0) */
mrs r0, cpsr
and r0, r0, #0x0000000f
/* Read PMUSERENR.EN (bit 0, always permitted in PL0) */
mrc p15, 0, r1, c9, c14, 0
and r1, r1, #0x00000001
/* Check if we are in PL1+ or in PL0 with PMUSERENR.EN set */
orrs r0, r0, r1
/* If PMCCNTR is unavailable, exit with status=0 and ZF set */
beq 1f
/* Set PMCR.E (bit 0), set exit status=1 and ZF clear */
movs r0, #0x00000001
mcr p15, 0, r0, c9, c12, 0
/* Set PMCNTENSET.C (bit 31) */
mov r1, #0x80000000
mcr p15, 0, r1, c9, c12, 1
1: /* Store PMCCNTR status */
ldr r1, pmccntr_status_ptr
str r0, [r1]
/* Restore registers and return */
ldmfd sp!, { r0, r1 }
bx lr
pmccntr_status_ptr:
.word pmccntr_status
.size pmccntr_check, . - pmccntr_check

View File

@ -43,8 +43,9 @@ bigint_init_raw ( uint32_t *value0, unsigned int size,
* @v addend0 Element 0 of big integer to add
* @v value0 Element 0 of big integer to be added to
* @v size Number of elements
* @ret carry Carry out
*/
static inline __attribute__ (( always_inline )) void
static inline __attribute__ (( always_inline )) int
bigint_add_raw ( const uint32_t *addend0, uint32_t *value0,
unsigned int size ) {
bigint_t ( size ) __attribute__ (( may_alias )) *value =
@ -54,8 +55,9 @@ bigint_add_raw ( const uint32_t *addend0, uint32_t *value0,
uint32_t *discard_end;
uint32_t discard_addend_i;
uint32_t discard_value_i;
int carry;
__asm__ __volatile__ ( "adds %2, %0, %8, lsl #2\n\t" /* clear CF */
__asm__ __volatile__ ( "adds %2, %0, %9, lsl #2\n\t" /* clear CF */
"\n1:\n\t"
"ldmia %0!, {%3}\n\t"
"ldr %4, [%1]\n\t"
@ -68,9 +70,11 @@ bigint_add_raw ( const uint32_t *addend0, uint32_t *value0,
"=l" ( discard_end ),
"=l" ( discard_addend_i ),
"=l" ( discard_value_i ),
"=@cccs" ( carry ),
"+m" ( *value )
: "0" ( addend0 ), "1" ( value0 ), "l" ( size )
: "cc" );
: "0" ( addend0 ), "1" ( value0 ),
"l" ( size ) );
return carry;
}
/**
@ -79,8 +83,9 @@ bigint_add_raw ( const uint32_t *addend0, uint32_t *value0,
* @v subtrahend0 Element 0 of big integer to subtract
* @v value0 Element 0 of big integer to be subtracted from
* @v size Number of elements
* @ret borrow Borrow out
*/
static inline __attribute__ (( always_inline )) void
static inline __attribute__ (( always_inline )) int
bigint_subtract_raw ( const uint32_t *subtrahend0, uint32_t *value0,
unsigned int size ) {
bigint_t ( size ) __attribute__ (( may_alias )) *value =
@ -90,8 +95,9 @@ bigint_subtract_raw ( const uint32_t *subtrahend0, uint32_t *value0,
uint32_t *discard_end;
uint32_t discard_subtrahend_i;
uint32_t discard_value_i;
int borrow;
__asm__ __volatile__ ( "add %2, %0, %8, lsl #2\n\t"
__asm__ __volatile__ ( "add %2, %0, %9, lsl #2\n\t"
"cmp %2, %0\n\t" /* set CF */
"\n1:\n\t"
"ldmia %0!, {%3}\n\t"
@ -105,27 +111,30 @@ bigint_subtract_raw ( const uint32_t *subtrahend0, uint32_t *value0,
"=l" ( discard_end ),
"=l" ( discard_subtrahend_i ),
"=l" ( discard_value_i ),
"=@cccc" ( borrow ),
"+m" ( *value )
: "0" ( subtrahend0 ), "1" ( value0 ),
"l" ( size )
: "cc" );
"l" ( size ) );
return borrow;
}
/**
* Rotate big integer left
* Shift big integer left
*
* @v value0 Element 0 of big integer
* @v size Number of elements
* @ret out Bit shifted out
*/
static inline __attribute__ (( always_inline )) void
bigint_rol_raw ( uint32_t *value0, unsigned int size ) {
static inline __attribute__ (( always_inline )) int
bigint_shl_raw ( uint32_t *value0, unsigned int size ) {
bigint_t ( size ) __attribute__ (( may_alias )) *value =
( ( void * ) value0 );
uint32_t *discard_value;
uint32_t *discard_end;
uint32_t discard_value_i;
int carry;
__asm__ __volatile__ ( "adds %1, %0, %5, lsl #2\n\t" /* clear CF */
__asm__ __volatile__ ( "adds %1, %0, %1, lsl #2\n\t" /* clear CF */
"\n1:\n\t"
"ldr %2, [%0]\n\t"
"adcs %2, %2\n\t"
@ -135,26 +144,29 @@ bigint_rol_raw ( uint32_t *value0, unsigned int size ) {
: "=l" ( discard_value ),
"=l" ( discard_end ),
"=l" ( discard_value_i ),
"=@cccs" ( carry ),
"+m" ( *value )
: "0" ( value0 ), "1" ( size )
: "cc" );
: "0" ( value0 ), "1" ( size ) );
return carry;
}
/**
* Rotate big integer right
* Shift big integer right
*
* @v value0 Element 0 of big integer
* @v size Number of elements
* @ret out Bit shifted out
*/
static inline __attribute__ (( always_inline )) void
bigint_ror_raw ( uint32_t *value0, unsigned int size ) {
static inline __attribute__ (( always_inline )) int
bigint_shr_raw ( uint32_t *value0, unsigned int size ) {
bigint_t ( size ) __attribute__ (( may_alias )) *value =
( ( void * ) value0 );
uint32_t *discard_value;
uint32_t *discard_end;
uint32_t discard_value_i;
int carry;
__asm__ __volatile__ ( "adds %1, %0, %5, lsl #2\n\t" /* clear CF */
__asm__ __volatile__ ( "adds %1, %0, %1, lsl #2\n\t" /* clear CF */
"\n1:\n\t"
"ldmdb %1!, {%2}\n\t"
"rrxs %2, %2\n\t"
@ -164,9 +176,10 @@ bigint_ror_raw ( uint32_t *value0, unsigned int size ) {
: "=l" ( discard_value ),
"=l" ( discard_end ),
"=l" ( discard_value_i ),
"=@cccs" ( carry ),
"+m" ( *value )
: "0" ( value0 ), "1" ( size )
: "cc" );
: "0" ( value0 ), "1" ( size ) );
return carry;
}
/**
@ -216,25 +229,6 @@ bigint_is_geq_raw ( const uint32_t *value0, const uint32_t *reference0,
return ( value_i >= reference_i );
}
/**
* Test if bit is set in big integer
*
* @v value0 Element 0 of big integer
* @v size Number of elements
* @v bit Bit to test
* @ret is_set Bit is set
*/
static inline __attribute__ (( always_inline )) int
bigint_bit_is_set_raw ( const uint32_t *value0, unsigned int size,
unsigned int bit ) {
const bigint_t ( size ) __attribute__ (( may_alias )) *value =
( ( const void * ) value0 );
unsigned int index = ( bit / ( 8 * sizeof ( value->element[0] ) ) );
unsigned int subindex = ( bit % ( 8 * sizeof ( value->element[0] ) ) );
return ( value->element[index] & ( 1 << subindex ) );
}
/**
* Find highest bit set in big integer
*
@ -309,10 +303,35 @@ bigint_done_raw ( const uint32_t *value0, unsigned int size __unused,
*(--out_byte) = *(value_byte++);
}
extern void bigint_multiply_raw ( const uint32_t *multiplicand0,
unsigned int multiplicand_size,
const uint32_t *multiplier0,
unsigned int multiplier_size,
uint32_t *value0 );
/**
* Multiply big integer elements
*
* @v multiplicand Multiplicand element
* @v multiplier Multiplier element
* @v result Result element
* @v carry Carry element
*/
static inline __attribute__ (( always_inline )) void
bigint_multiply_one ( const uint32_t multiplicand, const uint32_t multiplier,
uint32_t *result, uint32_t *carry ) {
uint32_t discard_low;
uint32_t discard_high;
__asm__ __volatile__ ( /* Perform multiplication */
"umull %0, %1, %4, %5\n\t"
/* Accumulate result */
"adds %2, %0\n\t"
"adc %1, #0\n\t"
/* Accumulate carry (cannot overflow) */
"adds %2, %3\n\t"
"adc %3, %1, #0\n\t"
: "=r" ( discard_low ),
"=r" ( discard_high ),
"+r" ( *result ),
"+r" ( *carry )
: "r" ( multiplicand ),
"r" ( multiplier )
: "cc" );
}
#endif /* _BITS_BIGINT_H */

View File

@ -11,19 +11,30 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
extern uint32_t pmccntr_status;
/**
* Get profiling timestamp
*
* @ret timestamp Timestamp
*/
static inline __attribute__ (( always_inline )) uint64_t
static inline __attribute__ (( always_inline )) unsigned long
profile_timestamp ( void ) {
uint32_t cycles;
/* Read cycle counter */
__asm__ __volatile__ ( "mcr p15, 0, %1, c9, c12, 0\n\t"
"mrc p15, 0, %0, c9, c13, 0\n\t"
: "=r" ( cycles ) : "r" ( 1 ) );
__asm__ __volatile__ ( /* Check PMCCNTR status */
"tst %0, %0\n\t"
/* Check availability if not yet known */
"it mi\n\t"
"blxmi pmccntr_check\n\t"
/* Read PMCCNTR if available */
"it ne\n\t"
"mrcne p15, 0, %0, c9, c13, 0\n\t"
"\n1:\n\t"
: "=r" ( cycles )
: "0" ( pmccntr_status )
: "cc", "lr" );
return cycles;
}

View File

@ -1,5 +1,5 @@
#ifndef _SETJMP_H
#define _SETJMP_H
#ifndef _BITS_SETJMP_H
#define _BITS_SETJMP_H
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
@ -29,10 +29,4 @@ typedef struct {
uint32_t lr;
} jmp_buf[1];
extern int __asmcall __attribute__ (( returns_twice ))
setjmp ( jmp_buf env );
extern void __asmcall __attribute__ (( noreturn ))
longjmp ( jmp_buf env, int val );
#endif /* _SETJMP_H */
#endif /* _BITS_SETJMP_H */

View File

@ -1,19 +0,0 @@
#ifndef _BITS_TCPIP_H
#define _BITS_TCPIP_H
/** @file
*
* Transport-network layer interface
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
static inline __attribute__ (( always_inline )) uint16_t
tcpip_continue_chksum ( uint16_t partial, const void *data, size_t len ) {
/* Not yet optimised */
return generic_tcpip_continue_chksum ( partial, data, len );
}
#endif /* _BITS_TCPIP_H */

View File

@ -1,45 +0,0 @@
#ifndef GDBMACH_H
#define GDBMACH_H
/** @file
*
* GDB architecture specifics
*
* This file declares functions for manipulating the machine state and
* debugging context.
*
*/
#include <stdint.h>
typedef unsigned long gdbreg_t;
/* Register snapshot */
enum {
/* Not yet implemented */
GDBMACH_NREGS,
};
#define GDBMACH_SIZEOF_REGS ( GDBMACH_NREGS * sizeof ( gdbreg_t ) )
static inline void gdbmach_set_pc ( gdbreg_t *regs, gdbreg_t pc ) {
/* Not yet implemented */
( void ) regs;
( void ) pc;
}
static inline void gdbmach_set_single_step ( gdbreg_t *regs, int step ) {
/* Not yet implemented */
( void ) regs;
( void ) step;
}
static inline void gdbmach_breakpoint ( void ) {
/* Not yet implemented */
}
extern int gdbmach_set_breakpoint ( int type, unsigned long addr, size_t len,
int enable );
extern void gdbmach_init ( void );
#endif /* GDBMACH_H */

View File

@ -1,3 +1,7 @@
# Specify compressor
#
ZBIN = $(ZBIN64)
# ARM64-specific directories containing source files
#
SRCDIRS += arch/arm64/core

View File

@ -4,10 +4,6 @@
#
ELF2EFI = $(ELF2EFI64)
# Specify EFI boot file
#
EFI_BOOT_FILE = bootaa64.efi
# Include generic EFI Makefile
#
MAKEDEPS += arch/arm/Makefile.efi

View File

@ -1,107 +0,0 @@
/*
* Copyright (C) 2016 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
* You can also choose to distribute this program under the terms of
* the Unmodified Binary Distribution Licence (as given in the file
* COPYING.UBDL), provided that you have satisfied its requirements.
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <string.h>
#include <ipxe/bigint.h>
/** @file
*
* Big integer support
*/
/**
* Multiply big integers
*
* @v multiplicand0 Element 0 of big integer to be multiplied
* @v multiplicand_size Number of elements in multiplicand
* @v multiplier0 Element 0 of big integer to be multiplied
* @v multiplier_size Number of elements in multiplier
* @v result0 Element 0 of big integer to hold result
*/
void bigint_multiply_raw ( const uint64_t *multiplicand0,
unsigned int multiplicand_size,
const uint64_t *multiplier0,
unsigned int multiplier_size,
uint64_t *result0 ) {
unsigned int result_size = ( multiplicand_size + multiplier_size );
const bigint_t ( multiplicand_size ) __attribute__ (( may_alias ))
*multiplicand = ( ( const void * ) multiplicand0 );
const bigint_t ( multiplier_size ) __attribute__ (( may_alias ))
*multiplier = ( ( const void * ) multiplier0 );
bigint_t ( result_size ) __attribute__ (( may_alias ))
*result = ( ( void * ) result0 );
unsigned int i;
unsigned int j;
uint64_t multiplicand_element;
uint64_t multiplier_element;
uint64_t *result_elements;
uint64_t discard_low;
uint64_t discard_high;
uint64_t discard_temp_low;
uint64_t discard_temp_high;
/* Zero result */
memset ( result, 0, sizeof ( *result ) );
/* Multiply integers one element at a time */
for ( i = 0 ; i < multiplicand_size ; i++ ) {
multiplicand_element = multiplicand->element[i];
for ( j = 0 ; j < multiplier_size ; j++ ) {
multiplier_element = multiplier->element[j];
result_elements = &result->element[ i + j ];
/* Perform a single multiply, and add the
* resulting double-element into the result,
* carrying as necessary. The carry can
* never overflow beyond the end of the
* result, since:
*
* a < 2^{n}, b < 2^{m} => ab < 2^{n+m}
*/
__asm__ __volatile__ ( "mul %1, %6, %7\n\t"
"umulh %2, %6, %7\n\t"
"ldp %3, %4, [%0]\n\t"
"adds %3, %3, %1\n\t"
"adcs %4, %4, %2\n\t"
"stp %3, %4, [%0], #16\n\t"
"bcc 2f\n\t"
"\n1:\n\t"
"ldr %3, [%0]\n\t"
"adcs %3, %3, xzr\n\t"
"str %3, [%0], #8\n\t"
"bcs 1b\n\t"
"\n2:\n\t"
: "+r" ( result_elements ),
"=&r" ( discard_low ),
"=&r" ( discard_high ),
"=r" ( discard_temp_low ),
"=r" ( discard_temp_high ),
"+m" ( *result )
: "r" ( multiplicand_element ),
"r" ( multiplier_element )
: "cc" );
}
}
}

View File

@ -43,8 +43,9 @@ bigint_init_raw ( uint64_t *value0, unsigned int size,
* @v addend0 Element 0 of big integer to add
* @v value0 Element 0 of big integer to be added to
* @v size Number of elements
* @ret carry Carry out
*/
static inline __attribute__ (( always_inline )) void
static inline __attribute__ (( always_inline )) int
bigint_add_raw ( const uint64_t *addend0, uint64_t *value0,
unsigned int size ) {
bigint_t ( size ) __attribute__ (( may_alias )) *value =
@ -54,6 +55,7 @@ bigint_add_raw ( const uint64_t *addend0, uint64_t *value0,
uint64_t discard_addend_i;
uint64_t discard_value_i;
unsigned int discard_size;
int carry;
__asm__ __volatile__ ( "cmn xzr, xzr\n\t" /* clear CF */
"\n1:\n\t"
@ -68,9 +70,11 @@ bigint_add_raw ( const uint64_t *addend0, uint64_t *value0,
"=r" ( discard_size ),
"=r" ( discard_addend_i ),
"=r" ( discard_value_i ),
"=@cccs" ( carry ),
"+m" ( *value )
: "0" ( addend0 ), "1" ( value0 ), "2" ( size )
: "cc" );
: "0" ( addend0 ), "1" ( value0 ),
"2" ( size ) );
return carry;
}
/**
@ -79,8 +83,9 @@ bigint_add_raw ( const uint64_t *addend0, uint64_t *value0,
* @v subtrahend0 Element 0 of big integer to subtract
* @v value0 Element 0 of big integer to be subtracted from
* @v size Number of elements
* @ret borrow Borrow out
*/
static inline __attribute__ (( always_inline )) void
static inline __attribute__ (( always_inline )) int
bigint_subtract_raw ( const uint64_t *subtrahend0, uint64_t *value0,
unsigned int size ) {
bigint_t ( size ) __attribute__ (( may_alias )) *value =
@ -90,6 +95,7 @@ bigint_subtract_raw ( const uint64_t *subtrahend0, uint64_t *value0,
uint64_t discard_subtrahend_i;
uint64_t discard_value_i;
unsigned int discard_size;
int borrow;
__asm__ __volatile__ ( "cmp xzr, xzr\n\t" /* set CF */
"\n1:\n\t"
@ -104,25 +110,28 @@ bigint_subtract_raw ( const uint64_t *subtrahend0, uint64_t *value0,
"=r" ( discard_size ),
"=r" ( discard_subtrahend_i ),
"=r" ( discard_value_i ),
"=@cccc" ( borrow ),
"+m" ( *value )
: "0" ( subtrahend0 ), "1" ( value0 ),
"2" ( size )
: "cc" );
"2" ( size ) );
return borrow;
}
/**
* Rotate big integer left
* Shift big integer left
*
* @v value0 Element 0 of big integer
* @v size Number of elements
* @ret out Bit shifted out
*/
static inline __attribute__ (( always_inline )) void
bigint_rol_raw ( uint64_t *value0, unsigned int size ) {
static inline __attribute__ (( always_inline )) int
bigint_shl_raw ( uint64_t *value0, unsigned int size ) {
bigint_t ( size ) __attribute__ (( may_alias )) *value =
( ( void * ) value0 );
uint64_t *discard_value;
uint64_t discard_value_i;
unsigned int discard_size;
int carry;
__asm__ __volatile__ ( "cmn xzr, xzr\n\t" /* clear CF */
"\n1:\n\t"
@ -134,40 +143,43 @@ bigint_rol_raw ( uint64_t *value0, unsigned int size ) {
: "=r" ( discard_value ),
"=r" ( discard_size ),
"=r" ( discard_value_i ),
"=@cccs" ( carry ),
"+m" ( *value )
: "0" ( value0 ), "1" ( size )
: "cc" );
: "0" ( value0 ), "1" ( size ) );
return carry;
}
/**
* Rotate big integer right
* Shift big integer right
*
* @v value0 Element 0 of big integer
* @v size Number of elements
* @ret out Bit shifted out
*/
static inline __attribute__ (( always_inline )) void
bigint_ror_raw ( uint64_t *value0, unsigned int size ) {
static inline __attribute__ (( always_inline )) int
bigint_shr_raw ( uint64_t *value0, unsigned int size ) {
bigint_t ( size ) __attribute__ (( may_alias )) *value =
( ( void * ) value0 );
uint64_t *discard_value;
uint64_t discard_value_i;
uint64_t discard_value_j;
uint64_t discard_high;
unsigned int discard_size;
uint64_t low;
__asm__ __volatile__ ( "mov %3, #0\n\t"
__asm__ __volatile__ ( "mov %2, #0\n\t"
"\n1:\n\t"
"sub %w1, %w1, #1\n\t"
"ldr %2, [%0, %1, lsl #3]\n\t"
"extr %3, %3, %2, #1\n\t"
"str %3, [%0, %1, lsl #3]\n\t"
"mov %3, %2\n\t"
"ldr %3, [%0, %1, lsl #3]\n\t"
"extr %2, %2, %3, #1\n\t"
"str %2, [%0, %1, lsl #3]\n\t"
"mov %2, %3\n\t"
"cbnz %w1, 1b\n\t"
: "=r" ( discard_value ),
"=r" ( discard_size ),
"=r" ( discard_value_i ),
"=r" ( discard_value_j ),
"=r" ( discard_high ),
"=r" ( low ),
"+m" ( *value )
: "0" ( value0 ), "1" ( size ) );
return ( low & 1 );
}
/**
@ -217,25 +229,6 @@ bigint_is_geq_raw ( const uint64_t *value0, const uint64_t *reference0,
return ( value_i >= reference_i );
}
/**
* Test if bit is set in big integer
*
* @v value0 Element 0 of big integer
* @v size Number of elements
* @v bit Bit to test
* @ret is_set Bit is set
*/
static inline __attribute__ (( always_inline )) int
bigint_bit_is_set_raw ( const uint64_t *value0, unsigned int size,
unsigned int bit ) {
const bigint_t ( size ) __attribute__ (( may_alias )) *value =
( ( const void * ) value0 );
unsigned int index = ( bit / ( 8 * sizeof ( value->element[0] ) ) );
unsigned int subindex = ( bit % ( 8 * sizeof ( value->element[0] ) ) );
return ( !! ( value->element[index] & ( 1UL << subindex ) ) );
}
/**
* Find highest bit set in big integer
*
@ -310,10 +303,36 @@ bigint_done_raw ( const uint64_t *value0, unsigned int size __unused,
*(--out_byte) = *(value_byte++);
}
extern void bigint_multiply_raw ( const uint64_t *multiplicand0,
unsigned int multiplicand_size,
const uint64_t *multiplier0,
unsigned int multiplier_size,
uint64_t *value0 );
/**
* Multiply big integer elements
*
* @v multiplicand Multiplicand element
* @v multiplier Multiplier element
* @v result Result element
* @v carry Carry element
*/
static inline __attribute__ (( always_inline )) void
bigint_multiply_one ( const uint64_t multiplicand, const uint64_t multiplier,
uint64_t *result, uint64_t *carry ) {
uint64_t discard_low;
uint64_t discard_high;
__asm__ __volatile__ ( /* Perform multiplication */
"mul %0, %4, %5\n\t"
"umulh %1, %4, %5\n\t"
/* Accumulate result */
"adds %2, %2, %0\n\t"
"adc %1, %1, xzr\n\t"
/* Accumulate carry (cannot overflow) */
"adds %2, %2, %3\n\t"
"adc %3, %1, xzr\n\t"
: "=&r" ( discard_low ),
"=r" ( discard_high ),
"+r" ( *result ),
"+r" ( *carry )
: "r" ( multiplicand ),
"r" ( multiplier )
: "cc" );
}
#endif /* _BITS_BIGINT_H */

View File

@ -0,0 +1,30 @@
#ifndef _BITS_LKRN_H
#define _BITS_LKRN_H
/** @file
*
* Linux kernel image invocation
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** Header magic value */
#define LKRN_MAGIC_ARCH LKRN_MAGIC_AARCH64
/**
* Jump to kernel entry point
*
* @v entry Kernel entry point
* @v fdt Device tree
*/
static inline __attribute__ (( noreturn )) void
lkrn_jump ( physaddr_t entry, physaddr_t fdt ) {
register unsigned long x0 asm ( "x0" ) = fdt;
__asm__ __volatile__ ( "br %1"
: : "r" ( x0 ), "r" ( entry ) );
__builtin_unreachable();
}
#endif /* _BITS_LKRN_H */

View File

@ -16,7 +16,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
*
* @ret timestamp Timestamp
*/
static inline __attribute__ (( always_inline )) uint64_t
static inline __attribute__ (( always_inline )) unsigned long
profile_timestamp ( void ) {
uint64_t cycles;

View File

@ -1,5 +1,5 @@
#ifndef _SETJMP_H
#define _SETJMP_H
#ifndef _BITS_SETJMP_H
#define _BITS_SETJMP_H
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
@ -35,10 +35,4 @@ typedef struct {
uint64_t sp;
} jmp_buf[1];
extern int __asmcall __attribute__ (( returns_twice ))
setjmp ( jmp_buf env );
extern void __asmcall __attribute__ (( noreturn ))
longjmp ( jmp_buf env, int val );
#endif /* _SETJMP_H */
#endif /* _BITS_SETJMP_H */

View File

@ -1,3 +1,7 @@
# Specify compressor
#
ZBIN = $(ZBIN32)
# Force i386-only instructions
#
CFLAGS += -march=i386

View File

@ -8,10 +8,6 @@ ELF2EFI = $(ELF2EFI32)
#
CFLAGS += -malign-double
# Specify EFI boot file
#
EFI_BOOT_FILE = bootia32.efi
# Include generic EFI Makefile
#
MAKEDEPS += arch/x86/Makefile.efi

View File

@ -16,12 +16,12 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
*
* @ret timestamp Timestamp
*/
static inline __attribute__ (( always_inline )) uint64_t
static inline __attribute__ (( always_inline )) unsigned long
profile_timestamp ( void ) {
uint64_t tsc;
uint32_t tsc;
/* Read timestamp counter */
__asm__ __volatile__ ( "rdtsc" : "=A" ( tsc ) );
__asm__ __volatile__ ( "rdtsc" : "=a" ( tsc ) : : "edx" );
return tsc;
}

View File

@ -1,5 +1,5 @@
#ifndef _SETJMP_H
#define _SETJMP_H
#ifndef _BITS_SETJMP_H
#define _BITS_SETJMP_H
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
@ -21,10 +21,4 @@ typedef struct {
uint32_t ebp;
} jmp_buf[1];
extern int __asmcall __attribute__ (( returns_twice ))
setjmp ( jmp_buf env );
extern void __asmcall __attribute__ (( noreturn ))
longjmp ( jmp_buf env, int val );
#endif /* _SETJMP_H */
#endif /* _BITS_SETJMP_H */

View File

@ -88,6 +88,8 @@ SECTIONS {
__rodata16 = .;
*(.rodata16)
*(.rodata16.*)
*(.srodata)
*(.srodata.*)
*(.rodata)
*(.rodata.*)
}
@ -95,6 +97,8 @@ SECTIONS {
__data16 = .;
*(.data16)
*(.data16.*)
*(.sdata)
*(.sdata.*)
*(.data)
*(.data.*)
KEEP(*(SORT(.tbl.*))) /* Various tables. See include/tables.h */
@ -107,6 +111,8 @@ SECTIONS {
_bss16 = .;
*(.bss16)
*(.bss16.*)
*(.sbss)
*(.sbss.*)
*(.bss)
*(.bss.*)
*(COMMON)

View File

@ -1,3 +1,7 @@
# Specify compressor
#
ZBIN = $(ZBIN64)
# Assembler section type character
#
ASM_TCHAR := @
@ -18,6 +22,9 @@ endif
# EFI requires -fshort-wchar, and nothing else currently uses wchar_t
CFLAGS += -fshort-wchar
# Include LoongArch64-specific headers
INCDIRS := arch/$(ARCH)/include $(INCDIRS)
# LoongArch64-specific directories containing source files
SRCDIRS += arch/loong64/core
SRCDIRS += arch/loong64/interface/efi

View File

@ -4,10 +4,6 @@
#
ELF2EFI = $(ELF2EFI64)
# Specify EFI boot file
#
EFI_BOOT_FILE = bootloongarch64.efi
# Include generic EFI Makefile
#
MAKEDEPS += Makefile.efi

View File

@ -1,124 +0,0 @@
/*
* Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
* Copyright (c) 2023, Xiaotian Wu <wuxiaotian@loongson.cn>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
* You can also choose to distribute this program under the terms of
* the Unmodified Binary Distribution Licence (as given in the file
* COPYING.UBDL), provided that you have satisfied its requirements.
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <string.h>
#include <ipxe/bigint.h>
/** @file
*
* Big integer support
*/
/**
* Multiply big integers
*
* @v multiplicand0 Element 0 of big integer to be multiplied
* @v multiplicand_size Number of elements in multiplicand
* @v multiplier0 Element 0 of big integer to be multiplied
* @v multiplier_size Number of elements in multiplier
* @v result0 Element 0 of big integer to hold result
*/
void bigint_multiply_raw ( const uint64_t *multiplicand0,
unsigned int multiplicand_size,
const uint64_t *multiplier0,
unsigned int multiplier_size,
uint64_t *result0 ) {
unsigned int result_size = ( multiplicand_size + multiplier_size );
const bigint_t ( multiplicand_size ) __attribute__ (( may_alias ))
*multiplicand = ( ( const void * ) multiplicand0 );
const bigint_t ( multiplier_size ) __attribute__ (( may_alias ))
*multiplier = ( ( const void * ) multiplier0 );
bigint_t ( result_size ) __attribute__ (( may_alias ))
*result = ( ( void * ) result0 );
unsigned int i;
unsigned int j;
uint64_t multiplicand_element;
uint64_t multiplier_element;
uint64_t *result_elements;
uint64_t discard_low;
uint64_t discard_high;
uint64_t discard_temp_low;
uint64_t discard_temp_high;
/* Zero result */
memset ( result, 0, sizeof ( *result ) );
/* Multiply integers one element at a time */
for ( i = 0 ; i < multiplicand_size ; i++ ) {
multiplicand_element = multiplicand->element[i];
for ( j = 0 ; j < multiplier_size ; j++ ) {
multiplier_element = multiplier->element[j];
result_elements = &result->element[ i + j ];
/* Perform a single multiply, and add the
* resulting double-element into the result,
* carrying as necessary. The carry can
* never overflow beyond the end of the
* result, since:
*
* a < 2^{n}, b < 2^{m} => ab < 2^{n+m}
*/
__asm__ __volatile__ ( "mul.d %1, %6, %7\n\t"
"mulh.du %2, %6, %7\n\t"
"ld.d %3, %0, 0\n\t"
"ld.d %4, %0, 8\n\t"
"add.d %3, %3, %1\n\t"
"sltu $t0, %3, %1\n\t"
"add.d %4, %4, %2\n\t"
"sltu $t1, %4, %2\n\t"
"add.d %4, %4, $t0\n\t"
"sltu $t0, %4, $t0\n\t"
"or $t0, $t0, $t1\n\t"
"st.d %3, %0, 0\n\t"
"st.d %4, %0, 8\n\t"
"addi.d %0, %0, 16\n\t"
"beqz $t0, 2f\n"
"1:\n\t"
"ld.d %3, %0, 0\n\t"
"add.d %3, %3, $t0\n\t"
"sltu $t0, %3, $t0\n\t"
"st.d %3, %0, 0\n\t"
"addi.d %0, %0, 8\n\t"
"bnez $t0, 1b\n"
"2:"
: "+r" ( result_elements ),
"=&r" ( discard_low ),
"=&r" ( discard_high ),
"=r" ( discard_temp_low ),
"=r" ( discard_temp_high ),
"+m" ( *result )
: "r" ( multiplicand_element ),
"r" ( multiplier_element )
: "t0", "t1" );
}
}
}

View File

@ -1,12 +0,0 @@
#ifndef _BITS_ACPI_H
#define _BITS_ACPI_H
/** @file
*
* LoongArch64-specific ACPI API implementations
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#endif /* _BITS_ACPI_H */

View File

@ -43,8 +43,9 @@ bigint_init_raw ( uint64_t *value0, unsigned int size,
* @v addend0 Element 0 of big integer to add
* @v value0 Element 0 of big integer to be added to
* @v size Number of elements
* @ret carry Carry out
*/
static inline __attribute__ (( always_inline )) void
static inline __attribute__ (( always_inline )) int
bigint_add_raw ( const uint64_t *addend0, uint64_t *value0,
unsigned int size ) {
bigint_t ( size ) __attribute__ (( may_alias )) *value =
@ -53,20 +54,20 @@ bigint_add_raw ( const uint64_t *addend0, uint64_t *value0,
uint64_t *discard_value;
uint64_t discard_addend_i;
uint64_t discard_value_i;
uint64_t discard_carry;
uint64_t discard_temp;
unsigned int discard_size;
uint64_t carry;
__asm__ __volatile__ ( "\n1:\n\t"
/* Load addend[i] and value[i] */
"ld.d %3, %0, 0\n\t"
"ld.d %4, %1, 0\n\t"
/* Add carry flag and addend */
"add.d %4, %4, %5\n\t"
"sltu %6, %4, %5\n\t"
"add.d %4, %4, %6\n\t"
"sltu %5, %4, %6\n\t"
"add.d %4, %4, %3\n\t"
"sltu %5, %4, %3\n\t"
"or %5, %5, %6\n\t"
"sltu %6, %4, %3\n\t"
"or %6, %5, %6\n\t"
/* Store value[i] */
"st.d %4, %1, 0\n\t"
/* Loop */
@ -79,11 +80,12 @@ bigint_add_raw ( const uint64_t *addend0, uint64_t *value0,
"=r" ( discard_size ),
"=r" ( discard_addend_i ),
"=r" ( discard_value_i ),
"=r" ( discard_carry ),
"=r" ( discard_temp ),
"=r" ( carry ),
"+m" ( *value )
: "0" ( addend0 ), "1" ( value0 ),
"2" ( size ), "5" ( 0 ) );
"2" ( size ), "6" ( 0 ) );
return carry;
}
/**
@ -92,8 +94,9 @@ bigint_add_raw ( const uint64_t *addend0, uint64_t *value0,
* @v subtrahend0 Element 0 of big integer to subtract
* @v value0 Element 0 of big integer to be subtracted from
* @v size Number of elements
* @ret borrow Borrow out
*/
static inline __attribute__ (( always_inline )) void
static inline __attribute__ (( always_inline )) int
bigint_subtract_raw ( const uint64_t *subtrahend0, uint64_t *value0,
unsigned int size ) {
bigint_t ( size ) __attribute__ (( may_alias )) *value =
@ -102,20 +105,20 @@ bigint_subtract_raw ( const uint64_t *subtrahend0, uint64_t *value0,
uint64_t *discard_value;
uint64_t discard_subtrahend_i;
uint64_t discard_value_i;
uint64_t discard_carry;
uint64_t discard_temp;
unsigned int discard_size;
uint64_t borrow;
__asm__ __volatile__ ( "\n1:\n\t"
/* Load subtrahend[i] and value[i] */
"ld.d %3, %0, 0\n\t"
"ld.d %4, %1, 0\n\t"
/* Subtract carry flag and subtrahend */
"sltu %6, %4, %5\n\t"
"sub.d %4, %4, %5\n\t"
"sltu %5, %4, %3\n\t"
"sltu %5, %4, %6\n\t"
"sub.d %4, %4, %6\n\t"
"sltu %6, %4, %3\n\t"
"sub.d %4, %4, %3\n\t"
"or %5, %5, %6\n\t"
"or %6, %5, %6\n\t"
/* Store value[i] */
"st.d %4, %1, 0\n\t"
/* Loop */
@ -128,38 +131,40 @@ bigint_subtract_raw ( const uint64_t *subtrahend0, uint64_t *value0,
"=r" ( discard_size ),
"=r" ( discard_subtrahend_i ),
"=r" ( discard_value_i ),
"=r" ( discard_carry ),
"=r" ( discard_temp ),
"=r" ( borrow ),
"+m" ( *value )
: "0" ( subtrahend0 ), "1" ( value0 ),
"2" ( size ), "5" ( 0 ) );
"2" ( size ), "6" ( 0 ) );
return borrow;
}
/**
* Rotate big integer left
* Shift big integer left
*
* @v value0 Element 0 of big integer
* @v size Number of elements
* @ret out Bit shifted out
*/
static inline __attribute__ (( always_inline )) void
bigint_rol_raw ( uint64_t *value0, unsigned int size ) {
static inline __attribute__ (( always_inline )) int
bigint_shl_raw ( uint64_t *value0, unsigned int size ) {
bigint_t ( size ) __attribute__ (( may_alias )) *value =
( ( void * ) value0 );
uint64_t *discard_value;
uint64_t discard_value_i;
uint64_t discard_carry;
uint64_t discard_temp;
unsigned int discard_size;
uint64_t carry;
__asm__ __volatile__ ( "\n1:\n\t"
/* Load value[i] */
"ld.d %2, %0, 0\n\t"
/* Shift left */
"rotri.d %2, %2, 63\n\t"
"andi %4, %2, 1\n\t"
"xor %2, %2, %4\n\t"
"or %2, %2, %3\n\t"
"move %3, %4\n\t"
"andi %3, %2, 1\n\t"
"xor %2, %2, %3\n\t"
"or %2, %2, %4\n\t"
"move %4, %3\n\t"
/* Store value[i] */
"st.d %2, %0, 0\n\t"
/* Loop */
@ -169,37 +174,39 @@ bigint_rol_raw ( uint64_t *value0, unsigned int size ) {
: "=r" ( discard_value ),
"=r" ( discard_size ),
"=r" ( discard_value_i ),
"=r" ( discard_carry ),
"=r" ( discard_temp ),
"=r" ( carry ),
"+m" ( *value )
: "0" ( value0 ), "1" ( size ), "3" ( 0 )
: "0" ( value0 ), "1" ( size ), "4" ( 0 )
: "cc" );
return ( carry & 1 );
}
/**
* Rotate big integer right
* Shift big integer right
*
* @v value0 Element 0 of big integer
* @v size Number of elements
* @ret out Bit shifted out
*/
static inline __attribute__ (( always_inline )) void
bigint_ror_raw ( uint64_t *value0, unsigned int size ) {
static inline __attribute__ (( always_inline )) int
bigint_shr_raw ( uint64_t *value0, unsigned int size ) {
bigint_t ( size ) __attribute__ (( may_alias )) *value =
( ( void * ) value0 );
uint64_t *discard_value;
uint64_t discard_value_i;
uint64_t discard_carry;
uint64_t discard_temp;
unsigned int discard_size;
uint64_t carry;
__asm__ __volatile__ ( "\n1:\n\t"
/* Load value[i] */
"ld.d %2, %0, -8\n\t"
/* Shift right */
"andi %4, %2, 1\n\t"
"xor %2, %2, %4\n\t"
"or %2, %2, %3\n\t"
"move %3, %4\n\t"
"andi %3, %2, 1\n\t"
"xor %2, %2, %3\n\t"
"or %2, %2, %4\n\t"
"move %4, %3\n\t"
"rotri.d %2, %2, 1\n\t"
/* Store value[i] */
"st.d %2, %0, -8\n\t"
@ -210,11 +217,12 @@ bigint_ror_raw ( uint64_t *value0, unsigned int size ) {
: "=r" ( discard_value ),
"=r" ( discard_size ),
"=r" ( discard_value_i ),
"=r" ( discard_carry ),
"=r" ( discard_temp ),
"=r" ( carry ),
"+m" ( *value )
: "0" ( value0 + size ), "1" ( size ), "3" ( 0 )
: "0" ( value0 + size ), "1" ( size ), "4" ( 0 )
: "cc" );
return ( carry & 1 );
}
/**
@ -264,25 +272,6 @@ bigint_is_geq_raw ( const uint64_t *value0, const uint64_t *reference0,
return ( value_i >= reference_i );
}
/**
* Test if bit is set in big integer
*
* @v value0 Element 0 of big integer
* @v size Number of elements
* @v bit Bit to test
* @ret is_set Bit is set
*/
static inline __attribute__ (( always_inline )) int
bigint_bit_is_set_raw ( const uint64_t *value0, unsigned int size,
unsigned int bit ) {
const bigint_t ( size ) __attribute__ (( may_alias )) *value =
( ( const void * ) value0 );
unsigned int index = ( bit / ( 8 * sizeof ( value->element[0] ) ) );
unsigned int subindex = ( bit % ( 8 * sizeof ( value->element[0] ) ) );
return ( !! ( value->element[index] & ( 1UL << subindex ) ) );
}
/**
* Find highest bit set in big integer
*
@ -357,10 +346,39 @@ bigint_done_raw ( const uint64_t *value0, unsigned int size __unused,
*(--out_byte) = *(value_byte++);
}
extern void bigint_multiply_raw ( const uint64_t *multiplicand0,
unsigned int multiplicand_size,
const uint64_t *multiplier0,
unsigned int multiplier_size,
uint64_t *value0 );
/**
* Multiply big integer elements
*
* @v multiplicand Multiplicand element
* @v multiplier Multiplier element
* @v result Result element
* @v carry Carry element
*/
static inline __attribute__ (( always_inline )) void
bigint_multiply_one ( const uint64_t multiplicand, const uint64_t multiplier,
uint64_t *result, uint64_t *carry ) {
uint64_t discard_low;
uint64_t discard_high;
uint64_t discard_carry;
__asm__ __volatile__ ( /* Perform multiplication */
"mul.d %0, %5, %6\n\t"
"mulh.du %1, %5, %6\n\t"
/* Accumulate low half */
"add.d %3, %3, %0\n\t"
"sltu %2, %3, %0\n\t"
"add.d %1, %1, %2\n\t"
/* Accumulate carry (cannot overflow) */
"add.d %3, %3, %4\n\t"
"sltu %2, %3, %4\n\t"
"add.d %4, %1, %2\n\t"
: "=&r" ( discard_low ),
"=r" ( discard_high ),
"=r" ( discard_carry ),
"+r" ( *result ),
"+r" ( *carry )
: "r" ( multiplicand ),
"r" ( multiplier ) );
}
#endif /* _BITS_BIGINT_H */

View File

@ -1,12 +0,0 @@
#ifndef _BITS_HYPERV_H
#define _BITS_HYPERV_H
/** @file
*
* Hyper-V interface
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#endif /* _BITS_HYPERV_H */

View File

@ -1,12 +0,0 @@
#ifndef _BITS_MP_H
#define _BITS_MP_H
/** @file
*
* LoongArch64-specific multiprocessor API implementation
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#endif /* _BITS_MP_H */

View File

@ -9,6 +9,12 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/efi/efiloong64_nap.h>
/**
* Sleep until next CPU interrupt
*
*/
static inline __attribute__ (( always_inline )) void cpu_halt ( void ) {
__asm__ __volatile__ ( "idle 0" );
}
#endif /* _BITS_NAP_H */

View File

@ -1,12 +0,0 @@
#ifndef _BITS_PCI_IO_H
#define _BITS_PCI_IO_H
/** @file
*
* LoongArch64-specific PCI I/O API implementations
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#endif /* _BITS_PCI_IO_H */

View File

@ -16,7 +16,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
*
* @ret timestamp Timestamp
*/
static inline __attribute__ (( always_inline )) uint64_t
static inline __attribute__ (( always_inline )) unsigned long
profile_timestamp ( void ) {
uint64_t cycles;

View File

@ -1,12 +0,0 @@
#ifndef _BITS_REBOOT_H
#define _BITS_REBOOT_H
/** @file
*
* LoongArch64-specific reboot API implementations
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#endif /* _BITS_REBOOT_H */

View File

@ -1,12 +0,0 @@
#ifndef _BITS_SANBOOT_H
#define _BITS_SANBOOT_H
/** @file
*
* LoongArch64-specific sanboot API implementations
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#endif /* _BITS_SANBOOT_H */

Some files were not shown because too many files have changed in this diff Show More