Browse Source

[efi] Add our own EFI_LOAD_FILE_PROTOCOL implementation

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>
tags/v1.20.1
Michael Brown 11 years ago
parent
commit
c7c3d839fc
2 changed files with 59 additions and 1 deletions
  1. 3
    0
      src/include/ipxe/efi/efi_snp.h
  2. 56
    1
      src/interface/efi/efi_snp.c

+ 3
- 0
src/include/ipxe/efi/efi_snp.h View File

@@ -16,6 +16,7 @@
16 16
 #include <ipxe/efi/Protocol/DevicePath.h>
17 17
 #include <ipxe/efi/Protocol/HiiConfigAccess.h>
18 18
 #include <ipxe/efi/Protocol/HiiDatabase.h>
19
+#include <ipxe/efi/Protocol/LoadFile.h>
19 20
 
20 21
 /** An SNP device */
21 22
 struct efi_snp_device {
@@ -49,6 +50,8 @@ struct efi_snp_device {
49 50
 	EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL nii;
50 51
 	/** Component name protocol */
51 52
 	EFI_COMPONENT_NAME2_PROTOCOL name2;
53
+	/** Load file protocol handle */
54
+	EFI_LOAD_FILE_PROTOCOL load_file;
52 55
 	/** HII configuration access protocol */
53 56
 	EFI_HII_CONFIG_ACCESS_PROTOCOL hii;
54 57
 	/** HII package list */

+ 56
- 1
src/interface/efi/efi_snp.c View File

@@ -34,6 +34,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
34 34
 #include <ipxe/efi/efi_strings.h>
35 35
 #include <ipxe/efi/efi_snp.h>
36 36
 #include <config/general.h>
37
+#include <usr/autoboot.h>
37 38
 
38 39
 /** EFI simple network protocol GUID */
39 40
 static EFI_GUID efi_simple_network_protocol_guid
@@ -57,10 +58,14 @@ static EFI_GUID efi_nii31_protocol_guid = {
57 58
 	{ 0xBC, 0x81, 0x76, 0x7F, 0x1F, 0x97, 0x7A, 0x89 }
58 59
 };
59 60
 
60
-/** EFI component name protocol */
61
+/** EFI component name protocol GUID */
61 62
 static EFI_GUID efi_component_name2_protocol_guid
62 63
 	= EFI_COMPONENT_NAME2_PROTOCOL_GUID;
63 64
 
65
+/** EFI load file protocol GUID */
66
+static EFI_GUID efi_load_file_protocol_guid
67
+	= EFI_LOAD_FILE_PROTOCOL_GUID;
68
+
64 69
 /** List of SNP devices */
65 70
 static LIST_HEAD ( efi_snp_devices );
66 71
 
@@ -754,6 +759,49 @@ efi_snp_get_controller_name ( EFI_COMPONENT_NAME2_PROTOCOL *name2,
754 759
 	return 0;
755 760
 }
756 761
 
762
+/******************************************************************************
763
+ *
764
+ * Load file protocol
765
+ *
766
+ ******************************************************************************
767
+ */
768
+
769
+/**
770
+ * Load file
771
+ *
772
+ * @v loadfile		Load file protocol
773
+ * @v path		File path
774
+ * @v booting		Loading as part of a boot attempt
775
+ * @ret efirc		EFI status code
776
+ */
777
+static EFI_STATUS EFIAPI
778
+efi_snp_load_file ( EFI_LOAD_FILE_PROTOCOL *load_file,
779
+		    EFI_DEVICE_PATH_PROTOCOL *path __unused,
780
+		    BOOLEAN booting, UINTN *len __unused,
781
+		    VOID *data __unused ) {
782
+	struct efi_snp_device *snpdev =
783
+		container_of ( load_file, struct efi_snp_device, load_file );
784
+	struct net_device *netdev = snpdev->netdev;
785
+
786
+	/* Fail unless this is a boot attempt */
787
+	if ( ! booting ) {
788
+		DBGC ( snpdev, "SNPDEV %p cannot load non-boot file\n",
789
+		       snpdev );
790
+		return EFI_UNSUPPORTED;
791
+	}
792
+
793
+	/* Boot from network device */
794
+	ipxe ( netdev );
795
+
796
+	/* Assume boot process was aborted */
797
+	return EFI_ABORTED;
798
+}
799
+
800
+/** Load file protocol */
801
+static EFI_LOAD_FILE_PROTOCOL efi_snp_load_file_protocol = {
802
+	.LoadFile	= efi_snp_load_file,
803
+};
804
+
757 805
 /******************************************************************************
758 806
  *
759 807
  * iPXE network driver
@@ -861,6 +909,10 @@ static int efi_snp_probe ( struct net_device *netdev ) {
861 909
 	snpdev->name2.GetControllerName = efi_snp_get_controller_name;
862 910
 	snpdev->name2.SupportedLanguages = "en";
863 911
 
912
+	/* Populate the load file protocol structure */
913
+	memcpy ( &snpdev->load_file, &efi_snp_load_file_protocol,
914
+		 sizeof ( snpdev->load_file ) );
915
+
864 916
 	/* Populate the device name */
865 917
 	efi_snprintf ( snpdev->name, ( sizeof ( snpdev->name ) /
866 918
 				       sizeof ( snpdev->name[0] ) ),
@@ -890,6 +942,7 @@ static int efi_snp_probe ( struct net_device *netdev ) {
890 942
 			&efi_nii_protocol_guid, &snpdev->nii,
891 943
 			&efi_nii31_protocol_guid, &snpdev->nii,
892 944
 			&efi_component_name2_protocol_guid, &snpdev->name2,
945
+			&efi_load_file_protocol_guid, &snpdev->load_file,
893 946
 			NULL ) ) != 0 ) {
894 947
 		DBGC ( snpdev, "SNPDEV %p could not install protocols: "
895 948
 		       "%s\n", snpdev, efi_strerror ( efirc ) );
@@ -931,6 +984,7 @@ static int efi_snp_probe ( struct net_device *netdev ) {
931 984
 			&efi_nii_protocol_guid, &snpdev->nii,
932 985
 			&efi_nii31_protocol_guid, &snpdev->nii,
933 986
 			&efi_component_name2_protocol_guid, &snpdev->name2,
987
+			&efi_load_file_protocol_guid, &snpdev->load_file,
934 988
 			NULL );
935 989
  err_install_protocol_interface:
936 990
 	bs->CloseEvent ( snpdev->snp.WaitForPacket );
@@ -992,6 +1046,7 @@ static void efi_snp_remove ( struct net_device *netdev ) {
992 1046
 			&efi_nii_protocol_guid, &snpdev->nii,
993 1047
 			&efi_nii31_protocol_guid, &snpdev->nii,
994 1048
 			&efi_component_name2_protocol_guid, &snpdev->name2,
1049
+			&efi_load_file_protocol_guid, &snpdev->load_file,
995 1050
 			NULL );
996 1051
 	bs->CloseEvent ( snpdev->snp.WaitForPacket );
997 1052
 	netdev_put ( snpdev->netdev );

Loading…
Cancel
Save