summaryrefslogtreecommitdiffstats
path: root/src/interface/efi/efi_bofm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/interface/efi/efi_bofm.c')
-rw-r--r--src/interface/efi/efi_bofm.c202
1 files changed, 79 insertions, 123 deletions
diff --git a/src/interface/efi/efi_bofm.c b/src/interface/efi/efi_bofm.c
index 4982b22cc..2a258a9b5 100644
--- a/src/interface/efi/efi_bofm.c
+++ b/src/interface/efi/efi_bofm.c
@@ -21,7 +21,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
#include <errno.h>
#include <ipxe/bofm.h>
-#include <ipxe/init.h>
#include <ipxe/efi/efi.h>
#include <ipxe/efi/efi_pci.h>
#include <ipxe/efi/efi_driver.h>
@@ -156,17 +155,10 @@ static EFI_GUID bofm2_protocol_guid =
/**
* Check if device is supported
*
- * @v driver EFI driver
* @v device EFI device
- * @v child Path to child device, if any
- * @ret efirc EFI status code
+ * @ret rc Return status code
*/
-static EFI_STATUS EFIAPI
-efi_bofm_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver,
- EFI_HANDLE device,
- EFI_DEVICE_PATH_PROTOCOL *child ) {
- struct efi_driver *efidrv =
- container_of ( driver, struct efi_driver, driver );
+static int efi_bofm_supported ( EFI_HANDLE device ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
union {
IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL *bofm1;
@@ -176,19 +168,24 @@ efi_bofm_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver,
EFI_STATUS efirc;
int rc;
- DBGCP ( efidrv, "EFIBOFM DRIVER_SUPPORTED %p (%p)\n", device, child );
+ /* Do nothing if we are already driving this device */
+ efipci = efipci_find_efi ( device );
+ if ( efipci ) {
+ DBGCP ( device, "EFIBOFM %p %s already started\n",
+ device, efi_devpath_text ( efipci->path ) );
+ rc = -EALREADY;
+ goto err_already_started;
+ }
/* Create corresponding PCI device, if any */
- efipci = efipci_create ( efidrv, device );
- if ( ! efipci ) {
- rc = -ENOTSUP;
- goto err_not_pci;
- }
+ if ( ( rc = efipci_create ( device, EFI_OPEN_PROTOCOL_GET_PROTOCOL,
+ &efipci ) ) != 0 )
+ goto err_create;
/* Look for a BOFM driver */
if ( ( rc = bofm_find_driver ( &efipci->pci ) ) != 0 ) {
- DBGCP ( efidrv, "EFIBOFM " PCI_FMT " has no driver\n",
- PCI_ARGS ( &efipci->pci ) );
+ DBGCP ( device, "EFIBOFM %p %s has no driver\n",
+ device, efi_devpath_text ( efipci->path ) );
goto err_no_driver;
}
@@ -196,8 +193,8 @@ efi_bofm_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver,
if ( ( efirc = bs->LocateProtocol ( &bofm1_protocol_guid, NULL,
&bofm1.interface ) ) != 0 ) {
rc = -EEFI ( efirc );
- DBGC ( efidrv, "EFIBOFM " PCI_FMT " cannot find BOFM "
- "protocol\n", PCI_ARGS ( &efipci->pci ) );
+ DBGC ( device, "EFIBOFM %p %s cannot find BOFM protocol\n",
+ device, efi_devpath_text ( efipci->path ) );
goto err_not_bofm;
}
@@ -207,41 +204,36 @@ efi_bofm_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver,
0x00 /* No iSCSI */,
0x02 /* Version */ ))!=0){
rc = -EEFI ( efirc );
- DBGC ( efidrv, "EFIBOFM " PCI_FMT " could not register "
- "support: %s\n", PCI_ARGS ( &efipci->pci ),
+ DBGC ( device, "EFIBOFM %p %s could not register support: %s\n",
+ device, efi_devpath_text ( efipci->path ),
strerror ( rc ) );
goto err_cannot_register;
}
- DBGC ( efidrv, "EFIBOFM " PCI_FMT " is supported by driver \"%s\"\n",
- PCI_ARGS ( &efipci->pci ), efipci->pci.id->name );
+ DBGC ( device, "EFIBOFM %p %s has driver \"%s\"\n", device,
+ efi_devpath_text ( efipci->path ), efipci->pci.id->name );
/* Destroy temporary PCI device */
- efipci_destroy ( efidrv, efipci );
+ efipci_destroy ( efipci );
return 0;
err_cannot_register:
err_not_bofm:
err_no_driver:
- efipci_destroy ( efidrv, efipci );
- err_not_pci:
- return EFIRC ( rc );
+ efipci_destroy ( efipci );
+ err_create:
+ err_already_started:
+ return rc;
}
/**
* Attach driver to device
*
- * @v driver EFI driver
* @v device EFI device
- * @v child Path to child device, if any
- * @ret efirc EFI status code
+ * @ret rc Return status code
*/
-static EFI_STATUS EFIAPI efi_bofm_start ( EFI_DRIVER_BINDING_PROTOCOL *driver,
- EFI_HANDLE device,
- EFI_DEVICE_PATH_PROTOCOL *child ) {
- struct efi_driver *efidrv =
- container_of ( driver, struct efi_driver, driver );
+static int efi_bofm_start ( EFI_HANDLE device ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
union {
IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL *bofm1;
@@ -258,14 +250,19 @@ static EFI_STATUS EFIAPI efi_bofm_start ( EFI_DRIVER_BINDING_PROTOCOL *driver,
EFI_STATUS efirc;
int rc;
- DBGCP ( efidrv, "EFIBOFM DRIVER_START %p (%p)\n", device, child );
+ /* Do nothing if we are already driving this device */
+ efipci = efipci_find_efi ( device );
+ if ( efipci ) {
+ DBGCP ( device, "EFIPCI %p %s already started\n",
+ device, efi_devpath_text ( efipci->path ) );
+ rc = -EALREADY;
+ goto err_already_started;
+ }
/* Create corresponding PCI device */
- efipci = efipci_create ( efidrv, device );
- if ( ! efipci ) {
- rc = -ENOMEM;
+ if ( ( rc = efipci_create ( device, EFI_OPEN_PROTOCOL_GET_PROTOCOL,
+ &efipci ) ) != 0 )
goto err_create;
- }
/* Enable PCI device */
if ( ( rc = efipci_enable ( efipci ) ) != 0 )
@@ -275,51 +272,51 @@ static EFI_STATUS EFIAPI efi_bofm_start ( EFI_DRIVER_BINDING_PROTOCOL *driver,
if ( ( efirc = bs->LocateProtocol ( &bofm1_protocol_guid, NULL,
&bofm1.interface ) ) != 0 ) {
rc = -EEFI ( efirc );
- DBGC ( efidrv, "EFIBOFM " PCI_FMT " cannot find BOFM "
- "protocol\n", PCI_ARGS ( &efipci->pci ) );
+ DBGC ( device, "EFIBOFM %p %s cannot find BOFM protocol\n",
+ device, efi_devpath_text ( efipci->path ) );
goto err_locate_bofm;
}
bofmtab = &bofm1.bofm1->BofmTable;
- DBGC ( efidrv, "EFIBOFM " PCI_FMT " found version 1 BOFM table at "
- "%p+%04x\n", PCI_ARGS ( &efipci->pci ), bofmtab,
+ DBGC ( device, "EFIBOFM %p %s found version 1 BOFM table at %p+%04x\n",
+ device, efi_devpath_text ( efipci->path ), bofmtab,
bofmtab->Parameters.Length );
/* Locate BOFM2 protocol, if available */
if ( ( efirc = bs->LocateProtocol ( &bofm2_protocol_guid, NULL,
&bofm2.interface ) ) == 0 ) {
bofmtab2 = &bofm2.bofm2->BofmTable;
- DBGC ( efidrv, "EFIBOFM " PCI_FMT " found version 2 BOFM table "
- "at %p+%04x\n", PCI_ARGS ( &efipci->pci ), bofmtab2,
- bofmtab2->Parameters.Length );
+ DBGC ( device, "EFIBOFM %p %s found version 2 BOFM table at "
+ "%p+%04x\n", device, efi_devpath_text ( efipci->path ),
+ bofmtab2, bofmtab2->Parameters.Length );
assert ( bofm2.bofm2->RegisterSupport ==
bofm1.bofm1->RegisterSupport );
} else {
- DBGC ( efidrv, "EFIBOFM " PCI_FMT " cannot find BOFM2 "
- "protocol\n", PCI_ARGS ( &efipci->pci ) );
+ DBGC ( device, "EFIBOFM %p %s cannot find BOFM2 protocol\n",
+ device, efi_devpath_text ( efipci->path ) );
/* Not a fatal error; may be a BOFM1-only system */
bofmtab2 = NULL;
}
/* Process BOFM table */
- DBGC2 ( efidrv, "EFIBOFM " PCI_FMT " version 1 before processing:\n",
- PCI_ARGS ( &efipci->pci ) );
- DBGC2_HD ( efidrv, bofmtab, bofmtab->Parameters.Length );
+ DBGC2 ( device, "EFIBOFM %p %s version 1 before processing:\n",
+ device, efi_devpath_text ( efipci->path ) );
+ DBGC2_HD ( device, bofmtab, bofmtab->Parameters.Length );
if ( bofmtab2 ) {
- DBGC2 ( efidrv, "EFIBOFM " PCI_FMT " version 2 before "
- "processing:\n", PCI_ARGS ( &efipci->pci ) );
- DBGC2_HD ( efidrv, bofmtab2, bofmtab2->Parameters.Length );
+ DBGC2 ( device, "EFIBOFM %p %s version 2 before processing:\n",
+ device, efi_devpath_text ( efipci->path ) );
+ DBGC2_HD ( device, bofmtab2, bofmtab2->Parameters.Length );
}
bofmrc = bofm ( virt_to_user ( bofmtab2 ? bofmtab2 : bofmtab ),
&efipci->pci );
- DBGC ( efidrv, "EFIBOFM " PCI_FMT " status %08x\n",
- PCI_ARGS ( &efipci->pci ), bofmrc );
- DBGC2 ( efidrv, "EFIBOFM " PCI_FMT " version 1 after processing:\n",
- PCI_ARGS ( &efipci->pci ) );
- DBGC2_HD ( efidrv, bofmtab, bofmtab->Parameters.Length );
+ DBGC ( device, "EFIBOFM %p %s status %08x\n",
+ device, efi_devpath_text ( efipci->path ), bofmrc );
+ DBGC2 ( device, "EFIBOFM %p %s version 1 after processing:\n",
+ device, efi_devpath_text ( efipci->path ) );
+ DBGC2_HD ( device, bofmtab, bofmtab->Parameters.Length );
if ( bofmtab2 ) {
- DBGC2 ( efidrv, "EFIBOFM " PCI_FMT " version 2 after "
- "processing:\n", PCI_ARGS ( &efipci->pci ) );
- DBGC2_HD ( efidrv, bofmtab2, bofmtab2->Parameters.Length );
+ DBGC2 ( device, "EFIBOFM %p %s version 2 after processing:\n",
+ device, efi_devpath_text ( efipci->path ) );
+ DBGC2_HD ( device, bofmtab2, bofmtab2->Parameters.Length );
}
/* Return BOFM status */
@@ -327,8 +324,9 @@ static EFI_STATUS EFIAPI efi_bofm_start ( EFI_DRIVER_BINDING_PROTOCOL *driver,
if ( ( efirc = bofm2.bofm2->SetStatus ( bofm2.bofm2, device,
FALSE, bofmrc ) ) != 0){
rc = -EEFI ( efirc );
- DBGC ( efidrv, "EFIBOFM " PCI_FMT " could not set "
- "BOFM2 status: %s\n", PCI_ARGS ( &efipci->pci ),
+ DBGC ( device, "EFIBOFM %p %s could not set BOFM2 "
+ "status: %s\n",
+ device, efi_devpath_text ( efipci->path ),
strerror ( rc ) );
goto err_set_status;
}
@@ -336,84 +334,42 @@ static EFI_STATUS EFIAPI efi_bofm_start ( EFI_DRIVER_BINDING_PROTOCOL *driver,
if ( ( efirc = bofm1.bofm1->SetStatus ( bofm1.bofm1, device,
FALSE, bofmrc ) ) != 0){
rc = -EEFI ( efirc );
- DBGC ( efidrv, "EFIBOFM " PCI_FMT " could not set "
- "BOFM status: %s\n", PCI_ARGS ( &efipci->pci ),
+ DBGC ( device, "EFIBOFM %p %s could not set BOFM "
+ "status: %s\n",
+ device, efi_devpath_text ( efipci->path ),
strerror ( rc ) );
goto err_set_status;
}
}
/* Destroy the PCI device anyway; we have no further use for it */
- efipci_destroy ( efidrv, efipci );
+ efipci_destroy ( efipci );
/* BOFM (ab)uses the "start" method to mean "process and exit" */
- return EFI_NOT_READY;
+ return -EAGAIN;
err_set_status:
err_locate_bofm:
err_enable:
- efipci_destroy ( efidrv, efipci );
+ efipci_destroy ( efipci );
err_create:
- return EFIRC ( rc );
+ err_already_started:
+ return rc;
}
/**
* Detach driver from device
*
- * @v driver EFI driver
* @v device EFI device
- * @v num_children Number of child devices
- * @v children List of child devices
- * @ret efirc EFI status code
*/
-static EFI_STATUS EFIAPI efi_bofm_stop ( EFI_DRIVER_BINDING_PROTOCOL *driver,
- EFI_HANDLE device, UINTN num_children,
- EFI_HANDLE *children ) {
- struct efi_driver *efidrv =
- container_of ( driver, struct efi_driver, driver );
-
- DBGCP ( efidrv, "EFIBOFM DRIVER_STOP %p (%ld %p)\n",
- device, ( ( unsigned long ) num_children ), children );
-
- return 0;
+static void efi_bofm_stop ( EFI_HANDLE device __unused ) {
+ /* Nothing to do */
}
/** EFI BOFM driver */
-static struct efi_driver efi_bofm_driver =
- EFI_DRIVER_INIT ( "BOFM",
- efi_bofm_supported, efi_bofm_start, efi_bofm_stop );
-
-/**
- * Install EFI BOFM driver
- *
- */
-static void efi_bofm_driver_startup ( void ) {
- struct efi_driver *efidrv = &efi_bofm_driver;
- int rc;
-
- /* Install driver */
- if ( ( rc = efi_driver_install ( efidrv ) ) != 0 ) {
- DBGC ( efidrv, "EFIBOFM could not install driver: %s\n",
- strerror ( rc ) );
- return;
- }
-
- DBGC ( efidrv, "EFIBOFM driver installed\n" );
-}
-
-/**
- * Shut down EFI BOFM driver
- *
- * @v booting System is shutting down for OS boot
- */
-static void efi_bofm_driver_shutdown ( int booting __unused ) {
- struct efi_driver *efidrv = &efi_bofm_driver;
-
- efi_driver_uninstall ( efidrv );
-}
-
-/** EFI BOFM startup function */
-struct startup_fn startup_bofm __startup_fn ( STARTUP_EARLY ) = {
- .startup = efi_bofm_driver_startup,
- .shutdown = efi_bofm_driver_shutdown,
+struct efi_driver efi_bofm_driver __efi_driver ( EFI_DRIVER_EARLY ) = {
+ .name = "BOFM",
+ .supported = efi_bofm_supported,
+ .start = efi_bofm_start,
+ .stop = efi_bofm_stop,
};