diff options
Diffstat (limited to 'src/interface/efi/efi_pci.c')
| -rw-r--r-- | src/interface/efi/efi_pci.c | 423 |
1 files changed, 217 insertions, 206 deletions
diff --git a/src/interface/efi/efi_pci.c b/src/interface/efi/efi_pci.c index e2eeeb344..4bf3977c5 100644 --- a/src/interface/efi/efi_pci.c +++ b/src/interface/efi/efi_pci.c @@ -22,8 +22,10 @@ */ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); +FILE_SECBOOT ( PERMITTED ); #include <stdlib.h> +#include <string.h> #include <errno.h> #include <ipxe/pci.h> #include <ipxe/acpi.h> @@ -63,33 +65,43 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); */ /** - * Check for a matching PCI root bridge I/O protocol + * Find closest bus:dev.fn address range within a root bridge * - * @v pci PCI device + * @v pci Starting PCI device * @v handle EFI PCI root bridge handle - * @v root EFI PCI root bridge I/O protocol + * @v range PCI bus:dev.fn address range to fill in * @ret rc Return status code */ -static int efipci_root_match ( struct pci_device *pci, EFI_HANDLE handle, - EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *root ) { +static int efipci_discover_one ( struct pci_device *pci, EFI_HANDLE handle, + struct pci_range *range ) { + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *root; union { union acpi_resource *res; void *raw; - } u; - unsigned int segment = PCI_SEG ( pci->busdevfn ); - unsigned int bus = PCI_BUS ( pci->busdevfn ); - unsigned int start; - unsigned int end; + } acpi; + uint32_t best = 0; + uint32_t start; + uint32_t count; + uint32_t index; unsigned int tag; EFI_STATUS efirc; int rc; - /* Check segment number */ - if ( root->SegmentNumber != segment ) - return -ENOENT; + /* Return empty range on error */ + range->start = 0; + range->count = 0; + + /* Open root bridge I/O protocol */ + if ( ( rc = efi_open ( handle, &efi_pci_root_bridge_io_protocol_guid, + &root ) ) != 0 ) { + DBGC ( pci, "EFIPCI " PCI_FMT " cannot open %s: %s\n", + PCI_ARGS ( pci ), efi_handle_name ( handle ), + strerror ( rc ) ); + return rc; + } /* Get ACPI resource descriptors */ - if ( ( efirc = root->Configuration ( root, &u.raw ) ) != 0 ) { + if ( ( efirc = root->Configuration ( root, &acpi.raw ) ) != 0 ) { rc = -EEFI ( efirc ); DBGC ( pci, "EFIPCI " PCI_FMT " cannot get configuration for " "%s: %s\n", PCI_ARGS ( pci ), @@ -97,57 +109,79 @@ static int efipci_root_match ( struct pci_device *pci, EFI_HANDLE handle, return rc; } - /* Assume success if no bus number range descriptors are found */ - rc = 0; - /* Parse resource descriptors */ - for ( ; ( ( tag = acpi_resource_tag ( u.res ) ) != ACPI_END_RESOURCE ) ; - u.res = acpi_resource_next ( u.res ) ) { + for ( ; ( ( tag = acpi_resource_tag ( acpi.res ) ) != + ACPI_END_RESOURCE ) ; + acpi.res = acpi_resource_next ( acpi.res ) ) { /* Ignore anything other than a bus number range descriptor */ if ( tag != ACPI_QWORD_ADDRESS_SPACE_RESOURCE ) continue; - if ( u.res->qword.type != ACPI_ADDRESS_TYPE_BUS ) + if ( acpi.res->qword.type != ACPI_ADDRESS_TYPE_BUS ) continue; - /* Check for a matching bus number */ - start = le64_to_cpu ( u.res->qword.min ); - end = ( start + le64_to_cpu ( u.res->qword.len ) ); - if ( ( bus >= start ) && ( bus < end ) ) - return 0; + /* Get range for this descriptor */ + start = PCI_BUSDEVFN ( root->SegmentNumber, + le64_to_cpu ( acpi.res->qword.min ), + 0, 0 ); + count = PCI_BUSDEVFN ( 0, le64_to_cpu ( acpi.res->qword.len ), + 0, 0 ); + DBGC2 ( pci, "EFIPCI " PCI_FMT " found %04x:[%02x-%02x] via " + "%s\n", PCI_ARGS ( pci ), root->SegmentNumber, + PCI_BUS ( start ), PCI_BUS ( start + count - 1 ), + efi_handle_name ( handle ) ); + + /* Check for a matching or new closest range */ + index = ( pci->busdevfn - start ); + if ( ( index < count ) || ( index > best ) ) { + range->start = start; + range->count = count; + best = index; + } - /* We have seen at least one non-matching range - * descriptor, so assume failure unless we find a - * subsequent match. - */ - rc = -ENOENT; + /* Stop if this range contains the target bus:dev.fn address */ + if ( index < count ) + break; } - return rc; + /* If no range descriptors were seen, assume that the root + * bridge has a single bus. + */ + if ( ! range->count ) { + range->start = PCI_BUSDEVFN ( root->SegmentNumber, 0, 0, 0 ); + range->count = PCI_BUSDEVFN ( 0, 1, 0, 0 ); + } + + return 0; } /** - * Open EFI PCI root bridge I/O protocol + * Find closest bus:dev.fn address range within any root bridge * - * @v pci PCI device - * @ret handle EFI PCI root bridge handle - * @ret root EFI PCI root bridge I/O protocol, or NULL if not found + * @v pci Starting PCI device + * @v range PCI bus:dev.fn address range to fill in + * @v handle PCI root bridge I/O handle to fill in * @ret rc Return status code */ -static int efipci_root_open ( struct pci_device *pci, EFI_HANDLE *handle, - EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL **root ) { +static int efipci_discover_any ( struct pci_device *pci, + struct pci_range *range, + EFI_HANDLE *handle ) { EFI_BOOT_SERVICES *bs = efi_systab->BootServices; + uint32_t best = 0; + uint32_t index; + struct pci_range tmp; EFI_HANDLE *handles; UINTN num_handles; - union { - void *interface; - EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *root; - } u; - EFI_STATUS efirc; UINTN i; + EFI_STATUS efirc; int rc; - /* Enumerate all handles */ + /* Return an empty range and no handle on error */ + range->start = 0; + range->count = 0; + *handle = NULL; + + /* Enumerate all root bridge I/O protocol handles */ if ( ( efirc = bs->LocateHandleBuffer ( ByProtocol, &efi_pci_root_bridge_io_protocol_guid, NULL, &num_handles, &handles ) ) != 0 ) { @@ -157,48 +191,87 @@ static int efipci_root_open ( struct pci_device *pci, EFI_HANDLE *handle, goto err_locate; } - /* Look for matching root bridge I/O protocol */ + /* Iterate over all root bridge I/O protocols */ for ( i = 0 ; i < num_handles ; i++ ) { - *handle = handles[i]; - if ( ( efirc = bs->OpenProtocol ( *handle, - &efi_pci_root_bridge_io_protocol_guid, - &u.interface, efi_image_handle, *handle, - EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBGC ( pci, "EFIPCI " PCI_FMT " cannot open %s: %s\n", - PCI_ARGS ( pci ), efi_handle_name ( *handle ), - strerror ( rc ) ); + + /* Get matching or closest range for this root bridge */ + if ( ( rc = efipci_discover_one ( pci, handles[i], + &tmp ) ) != 0 ) continue; + + /* Check for a matching or new closest range */ + index = ( pci->busdevfn - tmp.start ); + if ( ( index < tmp.count ) || ( index > best ) ) { + range->start = tmp.start; + range->count = tmp.count; + best = index; } - if ( efipci_root_match ( pci, *handle, u.root ) == 0 ) { - *root = u.root; - bs->FreePool ( handles ); - return 0; + + /* Stop if this range contains the target bus:dev.fn address */ + if ( index < tmp.count ) { + *handle = handles[i]; + break; } - bs->CloseProtocol ( *handle, - &efi_pci_root_bridge_io_protocol_guid, - efi_image_handle, *handle ); } - DBGC ( pci, "EFIPCI " PCI_FMT " found no root bridge\n", - PCI_ARGS ( pci ) ); - rc = -ENOENT; + /* Check for a range containing the target bus:dev.fn address */ + if ( ! *handle ) { + rc = -ENOENT; + goto err_range; + } + + /* Success */ + rc = 0; + + err_range: bs->FreePool ( handles ); err_locate: return rc; } /** - * Close EFI PCI root bridge I/O protocol + * Find next PCI bus:dev.fn address range in system * - * @v handle EFI PCI root bridge handle + * @v busdevfn Starting PCI bus:dev.fn address + * @v range PCI bus:dev.fn address range to fill in */ -static void efipci_root_close ( EFI_HANDLE handle ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; +static void efipci_discover ( uint32_t busdevfn, struct pci_range *range ) { + struct pci_device pci; + EFI_HANDLE handle; + + /* Find range */ + memset ( &pci, 0, sizeof ( pci ) ); + pci_init ( &pci, busdevfn ); + efipci_discover_any ( &pci, range, &handle ); +} + +/** + * Open EFI PCI root bridge I/O protocol for ephemeral use + * + * @v pci PCI device + * @ret handle EFI PCI root bridge handle + * @ret root EFI PCI root bridge I/O protocol, or NULL if not found + * @ret rc Return status code + */ +static int efipci_root_open ( struct pci_device *pci, EFI_HANDLE *handle, + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL **root ) { + struct pci_range tmp; + int rc; + + /* Find matching root bridge I/O protocol handle */ + if ( ( rc = efipci_discover_any ( pci, &tmp, handle ) ) != 0 ) + return rc; - /* Close protocol */ - bs->CloseProtocol ( handle, &efi_pci_root_bridge_io_protocol_guid, - efi_image_handle, handle ); + /* Open PCI root bridge I/O protocol */ + if ( ( rc = efi_open ( *handle, &efi_pci_root_bridge_io_protocol_guid, + root ) ) != 0 ) { + DBGC ( pci, "EFIPCI " PCI_FMT " cannot open %s: %s\n", + PCI_ARGS ( pci ), efi_handle_name ( *handle ), + strerror ( rc ) ); + return rc; + } + + return 0; } /** @@ -234,7 +307,7 @@ int efipci_read ( struct pci_device *pci, unsigned long location, /* Open root bridge */ if ( ( rc = efipci_root_open ( pci, &handle, &root ) ) != 0 ) - goto err_root; + return rc; /* Read from configuration space */ if ( ( efirc = root->Pci.Read ( root, EFIPCI_WIDTH ( location ), @@ -244,13 +317,10 @@ int efipci_read ( struct pci_device *pci, unsigned long location, DBGC ( pci, "EFIPCI " PCI_FMT " config read from offset %02lx " "failed: %s\n", PCI_ARGS ( pci ), EFIPCI_OFFSET ( location ), strerror ( rc ) ); - goto err_read; + return rc; } - err_read: - efipci_root_close ( handle ); - err_root: - return rc; + return 0; } /** @@ -270,7 +340,7 @@ int efipci_write ( struct pci_device *pci, unsigned long location, /* Open root bridge */ if ( ( rc = efipci_root_open ( pci, &handle, &root ) ) != 0 ) - goto err_root; + return rc; /* Read from configuration space */ if ( ( efirc = root->Pci.Write ( root, EFIPCI_WIDTH ( location ), @@ -280,13 +350,10 @@ int efipci_write ( struct pci_device *pci, unsigned long location, DBGC ( pci, "EFIPCI " PCI_FMT " config write to offset %02lx " "failed: %s\n", PCI_ARGS ( pci ), EFIPCI_OFFSET ( location ), strerror ( rc ) ); - goto err_write; + return rc; } - err_write: - efipci_root_close ( handle ); - err_root: - return rc; + return 0; } /** @@ -357,12 +424,12 @@ void * efipci_ioremap ( struct pci_device *pci, unsigned long bus_addr, } err_config: - efipci_root_close ( handle ); err_root: return ioremap ( bus_addr, len ); } -PROVIDE_PCIAPI_INLINE ( efi, pci_discover ); +PROVIDE_PCIAPI_INLINE ( efi, pci_can_probe ); +PROVIDE_PCIAPI ( efi, pci_discover, efipci_discover ); PROVIDE_PCIAPI_INLINE ( efi, pci_read_config_byte ); PROVIDE_PCIAPI_INLINE ( efi, pci_read_config_word ); PROVIDE_PCIAPI_INLINE ( efi, pci_read_config_dword ); @@ -370,6 +437,7 @@ PROVIDE_PCIAPI_INLINE ( efi, pci_write_config_byte ); PROVIDE_PCIAPI_INLINE ( efi, pci_write_config_word ); PROVIDE_PCIAPI_INLINE ( efi, pci_write_config_dword ); PROVIDE_PCIAPI ( efi, pci_ioremap, efipci_ioremap ); +PROVIDE_PCIAPI_RUNTIME ( efi, PCIAPI_PRIORITY_EFI ); /****************************************************************************** * @@ -389,7 +457,7 @@ PROVIDE_PCIAPI ( efi, pci_ioremap, efipci_ioremap ); * @ret rc Return status code */ static int efipci_dma_map ( struct dma_device *dma, struct dma_mapping *map, - physaddr_t addr, size_t len, int flags ) { + void *addr, size_t len, int flags ) { struct efi_pci_device *efipci = container_of ( dma, struct efi_pci_device, pci.dma ); struct pci_device *pci = &efipci->pci; @@ -398,6 +466,7 @@ static int efipci_dma_map ( struct dma_device *dma, struct dma_mapping *map, EFI_PHYSICAL_ADDRESS bus; UINTN count; VOID *mapping; + physaddr_t phys; EFI_STATUS efirc; int rc; @@ -420,18 +489,19 @@ static int efipci_dma_map ( struct dma_device *dma, struct dma_mapping *map, } /* Map buffer (if non-zero length) */ + phys = virt_to_phys ( addr ); count = len; if ( len ) { - if ( ( efirc = pci_io->Map ( pci_io, op, phys_to_virt ( addr ), - &count, &bus, &mapping ) ) != 0 ) { + if ( ( efirc = pci_io->Map ( pci_io, op, addr, &count, &bus, + &mapping ) ) != 0 ) { rc = -EEFI ( efirc ); - DBGC ( pci, "EFIPCI " PCI_FMT " cannot map %08lx+%zx: " + DBGC ( pci, "EFIPCI " PCI_FMT " cannot map %p+%zx: " "%s\n", PCI_ARGS ( pci ), addr, len, strerror ( rc ) ); goto err_map; } } else { - bus = addr; + bus = phys; mapping = NULL; } @@ -442,14 +512,14 @@ static int efipci_dma_map ( struct dma_device *dma, struct dma_mapping *map, */ if ( count != len ) { DBGC ( pci, "EFIPCI " PCI_FMT " attempted split mapping for " - "%08lx+%zx\n", PCI_ARGS ( pci ), addr, len ); + "%p+%zx\n", PCI_ARGS ( pci ), addr, len ); rc = -ENOTSUP; goto err_len; } /* Populate mapping */ map->dma = dma; - map->offset = ( bus - addr ); + map->offset = ( bus - phys ); map->token = mapping; /* Increment mapping count (for debugging) */ @@ -469,9 +539,10 @@ static int efipci_dma_map ( struct dma_device *dma, struct dma_mapping *map, * * @v dma DMA device * @v map DMA mapping + * @v len Used length */ static void efipci_dma_unmap ( struct dma_device *dma, - struct dma_mapping *map ) { + struct dma_mapping *map, size_t len __unused ) { struct efi_pci_device *efipci = container_of ( dma, struct efi_pci_device, pci.dma ); EFI_PCI_IO_PROTOCOL *pci_io = efipci->io; @@ -528,8 +599,7 @@ static void * efipci_dma_alloc ( struct dma_device *dma, memset ( addr, 0, ( pages * EFI_PAGE_SIZE ) ); /* Map buffer */ - if ( ( rc = efipci_dma_map ( dma, map, virt_to_phys ( addr ), - ( pages * EFI_PAGE_SIZE ), + if ( ( rc = efipci_dma_map ( dma, map, addr, ( pages * EFI_PAGE_SIZE ), DMA_BI ) ) != 0 ) goto err_map; @@ -539,7 +609,7 @@ static void * efipci_dma_alloc ( struct dma_device *dma, return addr; - efipci_dma_unmap ( dma, map ); + efipci_dma_unmap ( dma, map, len ); err_map: pci_io->FreeBuffer ( pci_io, pages, addr ); err_alloc: @@ -565,7 +635,7 @@ static void efipci_dma_free ( struct dma_device *dma, struct dma_mapping *map, pages = ( ( len + EFI_PAGE_SIZE - 1 ) / EFI_PAGE_SIZE ); /* Unmap buffer */ - efipci_dma_unmap ( dma, map ); + efipci_dma_unmap ( dma, map, len ); /* Free buffer */ pci_io->FreeBuffer ( pci_io, pages, addr ); @@ -576,38 +646,6 @@ static void efipci_dma_free ( struct dma_device *dma, struct dma_mapping *map, } /** - * Allocate and map DMA-coherent buffer from external (user) memory - * - * @v dma DMA device - * @v map DMA mapping to fill in - * @v len Length of buffer - * @v align Physical alignment - * @ret addr Buffer address, or NULL on error - */ -static userptr_t efipci_dma_umalloc ( struct dma_device *dma, - struct dma_mapping *map, - size_t len, size_t align ) { - void *addr; - - addr = efipci_dma_alloc ( dma, map, len, align ); - return virt_to_user ( addr ); -} - -/** - * Unmap and free DMA-coherent buffer from external (user) memory - * - * @v dma DMA device - * @v map DMA mapping - * @v addr Buffer address - * @v len Length of buffer - */ -static void efipci_dma_ufree ( struct dma_device *dma, struct dma_mapping *map, - userptr_t addr, size_t len ) { - - efipci_dma_free ( dma, map, user_to_virt ( addr, 0 ), len ); -} - -/** * Set addressable space mask * * @v dma DMA device @@ -645,8 +683,8 @@ static struct dma_operations efipci_dma_operations = { .unmap = efipci_dma_unmap, .alloc = efipci_dma_alloc, .free = efipci_dma_free, - .umalloc = efipci_dma_umalloc, - .ufree = efipci_dma_ufree, + .umalloc = efipci_dma_alloc, + .ufree = efipci_dma_free, .set_mask = efipci_dma_set_mask, }; @@ -658,44 +696,35 @@ static struct dma_operations efipci_dma_operations = { */ /** - * Open EFI PCI device + * Get EFI PCI device information * * @v device EFI device handle - * @v attributes Protocol opening attributes * @v efipci EFI PCI device to fill in * @ret rc Return status code */ -int efipci_open ( EFI_HANDLE device, UINT32 attributes, - struct efi_pci_device *efipci ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - union { - EFI_PCI_IO_PROTOCOL *pci_io; - void *interface; - } pci_io; +int efipci_info ( EFI_HANDLE device, struct efi_pci_device *efipci ) { + EFI_PCI_IO_PROTOCOL *pci_io; UINTN pci_segment, pci_bus, pci_dev, pci_fn; unsigned int busdevfn; EFI_STATUS efirc; int rc; /* See if device is a PCI device */ - if ( ( efirc = bs->OpenProtocol ( device, &efi_pci_io_protocol_guid, - &pci_io.interface, efi_image_handle, - device, attributes ) ) != 0 ) { - rc = -EEFI_PCI ( efirc ); + if ( ( rc = efi_open ( device, &efi_pci_io_protocol_guid, + &pci_io ) ) != 0 ) { DBGCP ( device, "EFIPCI %s cannot open PCI protocols: %s\n", efi_handle_name ( device ), strerror ( rc ) ); - goto err_open_protocol; + return rc; } - efipci->io = pci_io.pci_io; + efipci->io = pci_io; /* Get PCI bus:dev.fn address */ - if ( ( efirc = pci_io.pci_io->GetLocation ( pci_io.pci_io, &pci_segment, - &pci_bus, &pci_dev, - &pci_fn ) ) != 0 ) { + if ( ( efirc = pci_io->GetLocation ( pci_io, &pci_segment, &pci_bus, + &pci_dev, &pci_fn ) ) != 0 ) { rc = -EEFI ( efirc ); DBGC ( device, "EFIPCI %s could not get PCI location: %s\n", efi_handle_name ( device ), strerror ( rc ) ); - goto err_get_location; + return rc; } busdevfn = PCI_BUSDEVFN ( pci_segment, pci_bus, pci_dev, pci_fn ); pci_init ( &efipci->pci, busdevfn ); @@ -709,63 +738,20 @@ int efipci_open ( EFI_HANDLE device, UINT32 attributes, * support I/O cycles). Work around any such platforms by * enabling bits individually and simply ignoring any errors. */ - pci_io.pci_io->Attributes ( pci_io.pci_io, - EfiPciIoAttributeOperationEnable, - EFI_PCI_IO_ATTRIBUTE_IO, NULL ); - pci_io.pci_io->Attributes ( pci_io.pci_io, - EfiPciIoAttributeOperationEnable, - EFI_PCI_IO_ATTRIBUTE_MEMORY, NULL ); - pci_io.pci_io->Attributes ( pci_io.pci_io, - EfiPciIoAttributeOperationEnable, - EFI_PCI_IO_ATTRIBUTE_BUS_MASTER, NULL ); + pci_io->Attributes ( pci_io, EfiPciIoAttributeOperationEnable, + EFI_PCI_IO_ATTRIBUTE_IO, NULL ); + pci_io->Attributes ( pci_io, EfiPciIoAttributeOperationEnable, + EFI_PCI_IO_ATTRIBUTE_MEMORY, NULL ); + pci_io->Attributes ( pci_io, EfiPciIoAttributeOperationEnable, + EFI_PCI_IO_ATTRIBUTE_BUS_MASTER, NULL ); /* Populate PCI device */ if ( ( rc = pci_read_config ( &efipci->pci ) ) != 0 ) { DBGC ( device, "EFIPCI " PCI_FMT " cannot read PCI " "configuration: %s\n", PCI_ARGS ( &efipci->pci ), strerror ( rc ) ); - goto err_pci_read_config; - } - - return 0; - - err_pci_read_config: - err_get_location: - bs->CloseProtocol ( device, &efi_pci_io_protocol_guid, - efi_image_handle, device ); - err_open_protocol: - return rc; -} - -/** - * Close EFI PCI device - * - * @v device EFI device handle - */ -void efipci_close ( EFI_HANDLE device ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - - bs->CloseProtocol ( device, &efi_pci_io_protocol_guid, - efi_image_handle, device ); -} - -/** - * Get EFI PCI device information - * - * @v device EFI device handle - * @v efipci EFI PCI device to fill in - * @ret rc Return status code - */ -int efipci_info ( EFI_HANDLE device, struct efi_pci_device *efipci ) { - int rc; - - /* Open PCI device, if possible */ - if ( ( rc = efipci_open ( device, EFI_OPEN_PROTOCOL_GET_PROTOCOL, - efipci ) ) != 0 ) return rc; - - /* Close PCI device */ - efipci_close ( device ); + } return 0; } @@ -817,6 +803,26 @@ static int efipci_supported ( EFI_HANDLE device ) { } /** + * Exclude existing drivers + * + * @v device EFI device handle + * @ret rc Return status code + */ +static int efipci_exclude ( EFI_HANDLE device ) { + EFI_GUID *protocol = &efi_pci_io_protocol_guid; + int rc; + + /* Exclude existing PCI I/O protocol drivers */ + if ( ( rc = efi_driver_exclude ( device, protocol ) ) != 0 ) { + DBGC ( device, "EFIPCI %s could not exclude drivers: %s\n", + efi_handle_name ( device ), strerror ( rc ) ); + return rc; + } + + return 0; +} + +/** * Attach driver to device * * @v efidev EFI device @@ -834,10 +840,13 @@ static int efipci_start ( struct efi_device *efidev ) { goto err_alloc; } - /* Open PCI device */ - if ( ( rc = efipci_open ( device, ( EFI_OPEN_PROTOCOL_BY_DRIVER | - EFI_OPEN_PROTOCOL_EXCLUSIVE ), - efipci ) ) != 0 ) { + /* Get PCI device information */ + if ( ( rc = efipci_info ( device, efipci ) ) != 0 ) + goto err_info; + + /* Open PCI I/O protocol */ + if ( ( rc = efi_open_by_driver ( device, &efi_pci_io_protocol_guid, + &efipci->io ) ) != 0 ) { DBGC ( device, "EFIPCI %s could not open PCI device: %s\n", efi_handle_name ( device ), strerror ( rc ) ); DBGC_EFI_OPENERS ( device, device, &efi_pci_io_protocol_guid ); @@ -872,8 +881,9 @@ static int efipci_start ( struct efi_device *efidev ) { err_probe: list_del ( &efipci->pci.dev.siblings ); err_find_driver: - efipci_close ( device ); + efi_close_by_driver ( device, &efi_pci_io_protocol_guid ); err_open: + err_info: free ( efipci ); err_alloc: return rc; @@ -892,14 +902,15 @@ static void efipci_stop ( struct efi_device *efidev ) { list_del ( &efipci->pci.dev.siblings ); assert ( efipci->pci.dma.mapped == 0 ); assert ( efipci->pci.dma.allocated == 0 ); - efipci_close ( device ); + efi_close_by_driver ( device, &efi_pci_io_protocol_guid ); free ( efipci ); } /** EFI PCI driver */ -struct efi_driver efipci_driver __efi_driver ( EFI_DRIVER_NORMAL ) = { +struct efi_driver efipci_driver __efi_driver ( EFI_DRIVER_HARDWARE ) = { .name = "PCI", .supported = efipci_supported, + .exclude = efipci_exclude, .start = efipci_start, .stop = efipci_stop, }; |
