summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/drivers/net/efi/snpnet.c43
-rw-r--r--src/include/ipxe/efi/efi_utils.h2
-rw-r--r--src/interface/efi/efi_utils.c52
3 files changed, 63 insertions, 34 deletions
diff --git a/src/drivers/net/efi/snpnet.c b/src/drivers/net/efi/snpnet.c
index 0348e7d1a..f5b294aca 100644
--- a/src/drivers/net/efi/snpnet.c
+++ b/src/drivers/net/efi/snpnet.c
@@ -31,6 +31,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#include <ipxe/efi/Protocol/SimpleNetwork.h>
#include <ipxe/efi/efi_driver.h>
#include <ipxe/efi/efi_pci.h>
+#include <ipxe/efi/efi_utils.h>
#include "snpnet.h"
/** @file
@@ -414,57 +415,31 @@ static struct net_device_operations snpnet_operations = {
* @ret rc Return status code
*/
static int snpnet_pci_info ( struct efi_device *efidev, struct device *dev ) {
- EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
EFI_HANDLE device = efidev->device;
- union {
- EFI_DEVICE_PATH_PROTOCOL *path;
- void *interface;
- } path;
- EFI_DEVICE_PATH_PROTOCOL *devpath;
- struct pci_device pci;
EFI_HANDLE pci_device;
- EFI_STATUS efirc;
+ struct pci_device pci;
int rc;
- /* Get device path */
- if ( ( efirc = bs->OpenProtocol ( device,
- &efi_device_path_protocol_guid,
- &path.interface,
- efi_image_handle, device,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL ))!=0){
- rc = -EEFI ( efirc );
- DBGC ( device, "SNP %p %s cannot open device path: %s\n",
+ /* Find parent PCI device */
+ if ( ( rc = efi_locate_device ( device, &efi_pci_io_protocol_guid,
+ &pci_device ) ) != 0 ) {
+ DBGC ( device, "SNP %p %s is not a PCI device: %s\n",
device, efi_handle_name ( device ), strerror ( rc ) );
- goto err_open_device_path;
- }
- devpath = path.path;
-
- /* Check for presence of PCI I/O protocol */
- if ( ( efirc = bs->LocateDevicePath ( &efi_pci_io_protocol_guid,
- &devpath, &pci_device ) ) != 0 ) {
- rc = -EEFI ( efirc );
- DBGC ( device, "SNP %p %s is not a PCI device\n",
- device, efi_handle_name ( device ) );
- goto err_locate_pci_io;
+ return rc;
}
/* Get PCI device information */
if ( ( rc = efipci_info ( pci_device, &pci ) ) != 0 ) {
DBGC ( device, "SNP %p %s could not get PCI information: %s\n",
device, efi_handle_name ( device ), strerror ( rc ) );
- goto err_efipci_info;
+ return rc;
}
/* Populate SNP device information */
memcpy ( &dev->desc, &pci.dev.desc, sizeof ( dev->desc ) );
snprintf ( dev->name, sizeof ( dev->name ), "SNP-%s", pci.dev.name );
- err_efipci_info:
- err_locate_pci_io:
- bs->CloseProtocol ( device, &efi_device_path_protocol_guid,
- efi_image_handle, device );
- err_open_device_path:
- return rc;
+ return 0;
}
/**
diff --git a/src/include/ipxe/efi/efi_utils.h b/src/include/ipxe/efi/efi_utils.h
index 23972c7a3..92ca0a9c5 100644
--- a/src/include/ipxe/efi/efi_utils.h
+++ b/src/include/ipxe/efi/efi_utils.h
@@ -13,6 +13,8 @@ FILE_LICENCE ( GPL2_OR_LATER );
extern EFI_DEVICE_PATH_PROTOCOL *
efi_devpath_end ( EFI_DEVICE_PATH_PROTOCOL *path );
+extern int efi_locate_device ( EFI_HANDLE device, EFI_GUID *protocol,
+ EFI_HANDLE *parent );
extern int efi_child_add ( EFI_HANDLE parent, EFI_HANDLE child );
extern void efi_child_del ( EFI_HANDLE parent, EFI_HANDLE child );
diff --git a/src/interface/efi/efi_utils.c b/src/interface/efi/efi_utils.c
index 9a3ec1598..b4f073304 100644
--- a/src/interface/efi/efi_utils.c
+++ b/src/interface/efi/efi_utils.c
@@ -49,6 +49,58 @@ EFI_DEVICE_PATH_PROTOCOL * efi_devpath_end ( EFI_DEVICE_PATH_PROTOCOL *path ) {
}
/**
+ * Locate parent device supporting a given protocol
+ *
+ * @v device EFI device handle
+ * @v protocol Protocol GUID
+ * @v parent Parent EFI device handle to fill in
+ * @ret rc Return status code
+ */
+int efi_locate_device ( EFI_HANDLE device, EFI_GUID *protocol,
+ EFI_HANDLE *parent ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ union {
+ EFI_DEVICE_PATH_PROTOCOL *path;
+ void *interface;
+ } path;
+ EFI_DEVICE_PATH_PROTOCOL *devpath;
+ EFI_STATUS efirc;
+ int rc;
+
+ /* Get device path */
+ if ( ( efirc = bs->OpenProtocol ( device,
+ &efi_device_path_protocol_guid,
+ &path.interface,
+ efi_image_handle, device,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL ))!=0){
+ rc = -EEFI ( efirc );
+ DBGC ( device, "EFIDEV %p %s cannot open device path: %s\n",
+ device, efi_handle_name ( device ), strerror ( rc ) );
+ goto err_open_device_path;
+ }
+ devpath = path.path;
+
+ /* Check for presence of specified protocol */
+ if ( ( efirc = bs->LocateDevicePath ( protocol, &devpath,
+ parent ) ) != 0 ) {
+ rc = -EEFI ( efirc );
+ DBGC ( device, "EFIDEV %p %s has no parent supporting %s: %s\n",
+ device, efi_handle_name ( device ),
+ efi_guid_ntoa ( protocol ), strerror ( rc ) );
+ goto err_locate_protocol;
+ }
+
+ /* Success */
+ rc = 0;
+
+ err_locate_protocol:
+ bs->CloseProtocol ( device, &efi_device_path_protocol_guid,
+ efi_image_handle, device );
+ err_open_device_path:
+ return rc;
+}
+
+/**
* Add EFI device as child of another EFI device
*
* @v parent EFI parent device handle