aboutsummaryrefslogtreecommitdiffstats
path: root/src/image
Commit message (Collapse)AuthorAgeFilesLines
* [crypto] Extend asn1_enter() to handle partial object cursorsMichael Brown2024-08-071-11/+4
| | | | | | | | | | | | | | | | | | | | | | | 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>
* [libc] Make static_assert() available via assert.hassertMichael Brown2024-01-161-2/+1
| | | | | | | Expose static_assert() via assert.h and migrate link-time assertions to build-time assertions where possible. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Add support for executing images via a shimMichael Brown2023-05-221-3/+28
| | | | | | | | | | | | | | | | | | | | | | | Add support for using a shim as a helper to execute an EFI image. When a shim has been specified via shim(), the shim image will be passed to LoadImage() instead of the selected EFI image and the command line will be prepended with the name of the selected EFI image. The selected EFI image will be accessible to the shim via the virtual filesystem as a hidden file. Reduce the Secure Boot attack surface by removing, where possible, the spurious requirement for a third party second stage loader binary such as GRUB to be used solely in order to call the "shim lock protocol" entry point. Do not install the EFI PXE APIs when using a shim, since if shim finds EFI_PXE_BASE_CODE_PROTOCOL on the loaded image's device handle then it will attempt to download files afresh instead of using the files already downloaded by iPXE and exposed via the EFI_SIMPLE_FILE_SYSTEM protocol. (Experience shows that there is no point in trying to get a fix for this upstreamed into shim.) Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Add efi_asprintf() and efi_vasprintf()Michael Brown2023-05-221-10/+6
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [image] Generalise concept of selected imageMichael Brown2023-05-171-3/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Most image flags are independent values: any combination of flags may be set for any image, and the flags for one image are independent of the flags for any other image. The "selected" flag does not follow this pattern: at most one image may be marked as selected at any time. When invoking a kernel via the UEFI shim, there will be multiple "special" images: the selected kernel itself, the shim image, and potentially a shim-signed GRUB binary to be used as a crutch to assist shim in loading the kernel (since current versions of the UEFI shim are not capable of directly loading a Linux kernel). Remove the "selected" image flag and replace it with a general concept of an image tag with the same semantics: a given tag may be assigned to at most one image, an image may be found by its tag only while the image is currently registered, and a tag will survive unregistration and reregistration of an image (if it has not already been assigned to a new image). For visual consistency, also replace the current image pointer with a current image tag. The image pointer stored within the image tag holds only a weak reference to the image, since the selection of an image should not prevent that image from being freed. (The strong reference to the currently executing image is held locally within the execution scope of image_exec(), and is logically separate from the current image pointer.) Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Attempt to detect EFI images that fail Secure Boot verificationMichael Brown2023-05-171-5/+71
| | | | | | | | | | | | An EFI image that is rejected by LoadImage() due to failing Secure Boot verification is still an EFI image. Unfortunately, the extremely broken UEFI Secure Boot model provides no way for us to unambiguously determine that a valid EFI executable image was rejected only because it failed signature verification. We must therefore use heuristics to guess whether not an image that was rejected by LoadImage() could still be loaded via a separate PE loader such as the UEFI shim. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Allow currently executing image to be opened via virtual filesystemMichael Brown2023-05-051-0/+10
| | | | | | | | | | | | | When invoking a kernel via the UEFI shim, the kernel image must be accessible via EFI_SIMPLE_FILE_SYSTEM_PROTOCOL but must not be present in the magic initrd constructed from all registered images. Re-register a currently executing EFI image and mark it as hidden, thereby allowing it to be accessed via the virtual filesystem exposed via EFI_SIMPLE_FILE_SYSTEM_PROTOCOL without appearing in the magic initrd contents. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Use image name instead of pointer value in debug messagesMichael Brown2023-03-071-21/+21
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [image] Always unregister currently executing imageinterpreterMichael Brown2023-03-071-9/+0
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | We unregister script images during their execution, to prevent a "boot" command from re-executing the containing script. This also has the side effect of preventing executing scripts from showing up within the Linux magic initrd image (or the Multiboot module list). Additional logic in bzimage.c and efi_file.c prevents a currently executing kernel from showing up within the magic initrd image. Similar logic in multiboot.c prevents the Multiboot kernel from showing up as a Multiboot module. This still leaves some corner cases that are not covered correctly. For example: when using a gzip-compressed kernel image, nothing will currently hide the original compressed image from the magic initrd. Fix by moving the logic that temporarily unregisters the current image from script_exec() to image_exec(), so that it applies to all image types, and simplify the magic initrd and Multiboot module list construction logic on the basis that no further filtering of the registered image list is necessary. This change has the side effect of hiding currently executing EFI images from the virtual filesystem exposed by iPXE. For example, when using iPXE to boot wimboot, the wimboot binary itself will no longer be visible within the virtual filesystem. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Add efi_path_terminate() utility functionMichael Brown2023-01-231-3/+1
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [image] Allow single-member archive images to be executed transparentlyMichael Brown2021-05-122-0/+2
| | | | | | | | Provide image_extract_exec() as a helper method to allow single-member archive images (such as gzip compressed images) to be executed without an explicit "imgextract" step. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [gzip] Add support for gzip archive imagesimgextractMichael Brown2021-05-081-0/+166
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [zlib] Add support for zlib archive imagesMichael Brown2021-05-081-0/+162
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [image] Implicitly trust first embedded imageJoe Groocock2021-01-271-0/+3
| | | | | | | | | | | | | iPXE when used as a NIC option ROM can sometimes be reloaded by the UEFI/BIOS and any pre-initialised memory will remain loaded. When the imgtrust command is run it sets `require_trusted_images'. Upon reloading, iPXE tries to load the first embedded image but fails as it is not marked trusted. Setting this flag ensures that imgtrust with the first embedded script is reentrant. Signed-off-by: Joe Groocock <jgroocock@cloudflare.com>
* [efi] Split device path functions out to efi_path.cMichael Brown2020-10-161-2/+2
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Connect controllers after loading an EFI driverMichael Brown2020-10-021-0/+11
| | | | | | | | | | | | iPXE is already capable of loading EFI drivers on demand (via e.g. "chain UsbMassStorageDxe.efi") but there is currently no way to trigger connection of the driver to any preexisting handles. Add an explicit call to (re)connect all drivers after successfully loading an image with a code type that indicates a boot services driver. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Work around UEFI specification bug in LoadImageMichael Brown2020-06-041-2/+18
| | | | | | | | | | | | | | | | | | | | | | | | iPXE currently assumes that any error returned from LoadImage() indicates that the image was not loaded. This assumption was correct at the time the code was written and remained correct for UEFI specifications up to and including version 2.1. In version 2.3, the UEFI specification broke API and ABI compatibility by defining that a return value of EFI_SECURITY_VIOLATION would now indicate that the image had been loaded and a valid image handle had been created, but that the image should not be started. The wording in version 2.2 is ambiguous, and does not define whether or not a return value of EFI_SECURITY_VIOLATION indicates that a valid image handle has been created. Attempt to work around all of these incompatible and partially undefined APIs by calling UnloadImage if we get a return value of EFI_SECURITY_VIOLATION. Minimise the risk of passing an uninitialised pointer to UnloadImage by setting ImageHandle to NULL prior to calling LoadImage. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [png] Fix potential integer overflowMichael Brown2020-06-041-6/+6
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [crypto] Expose pem_asn1() for use with non-image dataMichael Brown2017-06-201-41/+74
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [crypto] Free correct pointer on the error pathMichael Brown2017-03-211-3/+4
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [crypto] Add PEM image formatMichael Brown2016-07-291-0/+208
| | | | | | | | | | | Add PEM-encoded ASN.1 as an image format. We accept as PEM any image containing a line starting with a "-----BEGIN" boundary marker. We allow for PEM files containing multiple ASN.1 objects, such as a certificate chain produced by concatenating individual certificate files. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [crypto] Add DER image formatMichael Brown2016-07-291-0/+120
| | | | | | | | Add DER-encoded ASN.1 as an image format. There is no fixed signature for DER files. We treat an image as DER if it comprises a single valid SEQUENCE object covering the entire length of the image. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [build] Allow assembler section type character to vary by architectureMichael Brown2016-03-131-1/+1
| | | | | | | | | | | | | | | On some architectures (such as ARM) the "@" character is used as a comment delimiter. A section type argument such as "@progbits" therefore becomes "%progbits". This is further complicated by the fact that the "%" character has special meaning for inline assembly when input or output operands are used, in which cases "@progbits" becomes "%%progbits". Allow the section type character(s) to be defined via Makefile variables. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Add support for EFI_GRAPHICS_OUTPUT_PROTOCOL frame buffer consolesMichael Brown2015-10-161-0/+4
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Provide efi_devpath_len()Michael Brown2015-09-131-2/+1
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Implement the EFI_PXE_BASE_CODE_PROTOCOLMichael Brown2015-09-021-0/+10
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Many UEFI NBPs expect to find an EFI_PXE_BASE_CODE_PROTOCOL installed in addition to the EFI_SIMPLE_NETWORK_PROTOCOL. Most NBPs use the EFI_PXE_BASE_CODE_PROTOCOL only to retrieve the cached DHCP packets. This implementation has been tested with grub.efi, shim.efi, syslinux.efi, and wdsmgfw.efi. Some methods (such as Discover() and Arp()) are not used by any known NBP and so have not (yet) been implemented. Usage notes for the tested bootstraps are: - grub.efi uses EFI_PXE_BASE_CODE_PROTOCOL only to retrieve the cached DHCP packet, and uses no other methods. - shim.efi uses EFI_PXE_BASE_CODE_PROTOCOL to retrieve the cached DHCP packet and to retrieve the next NBP via the Mtftp() method. If shim.efi was downloaded via HTTP (or other non-TFTP protocol) then shim.efi will blindly call Mtftp() with an HTTP URI as the filename: this allows the next NBP (e.g. grubx64.efi) to also be transparently retrieved by HTTP. shim.efi can also use the EFI_SIMPLE_FILE_SYSTEM_PROTOCOL to retrieve files previously loaded by "imgfetch" or similar commands in iPXE. The current implementation of shim.efi will use the EFI_SIMPLE_FILE_SYSTEM_PROTOCOL only if it does not find an EFI_PXE_BASE_CODE_PROTOCOL; this patch therefore prevents this usage of our EFI_SIMPLE_FILE_SYSTEM_PROTOCOL. This logic could be trivially reversed in shim.efi if needed. - syslinux.efi uses EFI_PXE_BASE_CODE_PROTOCOL only to retrieve the cached DHCP packet. Versions 6.03 and earlier have a bug which may cause syslinux.efi to attach to the wrong NIC if there are multiple NICs in the system (or if the UEFI firmware supports IPv6). - wdsmgfw.efi (ab)uses EFI_PXE_BASE_CODE_PROTOCOL to retrieve the cached DHCP packets, and to send and retrieve UDP packets via the UdpWrite() and UdpRead() methods. (This was presumably done in order to minimise the amount of benefit obtainable by switching to UEFI, by replicating all of the design mistakes present in the original PXE specification.) The EFI_DOWNGRADE_UX configuration option remains available for now, until this implementation has received more widespread testing. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [elf] Reject ELFBoot images requiring virtual addressingMichael Brown2015-07-291-51/+88
| | | | | | | | | | | | | | We do not set up any kind of virtual addressing before invoking an ELFBoot image. Reject if the image's program headers indicate that virtual addresses are not equal to physical addresses. This avoids problems when loading some RHEL5 kernels, which seem to include ELFBoot headers using virtual addressing. With this change, these kernels are no longer detected as ELFBoot, and so may be (correctly) detected as bzImage instead. Reported-by: Torgeir.Wulfsberg@kongsberg.com Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [legal] Relicense files under GPL2_OR_LATER_OR_UBDLMichael Brown2015-03-021-1/+1
| | | | | | | | | | These files cannot be automatically relicensed by util/relicense.pl since they either contain unusual but trivial contributions (such as the addition of __nonnull function attributes), or contain lines dating back to the initial git revision (and so require manual knowledge of the code's origin). Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [legal] Relicense files under GPL2_OR_LATER_OR_UBDLMichael Brown2015-03-025-5/+25
| | | | | | | Relicense files for which I am the sole author (as identified by util/relicense.pl). Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Provide dummy device path in efi_image_probe()Michael Brown2014-09-191-1/+6
| | | | | | | | | | | | | | | | | Some UEFI platforms will fail the call to LoadImage() with EFI_INVALID_PARAMETER if we do not provide a device path (even though we are providing a non-NULL SourceBuffer). Fix by providing an empty device path for the call to LoadImage() in efi_image_probe(). The call to LoadImage() in efi_image_exec() already constructs and provides a device path (based on the most recently opened SNP device), and so does not require this fix. Reported-by: NICOLAS CATTIE <nicolas.cattie@mpsa.com> Tested-by: NICOLAS CATTIE <nicolas.cattie@mpsa.com> Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Wrap any images loaded by our wrapped imageMichael Brown2014-08-291-1/+1
| | | | | | | | | | | | Propagate our modified EFI system table to any images loaded by the image that we wrap, thereby allowing us to observe boot services calls made by all subsequent EFI images. Also show details of intercepted ExitBootServices() calls. When wrapping is used, exiting boot services will almost certainly fail, but this at least allows us to see when it happens. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Move abstract device path and handle functions to efi_utils.cMichael Brown2014-08-061-1/+1
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Open device path protocol only at point of useMichael Brown2014-08-051-1/+1
| | | | | | | | | | | | Some EFI 1.10 systems (observed on an Apple iMac) do not allow us to open the device path protocol with an attribute of EFI_OPEN_PROTOCOL_BY_DRIVER and so we cannot maintain a safe, long-lived pointer to the device path. Work around this by instead opening the device path protocol with an attribute of EFI_OPEN_PROTOCOL_GET_PROTOCOL whenever we need to use it. Debugged-by: Curtis Larsen <larsen@dixie.edu> Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Provide centralised definitions of commonly-used GUIDsMichael Brown2014-08-051-4/+0
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Avoid unnecessarily passing pointers to EFI_HANDLEsMichael Brown2014-07-311-2/+2
| | | | | | | | | | | | efi_file_install() and efi_download_install() are both used to install onto existing handles. There is therefore no need to allow for each of their calls to InstallMultipleProtocolInterfaces() to create a new handle. By passing the handle directly (rather than a pointer to the handle), we avoid potential confusion (and erroneous debug message colours). Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Fill in loaded image's DeviceHandle if firmware fails to do soMichael Brown2014-07-301-0/+7
| | | | | | | | | | | | | | | | | | | Some EFI 1.10 implementations (observed with a mid-2011 iMac) seem to fail to fill in the DeviceHandle for our loaded images. It is plausible that these implementations fill in the DeviceHandle only if loading the image from a device path (rather than directly from a memory buffer). Work around this problem by filling in DeviceHandle if the firmware leaves it empty. We cannot sensibly fill in FilePath, because we have no way of knowing whether or not the firmware will treat this as a pointer to be freed when the image returns. Reported-by: Curtis Larsen <larsen@dixie.edu> Tested-by: Curtis Larsen <larsen@dixie.edu> Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Unload started images only on failureMichael Brown2014-07-301-9/+17
| | | | | | | | | | | | | | | | | If the StartImage() call returns with no error, then the image must have been started and returned successfully. It either unloaded itself, or it intended to remain loaded (e.g. it was a driver). We therefore do not unload successful images. If there was an error, we attempt to unload the image. This may not work. In particular, there is no way to tell whether an error returned from StartImage() was due to being unable to start the image (in which case we probably should call UnloadImage()), or due to the image itself returning an error (in which case we probably should not call UnloadImage()). We therefore ignore any failures from the UnloadImage() call itself. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Allow for interception of boot services calls by loaded imageMichael Brown2014-07-161-0/+4
| | | | | | | When building with DEBUG=efi_wrap, print details of calls made by the loaded image to selected boot services functions. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Disable SNP devices when running iPXE as the applicationMichael Brown2014-03-141-0/+4
| | | | | | | | | | | | | Some UEFI builds will set up a timer to continuously poll any SNP devices. This can drain packets from the network device's receive queue before iPXE gets a chance to process them. Use netdev_rx_[un]freeze() to explicitly indicate when we expect our network devices to be driven via the external SNP API (as we do with the UNDI API on the standard BIOS build), and disable the SNP API except when receive queue processing is frozen. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [png] Add support for PNG imagesMichael Brown2014-01-121-0/+1007
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [pnm] Add support for PNM imagesMichael Brown2013-11-271-0/+415
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [cmdline] Generate command option help text automaticallyMichael Brown2013-11-071-1/+1
| | | | | | | Generate the command option help text automatically from the list of defined options. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [parseopt] Add parse_timeout()Michael Brown2013-11-011-2/+2
| | | | | | | | Parsing a timeout value (specified in milliseconds) into an internal timeout value measured in timer ticks is a common operation. Provide a parse_timeout() value to carry out this conversion automatically. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [script] Allow commands following a script labelMichael Brown2013-07-251-43/+53
| | | | | | | | | | | | | | | | Allow commands to be placed on the same line as a label. This allows for improved legibility of loop constructions by incorporating the loop check condition into the same line as the loop label. For example, to iterate over network devices using the forthcoming "inc" command: set idx:int16 0 :loop isset ${net${idx}/mac} || goto loop_done echo net${idx} is a ${net${idx}/chip} with MAC ${net${idx}/mac} inc idx && goto loop :loop_done Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [script] Allow initial whitespace on lines containing labelsMichael Brown2013-07-251-4/+29
| | | | | | | | | Initial whitespace is already accepted on lines containing commands, since it gets ignored by the system() call. Minimise surprise and allow for neater indentation of scripts by also allowing whitespace on lines containing labels. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [script] Avoid trying to read final character of a zero-length stringMichael Brown2013-07-151-2/+2
| | | | | | Detected using Valgrind. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [script] Allow for backslash continuation of script linesMichael Brown2013-07-151-13/+41
| | | | | | | | | | | Allow long script lines to be broken up using backslash continuation. For example: choose --default linux --timeout 3000 os \ && goto boot_${os} || goto cancelled Requested-by: Robin Smidsrød <robin@smidsrod.no> Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Add sample platform-generated error disambiguationsMichael Brown2013-04-191-3/+19
| | | | | | | | Add disambiguated errors for LoadImage() and StartImage(), primarily to demonstrate how to use __einfo_uniqify() and __einfo_platformify() in the context of EFI platform errors. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Perform meaningful error code conversionsMichael Brown2013-04-191-8/+11
| | | | | | | | Exploit the redefinition of iPXE error codes to include a "platform error code" to allow for meaningful conversion of EFI_STATUS values to iPXE errors and vice versa. Signed-off-by: Michael Brown <mcb30@ipxe.org>
* [efi] Fix minor typos in efi_image.cMichael Brown2013-03-191-3/+3
| | | | Signed-off-by: Michael Brown <mcb30@ipxe.org>