On some models (notably ICH), the PHY reset mechanism appears to be
broken. In particular, the PHY_CTRL register will be correctly loaded
from NVM but the values will not be propagated to the "OEM bits" PHY
register. This typically has the effect of dropping the link speed to
10Mbps.
Since the original version of this driver in commit 945e428 ("[intel]
Replace driver for Intel Gigabit NICs"), we have always worked around
this problem by skipping the PHY reset if the link is already up.
Enhance this workaround by explicitly checking for known-broken PCI
IDs.
Reported-by: Robin Smidsrød <robin@smidsrod.no>
Tested-by: Robin Smidsrød <robin@smidsrod.no>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[comboot] Reset console before starting COMBOOT executable
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>
[dhcp] Limit maximum number of DHCP discovery deferrals
For switches which remain permanently in the non-forwarding state (or
which erroneously report a non-forwarding state), ensure that iPXE
will eventually give up waiting for the link to become unblocked.
Originally-fixed-by: Wissam Shoukair <wissams@mellanox.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
If we detect (via STP) that a switch port is in a non-forwarding
state, then the link is marked as being temporarily blocked and DHCP
discovery will be deferred until the link becomes unblocked.
The timer used to decide when to give up waiting for ProxyDHCPOFFERs
is currently based on the time that DHCP discovery was started, and
makes no allowances for any time spent waiting for the link to become
unblocked. Consequently, if STP is used then the timeout for
ProxyDHCPOFFERs becomes essentially zero.
Fix by resetting the recorded start time whenever DHCP discovery is
deferred due to a blocked link.
Debugged-by: Sebastian Roth <sebastian.roth@zoho.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[build] Generalise CONSOLE_VESAFB to CONSOLE_FRAMEBUFFER
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>
[peerdist] Avoid NULL pointer dereference for plaintext blocks
Avoid accidentally dereferencing a NULL cipher context pointer for
plaintext blocks (which are usually messages with a block length of
zero, indicating a missing block).
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[efi] Expose an UNDI interface alongside the existing SNP interface
UEFI UNDI is a hideously ugly lump of poorly specified garbage bolted
on as an appendix of the UEFI specification. My personal favourite
line from the UNDI 'specification' is section E.2.2, which states
"Basically, the rule is: Do it right, or don't do it at all". The
author appears to believe that such exhortations are a viable
substitute for documenting what it is that the wretched reader is
supposed to, in fact, do.
(Second favourite is the section listing the pros and cons of various
driver types. This fails to identify a single con for the mythical
"Hardware UNDI", a design so insanely intrinsically slow that it
appears to have been the inspiration for the EFI_USB_IO_PROTOCOL.)
UNDI is functionally isomorphic to the substantially less preposterous
EFI_SIMPLE_NETWORK_PROTOCOL. Provide an UNDI interface (as a thin
wrapper around the existing SNP interface) to allow for use by
third-party software that has made poor life choices.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[efi] Avoid infinite loops when asked to stop non-existent devices
Calling EDK2's OpenProtocol() with attributes BY_DRIVER|EXCLUSIVE will
call DisconnectController() in a loop to attempt to dislodge any
existing openers with attributes BY_DRIVER. The loop will continue
indefinitely until either no such openers remain, or until
DisconnectController() returns an error.
If our driver binding protocol's Stop() method is ever called to
disconnect a device that we are not in fact driving, then return
EFI_DEVICE_ERROR rather than EFI_SUCCESS, in order to break this
potentially infinite loop.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[efi] Work around broken 32-bit PE executable parsing in ImageHlp.dll
The Microsoft PE/COFF specification defines the MajorLinkerVersion and
MinorLinkerVersion fields as "The linker major version number" and
"The linker minor version number" respectively, and has nothing more
to say on the matter. These fields have no significance: they do not
affect the interpretation of the remainder of the file, but merely
provide diagnostic information for interested humans to read.
Apparently, versions 2.4 and earlier of the Microsoft linker produced
binaries so incorrigibly cursed that even to attempt to parse such a
binary would risk summoning a plague of enraged spiders. To protect
users from unwanted arachnids, ImageHlp.dll's MapAndLoad() function
will helpfully fail to map and/or load a 32-bit binary unless the
linker version field indicates version 2.5 or later. (64-bit binaries
are exempt from such helpfulness.)
Work around the broken Microsoft ImageHlp.dll library by providing a
linker version number that will satisfy the arbitrary whims of the
MapAndLoad() function.
This mirrors wimboot commit 670c7e2 ("[efi] Work around broken 32-bit
PE executable parsing in ImageHlp.dll").
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[pxe] Notify BIOS via INT 1a,564e for each new network device
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>
[pxe] Invoke INT 1a,564e when PXE stack is activated
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>
[efi] Minimise use of iPXE header files when building host utilities
Avoid dragging in unnecessary iPXE header files such as <ipxe/uuid.h>
and <ipxe/tables.h> when building host utilities, and ensure that
FILE_LICENCE() (present in the imported EDK2 headers) expands to a
no-op.
Reported-by: Michael Tautschnig <mt@debian.org>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Commit 7d36a1b ("[build] Explicitly link efilink against -liberty")
introduced a dependency on libiberty to cope with old versions of
libbfd. This commit dates from 2008 and seems to apply only to what
are now extremely old versions of libbfd (prior to binutils 2.12).
There are systems (such as current Debian) which do not include
libiberty within the binutils packages. On such systems, our build
dependency on libiberty represents a pointless hurdle.
Remove the explicit dependency on libiberty, hoping that there are no
modern systems where this will cause a problem.
Suggested-by: Ben Hildred <42656e@gmail.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[efi] Expose unused USB devices via EFI_USB_IO_PROTOCOL
Allow the UEFI platform firmware to provide drivers for unrecognised
devices, by exposing our own implementation of EFI_USB_IO_PROTOCOL.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Make the class ID a property of the USB driver (rather than a property
of the USB device ID), and allow USB drivers to specify a wildcard ID
for any of the three component IDs (class, subclass, or protocol).
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[usb] Select preferred USB device configuration based on driver score
Generate a score for each possible USB device configuration based on
the available driver support, and select the configuration with the
highest score. This will allow us to prefer ECM over RNDIS (for
devices which support both) and will allow us to meaningfully select a
configuration even when we have drivers available for all functions
(e.g. when exposing unused functions via EFI_USB_IO_PROTOCOL).
Signed-off-by: Michael Brown <mcb30@ipxe.org>
The decision on whether or not a zero-length packet needs to be
transmitted is independent of the host controller and belongs in the
USB core.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[tcpip] Avoid generating positive zero for transmitted UDP checksums
TCP/IP checksum fields are one's complement values and therefore have
two possible representations of zero: positive zero (0x0000) and
negative zero (0xffff).
In RFC768, UDP over IPv4 exploits this redundancy to repurpose the
positive representation of zero (0x0000) to mean "no checksum
calculated"; checksums are optional for UDP over IPv4.
In RFC2460, checksums are made mandatory for UDP over IPv4. The
wording of the RFC is such that the UDP header is mandated to use only
the negative representation of zero (0xffff), rather than simply
requiring the checksum to be correct but allowing for either
representation of zero to be used.
In RFC1071, an example algorithm is given for calculating the TCP/IP
checksum. This algorithm happens to produce only the positive
representation of zero (0x0000); this is an artifact of the way that
unsigned arithmetic is used to calculate a signed one's complement
sum (and its final negation).
A common misconception has developed (exemplified in RFC1624) that
this artifact is part of the specification. Many people have assumed
that the checksum field should never contain the negative
representation of zero (0xffff).
A sensible receiver will calculate the checksum over the whole packet
and verify that the result is zero (in whichever representation of
zero happens to be generated by the receiver's algorithm). Such a
receiver will not care which representation of zero happens to be used
in the checksum field.
However, there are receivers in existence which will verify the
received checksum the hard way: by calculating the checksum over the
remainder of the packet and comparing the result against the checksum
field. If the representation of zero used by the receiver's algorithm
does not match the representation of zero used by the transmitter (and
so placed in the checksum field), and if the receiver does not
explicitly allow for both representations to compare as equal, then
the receiver may reject packets with a valid checksum.
For UDP, the combined RFCs effectively mandate that we should generate
only the negative representation of zero in the checksum field.
For IP, TCP and ICMP, the RFCs do not mandate which representation of
zero should be used, but the misconceptions which have grown up around
RFC1071 and RFC1624 suggest that it would be least surprising to
generate only the positive representation of zero in the checksum
field.
Fix by ensuring that all of our checksum algorithms generate only the
positive representation of zero, and explicitly inverting this in the
case of transmitted UDP packets.
Reported-by: Wissam Shoukair <wissams@mellanox.com>
Tested-by: Wissam Shoukair <wissams@mellanox.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[efi] Add a USB host controller driver based on EFI_USB_IO_PROTOCOL
Allow iPXE to coexist with other USB device drivers, by attaching to
the EFI_USB_IO_PROTOCOL instances provided by the UEFI platform
firmware.
The EFI_USB_IO_PROTOCOL is an unsurprisingly badly designed
abstraction of a USB device. The poor design choices intrinsic in the
UEFI specification prevent efficient operation as a network device,
with the result that devices operated using the EFI_USB_IO_PROTOCOL
operate approximately two orders of magnitude slower than devices
operated using our native EHCI or xHCI host controller drivers.
Since the performance is so abysmally slow, and since the underlying
problems are due to fundamental architectural mistakes in the UEFI
specification, support for the EFI_USB_IO_PROTOCOL host controller
driver is left as disabled by default. Users are advised to use the
native iPXE host controller drivers instead.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Many UEFI NBPs expect to find an EFI_PXE_BASE_CODE_PROTOCOL installed
in addition to the EFI_SIMPLE_NETWORK_PROTOCOL. Most NBPs use the
EFI_PXE_BASE_CODE_PROTOCOL only to retrieve the cached DHCP packets.
This implementation has been tested with grub.efi, shim.efi,
syslinux.efi, and wdsmgfw.efi. Some methods (such as Discover() and
Arp()) are not used by any known NBP and so have not (yet) been
implemented.
Usage notes for the tested bootstraps are:
- grub.efi uses EFI_PXE_BASE_CODE_PROTOCOL only to retrieve the
cached DHCP packet, and uses no other methods.
- shim.efi uses EFI_PXE_BASE_CODE_PROTOCOL to retrieve the cached
DHCP packet and to retrieve the next NBP via the Mtftp() method.
If shim.efi was downloaded via HTTP (or other non-TFTP protocol)
then shim.efi will blindly call Mtftp() with an HTTP URI as the
filename: this allows the next NBP (e.g. grubx64.efi) to also be
transparently retrieved by HTTP.
shim.efi can also use the EFI_SIMPLE_FILE_SYSTEM_PROTOCOL to
retrieve files previously loaded by "imgfetch" or similar commands
in iPXE. The current implementation of shim.efi will use the
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL only if it does not find an
EFI_PXE_BASE_CODE_PROTOCOL; this patch therefore prevents this
usage of our EFI_SIMPLE_FILE_SYSTEM_PROTOCOL. This logic could be
trivially reversed in shim.efi if needed.
- syslinux.efi uses EFI_PXE_BASE_CODE_PROTOCOL only to retrieve the
cached DHCP packet. Versions 6.03 and earlier have a bug which
may cause syslinux.efi to attach to the wrong NIC if there are
multiple NICs in the system (or if the UEFI firmware supports
IPv6).
- wdsmgfw.efi (ab)uses EFI_PXE_BASE_CODE_PROTOCOL to retrieve the
cached DHCP packets, and to send and retrieve UDP packets via the
UdpWrite() and UdpRead() methods. (This was presumably done in
order to minimise the amount of benefit obtainable by switching to
UEFI, by replicating all of the design mistakes present in the
original PXE specification.)
The EFI_DOWNGRADE_UX configuration option remains available for now,
until this implementation has received more widespread testing.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
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>
[pxe] Populate ciaddr in fake PXE Boot Server ACK packet
We currently do not populate the ciaddr field in the constructed PXE
Boot Server ACK packet. This causes a WDS server to respond with a
broadcast packet, which is then ignored by wdsmgfw.efi since it does
not match the specified IP address filter.
Fix by populating ciaddr within the constructed PXE Boot Server ACK
packet.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[efi] Do not return EFI_NOT_READY from our ReceiveFilters() method
Our SNP ReceiveFilters() method is a no-op, since we always (if
possible) use promiscuous mode for all network cards. The method
currently returns EFI_NOT_READY if the SNP interfaces are claimed for
use by iPXE, as with all other SNP methods.
The WDS bootstrap wdsmgfw.efi attempts to use both the PXE Base Code
protocol and the Simple Network Protocol simultaneously. This is
fundamentally broken, since use of the PXE Base Code protocol requires
us to disable the use of SNP (by claiming the interfaces for use by
iPXE), otherwise MnpDxe swallows all of the received packets before
our PXE Base Code's UdpRead() method is able to return them.
The root cause of this problem is that, as with BIOS PXE, the network
booting portions of the UEFI specification are less of a specification
and more of an application note sketchily describing how the original
hacked-together Intel implementation works. No sane design would ever
have included the UdpWrite() and UdpRead() methods.
Work around these fundamental conceptual flaws by unconditionally
returning success from efi_snp_receive_filters().
Signed-off-by: Michael Brown <mcb30@ipxe.org>
[build] Search for ldlinux.c32 separately from isolinux.bin
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>
The debug directory size specified in the data directory should cover
only the EFI_IMAGE_DEBUG_DIRECTORY_ENTRY structure, not the whole of
the .debug section.
Reported-by: Andreas Hammarskjöld <junior@2PintSoftware.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>