| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
|
|
|
| |
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>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
| |
Signed-off-by: Michael Brown <mcb30@ipxe.org>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
| |
Signed-off-by: Michael Brown <mcb30@ipxe.org>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
| |
Signed-off-by: Michael Brown <mcb30@ipxe.org>
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
| |
Signed-off-by: Michael Brown <mcb30@ipxe.org>
|
|
|
|
| |
Signed-off-by: Michael Brown <mcb30@ipxe.org>
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
| |
Signed-off-by: Michael Brown <mcb30@ipxe.org>
|
|
|
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
| |
Signed-off-by: Michael Brown <mcb30@ipxe.org>
|
|
|
|
| |
Signed-off-by: Michael Brown <mcb30@ipxe.org>
|
|
|
|
| |
Signed-off-by: Michael Brown <mcb30@ipxe.org>
|
|
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
| |
Signed-off-by: Michael Brown <mcb30@ipxe.org>
|
|
|
|
| |
Signed-off-by: Michael Brown <mcb30@ipxe.org>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
|
|
|
| |
Relicense files for which I am the sole author (as identified by
util/relicense.pl).
Signed-off-by: Michael Brown <mcb30@ipxe.org>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
| |
Signed-off-by: Michael Brown <mcb30@ipxe.org>
|
|
|
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
| |
Signed-off-by: Michael Brown <mcb30@ipxe.org>
|
|
|
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
|
|
|
| |
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>
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
| |
Signed-off-by: Michael Brown <mcb30@ipxe.org>
|
|
|
|
| |
Signed-off-by: Michael Brown <mcb30@ipxe.org>
|
|
|
|
|
|
|
| |
Generate the command option help text automatically from the list of
defined options.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
|
|
| |
Detected using Valgrind.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
|
|
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
| |
Signed-off-by: Michael Brown <mcb30@ipxe.org>
|