aboutsummaryrefslogtreecommitdiffstats
Commit message (Collapse)AuthorAgeFilesLines
* [build] Centralise dummy architecture-specific headersriscv64Michael Brown2024-09-0345-336/+238
| | | | | | | | 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>
* [etherfabric] Fix use of uninitialised variable in falcon_xaui_link_ok()Michael Brown2024-09-021-6/+9
| | | | | | | | | | | | | | 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>
* [test] Add CMS decryption self-testsMichael Brown2024-08-291-2/+353
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [crypto] Allow cms_decrypt() to be called on unregistered imagesMichael Brown2024-08-291-9/+15
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [image] Add the "imgdecrypt" commandMichael Brown2024-08-295-0/+220
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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>
* [crypto] Support decryption of images via CMS envelopesMichael Brown2024-08-293-17/+529
| | | | | | | | 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>
* [image] Split image_strip_suffix() out from image_extract()Michael Brown2024-08-293-5/+22
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [crypto] Add cmsdetach script for detaching encrypted data from CMS messagesMichael Brown2024-08-281-0/+80
| | | | | | | | | | | | | | | | 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>
* [test] Update CMS self-test terminologyMichael Brown2024-08-281-59/+58
| | | | | | | | 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>
* [crypto] Allow for extraction of ASN.1 algorithm parametersMichael Brown2024-08-284-11/+92
| | | | | | | | | | | 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>
* [crypto] Hold CMS message as a single ASN.1 objectMichael Brown2024-08-232-29/+15
| | | | | | | | | | 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>
* [crypto] Remove the concept of a public-key algorithm reusable contextMichael Brown2024-08-2111-398/+304
| | | | | | | | | | | | | | | | | | | | | | | 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>
* [tls] Group client and server state in TLS connection structureMichael Brown2024-08-212-128/+147
| | | | | | | | | | | | 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>
* [tls] Group transmit and receive state in TLS connection structureMichael Brown2024-08-212-108/+119
| | | | | | | | | | | | 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>
* [gve] Add missing error codes in EUNIQ() list of potential errorsMichael Brown2024-08-201-4/+5
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [contrib] Remove obsolete rom-o-matic codeMichael Brown2024-08-2042-1955/+0
| | | | | | | | | | | | | | | 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>
* [test] Generalise public-key algorithm tests and use okx()Michael Brown2024-08-183-309/+336
| | | | | | | | 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>
* [crypto] Pass asymmetric keys as ASN.1 cursorsMichael Brown2024-08-1810-112/+74
| | | | | | | | | | | 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>
* [efi] Allow discovery of PCI bus:dev.fn address rangesMichael Brown2024-08-152-78/+176
| | | | | | | | | | | 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>
* [pci] Separate permission to probe buses from bus:dev.fn range discoveryMichael Brown2024-08-1514-0/+77
| | | | | | | | | | | | | | | | | 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>
* [crypto] Fix debug name for empty certificate chain validatorsMichael Brown2024-08-141-2/+4
| | | | | | | | | | | | | | | | | 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>
* [crypto] Generalise cms_signature to cms_messageMichael Brown2024-08-145-284/+364
| | | | | | | | | | | | | | | | | 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>
* [crypto] Add OID-identified algorithms for AES ciphersMichael Brown2024-08-145-0/+196
| | | | | | | 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>
* [crypto] Pass image as parameter to CMS functionsMichael Brown2024-08-134-65/+101
| | | | | | | | | | | | | 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>
* [crypto] Allow passing a NULL certificate store to x509_find() et alMichael Brown2024-08-134-40/+55
| | | | | | | | | | 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>
* [crypto] Centralise mechanisms for identifying X.509 certificatesMichael Brown2024-08-126-87/+133
| | | | | | | | | 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>
* [crypto] Extend asn1_enter() to handle partial object cursorsMichael Brown2024-08-073-22/+43
| | | | | | | | | | | | | | | | | | | | | | | 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>
* [crypto] Clarify ASN.1 cursor invalidation behaviourMichael Brown2024-08-071-8/+21
| | | | | | | | | | | | | | | 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>
* [crypto] Do not return an error when skipping the final ASN.1 objectMichael Brown2024-08-071-5/+0
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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>
* [cpuid] Allow hypervisor CPUID leaves to be accessed as settingsMichael Brown2024-08-011-4/+14
| | | | | | | | | | | | 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>
* [cpuid] Allow reading hypervisor CPUID leavesMichael Brown2024-08-012-2/+5
| | | | | | | | | | | | | | 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>
* [smbios] Allow reading an entire SMBIOS data structure as a settingMichael Brown2024-07-311-1/+9
| | | | | | | | | | | | | | | | | | | | 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>
* [smbios] Avoid reading beyond end of constructed SMBIOS settingMichael Brown2024-07-311-0/+7
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [cloud] Add utility to read INT13CON partition in Google Compute EngineMichael Brown2024-07-301-0/+146
| | | | | | | | | | | | | | 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>
* [gve] Increase number of receive buffers to reduce packet lossMichael Brown2024-07-252-5/+13
| | | | | | | | | | | 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>
* [gve] Add driver for Google Virtual Ethernet NICMichael Brown2024-07-244-0/+2313
| | | | | | | | 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>
* [cloud] Add utility for importing images to Google Compute EngineMichael Brown2024-07-081-0/+167
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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>
* [ipv6] Expose router address for DHCPv6 leased addressesMichael Brown2024-06-273-18/+97
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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>
* [ipv4] Support small subnets with no directed broadcast addressMichael Brown2024-06-263-6/+36
| | | | | | | | | | | | | | | | | | | | | | | | | 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>
* [hci] Remove the generalised widget user interface abstractionMichael Brown2024-06-214-254/+0
| | | | | | | | 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>
* [form] Reimplement the "login" user interfaceMichael Brown2024-06-211-61/+31
| | | | | | | | | | | | | | | | | | 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>
* [form] Add support for dynamically created interactive formsMichael Brown2024-06-206-0/+616
| | | | | | | | | | | | | | | | 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>
* [dynui] Add concept of a secret user interface itemMichael Brown2024-06-202-0/+9
| | | | | | | | | | | | | | 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>
* [dynui] Allow for multiple flags on a user interface itemMichael Brown2024-06-204-10/+17
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [dynui] Generalise mechanisms for looking up user interface itemsMichael Brown2024-06-203-32/+52
| | | | | | | | 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>
* [dynui] Generalise the concept of a menu to a dynamic user interfaceMichael Brown2024-06-209-192/+195
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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>
* [hci] Allow tab key to be used to cycle through UI elementsMichael Brown2024-06-204-33/+86
| | | | | | | | | | | 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>
* [hci] Rename "item" command's first parameter from "label" to "name"Michael Brown2024-06-184-33/+33
| | | | | | | | | | | 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>
* [hci] Split out msg() and alert() from settings UI codeMichael Brown2024-06-183-72/+131
| | | | | | | | | | | 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>
* [hci] Draw all widgets on the standard screenMichael Brown2024-06-186-36/+21
| | | | | | | | | | | | | | | 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>