Browse Source

[efi] Implement the EFI_PXE_BASE_CODE_PROTOCOL

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>
tags/v1.20.1
Michael Brown 9 years ago
parent
commit
3376fa520b
4 changed files with 1627 additions and 0 deletions
  1. 10
    0
      src/image/efi_image.c
  2. 17
    0
      src/include/ipxe/efi/efi_pxe.h
  3. 1
    0
      src/include/ipxe/errfile.h
  4. 1599
    0
      src/interface/efi/efi_pxe.c

+ 10
- 0
src/image/efi_image.c View File

29
 #include <ipxe/efi/efi_utils.h>
29
 #include <ipxe/efi/efi_utils.h>
30
 #include <ipxe/efi/efi_strings.h>
30
 #include <ipxe/efi/efi_strings.h>
31
 #include <ipxe/efi/efi_wrap.h>
31
 #include <ipxe/efi/efi_wrap.h>
32
+#include <ipxe/efi/efi_pxe.h>
32
 #include <ipxe/image.h>
33
 #include <ipxe/image.h>
33
 #include <ipxe/init.h>
34
 #include <ipxe/init.h>
34
 #include <ipxe/features.h>
35
 #include <ipxe/features.h>
159
 		goto err_file_install;
160
 		goto err_file_install;
160
 	}
161
 	}
161
 
162
 
163
+	/* Install PXE base code protocol */
164
+	if ( ( rc = efi_pxe_install ( snpdev->handle, snpdev->netdev ) ) != 0 ){
165
+		DBGC ( image, "EFIIMAGE %p could not install PXE protocol: "
166
+		       "%s\n", image, strerror ( rc ) );
167
+		goto err_pxe_install;
168
+	}
169
+
162
 	/* Install iPXE download protocol */
170
 	/* Install iPXE download protocol */
163
 	if ( ( rc = efi_download_install ( snpdev->handle ) ) != 0 ) {
171
 	if ( ( rc = efi_download_install ( snpdev->handle ) ) != 0 ) {
164
 		DBGC ( image, "EFIIMAGE %p could not install iPXE download "
172
 		DBGC ( image, "EFIIMAGE %p could not install iPXE download "
266
  err_image_path:
274
  err_image_path:
267
 	efi_download_uninstall ( snpdev->handle );
275
 	efi_download_uninstall ( snpdev->handle );
268
  err_download_install:
276
  err_download_install:
277
+	efi_pxe_uninstall ( snpdev->handle );
278
+ err_pxe_install:
269
 	efi_file_uninstall ( snpdev->handle );
279
 	efi_file_uninstall ( snpdev->handle );
270
  err_file_install:
280
  err_file_install:
271
  err_no_snpdev:
281
  err_no_snpdev:

+ 17
- 0
src/include/ipxe/efi/efi_pxe.h View File

1
+#ifndef _IPXE_EFI_PXE_H
2
+#define _IPXE_EFI_PXE_H
3
+
4
+/** @file
5
+ *
6
+ * EFI PXE base code protocol
7
+ */
8
+
9
+#include <ipxe/efi/efi.h>
10
+#include <ipxe/netdevice.h>
11
+
12
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
13
+
14
+extern int efi_pxe_install ( EFI_HANDLE handle, struct net_device *netdev );
15
+extern void efi_pxe_uninstall ( EFI_HANDLE handle );
16
+
17
+#endif /* _IPXE_EFI_PXE_H */

+ 1
- 0
src/include/ipxe/errfile.h View File

339
 #define ERRFILE_vmbus		      ( ERRFILE_OTHER | 0x00470000 )
339
 #define ERRFILE_vmbus		      ( ERRFILE_OTHER | 0x00470000 )
340
 #define ERRFILE_efi_time	      ( ERRFILE_OTHER | 0x00480000 )
340
 #define ERRFILE_efi_time	      ( ERRFILE_OTHER | 0x00480000 )
341
 #define ERRFILE_efi_watchdog	      ( ERRFILE_OTHER | 0x00490000 )
341
 #define ERRFILE_efi_watchdog	      ( ERRFILE_OTHER | 0x00490000 )
342
+#define ERRFILE_efi_pxe		      ( ERRFILE_OTHER | 0x004a0000 )
342
 
343
 
343
 /** @} */
344
 /** @} */
344
 
345
 

+ 1599
- 0
src/interface/efi/efi_pxe.c
File diff suppressed because it is too large
View File


Loading…
Cancel
Save