]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[efi] Add our own EFI_LOAD_FILE_PROTOCOL implementation
authorMichael Brown <mcb30@ipxe.org>
Wed, 13 Mar 2013 22:42:26 +0000 (22:42 +0000)
committerMichael Brown <mcb30@ipxe.org>
Wed, 13 Mar 2013 23:01:53 +0000 (23:01 +0000)
When iPXE is used as a UEFI driver, the UEFI PXE base code currently
provides the TCP/IP stack, network protocols, and user interface.
This represents a substantial downgrade from the standard BIOS iPXE
user experience.

Fix by installing our own EFI_LOAD_FILE_PROTOCOL implementation which
initiates the standard iPXE boot procedure.  This upgrades the UEFI
iPXE user experience to match the standard BIOS iPXE user experience.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/include/ipxe/efi/efi_snp.h
src/interface/efi/efi_snp.c

index 074d1b27dff261a8d38322ec28cf624588a1215c..3791645975d3a4e0595ebe8d61df61ce35d91a37 100644 (file)
@@ -16,6 +16,7 @@
 #include <ipxe/efi/Protocol/DevicePath.h>
 #include <ipxe/efi/Protocol/HiiConfigAccess.h>
 #include <ipxe/efi/Protocol/HiiDatabase.h>
+#include <ipxe/efi/Protocol/LoadFile.h>
 
 /** An SNP device */
 struct efi_snp_device {
@@ -49,6 +50,8 @@ struct efi_snp_device {
        EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL nii;
        /** Component name protocol */
        EFI_COMPONENT_NAME2_PROTOCOL name2;
+       /** Load file protocol handle */
+       EFI_LOAD_FILE_PROTOCOL load_file;
        /** HII configuration access protocol */
        EFI_HII_CONFIG_ACCESS_PROTOCOL hii;
        /** HII package list */
index 48a6f397eddd080984759d65dec1f85e110766a0..95e39b7d954916a2c438d52255f31359695ca84d 100644 (file)
@@ -34,6 +34,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #include <ipxe/efi/efi_strings.h>
 #include <ipxe/efi/efi_snp.h>
 #include <config/general.h>
+#include <usr/autoboot.h>
 
 /** EFI simple network protocol GUID */
 static EFI_GUID efi_simple_network_protocol_guid
@@ -57,10 +58,14 @@ static EFI_GUID efi_nii31_protocol_guid = {
        { 0xBC, 0x81, 0x76, 0x7F, 0x1F, 0x97, 0x7A, 0x89 }
 };
 
-/** EFI component name protocol */
+/** EFI component name protocol GUID */
 static EFI_GUID efi_component_name2_protocol_guid
        = EFI_COMPONENT_NAME2_PROTOCOL_GUID;
 
+/** EFI load file protocol GUID */
+static EFI_GUID efi_load_file_protocol_guid
+       = EFI_LOAD_FILE_PROTOCOL_GUID;
+
 /** List of SNP devices */
 static LIST_HEAD ( efi_snp_devices );
 
@@ -754,6 +759,49 @@ efi_snp_get_controller_name ( EFI_COMPONENT_NAME2_PROTOCOL *name2,
        return 0;
 }
 
+/******************************************************************************
+ *
+ * Load file protocol
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Load file
+ *
+ * @v loadfile         Load file protocol
+ * @v path             File path
+ * @v booting          Loading as part of a boot attempt
+ * @ret efirc          EFI status code
+ */
+static EFI_STATUS EFIAPI
+efi_snp_load_file ( EFI_LOAD_FILE_PROTOCOL *load_file,
+                   EFI_DEVICE_PATH_PROTOCOL *path __unused,
+                   BOOLEAN booting, UINTN *len __unused,
+                   VOID *data __unused ) {
+       struct efi_snp_device *snpdev =
+               container_of ( load_file, struct efi_snp_device, load_file );
+       struct net_device *netdev = snpdev->netdev;
+
+       /* Fail unless this is a boot attempt */
+       if ( ! booting ) {
+               DBGC ( snpdev, "SNPDEV %p cannot load non-boot file\n",
+                      snpdev );
+               return EFI_UNSUPPORTED;
+       }
+
+       /* Boot from network device */
+       ipxe ( netdev );
+
+       /* Assume boot process was aborted */
+       return EFI_ABORTED;
+}
+
+/** Load file protocol */
+static EFI_LOAD_FILE_PROTOCOL efi_snp_load_file_protocol = {
+       .LoadFile       = efi_snp_load_file,
+};
+
 /******************************************************************************
  *
  * iPXE network driver
@@ -861,6 +909,10 @@ static int efi_snp_probe ( struct net_device *netdev ) {
        snpdev->name2.GetControllerName = efi_snp_get_controller_name;
        snpdev->name2.SupportedLanguages = "en";
 
+       /* Populate the load file protocol structure */
+       memcpy ( &snpdev->load_file, &efi_snp_load_file_protocol,
+                sizeof ( snpdev->load_file ) );
+
        /* Populate the device name */
        efi_snprintf ( snpdev->name, ( sizeof ( snpdev->name ) /
                                       sizeof ( snpdev->name[0] ) ),
@@ -890,6 +942,7 @@ static int efi_snp_probe ( struct net_device *netdev ) {
                        &efi_nii_protocol_guid, &snpdev->nii,
                        &efi_nii31_protocol_guid, &snpdev->nii,
                        &efi_component_name2_protocol_guid, &snpdev->name2,
+                       &efi_load_file_protocol_guid, &snpdev->load_file,
                        NULL ) ) != 0 ) {
                DBGC ( snpdev, "SNPDEV %p could not install protocols: "
                       "%s\n", snpdev, efi_strerror ( efirc ) );
@@ -931,6 +984,7 @@ static int efi_snp_probe ( struct net_device *netdev ) {
                        &efi_nii_protocol_guid, &snpdev->nii,
                        &efi_nii31_protocol_guid, &snpdev->nii,
                        &efi_component_name2_protocol_guid, &snpdev->name2,
+                       &efi_load_file_protocol_guid, &snpdev->load_file,
                        NULL );
  err_install_protocol_interface:
        bs->CloseEvent ( snpdev->snp.WaitForPacket );
@@ -992,6 +1046,7 @@ static void efi_snp_remove ( struct net_device *netdev ) {
                        &efi_nii_protocol_guid, &snpdev->nii,
                        &efi_nii31_protocol_guid, &snpdev->nii,
                        &efi_component_name2_protocol_guid, &snpdev->name2,
+                       &efi_load_file_protocol_guid, &snpdev->load_file,
                        NULL );
        bs->CloseEvent ( snpdev->snp.WaitForPacket );
        netdev_put ( snpdev->netdev );