From 5c4f1da2ceac87ab13ca946f2dfbaadcd19e208d Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 6 Aug 2014 14:04:02 +0100 Subject: [PATCH] [efi] Generalise snpnet_pci_info() to efi_locate_device() Signed-off-by: Michael Brown --- src/drivers/net/efi/snpnet.c | 43 ++++++-------------------- src/include/ipxe/efi/efi_utils.h | 2 ++ src/interface/efi/efi_utils.c | 52 ++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 34 deletions(-) diff --git a/src/drivers/net/efi/snpnet.c b/src/drivers/net/efi/snpnet.c index 0348e7d1..f5b294ac 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 #include #include +#include #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 23972c7a..92ca0a9c 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 9a3ec159..b4f07330 100644 --- a/src/interface/efi/efi_utils.c +++ b/src/interface/efi/efi_utils.c @@ -48,6 +48,58 @@ EFI_DEVICE_PATH_PROTOCOL * efi_devpath_end ( EFI_DEVICE_PATH_PROTOCOL *path ) { return 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 *