Commit Graph

6756 Commits (9dd30f11f74722a43ed590df9f525e038d155283)

Author SHA1 Message Date
Michael Brown 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
Michael Brown 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
Michael Brown 8816ddcd96 [efi] Update to current EDK2 headers
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-12-17 13:30:16 +00:00
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Animesh Bhatt 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
Michael Brown 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
Michael Brown 301644ab48 [test] Add CMS decryption self-tests
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-08-29 23:36:00 +01:00
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown 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
Michael Brown e965f179e1 [libc] Add stpcpy()
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-05-31 10:11:22 +01:00
Michael Brown 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
Michael Brown d7e58c5a81 [test] Add test cases for editable strings
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-04-17 15:56:08 +01:00