diff options
author | Michael Brown | 2014-10-17 17:36:00 +0200 |
---|---|---|
committer | Michael Brown | 2014-10-17 17:52:31 +0200 |
commit | af17abf67f1c89ee7193185b6ba1584e4eded4bc (patch) | |
tree | 0c40a20175046e9b5214b9965ecf00f44163bf11 /src/drivers/net/efi/snponly.c | |
parent | [efi] Check for presence of UNDI in NII protocol (diff) | |
download | ipxe-af17abf67f1c89ee7193185b6ba1584e4eded4bc.tar.gz ipxe-af17abf67f1c89ee7193185b6ba1584e4eded4bc.tar.xz ipxe-af17abf67f1c89ee7193185b6ba1584e4eded4bc.zip |
[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 <mcb30@ipxe.org>
Diffstat (limited to 'src/drivers/net/efi/snponly.c')
-rw-r--r-- | src/drivers/net/efi/snponly.c | 196 |
1 files changed, 133 insertions, 63 deletions
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,78 +19,164 @@ FILE_LICENCE ( GPL2_OR_LATER ); +#include <string.h> #include <errno.h> #include <ipxe/init.h> #include <ipxe/efi/efi.h> #include <ipxe/efi/efi_driver.h> +#include <ipxe/efi/efi_utils.h> #include <ipxe/efi/Protocol/SimpleNetwork.h> +#include <ipxe/efi/Protocol/NetworkInterfaceIdentifier.h> #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 snponly_supported ( EFI_HANDLE device ) { +static int chained_supported ( EFI_HANDLE device, + struct chained_protocol *chained ) { EFI_BOOT_SERVICES *bs = efi_systab->BootServices; EFI_STATUS efirc; - union { - EFI_SIMPLE_NETWORK_PROTOCOL *snp; - void *interface; - } snp; + void *interface; int rc; - /* Get SNP protocol */ - if ( ( efirc = bs->OpenProtocol ( device, - &efi_simple_network_protocol_guid, - &snp.interface, efi_image_handle, - device, + /* 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, "SNPONLY %p %s is not an SNP device\n", - device, efi_handle_name ( device ) ); - goto err_not_snp; + 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 ( snp.snp != snponly ) { - DBGC ( device, "SNPONLY %p %s SNP %p is not the " - "chainloading SNP\n", device, - efi_handle_name ( device ), snp.snp ); + 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_not_snponly; + goto err_no_match; } /* Success */ rc = 0; - DBGC ( device, "SNPONLY %p %s SNP %p is the chainloading SNP\n", - device, efi_handle_name ( device ), snp.snp ); + DBGC ( device, "CHAINED %p %s %p is the chainloaded %s\n", + device, efi_handle_name ( device ), interface, + efi_guid_ntoa ( chained->protocol ) ); - err_not_snponly: - bs->CloseProtocol ( device, &efi_simple_network_protocol_guid, - efi_image_handle, device ); - err_not_snp: + err_no_match: + bs->CloseProtocol ( device, chained->protocol, efi_image_handle, + device ); + err_open_protocol: return rc; } -/** 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 snponly_supported ( EFI_HANDLE device ) { + + return chained_supported ( device, &chained_snp ); +} + +/** + * 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, }; |