From af17abf67f1c89ee7193185b6ba1584e4eded4bc Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 17 Oct 2014 16:36:00 +0100 Subject: [PATCH] [efi] Include NII driver within "snp" and "snponly" build targets End users almost certainly don't care whether the underlying interface is SNP or NII/UNDI. Try to minimise surprise and unnecessary documentation by including the NII driver whenever the SNP driver is requested. Signed-off-by: Michael Brown --- src/drivers/net/efi/nii.c | 47 +------ src/drivers/net/efi/nii.h | 17 +++ src/drivers/net/efi/snp.c | 41 +++++++ src/drivers/net/efi/snponly.c | 224 ++++++++++++++++++++++------------ 4 files changed, 209 insertions(+), 120 deletions(-) create mode 100644 src/drivers/net/efi/nii.h diff --git a/src/drivers/net/efi/nii.c b/src/drivers/net/efi/nii.c index 56b6340b..d0d7da95 100644 --- a/src/drivers/net/efi/nii.c +++ b/src/drivers/net/efi/nii.c @@ -28,10 +28,11 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include -#include #include #include +#include #include +#include "nii.h" /** @file * @@ -955,45 +956,13 @@ static struct net_device_operations nii_operations = { .poll = nii_poll, }; -/** - * 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 ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - EFI_STATUS efirc; - - /* Check that this is not a device we are providing ourselves */ - if ( find_snpdev ( device ) != NULL ) { - DBGCP ( device, "NII %p %s is provided by this binary\n", - device, efi_handle_name ( device ) ); - return -ENOTTY; - } - - /* 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 %p %s is not an NII device\n", - device, efi_handle_name ( device ) ); - return -EEFI ( efirc ); - } - DBGC ( device, "NII %p %s is an NII device\n", - device, efi_handle_name ( device ) ); - - return 0; -} - /** * Attach driver to device * * @v efidev EFI device * @ret rc Return status code */ -static int nii_start ( struct efi_device *efidev ) { +int nii_start ( struct efi_device *efidev ) { EFI_BOOT_SERVICES *bs = efi_systab->BootServices; EFI_HANDLE device = efidev->device; struct net_device *netdev; @@ -1106,7 +1075,7 @@ static int nii_start ( struct efi_device *efidev ) { * * @v efidev EFI device */ -static void nii_stop ( struct efi_device *efidev ) { +void nii_stop ( struct efi_device *efidev ) { EFI_BOOT_SERVICES *bs = efi_systab->BootServices; struct net_device *netdev = efidev_get_drvdata ( efidev ); struct nii_nic *nii = netdev->priv; @@ -1130,11 +1099,3 @@ static void nii_stop ( struct efi_device *efidev ) { netdev_nullify ( netdev ); netdev_put ( netdev ); } - -/** EFI NII driver */ -struct efi_driver nii_driver __efi_driver ( EFI_DRIVER_NORMAL ) = { - .name = "NII", - .supported = nii_supported, - .start = nii_start, - .stop = nii_stop, -}; diff --git a/src/drivers/net/efi/nii.h b/src/drivers/net/efi/nii.h new file mode 100644 index 00000000..de0ac687 --- /dev/null +++ b/src/drivers/net/efi/nii.h @@ -0,0 +1,17 @@ +#ifndef _NII_H +#define _NII_H + +/** @file + * + * NII driver + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +struct efi_device; + +extern int nii_start ( struct efi_device *efidev ); +extern void nii_stop ( struct efi_device *efidev ); + +#endif /* _NII_H */ diff --git a/src/drivers/net/efi/snp.c b/src/drivers/net/efi/snp.c index a20bd21a..2b5fc861 100644 --- a/src/drivers/net/efi/snp.c +++ b/src/drivers/net/efi/snp.c @@ -24,6 +24,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include "snpnet.h" +#include "nii.h" /** @file * @@ -63,6 +64,38 @@ static int snp_supported ( EFI_HANDLE device ) { return 0; } +/** + * 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 ) { + EFI_BOOT_SERVICES *bs = efi_systab->BootServices; + EFI_STATUS efirc; + + /* Check that this is not a device we are providing ourselves */ + if ( find_snpdev ( device ) != NULL ) { + DBGCP ( device, "NII %p %s is provided by this binary\n", + device, efi_handle_name ( device ) ); + return -ENOTTY; + } + + /* 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 %p %s is not an NII device\n", + device, efi_handle_name ( device ) ); + return -EEFI ( efirc ); + } + DBGC ( device, "NII %p %s is an NII device\n", + device, efi_handle_name ( device ) ); + + return 0; +} + /** EFI SNP driver */ struct efi_driver snp_driver __efi_driver ( EFI_DRIVER_NORMAL ) = { .name = "SNP", @@ -70,3 +103,11 @@ struct efi_driver snp_driver __efi_driver ( EFI_DRIVER_NORMAL ) = { .start = snpnet_start, .stop = snpnet_stop, }; + +/** EFI NII driver */ +struct efi_driver nii_driver __efi_driver ( EFI_DRIVER_NORMAL ) = { + .name = "NII", + .supported = nii_supported, + .start = nii_start, + .stop = nii_stop, +}; diff --git a/src/drivers/net/efi/snponly.c b/src/drivers/net/efi/snponly.c index d454ed20..99f264bc 100644 --- a/src/drivers/net/efi/snponly.c +++ b/src/drivers/net/efi/snponly.c @@ -19,28 +19,140 @@ FILE_LICENCE ( GPL2_OR_LATER ); +#include #include #include #include #include +#include #include +#include #include "snpnet.h" +#include "nii.h" /** @file * - * SNP chainloading-device-only driver + * EFI chainloaded-device-only driver * */ +/** A chainloaded protocol */ +struct chained_protocol { + /** Protocol GUID */ + EFI_GUID *protocol; + /** + * Protocol instance installed on the loaded image's device handle + * + * We match against the protocol instance (rather than simply + * matching against the device handle itself) because some + * systems load us via a child of the underlying device, with + * a duplicate protocol installed on the child handle. + */ + void *interface; +}; + +/** Chainloaded SNP protocol */ +static struct chained_protocol chained_snp = { + .protocol = &efi_simple_network_protocol_guid, +}; + +/** Chainloaded NII protocol */ +static struct chained_protocol chained_nii = { + .protocol = &efi_nii31_protocol_guid, +}; + /** - * SNP protocol instance installed on the loaded image's device handle + * Locate chainloaded protocol instance * - * We match against the SNP protocol instance (rather than simply - * matching against the device handle itself) because some systems - * load us via a child of the SNP device, with a duplicate SNP - * protocol installed on the child handle. + * @v chained Chainloaded protocol + * @ret rc Return status code */ -static EFI_SIMPLE_NETWORK_PROTOCOL *snponly; +static int chained_locate ( struct chained_protocol *chained ) { + EFI_BOOT_SERVICES *bs = efi_systab->BootServices; + EFI_HANDLE device = efi_loaded_image->DeviceHandle; + EFI_HANDLE parent; + EFI_STATUS efirc; + int rc; + + /* Locate handle supporting this protocol */ + if ( ( rc = efi_locate_device ( device, chained->protocol, + &parent ) ) != 0 ) { + DBGC ( device, "CHAINED %p %s does not support %s: %s\n", + device, efi_handle_name ( device ), + efi_guid_ntoa ( chained->protocol ), strerror ( rc ) ); + goto err_locate_device; + } + DBGC ( device, "CHAINED %p %s found %s on ", device, + efi_handle_name ( device ), efi_guid_ntoa ( chained->protocol )); + DBGC ( device, "%p %s\n", parent, efi_handle_name ( parent ) ); + + /* Get protocol instance */ + if ( ( efirc = bs->OpenProtocol ( parent, chained->protocol, + &chained->interface, efi_image_handle, + device, + EFI_OPEN_PROTOCOL_GET_PROTOCOL ))!=0){ + rc = -EEFI ( efirc ); + DBGC ( device, "CHAINED %p %s could not open %s on ", + device, efi_handle_name ( device ), + efi_guid_ntoa ( chained->protocol ) ); + DBGC ( device, "%p %s: %s\n", + parent, efi_handle_name ( parent ), strerror ( rc ) ); + goto err_open_protocol; + } + + err_locate_device: + bs->CloseProtocol ( parent, chained->protocol, efi_image_handle, + device ); + err_open_protocol: + return rc; +} + +/** + * Check to see if driver supports a device + * + * @v device EFI device handle + * @v chained Chainloaded protocol + * @ret rc Return status code + */ +static int chained_supported ( EFI_HANDLE device, + struct chained_protocol *chained ) { + EFI_BOOT_SERVICES *bs = efi_systab->BootServices; + EFI_STATUS efirc; + void *interface; + int rc; + + /* Get protocol */ + if ( ( efirc = bs->OpenProtocol ( device, chained->protocol, &interface, + efi_image_handle, device, + EFI_OPEN_PROTOCOL_GET_PROTOCOL ))!=0){ + rc = -EEFI ( efirc ); + DBGCP ( device, "CHAINED %p %s is not a %s device\n", + device, efi_handle_name ( device ), + efi_guid_ntoa ( chained->protocol ) ); + goto err_open_protocol; + } + + /* Test for a match against the chainloading device */ + if ( interface != chained->interface ) { + DBGC ( device, "CHAINED %p %s %p is not the chainloaded " + "%s\n", device, efi_handle_name ( device ), + interface, efi_guid_ntoa ( chained->protocol ) ); + rc = -ENOTTY; + goto err_no_match; + } + + /* Success */ + rc = 0; + DBGC ( device, "CHAINED %p %s %p is the chainloaded %s\n", + device, efi_handle_name ( device ), interface, + efi_guid_ntoa ( chained->protocol ) ); + + err_no_match: + bs->CloseProtocol ( device, chained->protocol, efi_image_handle, + device ); + err_open_protocol: + return rc; +} /** * Check to see if driver supports a device @@ -49,48 +161,22 @@ static EFI_SIMPLE_NETWORK_PROTOCOL *snponly; * @ret rc Return status code */ static int snponly_supported ( EFI_HANDLE device ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - EFI_STATUS efirc; - union { - EFI_SIMPLE_NETWORK_PROTOCOL *snp; - void *interface; - } snp; - int rc; - /* Get SNP protocol */ - if ( ( efirc = bs->OpenProtocol ( device, - &efi_simple_network_protocol_guid, - &snp.interface, efi_image_handle, - device, - EFI_OPEN_PROTOCOL_GET_PROTOCOL ))!=0){ - rc = -EEFI ( efirc ); - DBGCP ( device, "SNPONLY %p %s is not an SNP device\n", - device, efi_handle_name ( device ) ); - goto err_not_snp; - } - - /* Test for a match against the chainloading device */ - if ( snp.snp != snponly ) { - DBGC ( device, "SNPONLY %p %s SNP %p is not the " - "chainloading SNP\n", device, - efi_handle_name ( device ), snp.snp ); - rc = -ENOTTY; - goto err_not_snponly; - } - - /* Success */ - rc = 0; - DBGC ( device, "SNPONLY %p %s SNP %p is the chainloading SNP\n", - device, efi_handle_name ( device ), snp.snp ); - - err_not_snponly: - bs->CloseProtocol ( device, &efi_simple_network_protocol_guid, - efi_image_handle, device ); - err_not_snp: - return rc; + return chained_supported ( device, &chained_snp ); } -/** EFI chainloading-device-only driver */ +/** + * Check to see if driver supports a device + * + * @v device EFI device handle + * @ret rc Return status code + */ +static int niionly_supported ( EFI_HANDLE device ) { + + return chained_supported ( device, &chained_nii ); +} + +/** EFI SNP chainloading-device-only driver */ struct efi_driver snponly_driver __efi_driver ( EFI_DRIVER_NORMAL ) = { .name = "SNPONLY", .supported = snponly_supported, @@ -98,41 +184,25 @@ struct efi_driver snponly_driver __efi_driver ( EFI_DRIVER_NORMAL ) = { .stop = snpnet_stop, }; +/** EFI NII chainloading-device-only driver */ +struct efi_driver niionly_driver __efi_driver ( EFI_DRIVER_NORMAL ) = { + .name = "NIIONLY", + .supported = niionly_supported, + .start = nii_start, + .stop = nii_stop, +}; + /** - * Initialise EFI chainloading-device-only driver + * Initialise EFI chainloaded-device-only driver * */ -static void snponly_init ( void ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - EFI_HANDLE device = efi_loaded_image->DeviceHandle; - union { - EFI_SIMPLE_NETWORK_PROTOCOL *snp; - void *interface; - } snp; - EFI_STATUS efirc; +static void chained_init ( void ) { - /* Look for SNP protocol on the loaded image's device handle */ - if ( ( efirc = bs->OpenProtocol ( device, - &efi_simple_network_protocol_guid, - &snp.interface, efi_image_handle, - device, - EFI_OPEN_PROTOCOL_GET_PROTOCOL ))!=0){ - DBGC ( device, "SNPONLY %p %s is not an SNP device\n", - device, efi_handle_name ( device ) ); - goto err_open_protocol; - } - - /* Record SNP protocol instance */ - snponly = snp.snp; - DBGC ( device, "SNPONLY %p %s found chainloading SNP %p\n", - device, efi_handle_name ( device ), snponly ); - - err_open_protocol: - bs->CloseProtocol ( device, &efi_simple_network_protocol_guid, - efi_image_handle, device ); + chained_locate ( &chained_snp ); + chained_locate ( &chained_nii ); } -/** EFI chainloading-device-only initialisation function */ -struct init_fn snponly_init_fn __init_fn ( INIT_LATE ) = { - .initialise = snponly_init, +/** EFI chainloaded-device-only initialisation function */ +struct init_fn chained_init_fn __init_fn ( INIT_LATE ) = { + .initialise = chained_init, };