Skip to content

Commit

Permalink
[efi] Implement the EFI_PXE_BASE_CODE_PROTOCOL
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
mcb30 committed Sep 2, 2015
1 parent 53d2d9e commit 3376fa5
Show file tree
Hide file tree
Showing 4 changed files with 1,627 additions and 0 deletions.
10 changes: 10 additions & 0 deletions src/image/efi_image.c
Expand Up @@ -29,6 +29,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#include <ipxe/efi/efi_utils.h>
#include <ipxe/efi/efi_strings.h>
#include <ipxe/efi/efi_wrap.h>
#include <ipxe/efi/efi_pxe.h>
#include <ipxe/image.h>
#include <ipxe/init.h>
#include <ipxe/features.h>
Expand Down Expand Up @@ -159,6 +160,13 @@ static int efi_image_exec ( struct image *image ) {
goto err_file_install;
}

/* Install PXE base code protocol */
if ( ( rc = efi_pxe_install ( snpdev->handle, snpdev->netdev ) ) != 0 ){
DBGC ( image, "EFIIMAGE %p could not install PXE protocol: "
"%s\n", image, strerror ( rc ) );
goto err_pxe_install;
}

/* Install iPXE download protocol */
if ( ( rc = efi_download_install ( snpdev->handle ) ) != 0 ) {
DBGC ( image, "EFIIMAGE %p could not install iPXE download "
Expand Down Expand Up @@ -266,6 +274,8 @@ static int efi_image_exec ( struct image *image ) {
err_image_path:
efi_download_uninstall ( snpdev->handle );
err_download_install:
efi_pxe_uninstall ( snpdev->handle );
err_pxe_install:
efi_file_uninstall ( snpdev->handle );
err_file_install:
err_no_snpdev:
Expand Down
17 changes: 17 additions & 0 deletions src/include/ipxe/efi/efi_pxe.h
@@ -0,0 +1,17 @@
#ifndef _IPXE_EFI_PXE_H
#define _IPXE_EFI_PXE_H

/** @file
*
* EFI PXE base code protocol
*/

#include <ipxe/efi/efi.h>
#include <ipxe/netdevice.h>

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );

extern int efi_pxe_install ( EFI_HANDLE handle, struct net_device *netdev );
extern void efi_pxe_uninstall ( EFI_HANDLE handle );

#endif /* _IPXE_EFI_PXE_H */
1 change: 1 addition & 0 deletions src/include/ipxe/errfile.h
Expand Up @@ -339,6 +339,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define ERRFILE_vmbus ( ERRFILE_OTHER | 0x00470000 )
#define ERRFILE_efi_time ( ERRFILE_OTHER | 0x00480000 )
#define ERRFILE_efi_watchdog ( ERRFILE_OTHER | 0x00490000 )
#define ERRFILE_efi_pxe ( ERRFILE_OTHER | 0x004a0000 )

/** @} */

Expand Down

0 comments on commit 3376fa5

Please sign in to comment.