Some older operating systems (e.g. RHEL6) use a non-default filename
on the root disk and rely on setting an EFI variable to point to the
bootloader. This does not work when performing a SAN boot on a
machine where the EFI variable is not present.
Fix by allowing a non-default filename to be specified via the
"sanboot --filename" option or the "san-filename" setting. For
example:
sanboot --filename \efi\redhat\grub.efi \
iscsi:192.168.0.1::::iqn.2010-04.org.ipxe.demo:rhel6
or
option ipxe.san-filename code 188 = string;
option ipxe.san-filename "\\efi\\redhat\\grub.efi";
option root-path "iscsi:192.168.0.1::::iqn.2010-04.org.ipxe.demo:rhel6";
Originally-implemented-by: Vishvananda Ishaya Abrams <vish.ishaya@oracle.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Describe all SAN devices via ACPI tables such as the iBFT. For tables
that can describe only a single device (i.e. the aBFT and sBFT), one
table is installed per device. For multi-device tables (i.e. the
iBFT), all devices are described in a single table.
An underlying SAN device connection may be closed at the time that we
need to construct an ACPI table. We therefore introduce the concept
of an "ACPI descriptor" which enables the SAN boot code to maintain an
opaque pointer to the underlying object, and an "ACPI model" which can
build tables from a list of such descriptors. This separates the
lifecycles of ACPI descriptions from the lifecycles of the block
device interfaces, and allows for construction of the ACPI tables even
if the block device interface has been closed.
For a multipath SAN device, iPXE will wait until sufficient
information is available to describe all devices but will not wait for
all paths to connect successfully. For example: with a multipath
iSCSI boot iPXE will wait until at least one path has become available
and name resolution has completed on all other paths. We do this
since the iBFT has to include IP addresses rather than DNS names. We
will commence booting without waiting for the inactive paths to either
become available or close; this avoids unnecessary boot delays.
Note that the Linux kernel will refuse to accept an iBFT with more
than two NIC or target structures. We therefore describe only the
NICs that are actually required in order to reach the described
targets. Any iBFT with at most two targets is therefore guaranteed to
describe at most two NICs.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
The INT13 console type (CONSOLE_INT13) autodetects at initialisation
time a magic partition to be used for logging iPXE console output. If
the INT13 drive number mapping is subsequently changed (e.g. because
iPXE was used to perform a SAN boot), then the console logging output
will be written to the incorrect disk.
Fix by recording the INT13 vector at initialisation time, and using
this original vector to emulate INT13 calls for all subsequent
accesses. This should be robust against drive remapping performed
either by ourselves or by another bootloader (e.g. a chainloaded
undionly.kpxe which then performs a SAN boot).
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Some partition tables have partitions that are not aligned to a
cylinder boundary, which confuses the current geometry guessing logic.
Enhance the existing logic to ensure that we never reduce our guesses
for the number of heads or sectors per track, and add extra logic to
calculate the exact number of sectors per track if we find a partition
that starts within cylinder zero.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Add basic support for multipath block devices. The "sanboot" and
"sanhook" commands now accept a list of SAN URIs. We open all URIs
concurrently. The first connection to become available for issuing
block device commands is marked as the active path and used for all
subsequent commands; all other connections are then closed. Whenever
the active path fails, we reopen all URIs and repeat the process.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
As of commit 10d19bd ("[pxe] Always retrieve cached DHCPACK and apply
to relevant network device"), the UNDI driver has been the only user
of pxeparent_call(). Remove the unnecessary layer of abstraction by
refactoring this code back into undinet.c, and fix the ability of
undiisr.S to fall back to chaining to the original handler if we were
unable to unhook our own ISR.
This effectively reverts commit 337e1ed ("[pxe] Separate parent PXE
API caller from UNDINET driver").
Signed-off-by: Michael Brown <mcb30@ipxe.org>
The concept of the SAN drive number is meaningful only in a BIOS
environment, where it represents the INT13 drive number (0x80 for the
first hard disk). We retain this concept in a UEFI environment to
allow for a simple way for iPXE commands to refer to SAN drives.
Centralise the concept of the default drive number, since it is shared
between all supported environments.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
INT 13 calls return a status value via %ah, with CF set if %ah is
non-zero (indicating an error). Our wrappers zero the whole of %ax if
CF is clear, to allow C code (which has no easy access to CF) to
simply test for a non-zero status to detect an error.
The current code assigns the returned status to a uint8_t, effectively
testing %al rather than %ah. Fix by treating the returned status as a
uint16_t instead.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Avoid using a zero sector count to guess the disk geometry, since that
would result in a division by zero when calculating the number of
cylinders.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
When running on AMD platforms, the legacy hardware emulation is
extremely unreliable. In particular, the IRQ0 timer interrupt is
likely to simply stop working, resulting in a total failure of any
code that relies on timers (such as DHCP retransmission attempts).
Work around this by using the 10MHz time counter provided by Hyper-V
via an MSR. (This timer can be tested in KVM via the command-line
option "-cpu host,hv_time".)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Allow the active timer (providing udelay() and currticks()) to be
selected at runtime based on probing during the INIT_EARLY stage of
initialisation.
TICKS_PER_SEC is now a fixed compile-time constant for all builds, and
is independent of the underlying clock tick rate. We choose the value
1024 to allow multiplications and divisions on seconds to be converted
to bit shifts.
TICKS_PER_MS is defined as 1, allowing multiplications and divisions
on milliseconds to be omitted entirely. The 2% inaccuracy in this
definition is negligible when using the standard BIOS timer (running
at around 18.2Hz).
TIMER_RDTSC now checks for a constant TSC before claiming to be a
usable timer. (This timer can be tested in KVM via the command-line
option "-cpu host,+invtsc".)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
This code largely inspired by tap.c. Allows for testing iPXE on real
NICs from within Linux. For example:
make bin-x86_64-linux/af_packet.linux
valgrind ./bin-x86_64-linux/af_packet.linux --net af_packet,if=eth3
Tested as x86_64 and i386 binary.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
When searching for an UNDI ROM to match against a PCI device, search
in order of increasing ROM address (within the 128kB BIOS option ROM
area). This is likely (though not guaranteed) to match the order of
the original enumeration performed by the BIOS, which is in turn
likely to match the order of enumeration on the PCI bus.
Since we load at most one UNDI ROM, the net result is that we increase
our chances of loading the ROM corresponding to the selected PCI
device (rather than loading a ROM corresponding to a higher-numbered
PCI device with the same vendor and device IDs.)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
The "progress" macro can be used only from within the .prefix section.
At the point of calling relocate(), we are running in .text16 and so
the near call to print_message() will end up calling a random function
somewhere in .text16.
Interestingly, this problem has remained unnoticed for some time. It
is rare to build with DEBUG=libprefix. In the few cases that it has
been used during development, the randomly selected function in
.text16 seems to have been a harmless no-op with no visible
side-effects (beyond the unnoticed failure to print the "relocate"
progress message).
Fix by removing the futile attempt to print a progress message before
calling relocate().
Reported-by: Raed Salem <raeds@mellanox.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Fix the <NULL> driver name reported by "ifstat" when using the undipci
driver (due to the unnecessary extra device node inserted as a child
of the PCI device).
Remove the "UNDI-" prefix from device names since the driver name is
also now visible via "ifstat", and tidy up the device name to match
the format used by standard PCI devices.
The output from "ifstat" now resembles:
iPXE> ifstat
net0: 52:54:00:12:34:56 using undipci on 0000:00:03.0
iPXE> ifstat
net0: 52:54:00:12:34:56 using undionly on 0000:00:03.0
Signed-off-by: Michael Brown <mcb30@ipxe.org>
The UNDI loader entry point is very likely to be called after POST,
when there is a high chance that the PMM-allocated image source area
and decompression area have been reused by something else.
In particular, using an iPXE .iso to test a separate iPXE ROM's UNDI
loader entry point in a qemu VM is likely to crash. SeaBIOS allocates
PMM blocks from close to the top of memory and so these blocks have a
high chance of colliding with the runtime addresses subsequently
chosen by the non-ROM iPXE by scanning the INT 15,e820 memory map.
The standard romprefix.S has no choice about relying on the
PMM-allocated image source area, since it has no other way to retrieve
its compressed payload.
In mromprefix.S, the image source area functions only as an optional
buffer used to avoid repeated reads from the (potentially slow)
expansion ROM BAR by the decompression code. We can therefore always
set %esi=0 when calling install_prealloc from the UNDI loader entry
point, and simply fall back to reading directly from the expansion ROM
BAR.
We can always set %edi=0 when calling install_prealloc from the UNDI
loader entry point. This will behave as though the decompression area
PMM allocation failed, and will therefore use INT 15,88 to find a
temporary decompression area somewhere close to 64MB. This is by no
means guaranteed to be safe from collisions, but it's probably safer
on balance than the PMM-allocated address.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Allocate base memory (by decreasing the free base memory counter)
before calling the UNDI loader entry point, to minimise surprises for
the UNDI loader code.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Commit 71560d1 ("[librm] Preserve FPU, MMX and SSE state across calls
to virt_call()") added FXSAVE and FXRSTOR instructions to iPXE. In
KVM virtual machines, these instructions execute fine as long as the
host CPU supports the "unrestricted_guest" feature (that is, it can
virtualize big real mode natively). On older host CPUs however, KVM
has to emulate big real mode, and it currently doesn't implement
FXSAVE emulation.
Upstream QEMU rebuilt iPXE at commit 0418631 ("[thunderx] Fix
compilation with older versions of gcc") which is a descendant of
commit 71560d1 (see above).
This was done in QEMU commit ffdc5a2 ("ipxe: update submodule from
4e03af8ec to 041863191"). The resultant binaries were bundled with
the QEMU v2.7.0 release; see QEMU commit c52125a ("ipxe: update
prebuilt binaries").
This distributed the iPXE workaround for the Tivoli VMM bug to a
number of KVM users with old host CPUs, causing KVM emulation failures
(guest crashes) for them while netbooting.
Make the FXSAVE and FXRSTOR instructions conditional on a new feature
test macro called TIVOLI_VMM_WORKAROUND. Define the macro by default.
There is prior art for an assembly file including config/general.h:
see arch/x86/prefix/romprefix.S. Also, TIVOLI_VMM_WORKAROUND seems to
be a good fit for the "Obscure configuration options" section in
config/general.h.
Cc: Bandan Das <bsd@redhat.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Greg <rollenwiese@yahoo.com>
Cc: Michael Brown <mcb30@ipxe.org>
Cc: Michael Prokop <launchpad@michael-prokop.at>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Peter Pickford <arch@netremedies.ca>
Cc: Radim Krčmář <rkrcmar@redhat.com>
Ref: https://bugs.archlinux.org/task/50778
Ref: https://bugs.launchpad.net/qemu/+bug/1623276
Ref: https://bugzilla.proxmox.com/show_bug.cgi?id=1182
Ref: https://bugzilla.redhat.com/show_bug.cgi?id=1356762
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
The initrd_addr_max field represents the highest byte address that may
be used to hold initrd images, and is therefore almost certainly not
aligned to a page boundary: a typical value might be 0x7fffffff.
Fix the address calculations to ensure that the initrd images are
always aligned to a page boundary.
Reported-by: Sitsofe Wheeler <sitsofe@gmail.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
The ACPI power off sequence may not take effect immediately. Delay
for one second, to eliminate potentially confusing log messages such
as "Could not power off: Error 0x43902001 (http://ipx".
Reported-by: Leonid Vasetsky <leonidv@velostrata.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
On some platforms (observed in a small subset of Microsoft Azure
(Hyper-V) virtual machines), the RTC appears to be incapable of
generating an interrupt via the legacy PIC. The RTC status registers
show that a periodic interrupt has been asserted, but the PIC IRR
shows that IRQ8 remains inactive.
On such systems, iPXE will currently freeze during the "iPXE
initialising devices..." message.
Work around this problem by checking that RTC interrupts are being
raised before returning from rtc_entropy_enable(). If no interrupt is
seen within 100ms, then we assume that the RTC interrupt mechanism is
broken. In these circumstances, iPXE will continue to initialise but
any subsequent attempt to generate entropy will fail. In particular,
HTTPS connections will fail with an error indicating that no entropy
is available.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
The vendor class identifier strings in DHCP_ARCH_VENDOR_CLASS_ID are
out of sync with the (correct) client architecture values in
DHCP_ARCH_CLIENT_ARCHITECTURE.
Fix by removing all definitions of DHCP_ARCH_VENDOR_CLASS_ID, and
instead generating the vendor class identifier string automatically
based on DHCP_ARCH_CLIENT_ARCHITECTURE and DHCP_ARCH_CLIENT_NDI.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
DHCPv4 and DHCPv6 share some values in common for the architecture-
specific options (such as the client system architecture type), but
use different encapsulations: DHCPv4 has a single byte for the option
length while DHCPv6 has a 16-bit field for the option length.
Move the containing DHCP_OPTION() and related wrappers from the
individual dhcp_arch.h files to dhcp.c, thus allowing for the
architecture-specific values to be reused in dhcpv6.c.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Some BIOSes (observed with an HP Gen9) seem to spuriously enable
interrupts at the PIC. This causes problems with NBPs such as GRUB
which use the UNDI API (thereby enabling interrupts on the NIC)
without first hooking an interrupt service routine. In this
situation, the interrupt will end up being handled by the default BIOS
ISR, which will typically just send an EOI and return. Since nothing
in this handler causes the NIC to deassert the interrupt, this will
result in an interrupt storm.
Entertainingly, some BIOSes are immune to this problem because the
default ISR sends the EOI only to the slave PIC; this effectively
disables the interrupt.
Work around this problem by disabling the interrupt on the PIC before
invoking the PXE NBP. An NBP that expects to make use of interrupts
will need to be configuring the PIC anyway, so it is probably safe to
assume that it will explicitly reenable the interrupt.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
There seems to be no reason for the sti/cli pair used around each call
to INT 10. Remove these instructions, so that printing debug messages
from within an ISR does not temporarily reenable interrupts.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Extend the 16-bit PCI bus:dev.fn address to a 32-bit seg🚌dev.fn
address, assuming a segment value of zero in contexts where multiple
segments are unsupported by the underlying data structures (e.g. in
the iBFT or BOFM tables).
Signed-off-by: Michael Brown <mcb30@ipxe.org>
The raw cycle counter at PMCCNTR_EL0 works in qemu but seems to always
read as zero on physical hardware (tested on Juno r1 and Cavium
ThunderX), even after ensuring that PMCR_EL0.E and PMCNTENSET_EL0.C
are both enabled.
Use CNTVCT_EL0 instead; this seems to count at a lower resolution
(tens of CPU cycles), but is usable for profiling.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Require architecture-specific code to make a deliberate choice to use
the unoptimised generic_tcpip_continue_chksum() function, if there is
no optimised version available.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
The IBM Tivoli Provisioning Manager for OS Deployment (also known as
TPMfOSD, Rembo-ia32, or Rembo Auto-Deploy) has a serious bug in some
older versions (observed with v5.1.1.0, apparently fixed by v7.1.1.0)
which can lead to arbitrary data corruption.
As mentioned in commit 87723a0 ("[libflat] Test A20 gate without
switching to flat real mode"), Tivoli's NBP sets up a VMM and makes
calls to the PXE stack in VM86 mode. This appears to be some kind of
attempt to run PXE API calls inside a sandbox. The VMM is fairly
sophisticated: for example, it handles our attempts to switch into
protected mode and patches our GDT so that our protected-mode code
runs in ring 1 instead of ring 0. However, it neglects to apply any
memory protections. In particular, it does not enable paging and
leaves us with 4GB segment limits. We can therefore trivially break
out of the sandbox by simply overwriting the GDT (or by modifying any
of Tivoli's VMM code or data structures).
When we attempt to execute privileged instructions (such as "lidt"),
the CPU raises an exception and control is passed to the Tivoli VMM.
This may result in a call to Tivoli's memcpy() function.
Tivoli's memcpy() function includes optimisations which use the SSE
registers %xmm0-%xmm3 to speed up aligned memory copies.
Unfortunately, the Tivoli VMM's exception handler does not save or
restore %xmm0-%xmm3. The net effect of this bug in the Tivoli VMM is
that any privileged instruction (such as "lidt") issued by iPXE may
result in unexpected corruption of the %xmm0-%xmm3 registers.
Even more unfortunately, this problem affects the code path taken in
response to a hardware interrupt from the NIC, since that code path
will call PXENV_UNDI_ISR. The net effect therefore becomes that any
NIC hardware interrupt (e.g. due to a received packet) may result in
unexpected corruption of the %xmm0-%xmm3 registers.
If a packet arrives while Tivoli is in the middle of using its
memcpy() function, then the unexpected corruption of the %xmm0-%xmm3
registers will result in unexpected corruption in the destination
buffer. The net effect therefore becomes that any received packet may
result in a 16-byte block of corruption somewhere in any data that
Tivoli copied using its memcpy() function.
We can work around this bug in the Tivoli VMM by saving and restoring
the %xmm0-%xmm3 registers across calls to virt_call(). To work around
the problem, we need to save registers before attempting to execute
any privileged instructions, and ensure that we attempt no further
privileged instructions after restoring the registers.
This is less simple than it may sound. We can use the "movups"
instruction to save and restore individual registers, but this will
itself generate an undefined opcode exception if SSE is not currently
enabled according to the flags in %cr0 and %cr4. We can't access %cr0
or %cr4 before attempting the "movups" instruction, because access a
control register is itself a privileged instruction (which may
therefore trigger corruption of the registers that we're trying to
save).
The best solution seems to be to use the "fxsave" and "fxrstor"
instructions. If SSE is not enabled, then these instructions may fail
to save and restore the SSE register contents, but will not generate
an undefined opcode exception. (If SSE is not enabled, then we don't
really care about preserving the SSE register contents anyway.)
The use of "fxsave" and "fxrstor" introduces an implicit assumption
that the CPU supports SSE instructions (even though we make no
assumption about whether or not SSE is currently enabled). SSE was
introduced in 1999 with the Pentium III (and added by AMD in 2001),
and is an architectural requirement for x86_64. Experimentation with
current versions of gcc suggest that it may generate SSE instructions
even when using "-m32", unless an explicit "-march=i386" or "-mno-sse"
is used to inhibit this. It therefore seems reasonable to assume that
SSE will be supported on any hardware that might realistically be used
with new iPXE builds.
As a side benefit of this change, the MMX register %mm0 will now be
preserved across virt_call() even in an i386 build of iPXE using a
driver that requires readq()/writeq(), and the SSE registers
%xmm0-%xmm5 will now be preserved across virt_call() even in an x86_64
build of iPXE using the Hyper-V netvsc driver.
Experimentation suggests that this change adds around 10% to the
number of cycles required for a do-nothing virt_call(), most of which
are due to the extra bytes copied using "rep movsb". Since the number
of bytes copied is a compile-time constant local to librm.S, we could
potentially reduce this impact by ensuring that we always copy a whole
number of dwords and so can use "rep movsl" instead of "rep movsb".
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Some PXE NBPs are known to make PXE API calls with very little space
available on the real-mode stack. For example, the Rembo-ia32 NBP
from some versions of IBM's Tivoli Provisioning Manager for Operating
System Deployment (TPMfOSD) will issue calls with the real-mode stack
placed at 0000:03d2; this is at the end of the interrupt vector table
and leaves only 498 bytes of stack space available before overwriting
the hardware IRQ vectors. This limits the amount of state that we can
preserve before transitioning to protected mode.
Work around these challenging conditions by preserving everything
other than the initial register dump in a temporary static buffer
within our real-mode data segment, and copying the contents of this
buffer to the protected-mode stack.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Some end-user configurations have been observed in which the first NBP
(such as GRUB2) uses the UNDI API and then transfers control to a
second NBP (such as pxelinux) which uses the UDP API. The first NBP
closes the network device using PXENV_UNDI_CLOSE, which renders the
UDP API unable to transmit or receive packets.
The correct behaviour under these circumstances is (as often) simply
not documented by the PXE specification. Testing with the Intel PXE
stack suggests that PXENV_UDP_OPEN will implicitly reopen the network
device if necessary, so match this behaviour.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
The DHCP option 175.189 has been defined (by us) since 2006 as
containing the drive number to be used for a SAN boot, but has never
been automatically used as such by iPXE.
Use this option (if specified) to override the default SAN drive
number.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Interpret the maximum drive number (0xff for hard disks, 0x7f for
floppy disks) as meaning "use natural drive number".
Signed-off-by: Michael Brown <mcb30@ipxe.org>
The mbr.bin and usbdisk.bin standalone blobs are currently generated
using "objcopy -O binary", which does not process relocation records.
For the i386 build, this does not matter since the section start
address is zero and so the ".rel" relocation records are effectively
no-ops anyway.
For the x86_64 build, the ".rela" relocation records are not no-ops,
since the addend is included as part of the relocation record (rather
than inline). Using "objcopy -O binary" will silently discard the
relocation records, with the result that all symbols are effectively
given a value of zero.
Fix by using "ld --oformat binary" instead of "objcopy -O binary" to
generate mbr.bin and usbdisk.bin.
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>
Commit 196f0f2 ("[librm] Convert prot_call() to a real-mode near
call") introduced a regression in which any deliberate modification to
the low 16 bits of the CPU flags (in struct i386_all_regs) would be
overwritten with the original flags value at the time of entry to
prot_call().
The regression arose because the alignment requirements of the
protected-mode stack necessitated the insertion of two bytes of
padding immediately below the prot_call() return address. The
solution chosen was to extend the existing "pushfl / popfl" pair to
"pushfw;pushfl / popfl;popfw". The extra "pushfw / popfw" appears at
first glance to be a no-op, but fails to take into account the fact
that the flags restored by popfl may have been deliberately modified
by the protected-mode function.
Fix by replacing "pushfw / popfw" with "pushw %ss / popw %ss". While
%ss does appear within struct i386_all_regs, any modification to the
stored value has always been ignored by prot_call() anyway.
The most visible symptom of this regression was that SAN booting would
fail since every INT 13 call would be chained to the original INT 13
vector.
Reported-by: Vishvananda Ishaya <vishvananda@gmail.com>
Reported-by: Jamie Thompson <forum.ipxe@jamie-thompson.co.uk>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
When running the 64-bit BIOS version of iPXE, restrict external memory
allocations to the low 4GB to ensure that allocations (such as for
initrds) fall within our identity-mapped memory region, and will be
accessible to the potentially 32-bit operating system.
Move largest_memblock() back to memtop_umalloc.c, since this change
imposes a restriction that applies only to BIOS builds.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Add support for running the BIOS version of iPXE in 64-bit long mode.
A 64-bit BIOS version of iPXE can be built using e.g.
make bin-x86_64-pcbios/ipxe.usb
make bin-x86_64-pcbios/8086100e.mrom
The 64-bit BIOS version should appear to function identically to the
normal 32-bit BIOS version. The physical memory layout is unaltered:
iPXE is still relocated to the top of the available 32-bit address
space. The code is linked to a virtual address of 0xffffffffeb000000
(in the negative 2GB as required by -mcmodel=kernel), with 4kB pages
created to cover the whole of .textdata. 2MB pages are created to
cover the whole of the 32-bit address space.
The 32-bit portions of the code run with VIRTUAL_CS and VIRTUAL_DS
configured such that truncating a 64-bit virtual address gives a
32-bit virtual address pointing to the same physical location.
The stack pointer remains as a physical address when running in long
mode (although the .stack section is accessible via the negative 2GB
virtual address); this is done in order to simplify the handling of
interrupts occurring while executing a portion of 32-bit code with
flat physical addressing via PHYS_CODE().
Interrupts may be enabled in either 64-bit long mode, 32-bit protected
mode with virtual addresses, 32-bit protected mode with physical
addresses, or 16-bit real mode. Interrupts occurring in any mode
other than real mode will be reflected down to real mode and handled
by whichever ISR is hooked into the BIOS interrupt vector table.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
In a 64-bit build, the entirety of the 32-bit address space is
identity-mapped and so any valid physical address may immediately be
used as a virtual address. Conversely, a virtual address that is
already within the 32-bit address space may immediately be used as a
physical address.
A valid virtual address that lies outside the 32-bit address space
must be an address within .textdata, and so can be converted to a
physical address by adding virt_offset.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
The physical locations of .textdata, .text16 and .data16 are constant
from the point of view of C code. Mark the relevant variables as
constant to allow gcc to optimise out redundant reads.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
No callers of prot_to_phys, phys_to_prot, or intr_to_prot require the
flags to be preserved. Remove the unnecessary pushfl/popfl pairs.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Add a phys_call() wrapper function (analogous to the existing
real_call() wrapper function) for calling code with flat physical
addressing, and use this wrapper within the PHYS_CODE() macro.
Move the relevant functionality inside librm.S, where it more
naturally belongs.
The COMBOOT code currently uses explicit calls to _virt_to_phys and
_phys_to_virt. These will need to be rewritten if our COMBOOT support
is ever generalised to be able to run in a 64-bit build.
Specifically:
- com32_exec_loop() should be restructured to use PHYS_CODE()
- com32_wrapper.S should be restructured to use an equivalent of
prot_call(), passing parameters via a struct i386_all_regs
- there appears to be no need for com32_wrapper.S to switch between
external and internal stacks; this could be omitted to simplify
the design.
For now, librm.S continues to expose _virt_to_phys and _phys_to_virt
for use by com32.c and com32_wrapper.S. Similarly, librm.S continues
to expose _intr_to_virt for use by gdbidt.S.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Some older versions of binutils have issues with both the use of
PROVIDE() and the interpretation of numeric literals within a section
description.
Work around these older versions by defining the required numeric
literals outside of any section description, and by automatically
determining whether or not to generate extra space for page tables
rather than relying on LDFLAGS.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
The bulk of the iPXE binary (the .textdata section) is physically
relocated at runtime to the top of the 32-bit address space in order
to allow space for an OS to be loaded. The relocation is achieved
with the assistance of segmentation: we adjust the code and data
segment bases so that the link-time addresses remain valid.
Segmentation is not available (for normal code and data segments) in
long mode. We choose to compile the C code with -mcmodel=kernel and
use a link-time address of 0xffffffffeb000000. This choice allows us
to identity-map the entirety of the 32-bit address space, and to alias
our chosen link-time address to the physical location of our .textdata
section. (This requires the .textdata section to always be aligned to
a page boundary.)
We simultaneously choose to set the 32-bit virtual address segment
bases such that the link-time addresses may simply be truncated to 32
bits in order to generate a valid 32-bit virtual address. This allows
symbols in .textdata to be trivially accessed by both 32-bit and
64-bit code.
There is no (sensible) way in 32-bit assembly code to generate the
required R_X86_64_32S relocation records for these truncated symbols.
However, subtracting the fixed constant 0xffffffff00000000 has the
same effect as truncation, and can be represented in a standard
R_X86_64_32 relocation record. We define the VIRTUAL() macro to
abstract away this truncation operation, and apply it to all
references by 32-bit (or 16-bit) assembly code to any symbols within
the .textdata section.
We define "virt_offset" for a 64-bit build as "the value to be added
to an address within .textdata in order to obtain its physical
address". With this definition, the low 32 bits of "virt_offset" can
be treated by 32-bit code as functionally equivalent to "virt_offset"
in a 32-bit build.
We define "text16" and "data16" for a 64-bit build as the physical
addresses of the .text16 and .data16 sections. Since a physical
address within the 32-bit address space may be used directly as a
64-bit virtual address (thanks to the identity map), this definition
provides the most natural access to variables in .text16 and .data16.
Note that this requires a minor adjustment in prot_to_real(), which
accesses .text16 using 32-bit virtual addresses.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Long-mode operation will require page tables, which are too large to
sensibly fit in our .data16 segment in base memory.
Add a portion of init_librm() running in 32-bit protected mode to
provide access to high memory. Use this portion of init_librm() to
initialise the .textdata variables "virt_offset", "text16", and
"data16", eliminating the redundant (re)initialisation currently
performed on every mode transition as part of real_to_prot().
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Use the standard "pushl $function ; pushw %cs ; call prot_call"
sequence everywhere that prot_call() is used.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
On a 64-bit CPU, any modification of a register by 32-bit or 16-bit
code will destroy the invisible upper 32 bits of the corresponding
64-bit register. For example: a 32-bit "pushl %eax" followed by a
"popl %eax" will zero the upper half of %rax. This differs from the
treatment of upper halves of 32-bit registers by 16-bit code: a
"pushw %ax" followed by a "popw %ax" will leave the upper 16 bits of
%eax unmodified.
Inline assembly generated using REAL_CODE() or PHYS_CODE() will
therefore have to preserve the upper halves of all registers, to avoid
clobbering registers that gcc expects to be preserved.
Output operands from REAL_CODE() and PHYS_CODE() assembly may
therefore contain undefined values in the upper 32 bits.
Fix by using explicit variable widths (e.g. uint32_t) for
non-discarded output operands, to ensure that undefined values in the
upper 32 bits of 64-bit registers are ignored.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Move most arch/i386 files to arch/x86, and adjust the contents of the
Makefiles and the include/bits/*.h headers to reflect the new
locations.
This patch makes no substantive code changes, as can be seen using a
rename-aware diff (e.g. "git show -M5").
This patch does not make the pcbios platform functional for x86_64; it
merely allows it to compile without errors.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Commit c64747d ("[librm] Speed up real-to-protected mode transition
under KVM") rounded down the .text16 segment address calculated in
alloc_basemem() to a multiple of 64 bytes in order to speed up mode
transitions under KVM.
This creates a potential discrepancy between alloc_basemem() and
free_basemem(), meaning that free_basemem() may free less memory than
was allocated by alloc_basemem().
Fix by padding the calculated sizes of both .text16 and .data16 to a
multiple of 64 bytes at build time.
Debugged-by: Yossef Efraim <yossefe@mellanox.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Provide a debug function check_bios_interrupts() to look for changes
to the interrupt vector table. This can be useful when investigating
the behaviour (including crashes) of external PXE NBPs.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Commit 5de45cd ("[romprefix] Report a pessimistic runtime size
estimate") set the PCI3.0 "runtime size" field equal to the worst-case
runtime size, on the basis that there is no guarantee that PMM
allocation will succeed and hence no guarantee that we will be able to
shrink the ROM image.
On a PCI3.0 system where PMM allocation would succeed, this can cause
the BIOS to unnecessarily refuse to initialise the iPXE ROM due to a
perceived shortage of option ROM space.
Fix by reporting the best-case runtime size via the PCI header, and
checking that we have sufficient runtime space (if applicable). This
allows iPXE ROMs to initialise on PCI3.0 systems that might otherwise
fail due to a shortage of option ROM space.
This may cause iPXE ROMs to fail to initialise on PCI3.0 systems where
PMM is broken. (Pre-PCI3.0 systems are unaffected since there must
already have been sufficient option ROM space available for the
initialisation entry point to be called.)
On balance, it seems preferable to avoid breaking "good" systems
(PCI3.0 with working PMM) at the cost of potentially breaking "bad"
systems (PCI3.0 with broken PMM).
Signed-off-by: Michael Brown <mcb30@ipxe.org>
The GuestRPC mechanism (used for VMWARE_SETTINGS and CONSOLE_VMWARE)
does not use any real-mode code and so can be exposed in both 64-bit
and 32-bit builds.
Reported-by: Matthew Helton <mwhelton@gmail.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
When USB network card drivers are used, the BIOS' legacy USB
capability is necessarily disabled since there is no way to share the
host controller between the BIOS and iPXE.
Commit 3726722 ("[usb] Add basic support for USB keyboards") added
support allowing a USB keyboard to be used within iPXE. However,
external code such as a PXE NBP has no way to utilise this support,
and so a USB keyboard cannot be used to control a PXE NBP loaded from
a USB network card.
Add support for injecting keypresses from any iPXE console into the
BIOS keyboard buffer. This allows external code such as a PXE NBP to
function with a USB keyboard even after the BIOS' legacy USB
capability has been disabled.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
iPXE does not call shutdown() before invoking a COMBOOT executable,
since the executable is allowed to make API calls back into iPXE. If
a background picture is used, then the console will not be restored to
text mode before invoking the COMBOOT executable. This can cause
undefined behaviour.
Fix by adding an explicit call to console_reset() immediately before
invoking a COMBOOT or COM32 executable, analogous to the call made to
console_reset() immediately before invokving a PXE NBP.
Debugged-by: Andrew Widdersheim <awiddersheim@inetu.net>
Tested-by: Andrew Widdersheim <awiddersheim@inetu.net>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
The name "vesafb" is intrinsically specific to a BIOS environment.
Generalise the build configuration option CONSOLE_VESAFB to
CONSOLE_FRAMEBUFFER, in preparation for adding EFI framebuffer
support.
Existing configurations using CONSOLE_VESAFB will continue to work.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Use INT 1a,564e to notify the BIOS of each network device that we
detect. This provides an opportunity for the BIOS to implement
platform policy such as changing the MAC address by issuing a call to
PXENV_UNDI_SET_STATION_ADDRESS.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Invoke INT 1a,564e whenever a PXE stack is activated, passing the
address of the PXENV+ structure in %es:%bx. This is designed to allow
a BIOS to be notified when a PXE stack has been installed, providing
an opportunity for start-of-day commands such as setting the MAC
address according to a policy chosen by the BIOS.
PXE defines INT 1a,5650 as a means of locating the PXENV+ structure:
this call returns %ax=0x564e and the address of the PXENV+ structure
in %es:%bx. We choose INT 1a,564e as a fairly natural notification
call, using the parameters as would be returned by INT 1a,5650.
The full calling convention (documented as per section 3.1 of the PXE
specification) is:
INT 1a,564e - PXE installation notification
Enter:
%ax = 0x564e
%es = 16-bit segment address of the PXENV+ structure
%bx = 16-bit offset of the PXENV+ structure
Exit:
%edx may be trashed (as is the case for INT 1a,5650)
All other register contents must be preserved
CF is cleared
IF is preserved
All other flags are undefined
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Merge the functionality of parse_next_server_and_filename() and
tftp_uri() into a single pxe_uri(), which takes a server address
(IPv4/IPv6/none) and a filename, and produces a URI using the rule:
- if the filename is a hierarchical absolute URI (i.e. includes a
scheme such as "http://" or "tftp://") then use that URI and ignore
the server address,
- otherwise, if the server address is recognised (according to
sa_family) then construct a TFTP URI based on the server address,
port, and filename
- otherwise fail.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Some distributions (observed with Ubuntu 15.04) place ldlinux.c32 in a
separate directory from isolinux.bin. Search for these files
separately, and allow an alternative location of ldlinux.c32 to be
provided via LDLINUX_C32=... on the make command line.
Reported-by: Adrian Koshka <adriankoshcha@teknik.io>
Tested-by: Adrian Koshka <adriankoshcha@teknik.io>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Commit edf74df ("[pxe] Always reconstruct packet for
PXENV_GET_CACHED_INFO") fixed the problems caused by returning stale
DHCP packets (e.g. from an earlier boot attempt using a different
network device), but broke interoperability with NBPs such as WDS
which may overwrite our cached (fake) DHCP packets and expect the
modified packets to be returned by a subsequent call to
PXENV_GET_CACHED_INFO.
Fix by constructing the fake DHCP packets immediately before
transferring control to a PXE NBP. Calls to PXENV_GET_CACHED_INFO
will now never modify the cached packets.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
A relatively common user mistake is to attempt to boot an EFI
executable (such as grub.efi) using a BIOS version of iPXE.
Unfortunately there are no signature checks that we can use to
unambiguously identify a PXE NBP, since a PXE NBP is just raw machine
code. We therefore have to accept anything sufficiently small to fit
into base memory as a valid PXE NBP.
We can detect that a file might be an EFI executable by checking for
the initial "MZ" signature bytes. This does not necessarily preclude
the file from also being a PXE NBP (since it would be possible to
create a hybrid binary which acts as both an EFI executable and a PXE
NBP, similar to the way in which wimboot and the Linux kernel are
hybrid binaries which act as both an EFI executable and a bzImage).
If the initial "MZ" signature bytes are present, then attempt to warn
the user by setting the image type to "PXE-NBP (may be EFI?)". We
can't (sensibly) prevent the user from accidentally running an EFI
executable as a PXE NBP, but we can at least make it easier for the
user to identify their mistake.
Inspired-by: Robin Smidsrød <robin@smidsrod.no>
Inspired-by: Wissam Shoukair <wissams@mellanox.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
UEFI platforms may provide a watchdog timer, which will reboot the
machine if an operating system takes more than five minutes to load.
This can cause long-lived iPXE downloads (or interactive shell
sessions) to unexpectedly reboot.
Fix by resetting the watchdog timer every ten seconds while the iPXE
main processing loop continues to run.
Reported-by: Bradley B Williams <bradleybwilliams@swbell.net>
Reported-by: John Clark <john.r.clark.3@gmail.com>
Reported-by: wdriever@gmail.com
Reported-by: Charlie Beima <cbeima@indiana.edu>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Check for existence of the UART in uart_select(), not just in
uart_init(). This allows uart_select() to refuse to set a non-working
address in uart->base, which in turns means that the serial console
code will not attempt to use a non-existent UART.
Reported-by: Torgeir Wulfsberg <Torgeir.Wulfsberg@kongsberg.com>
Reported-by: Ján ONDREJ (SAL) <ondrejj@salstar.sk>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
When the ability for iPXE to handle multiple serial ports was added,
the choice was made that the singular serial port referred to by
COMBOOT calls should mean the port used for the serial console. This
unintentionally caused IMAGE_COMBOOT to also enable CONSOLE_SERIAL.
Fix by providing a weak-symbol version of the serial console which
will be used if serial console support was not explicitly enabled.
Reported-by: Torgeir Wulfsberg <Torgeir.Wulfsberg@kongsberg.com>
Reported-by: Ján ONDREJ (SAL) <ondrejj@salstar.sk>
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>
Expose the high bit of the VGA text attribute byte via the ANSI SGR
parameters 5 ("blink on") and 25 ("blink off").
Note that some video cards (and virtual machines) may display a high
intensity background colour instead of blinking text.
Signed-off-by: Christian Nilsson <nikize@gmail.com>
Modified-by: Michael Brown <mcb30@ipxe.org>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Older, out-of-tree Xen kernel modules (such as those provided with
SuSE Linux Enterprise Server 11) do not clear the leftover "event
pending" bit when opening an event channel. Consequently, no event is
ever delivered to indicate that there is information in the XenStore
ring buffer, and the system hangs shortly after loading the
xen-platform-pci kernel module.
Work around this problem by always waiting for the XenStore event
channel to be signalled, and clearing the event before processing the
received data.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Avoid accidentally returning stale packets (e.g. for a previously
attempted network device) by always constructing a fresh DHCP packet.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
The size of the .mrom payload (the second PCI ROM image) is defined in
its PCI header. The code type for the .mrom payload image is
deliberately set to an invalid value (0xff) to ensure that no BIOS
tries to parse anything in the image other than the PCI header.
Since the code type is not set to 0x00 ("Intel x86, PC-AT
compatible"), bytes 0x02-0x17 should not be interpreted by the BIOS as
being in the standard ISA expansion ROM format. In particular, the
byte at offset 0x02 does not represent the length of the ROM image (in
512-byte blocks).
However, some Dell BIOSes seem to erroneously use the byte at offset
0x02 to determine the length of the .mrom payload when walking the
list of PCI ROM images. Since this byte is currently set to zero,
this can lead to the BIOS getting stuck in an infinite loop during
POST. (This problem may not arise if the .mrom payload is the final
image in the ROM, since the BIOS will then have no reason to attempt
to locate the next image.)
One possible workaround would be to put the real payload size in this
byte, but doing so would constrain the .mrom payload size to 128kB
(see commit 8049a52 ("[mromprefix] Allow for .mrom images larger than
128kB") for more details).
Another possible workaround would be to put the real payload size as a
word in bytes 0x02-0x03 (as is done for EFI ROMs). This would not
constrain the .mrom payload size, but a payload size which happened to
be exactly 128kB would result in a zero value in the byte at offset
0x02 and so could still result in infinite loops on BIOSes with this
bug.
We choose to place a fixed value of 0x01 in the byte at offset 0x02.
This should at least prevent the BIOS from getting stuck in an
infinite loop. (The BIOS may walk into the middle of the .mrom
payload, where it will almost certainly not find a valid {0x55,0xaa}
signature or a valid PCIR header, and will therefore hopefully abort
processing.)
Reported-by: Wissam Shoukair <wissams@mellanox.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Some HP BIOSes (observed with an HP ProLiant m710p Server Cartridge)
have a bug in the implementation of INT 1a,b101: they blithely assume
that real-mode code is able to read from anywhere in the 32-bit memory
space.
This problem affects the call to INT 1a,b101 made from within
pcibios_num_bus() (which uses REAL_CODE() and hence executes in
genuine real mode) but does not affect the call made from within
romprefix.S (since with a PMM BIOS, that call executes in flat real
mode anyway).
Work around the problem by explicitly calling flatten_real_mode()
before invoking INT 1a,b101. This is a rarely-used code path, and so
the extra overhead of emulating instructions in some VM configurations
(see commit 6d4deee ("[librm] Use genuine real mode to accelerate
operation in virtual machines") for more details) is negligible.
Reported-by: Wissam Shoukair <wissams@mellanox.com>
Debugged-by: Wissam Shoukair <wissams@mellanox.com>
Debugged-by: Michael Brown <mcb30@ipxe.org>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Several popular public cloud providers do not provide any sensible
mechanism for obtaining debug output from an OS which is failing to
boot. For example, Amazon EC2 provides the "Get System Log" facility,
which occasionally deigns to report a random subset of the characters
emitted via the VM's serial port, but usually returns only a blank
screen. (Amazingly, this is still superior to the debugging
facilities provided by Azure.)
Work around these shortcomings by adding a console type which sends
output to a magically detected raw disk partition, and including such
a partition within any iPXE .usb-format image.
To use this facility:
- build an iPXE .usb image with CONSOLE_INT13 enabled
- boot the cloud VM from this image
- after the boot fails, attach the VM's boot disk to a second VM
- from this second VM, use "less -f -R /dev/sdb3" (or similar) to
view the iPXE output.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Rename PCI_CLASS() (which constructs a struct pci_class_id) to
PCI_CLASS_ID(), and provide PCI_CLASS() as a macro which constructs
the 24-bit scalar value of a PCI class code.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
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>
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>
The assembler on OpenBSD 5.7 seems not to correctly handle the
combinations of .struct and .previous used in unlzma.S, and ends up
complaining about an "attempt to allocate data in absolute section".
Work around this problem by explicitly resetting the section after the
data structure definitions.
Reported-by: Jiri B <jirib@devio.us>
Tested-by: Jiri B <jirib@devio.us>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
PCI v3.0 supports a "device list" which allows the ROM to claim
support for multiple PCI device IDs (but only a single vendor ID).
Add support for building such ROMs by scanning the build target
element list and incorporating any device IDs into the ROM's device
list header. For example:
make bin/8086153a--8086153b.mrom
would build a ROM claiming support for both 8086:153a and 8086:153b.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
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>
Our current behaviour when booting as a ROM is to autoboot only from
devices which are attached via the PCI bus:dev.fn address passed to
the ROM's initialisation vector.
Add a build configuration option AUTOBOOT_ROM_FILTER (enabled by
default) to control this behaviour. This allows for ROMs to be built
which will attempt to boot from any detected device, even if not
attached via the original PCI bus:dev.fn address. (This is
particularly useful when building combined EHCI/xHCI ROMs for USB
network boot, since the BIOS may request a boot via the EHCI
controller but the xHCI driver will reroute the root hub ports to the
xHCI controller.)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
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>
None of the x86_64 builds currently have any way of invoking these
functions. They are included only to avoid introducing unnecessary
architecture-specific dependencies into the self-test suite.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
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>
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>
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>
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>
Relicence files with kind permission from the following contributors:
Alex Williamson <alex.williamson@redhat.com>
Eduardo Habkost <ehabkost@redhat.com>
Greg Jednaszewski <jednaszewski@gmail.com>
H. Peter Anvin <hpa@zytor.com>
Marin Hannache <git@mareo.fr>
Robin Smidsrød <robin@smidsrod.no>
Shao Miller <sha0.miller@gmail.com>
Thomas Horsten <thomas@horsten.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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.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>
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>
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>
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>