diff options
author | Michael Brown <mcb30@ipxe.org> | 2023-01-23 19:18:21 +0000 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2023-01-23 19:27:13 +0000 |
commit | 68734b9a4dafa540e5333d7af3849b59a10f7a93 (patch) | |
tree | d4b2d9f1b69c4fcc13571c30dd98041263f92b66 | |
parent | 2fef0c541e4e2417fc285c4d9ddfcb6f23f394ad (diff) | |
download | ipxe-68734b9a4dafa540e5333d7af3849b59a10f7a93.zip ipxe-68734b9a4dafa540e5333d7af3849b59a10f7a93.tar.gz ipxe-68734b9a4dafa540e5333d7af3849b59a10f7a93.tar.bz2 |
[efi] Bind to only the topmost instance of the SNP or NII protocolssnploop
UEFI has the mildly annoying habit of installing copies of the
EFI_SIMPLE_NETWORK_PROTOCOL instance on the IPv4 and IPv6 child device
handles. This can cause iPXE's SNP driver to attempt to bind to a
copy of the EFI_SIMPLE_NETWORK_PROTOCOL that iPXE itself provided on a
different handle.
Fix by refusing to bind to an SNP (or NII) handle if there exists
another instance of the same protocol further up the device path (on
the basis that we always want to bind to the highest possible device).
Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r-- | src/drivers/net/efi/snp.c | 66 |
1 files changed, 36 insertions, 30 deletions
diff --git a/src/drivers/net/efi/snp.c b/src/drivers/net/efi/snp.c index fbd6069..1920cdb 100644 --- a/src/drivers/net/efi/snp.c +++ b/src/drivers/net/efi/snp.c @@ -27,6 +27,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include <ipxe/efi/efi.h> #include <ipxe/efi/efi_driver.h> #include <ipxe/efi/efi_snp.h> +#include <ipxe/efi/efi_utils.h> #include "snpnet.h" #include "nii.h" @@ -40,31 +41,46 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); * Check to see if driver supports a device * * @v device EFI device handle + * @v protocol Protocol GUID * @ret rc Return status code */ -static int snp_supported ( EFI_HANDLE device ) { +static int snp_nii_supported ( EFI_HANDLE device, EFI_GUID *protocol ) { EFI_BOOT_SERVICES *bs = efi_systab->BootServices; + EFI_HANDLE parent; EFI_STATUS efirc; + int rc; /* Check that this is not a device we are providing ourselves */ if ( find_snpdev ( device ) != NULL ) { - DBGCP ( device, "SNP %s is provided by this binary\n", + DBGCP ( device, "HANDLE %s is provided by this binary\n", efi_handle_name ( device ) ); return -ENOTTY; } - /* Test for presence of simple network protocol */ - if ( ( efirc = bs->OpenProtocol ( device, - &efi_simple_network_protocol_guid, + /* Test for presence of protocol */ + if ( ( efirc = bs->OpenProtocol ( device, protocol, NULL, efi_image_handle, device, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))!=0){ - DBGCP ( device, "SNP %s is not an SNP device\n", - efi_handle_name ( device ) ); + DBGCP ( device, "HANDLE %s is not a %s device\n", + efi_handle_name ( device ), + efi_guid_ntoa ( protocol ) ); return -EEFI ( efirc ); } - DBGC ( device, "SNP %s is an SNP device\n", - efi_handle_name ( device ) ); + /* Check that there are no instances of this protocol further + * up this device path. + */ + if ( ( rc = efi_locate_device ( device, protocol, + &parent, 1 ) ) == 0 ) { + DBGC2 ( device, "HANDLE %s has %s-supporting parent ", + efi_handle_name ( device ), + efi_guid_ntoa ( protocol ) ); + DBGC2 ( device, "%s\n", efi_handle_name ( parent ) ); + return -ENOTTY; + } + + DBGC ( device, "HANDLE %s is a %s device\n", + efi_handle_name ( device ), efi_guid_ntoa ( protocol ) ); return 0; } @@ -74,30 +90,20 @@ static int snp_supported ( EFI_HANDLE device ) { * @v device EFI device handle * @ret rc Return status code */ -static int nii_supported ( EFI_HANDLE device ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - EFI_STATUS efirc; +static int snp_supported ( EFI_HANDLE device ) { - /* Check that this is not a device we are providing ourselves */ - if ( find_snpdev ( device ) != NULL ) { - DBGCP ( device, "NII %s is provided by this binary\n", - efi_handle_name ( device ) ); - return -ENOTTY; - } + return snp_nii_supported ( device, &efi_simple_network_protocol_guid ); +} - /* Test for presence of NII protocol */ - if ( ( efirc = bs->OpenProtocol ( device, - &efi_nii31_protocol_guid, - NULL, efi_image_handle, device, - EFI_OPEN_PROTOCOL_TEST_PROTOCOL))!=0){ - DBGCP ( device, "NII %s is not an NII device\n", - efi_handle_name ( device ) ); - return -EEFI ( efirc ); - } - DBGC ( device, "NII %s is an NII device\n", - efi_handle_name ( device ) ); +/** + * Check to see if driver supports a device + * + * @v device EFI device handle + * @ret rc Return status code + */ +static int nii_supported ( EFI_HANDLE device ) { - return 0; + return snp_nii_supported ( device, &efi_nii31_protocol_guid ); } /** EFI SNP driver */ |