[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>
[efi] Use EFI_CONSOLE_CONTROL_PROTOCOL to set text mode if available
On some older EFI 1.10 implementations (observed with an old iMac), we
must use the (now obsolete) EFI_CONSOLE_CONTROL_PROTOCOL to switch the
console into text mode.
Modified-by: Michael Brown <mcb30@ipxe.org>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
The EFI_CONSOLE_CONTROL_PROTOCOL does not exist in the current UEFI
specification, but is required to enable text output on some older EFI
1.10 implementations (observed on an old iMac).
The header is not present in any of the standard include directories,
but can still be found in the EDK2 codebase as part of
EdkCompatibilityPkg.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[efi] Allow for interception of boot services calls by loaded image
When building with DEBUG=efi_wrap, print details of calls made by the
loaded image to selected boot services functions.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[efi] Install our own disk I/O protocol and claim exclusive use of it
The EFI FAT filesystem driver has a bug: if a block device contains no
FAT filesystem but does have an EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
instance, the FAT driver will assume that it must have previously
installed the EFI_SIMPLE_FILE_SYSTEM_PROTOCOL. This causes the FAT
driver to claim control of our device, and to refuse to stop driving
it, which prevents us from later uninstalling correctly.
Work around this bug by opening the disk I/O protocol ourselves,
thereby preventing the FAT driver from opening it.
Note that the alternative approach of opening the block I/O protocol
(and thereby in theory preventing DiskIo from attaching to the block
I/O protocol) causes an endless loop of calls to our DRIVER_STOP
method when starting the EFI shell. I have no idea why this is.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[netdevice] Reset network device index when last device is unregistered
When functioning as an EFI driver, drivers can be disconnected and
reconnected multiple times (e.g. via the EFI shell "connect" command,
or by running an executable such as ipxe.efi which will temporarily
disconnect existing drivers).
Minimise surprise by resetting the network device index to zero
whenever the last device is unregistered. This is not foolproof, but
it does handle the common case of having all devices unregistered and
then reregistered in the original order.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Rewrite the SNP NIC driver to use non-blocking and deferrable
transmissions, to provide link status detection, to provide
information about the underlying (PCI) hardware device, and to avoid
unnecessary I/O buffer allocations during receive polling.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[build] Fix erroneous object name in version object
Commit 8290a95 ("[build] Expose build timestamp, build name, and
product names") introduced a regression in the build process which
resulted in broken final binaries which had names based on object
files (e.g. "undionly.kpxe" or "intel.rom") rather than on device IDs
(e.g. "8086100e.mrom").
The underlying problem is the -DOBJECT=<name> macro which is used to
generate the obj_<name> symbols used to select objects required for
the final binary. The macro definition is derived from the initial
portion (up to the first dot) of the object being built. In the case
of e.g. undionly.kpxe.version.o, this gives -DOBJECT=undionly. This
results in undionly.kpxe.version.o claiming to be the "undionly"
object; the real "undionly" object will therefore never get dragged in
to the build.
Fix by renaming $(BIN)/%.version.o to $(BIN)/version.%.o, so that the
object is always built with -DOBJECT=version (as might be expected,
since it is built from core/version.c).
Final binaries which have names based on device IDs (such as
"8086100e.mrom") are not affected by this problem, since the object
name "8086100e" will not conflict with that of the underlying "intel"
object.
This problem was not detected by the per-commit smoke testing
procedure, which happens to use the binary bin/8086100e.mrom.
Reported-by: Christian Hesse <list@eworm.de>
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>
[build] Expose build timestamp, build name, and product names
Expose the build timestamp (measured in seconds since the Epoch) and
the build name (e.g. "rtl8139.rom" or "ipxe.efi"), and provide the
product name and product short name in a single centralised location.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[debug] Allow debug message colours to be customised via DBGCOL=...
When multiple iPXE binaries are running concurrently (e.g. in the case
of undionly.kpxe using an underlying iPXE driver via the UNDI
interface) it would be helpful to be able to visually distinguish
debug messages from each binary.
Allow the range of debug colours used to be customised via the
DBGCOL=... build parameter. For example:
# Restrict to colours 31-33 (red, green, yellow)
make DBGCOL=31-33
# Restrict to colours 34-36 (blue, magenta, cyan)
make DBGCOL=34-36
Signed-off-by: Michael Brown <mcb30@ipxe.org>
If iPXE is used as a git submodule then the ../.git/index file will
not exist, and the build will fail. Fix by checking that the git
index file exists before adding it as a build dependency.
Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[smbios] Expose board serial number as ${board-serial}
With blade servers, the chassis serial number (exposed via ${serial})
may not be unique. Expose ${board-serial} as a named setting to
provide easy access to a more meaningful serial number.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
The VF might not have assigned a MAC address upon startup, and will
end up with a random MAC address during probe(). With this patch the
MAC address can be changed later on.
Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
If the VF doesn't have a MAC address assigned we should create a
random MAC address.
Signed-off-by: Hannes Reinecke <hare@suse.de>
Modified-by: Michael Brown <mcb30@ipxe.org>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
The iBFT includes an "origin" field to indicate the source of the IP
address. We use the heuristic of assuming that the source should be
"manual" if the IP address originates directly from the network device
settings block, and "DHCP" otherwise. This is an imperfect guess, but
is likely to be correct in most common situations.
Originally-implemented-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Parse the sense data to extract the reponse code, the sense key, the
additional sense code, and the additional sense code qualifier.
Originally-implemented-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[ifmgmt] Do not sleep CPU while configuring network devices
iPXE currently calls cpu_nap() while performing DHCP, in order to
reduce CPU utilisation on virtual machines. Under mild broadcast load
(~100 packets per second), this can cause received packets to be
dropped because the receive descriptor ring is overrun before the next
18Hz timer interrupt wakes up the CPU. The result is that DHCP is
likely to intermittently fail on networks with appreciable amounts of
broadcast (or multicast) traffic.
This behaviour was introduced in the series of commits which
generalised the "dhcp" command to the "ifconf" command. The earlier
code (which did not handle IPv6 configuration) had no call to
cpu_nap() and so did not suffer from this problem.
Fix by removing the call to cpu_nap() in ifpoller_progress(). This
has the undesirable side effect that CPU utilisation will remain at
100% while waiting for DHCP to complete (which can take several
seconds, if we have to wait around for potential ProxyDHCP offers to
arrive).
Reported-by: Alex Davies <adavies@jumptrading.com>
Reported-by: Christoffer Stokbæk <christoffers@easyspeedy.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[librm] Allow for the PIC interrupt vector offset to be changed
Some external code (observed with FreeBSD's bootloader) will continue
to make INT 13 calls after reconfiguring the 8259 PIC to change the
vector offsets for IRQs. If an IRQ (e.g. the timer IRQ) subsequently
occurs while iPXE is in protected mode, this will cause a general
protection fault since the corresponding IDT entry is empty.
A general protection fault is INT 0x0d, which happens to overlap with
the original IRQ5. We therefore do have an ISR set up to handle a
general protection fault, but this ISR simply reflects the interrupt
down to the real-mode INT 0x0d and then attempts to return. Since our
ISR is expecting a hardware interrupt rather than a general protection
fault, it doesn't remove the error code from the stack before issuing
the iret instruction; it therefore attempts to return to a garbage
address. Since the segment part of this address is likely to be
invalid, a second general protection fault occurs. This cycle
continues until we run out of stack space and triple fault.
Fix by reflecting all INTs down to real mode. This actually reduces
the code size by four bytes (but increases the bss size by almost
2kB).
Reported-by: Brian Rak <dn@devicenull.org>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[ipv6] Avoid potentially copying from a NULL pointer in ipv6_tx()
If ipv6_tx() is called with a non-NULL network device, a NULL or
unspecified source address, and a destination address which does not
match any routing table entry, then it will attempt to copy the source
address from a NULL pointer.
I don't think that there is currently any code path which could
trigger this behaviour, but we should probably ensure that it can
never happen.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[ipv6] Include network device when transcribing multicast addresses
Destination multicast addresses require a sin6_scope_id, which should
therefore be transcribed to a network device name by ipv6_sock_ntoa().
Signed-off-by: Michael Brown <mcb30@ipxe.org>
The transmitting network device is specified via the destination
address, not the source address. There is no reason to set
sin6_scope_id on the source address.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[dhcpv6] Do not set sin6_scope_id on the unspecified client socket address
Setting sin6_scope_id to a non-zero value will cause the check against
the "empty socket address" in udp_demux() to fail, and incoming DHCPv6
responses on interfaces other than net0 will be rejected with a
spurious "No UDP connection listening on port 546" error.
The transmitting network device is specified via the destination
address, not the source address. Fix by simply not setting
sin6_scope_id on the client socket address.
Reported-by: Anton D. Kachalov <mouse@yandex-team.ru>
Tested-by: Anton D. Kachalov <mouse@yandex-team.ru>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Fix an erroneous htonl() in the definition of IN6_IS_ADDR_LINKLOCAL(),
and add self-tests for the IN6_IS_ADDR_xxx() family of macros.
Reported-by: Marin Hannache <git@mareo.fr>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[efi] Do not try to fetch loaded image device path protocol
Some UEFI systems (observed with a Mac Pro) do not provide a loaded
image device path protocol. We don't currently use the loaded image
device path protocol for anything beyond printing a debug message, so
simply remove the code which attempts to fetch it.
Reported-by: Matt Woodward <pxematt@woodwardcc.com>
Tested-by: Matt Woodward <pxematt@woodwardcc.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Some UEFI systems (observed with a Mac Pro) do not provide
EFI_HII_DATABASE_PROTOCOL. We can continue to function without
providing access to network device settings via HII, so make this
protocol optional and fall back to simply not providing any HII
protocols.
Reported-by: Matt Woodward <pxematt@woodwardcc.com>
Tested-by: Matt Woodward <pxematt@woodwardcc.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[efi] Make EFI_DEVICE_PATH_TO_TEXT_PROTOCOL optional
Some UEFI systems (observed with a Mac Pro) do not provide
EFI_DEVICE_PATH_TO_TEXT_PROTOCOL. Since we use this protocol only for
debug messages, make it optional and fall back to printing the raw
device path bytes.
Reported-by: Matt Woodward <pxematt@woodwardcc.com>
Tested-by: Matt Woodward <pxematt@woodwardcc.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Get the NFS URI manipulation code out of nfs_open.c. The resulting
code is now much more readable.
Signed-off-by: Marin Hannache <git@mareo.fr>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[libc] Prevent strndup() from reading beyond the end of the string
strndup() may be called on a string which is not NUL-terminated. Use
strnlen() instead of strlen() to ensure that we do not read beyond the
end of such a string.
Add self-tests for strndup(), including a test case with an
unterminated string.
Originally-fixed-by: Marin Hannache <git@mareo.fr>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Avoid generating syntactically invalid log messages by ensuring that
invalid characters are not present in the hostname. In particular,
ensure that any whitespace is stripped, since whitespace functions as
a field separator for syslog messages.
Reported-by: Alex Davies <adavies@jumptrading.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
As of commit d28bb51 ("[tcp] Defer sending ACKs until all received
packets have been processed"), increasing the RX ring size will
increase the number of received packets per transmitted ACK (since
each poll will process up to one complete receive ring). Under KVM,
this can make a substantial (up to ~200%) difference to the overall
download speed, since transmissions are very expensive.
Increase the ring fill level from four to eight packets: this
increases the download speed by around 50% at a cost of around 8kB of
heap space. Further speedups are possible by increasing the ring size
further, but it would be preferable to find alternative methods which
do not use noticeable amounts of heap space.
Tested-by: Robin Smidsrød <robin@smidsrod.no>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[nfs] Fix an invalid free() when loading a regular (non-symlink) file
An invalid free() was ironically introduced by fixing another invalid
free in commit 7aa69c4 ("[nfs] Fix an invalid free() when loading a
symlink").
Signed-off-by: Marin Hannache <git@mareo.fr>
Signed-off-by: Michael Brown <mcb30@ipxe.org>