Commit 8ab4b00 ("[libc] Rewrite setjmp() and longjmp()") introduced a
regression in which the saved values of %ebx, %esi, and %edi were all
accidentally restored into %esp. The result is that the second and
subsequent returns from setjmp() would effectively corrupt %ebx, %esi,
%edi, and the stack pointer %esp.
Use of setjmp() and longjmp() is generally discouraged: our only use
occurs as part of the implementation of PXENV_RESTART_TFTP, since the
PXE API effectively mandates its use here. The call to setjmp()
occurs at the start of pxe_start_nbp(), where there are almost
certainly no values held in %ebx, %esi, or %edi. The corruption of
these registers therefore had no visible effect on program execution.
The corruption of %esp would have been visible on return from
pxe_start_nbp(), but there are no known PXE NBPs which first call
PXENV_RESTART_TFTP and subsequently attempt to return to the PXE base
code. The effect on program execution was therefore similar to that
of moving the stack to a pseudo-random location in the 32-bit address
space; this will often allow execution to complete successfully since
there is a high chance that the pseudo-random location will be unused.
The regression therefore went undetected for around one month.
Fix by restoring the correct registers from the saved jmp_buf
structure.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[legal] Relicense files under GPL2_OR_LATER_OR_UBDL
Several of the assembly files in arch/i386/prefix were missed by the
automated relicensing tool due to missing licence declarations, code
dating back to the initial git revision, etc. Manual review shows
that these files may be relicensed.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[legal] Relicense files under GPL2_OR_LATER_OR_UBDL
Relicense files with kind permission from
Stefan Hajnoczi <stefanha@redhat.com>
alongside the contributors who have already granted such relicensing
permission.
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>
[zbin] Fix check for existence of most recent output byte
The code in lzma_literal() checks to see if we are at the start of the
compressed input data in order to determine whether or not a most
recent output byte exists. This check is incorrect, since
initialisation of the decompressor will always consume the first five
bytes of the compressed input data.
Fix by instead checking whether or not we are at the start of the
output data stream. This is, in any case, a more logical check.
This issue was masked during development and testing since virtual
machines tend to zero the initial contents of RAM; the spuriously-read
"most recent output byte" is therefore likely to already be a zero
when running in a virtual machine.
Reported-by: Robin Smidsrød <robin@smidsrod.no>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[zbin] Allow decompressor to generate debug output via BIOS console
The 0xe9 debug port exists only on virtual machines. Provide an
option to print debug output on the BIOS console, to allow for
debugging on real hardware.
Note that this option can be used only if the decompressor is called
in flat real mode; the easiest way to achieve this is to build with
DEBUG=libprefix.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[prefix] Call decompressor in flat real mode when DEBUG=libprefix is enabled
Allow the decompressor the option of generating debugging output via
the BIOS console by calling it in flat real mode (rather than 16-bit
protected mode) when libprefix.S is built with debugging enabled.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[zbin] Perform extra normalisation after completing decompression
LZMA performs an extra normalisation after decompression is complete,
which does not affect the output but may consume an extra byte from
the input (and so may affect which byte is identified as being the
start of the next block).
Reported-by: Robin Smidsrød <robin@smidsrod.no>
Tested-by: Robin Smidsrød <robin@smidsrod.no>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
LZMA provides significantly better compression (by ~15%) than the
current NRV2B algorithm.
We use a raw LZMA stream (aka LZMA1) to avoid the need for code to
parse the LZMA2 block headers. We use parameters {lc=2,lp=0,pb=0} to
reduce the stack space required by the decompressor to acceptable
levels (around 8kB). Using lc=3 or pb=2 would give marginally better
compression, but at the cost of substantially increasing the required
stack space.
The build process now requires the liblzma headers to be present on
the build system, since we do not include a copy of an LZMA compressor
within the iPXE source tree. The decompressor is written from scratch
(based on XZ Embedded) and is entirely self-contained within the
iPXE source.
The branch-call-jump (BCJ) filter used to improve the compressibility
is specific to iPXE. We choose not to use liblzma's built-in BCJ
filter since the algorithm is complex and undocumented. Our BCJ
filter achieves approximately the same results (on typical iPXE
binaries) with a substantially simpler algorithm.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[prefix] Use .bss16 as temporary stack space for calls to install_block
Some decompression algorithms (e.g. LZMA) require large amounts of
temporary stack space, which may not be made available by all
prefixes. Use .bss16 as a temporary stack for the duration of the
calls to install_block (switching back to the external stack before we
start making calls into code which might access variables in .bss16),
and allow the decompressor to define a global symbol to force a
minimum value on the size of .bss16.
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>
[build] Apply the "-fno-PIE -nopie" workaround only to i386 builds
Hardened versions of gcc default to building position-independent
code, which breaks our i386 build. Our build process therefore
detects such platforms and automatically adds "-fno-PIE -nopie" to the
gcc command line.
On x86_64, we choose to build position-independent code (in order to
reduce the final binary size and, in particular, the number of
relocations required for UEFI binaries). The workaround therefore
breaks the build process for x86_64 binaries on such platforms.
Fix by moving the workaround to the i386-specific portion of the
Makefile.
Reported-by: Jan Kundrát <jkt@kde.org>
Debugged-by: Jan Kundrát <jkt@kde.org>
Debugged-by: Marin Hannache <git@mareo.fr>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[build] Use PRODUCT_SHORT_NAME for end-user visible strings
Use PRODUCT_SHORT_NAME instead of a hardcoded "iPXE" for strings which
are typically shown in the user interface.
Note that this only allows for customisation of the user interface.
Where the "iPXE" string serves a technical purpose (such as in the
HTTP User-Agent), the string cannot be customised.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[pxe] Maintain a queue for received PXE UDP packets
Some devices return multiple packets in a single poll. Handle such
devices gracefully by enqueueing received PXE UDP packets (along with
a pseudo-header to hold the IPv4 addresses and port numbers) and
dequeueing them on subsequent calls to PXENV_UDP_READ.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[tftp] Explicitly abort connection whenever parent interface is closed
Fetching the TFTP file size is currently implemented via a custom
"tftpsize://" protocol hack. Generalise this approach to instead
close the TFTP connection whenever the parent data-transfer interface
is closed.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Allow drivers to specify a supported PCI class code. To save space in
the final binary, make this an attribute of the driver rather than an
attribute of a PCI device ID list entry.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[build] Use -malign-double to build 32-bit UEFI binaries
The EDK2 codebase uses -malign-double for 32-bit builds, which causes
64-bit integers to be naturally aligned. This affects the layout of
some structures (including EFI_BLOCK_IO_MEDIA).
This mirrors wimboot commit 7b8f39d ("[build] Fix building of 32-bit
UEFI version").
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[mromprefix] Allow for .mrom images larger than 128kB
The .mrom payload has a code type of 0xff and so the initialisation
length field (single byte at offset 0x02) does not need to be
present. Use only the PCI header's image length field, which allows
the .mrom payload to be up to 32MB in size.
Inspired-by: Swift Geek <swiftgeek@gmail.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[mromprefix] Use PCI length field to obtain length of individual images
mromprefix.S currently uses the initialisation length field (single
byte at offset 0x02) to determine the length of a ROM image within a
multi-image ROM BAR. For PCI ROM images with a code type other than
0, the initialisation length field may not be present.
Fix by using the PCI header's image length field instead.
Inspired-by: Swift Geek <swiftgeek@gmail.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
The build process has for a long time assumed that every ROM is a PCI
ROM, and will always include the PCI header and PCI-related
functionality (such as checking the PCI BIOS version, including the
PCI bus:dev.fn address within the ROM product name string, etc.).
While real ISA cards are no longer in use, some virtualisation
environments (notably VirtualBox) have support only for ISA ROMs.
This can cause problems: in particular, VirtualBox will call our
initialisation entry point with random garbage in %ax, which we then
treat as the PCI bus:dev.fn address of the autoboot device: this
generally prevents the default boot sequence from using any network
devices.
Create .isarom and .pcirom prefixes which can be used to explicitly
specify the type of ROM to be created. (Note that the .mrom prefix
always implies a PCI ROM, since the .mrom mechanism relies on
reconfiguring PCI BARs.)
Make .rom a magic prefix which will automatically select the
appropriate PCI or ISA ROM prefix for ROMs defined via a PCI_ROM() or
ISA_ROM() macro. To maintain backwards compatibility, we default to
building a PCI ROM for anything which is not directly derived from a
PCI_ROM() or ISA_ROM() macro (e.g. bin/intel.rom).
Add a selection of targets to "make everything" to ensure that the
(relatively obscure) ISA ROM build process is included within the
per-commit QA checks.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Since some PnP BIOSes fail to set %es:di to point to the PnP signature
on entry, we identify a PnP BIOS by scanning through the top 64kB of
base memory looking for the PnP structure. We therefore don't
actually use the values of %es:di provided to the initialisation entry
point, and so there is no need to preserve them.
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>