summaryrefslogtreecommitdiffstats
path: root/src/drivers/net/efi/snponly.c
diff options
context:
space:
mode:
authorMichael Brown2014-10-17 17:36:00 +0200
committerMichael Brown2014-10-17 17:52:31 +0200
commitaf17abf67f1c89ee7193185b6ba1584e4eded4bc (patch)
tree0c40a20175046e9b5214b9965ecf00f44163bf11 /src/drivers/net/efi/snponly.c
parent[efi] Check for presence of UNDI in NII protocol (diff)
downloadipxe-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.c196
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,
};