summaryrefslogtreecommitdiffstats
path: root/src/interface/efi/efi_snp.c
diff options
context:
space:
mode:
authorMichael Brown2013-03-13 23:42:26 +0100
committerMichael Brown2013-03-14 00:01:53 +0100
commitc7c3d839fc9120aee28de9aabe452dc85ad91502 (patch)
tree07526ab554633c407bdd78c8fea20fc81e82c541 /src/interface/efi/efi_snp.c
parent[efi] Expose downloaded images via EFI_SIMPLE_FILE_SYSTEM_PROTOCOL (diff)
downloadipxe-c7c3d839fc9120aee28de9aabe452dc85ad91502.tar.gz
ipxe-c7c3d839fc9120aee28de9aabe452dc85ad91502.tar.xz
ipxe-c7c3d839fc9120aee28de9aabe452dc85ad91502.zip
[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>
Diffstat (limited to 'src/interface/efi/efi_snp.c')
-rw-r--r--src/interface/efi/efi_snp.c57
1 files changed, 56 insertions, 1 deletions
diff --git a/src/interface/efi/efi_snp.c b/src/interface/efi/efi_snp.c
index 48a6f397..95e39b7d 100644
--- a/src/interface/efi/efi_snp.c
+++ b/src/interface/efi/efi_snp.c
@@ -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 );
@@ -756,6 +761,49 @@ efi_snp_get_controller_name ( EFI_COMPONENT_NAME2_PROTOCOL *name2,
/******************************************************************************
*
+ * 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 );