summaryrefslogtreecommitdiffstats
path: root/src/interface/efi/efi_pci.c
diff options
context:
space:
mode:
authorMichael Brown2011-03-15 17:55:04 +0100
committerMichael Brown2011-03-15 17:59:19 +0100
commitb9326c365520806978b6ab9b8532cbc983f36da1 (patch)
treee4babeb89e442fca60d6841c93fa9af79312368c /src/interface/efi/efi_pci.c
parent[romprefix] Use correct size for PMM allocation of image source block (diff)
downloadipxe-b9326c365520806978b6ab9b8532cbc983f36da1.tar.gz
ipxe-b9326c365520806978b6ab9b8532cbc983f36da1.tar.xz
ipxe-b9326c365520806978b6ab9b8532cbc983f36da1.zip
[efi] Mark SNP devices as children of EFI PCI device
Re-open the EFI_PCI_IO_PROTOCOL specifying an Attributes value of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER. This causes the SNP devices to be marked as children of the EFI PCI device (as shown in the "devtree" command). On at least one IBM blade system, this is required in order to have the relevant drivers automatically attach to the SNP controller at device creation time. Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/interface/efi/efi_pci.c')
-rw-r--r--src/interface/efi/efi_pci.c49
1 files changed, 49 insertions, 0 deletions
diff --git a/src/interface/efi/efi_pci.c b/src/interface/efi/efi_pci.c
index d866e30e..3b393fcb 100644
--- a/src/interface/efi/efi_pci.c
+++ b/src/interface/efi/efi_pci.c
@@ -139,6 +139,7 @@ struct efi_pci_device * efipci_create ( struct efi_driver *efidrv,
if ( ! efipci )
goto err_zalloc;
efipci->device = device;
+ efipci->efidrv = efidrv;
/* See if device is a PCI device */
if ( ( efirc = bs->OpenProtocol ( device,
@@ -263,6 +264,54 @@ struct efi_pci_device * efipci_find ( struct device *dev ) {
}
/**
+ * Add EFI device as child of EFI PCI device
+ *
+ * @v efipci EFI PCI device
+ * @v device EFI child device
+ * @ret efirc EFI status code
+ */
+EFI_STATUS efipci_child_add ( struct efi_pci_device *efipci,
+ EFI_HANDLE device ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ struct efi_driver *efidrv = efipci->efidrv;
+ union {
+ EFI_PCI_IO_PROTOCOL *pci_io;
+ void *interface;
+ } pci_io;
+ EFI_STATUS efirc;
+
+ /* Re-open the PCI_IO_PROTOCOL */
+ if ( ( efirc = bs->OpenProtocol ( efipci->device,
+ &efi_pci_io_protocol_guid,
+ &pci_io.interface,
+ efidrv->driver.DriverBindingHandle,
+ device,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ ) ) != 0 ) {
+ DBGC ( efipci, "EFIPCI " PCI_FMT " could not add child: %s\n",
+ PCI_ARGS ( &efipci->pci ), efi_strerror ( efirc ) );
+ return efirc;
+ }
+
+ return 0;
+}
+
+/**
+ * Remove EFI device as child of PCI device
+ *
+ * @v efipci EFI PCI device
+ * @v device EFI child device
+ * @ret efirc EFI status code
+ */
+void efipci_child_del ( struct efi_pci_device *efipci, EFI_HANDLE device ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ struct efi_driver *efidrv = efipci->efidrv;
+
+ bs->CloseProtocol ( efipci->device, &efi_pci_io_protocol_guid,
+ efidrv->driver.DriverBindingHandle, device );
+}
+
+/**
* Destroy EFI PCI device
*
* @v efidrv EFI driver