[vram] Add "vram" built-in setting to dump video RAM
The "vram" setting returns the (Base64-encoded) contents of video RAM,
and can be used to capture a screenshot. For example: after running
memtest.0 and encountering an error, the output can be captured and
sent to a remote server for later diagnosis:
#!ipxe
chain -a http://server/memtest.0 && goto ok || goto bad
:bad
params
param errno ${errno}
param vram ${vram}
chain -a http://server/report.php##params
:ok
Inspired-by: Christian Nilsson <nikize@gmail.com>
Originally-implemented-by: Christian Nilsson <nikize@gmail.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[build] Construct all-drivers list based on driver class
The USB bus drivers (ehci.c and xhci.c) have PCI device ID tables and
hence PCI_ROM() lines, but should probably not be included in the
all-drivers build on this basis, since they do nothing useful unless a
USB network driver is also present.
Fix by constructing the all-drivers list based on the driver class
(i.e. the portion of the source path immediately after "drivers/").
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[efi] Use the EFI_RNG_PROTOCOL as an entropy source if available
Entropy gathering via timer ticks is slow under UEFI (of the order of
20-30 seconds on some machines). Use the EFI_RNG_PROTOCOL if
available, to speed up the process of entropy gathering.
Note that some implementations (including EDK2) will fail if we
request fewer than 32 random bytes at a time, and that the RNG
protocol provides no guarantees about the amount of entropy provided
by a call to GetRNG(). We take the (hopefully pessimistic) view that
a 32-byte block returned by GetRNG() will contain at least the 1.3
bits of entropy claimed by min_entropy_per_sample().
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[efi] Ensure drivers are disconnected when ExitBootServices() is called
We hook the UEFI ExitBootServices() event and use it to trigger a call
to shutdown_boot(). This does not automatically cause drivers to be
disconnected from their devices, since device enumeration is now
handled by the UEFI core rather than by iPXE. (Under the old and
dubiously compatible device model, iPXE used to perform its own device
enumeration and so the call to shutdown_boot() would indeed have
caused drivers to be disconnected.)
Fix by replicating parts of the dummy "EFI root device" from
efiprefix.c to efidrvprefix.c, so that the call to shutdown_boot()
will call efi_driver_disconnect_all().
Originally-fixed-by: Laszlo Ersek <lersek@redhat.com>
Tested-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
At some point in the past few years, binutils became more aggressive
at removing unused symbols. To function as a symbol requirement, a
relocation record must now be in a section marked with @progbits and
must not be in a section which gets discarded during the link (either
via --gc-sections or via /DISCARD/).
Update REQUIRE_SYMBOL() to generate relocation records meeting these
criteria. To minimise the impact upon the final binary size, we use
existing symbols (specified via the REQUIRING_SYMBOL() macro) as the
relocation targets where possible. We use R_386_NONE or R_X86_64_NONE
relocation types to prevent any actual unwanted relocation taking
place. Where no suitable symbol exists for REQUIRING_SYMBOL() (such
as in config.c), the macro PROVIDE_REQUIRING_SYMBOL() can be used to
generate a one-byte-long symbol to act as the relocation target.
If there are versions of binutils for which this approach fails, then
the fallback will probably involve killing off REQUEST_SYMBOL(),
redefining REQUIRE_SYMBOL() to use the current definition of
REQUEST_SYMBOL(), and postprocessing the linked ELF file with
something along the lines of "nm -u | wc -l" to check that there are
no undefined symbols remaining.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
The valgrind headers are not x86-specific; they detect the CPU
architecture and contain inline assembly for multiple architectures.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[legal] Relicense files under GPL2_OR_LATER_OR_UBDL
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>
Other hypervisors (e.g. KVM) may provide an unusable subset of the
Hyper-V features, and our attempts to use these non-existent features
cause the guest to reboot.
Fix by explicitly checking for the Hyper-V features that we use.
Reported-by: Ján ONDREJ (SAL) <ondrejj@salstar.sk>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[timer] Rewrite the 8254 Programmable Interval Timer support
The 8254 timer code (used to implement udelay()) has an unknown
provenance. Rewrite this code to avoid potential licensing
uncertainty.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
As with memcpy(), we can reduce the code size (by an average of 0.2%)
by giving the compiler more visibility into what memset() is doing,
and by avoiding the "rep" prefix on short fixed-length sequences of
string operations.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Some of the C library string functions have an unknown provenance.
Reimplement all such functions to avoid potential licensing
uncertainty.
Remove the inline-assembler versions of strlen(), memswap(), and
strncmp(); these save a minimal amount of space (around 40 bytes in
total) and are not performance-critical.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Using version 1 grant tables limits guests to using 16TB of grantable
RAM, and prevents the use of subpage grants. Some versions of the Xen
hypervisor refuse to allow the grant table version to be set after the
first grant references have been created, so the loaded operating
system may be stuck with whatever choice we make here. We therefore
currently use version 2 grant tables, since they give the most
flexibility to the loaded OS.
Current versions (7.2.0) of the Windows PV drivers have no support for
version 2 grant tables, and will merrily create version 1 entries in
what the hypervisor believes to be a version 2 table. This causes
some confusion.
Avoid this problem by attempting to use version 1 tables, since
otherwise we may render Windows unable to boot.
Play nicely with other potential bootloaders by accepting either
version 1 or version 2 grant tables (if we are unable to set our
requested version).
Note that the use of version 1 tables on a 64-bit system introduces a
possible failure path in which a frame number cannot fit into the
32-bit field within the v1 structure. This in turn introduces
additional failure paths into netfront_transmit() and
netfront_refill_rx().
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[xen] Accept alternative Xen platform PCI device ID 5853:0002
At some point during XenServer development history, the Windows PV
drivers changed to using a PCI device ID of 5853:0002 rather than
5853:0001. Current (7.2.0) drivers will bind to either 5853:0001 or
5853:0002, and the general approach taken by the world at large
(including Amazon EC2) seems to be to use only 5853:0001.
However, the current version of XenServer (6.2.0) will create the
platform device as 5853:0002 (via the platform:device_id VM parameter)
for any VMs created using the built-in templates for Windows Vista or
later.
Accept either PCI ID, since the underlying device is identical.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[efi] Default to releasing network devices for use via SNP
We currently treat network devices as available for use via the SNP
API only if RX queue processing has been frozen. (This is similar in
spirit to the way that RX queue processing is frozen for the network
device currently exposed via the PXE API.)
The default state of a freshly created network device is for the RX
queue to not be frozen, and thus to be unavailable for use via SNP.
This causes problems when devices are added through code paths other
than _efidrv_start() (which explicitly releases devices for use via
SNP).
We don't actually need to freeze RX queue processing, since calls via
the SNP API will always use netdev_poll() rather than net_poll(), and
so will never trigger the RX queue processing code path anyway.
We can therefore simplify the code to use a single global flag to
indicate whether network devices are claimed for use by iPXE or
available for use via SNP. Using a global flag allows the default
state for dynamically created network devices to behave sensibly.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Add basic support for Xen PV-HVM domains (detected via the Xen
platform PCI device with IDs 5853:0001), including support for
accessing configuration via XenStore and enumerating devices via
XenBus.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[ioapi] Fail ioremap() when attempting to map a zero bus address
When a 32-bit iPXE binary is running on a system which allocates PCI
memory BARs above 4GB, our PCI subsystem will return the base address
for any such BARs as zero (with a warning message if DEBUG=pci is
enabled). Currently, ioremap() will happily map an address pointing
to the start of physical memory, providing no sensible indication of
failure.
Fix by always returning NULL if we are asked to ioremap() a zero bus
address.
With a totally flat memory model (e.g. under EFI), this provides an
accurate failure indication since no PCI peripheral will be mapped to
the zero bus address.
With the librm memory model, there is the possibility of a spurious
NULL return from ioremap() if the bus address happens to be equal to
virt_offset. Under the current virtual memory map, the NULL virtual
address will always be the start of .textdata, and so this problem
cannot occur; a NULL return from ioremap() will always be an accurate
failure indication.
Debugged-by: Anton D. Kachalov <mouse@yandex-team.ru>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Provide a single instance of EFI_DRIVER_BINDING_PROTOCOL (attached to
our image handle); this matches the expectations scattered throughout
the EFI specification.
Open the underlying hardware device using EFI_OPEN_PROTOCOL_BY_DRIVER
and EFI_OPEN_PROTOCOL_EXCLUSIVE, to prevent other drivers from
attaching to the same device.
Do not automatically connect to devices when being loaded as a driver;
leave this task to the platform firmware (or to the user, if loading
directly from the EFI shell).
When running as an application, forcibly disconnect any existing
drivers from devices that we want to control, and reconnect them on
exit.
Provide a meaningful driver version number (based on the build
timestamp), to allow platform firmware to automatically load newer
versions of iPXE drivers if multiple drivers are present.
Include device paths within debug messages where possible, to aid in
debugging.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[efi] Disable SNP devices when running iPXE as the application
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>
EFIRC() uses PLATFORM_TO_ERRNO(), which evaluates its argument twice
(and can't trivially use a braced-group expression or an inline
function to avoid this, since it gets used outside of function
context).
The expression "EFIRC(main())" will therefore end up calling main()
twice, which is not the intended behaviour. Every other instance of
EFIRC() is of the simple form "EFIRC(rc)", so fix by converting this
instance to match.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[settings] Explicitly separate the concept of a completed fetched setting
The fetch_setting() family of functions may currently modify the
definition of the specified setting (e.g. to add missing type
information). Clean up this interface by requiring callers to provide
an explicit buffer to contain the completed definition of the fetched
setting, if required.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
The VESA frame buffer console uses the VESA BIOS extensions (VBE) to
enumerate video modes, selects an appropriate mode, and then hands off
to the generic frame buffer code.
The font is extracted from the VGA BIOS, avoiding the need to provide
an external font file.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[settings] Expose CPUID instruction via settings mechanism
Allow CPUID values to be read using the syntax
${cpuid/<register>.<function>}
For example, ${cpuid/2.0x80000001} will give the value of %ecx after
calling CPUID with %eax=0x80000001. Values for <register> are encoded
as %eax=0, %ebx=1, %ecx=2, %edx=3.
The numeric encoding is more sophisticated than described above,
allowing for settings such as the CPU model (obtained by calling CPUID
with %eax=0x80000002-0x80000004 inclusive and concatenating the values
returned in %eax:%ebx:%ecx:%edx). See the source code for details.
The "cpuvendor" and "cpumodel" settings provide easy access to these
more complex CPUID settings.
This functionality is intended to complement the "cpuid" command,
which allows for testing individual CPUID feature bits.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Our use of --gc-sections causes the linker to discard the symbols
defined by FILE_LICENCE(), meaning that the resulting licence
determination is incomplete.
We must use the KEEP() directive in the linker script to force the
linker to not discard the licence symbols. Using KEEP(*(COMMON))
would be undesirable, since there are some symbols in COMMON which we
may wish to discard.
Fix by placing symbols defined by PROVIDE_SYMBOL() (which is used by
FILE_LICENCE()) into a special ".provided" section, which we then mark
with KEEP(). All such symbols are zero-length, so there is no cost in
terms of the final binary size.
Since the symbols are no longer in COMMON, the linker will reject
symbols with the same name coming from multiple objects. We therefore
append the object name to the licence symbol, to ensure that it is
unique.
Reported-by: Marin Hannache <git@mareo.fr>
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>
No code from the original source remains within this file; relicense
under GPL2+ with a new copyright notice.
Signed-off-by: Michael Brown <mcb30@ipxe.org>