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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>