Skip to content

Commit 0e3ab60

Browse files
committed
[efi] Restructure EFI driver model
Provide a single instance of EFI_DRIVER_BINDING_PROTOCOL (attached to our image handle); this matches the expectations scattered throughout the EFI specification. Open the underlying hardware device using EFI_OPEN_PROTOCOL_BY_DRIVER and EFI_OPEN_PROTOCOL_EXCLUSIVE, to prevent other drivers from attaching to the same device. Do not automatically connect to devices when being loaded as a driver; leave this task to the platform firmware (or to the user, if loading directly from the EFI shell). When running as an application, forcibly disconnect any existing drivers from devices that we want to control, and reconnect them on exit. Provide a meaningful driver version number (based on the build timestamp), to allow platform firmware to automatically load newer versions of iPXE drivers if multiple drivers are present. Include device paths within debug messages where possible, to aid in debugging. Signed-off-by: Michael Brown <mcb30@ipxe.org>
1 parent f2c116f commit 0e3ab60

File tree

7 files changed

+582
-486
lines changed

7 files changed

+582
-486
lines changed

src/arch/x86/prefix/efiprefix.c

+35
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ FILE_LICENCE ( GPL2_OR_LATER );
2121

2222
#include <stdlib.h>
2323
#include <errno.h>
24+
#include <ipxe/device.h>
2425
#include <ipxe/efi/efi.h>
26+
#include <ipxe/efi/efi_driver.h>
2527

2628
/**
2729
* EFI entry point
@@ -47,6 +49,39 @@ EFI_STATUS EFIAPI _efi_start ( EFI_HANDLE image_handle,
4749

4850
err_main:
4951
efi_loaded_image->Unload ( image_handle );
52+
efi_driver_reconnect_all();
5053
err_init:
5154
return efirc;
5255
}
56+
57+
/**
58+
* Probe EFI root bus
59+
*
60+
* @v rootdev EFI root device
61+
*/
62+
static int efi_probe ( struct root_device *rootdev __unused ) {
63+
64+
return efi_driver_connect_all();
65+
}
66+
67+
/**
68+
* Remove EFI root bus
69+
*
70+
* @v rootdev EFI root device
71+
*/
72+
static void efi_remove ( struct root_device *rootdev __unused ) {
73+
74+
efi_driver_disconnect_all();
75+
}
76+
77+
/** EFI root device driver */
78+
static struct root_driver efi_root_driver = {
79+
.probe = efi_probe,
80+
.remove = efi_remove,
81+
};
82+
83+
/** EFI root device */
84+
struct root_device efi_root_device __root_device = {
85+
.dev = { .name = "EFI" },
86+
.driver = &efi_root_driver,
87+
};

src/include/ipxe/efi/efi_driver.h

+35-26
Original file line numberDiff line numberDiff line change
@@ -8,43 +8,52 @@
88

99
FILE_LICENCE ( GPL2_OR_LATER );
1010

11+
#include <ipxe/tables.h>
1112
#include <ipxe/efi/efi.h>
12-
#include <ipxe/efi/Protocol/DriverBinding.h>
13-
#include <ipxe/efi/Protocol/ComponentName2.h>
1413
#include <ipxe/efi/Protocol/DevicePath.h>
1514

1615
/** An EFI driver */
1716
struct efi_driver {
1817
/** Name */
1918
const char *name;
20-
/** EFI name */
21-
CHAR16 wname[32];
22-
/** EFI driver binding protocol */
23-
EFI_DRIVER_BINDING_PROTOCOL driver;
24-
/** EFI component name protocol */
25-
EFI_COMPONENT_NAME2_PROTOCOL wtf;
19+
/**
20+
* Check if driver supports device
21+
*
22+
* @v device Device
23+
* @ret rc Return status code
24+
*/
25+
int ( * supported ) ( EFI_HANDLE device );
26+
/**
27+
* Attach driver to device
28+
*
29+
* @v device Device
30+
* @ret rc Return status code
31+
*/
32+
int ( * start ) ( EFI_HANDLE device );
33+
/**
34+
* Detach driver from device
35+
*
36+
* @v device Device
37+
*/
38+
void ( * stop ) ( EFI_HANDLE device );
2639
};
2740

28-
/** Initialise an EFI driver
29-
*
30-
* @v name Driver name
31-
* @v supported Device supported method
32-
* @v start Device start method
33-
* @v stop Device stop method
34-
*/
35-
#define EFI_DRIVER_INIT( _name, _supported, _start, _stop ) { \
36-
.name = _name, \
37-
.driver = { \
38-
.Supported = _supported, \
39-
.Start = _start, \
40-
.Stop = _stop, \
41-
.Version = 0x10, \
42-
} }
41+
/** EFI driver table */
42+
#define EFI_DRIVERS __table ( struct efi_driver, "efi_drivers" )
43+
44+
/** Declare an EFI driver */
45+
#define __efi_driver( order ) __table_entry ( EFI_DRIVERS, order )
46+
47+
#define EFI_DRIVER_EARLY 01 /**< Early drivers */
48+
#define EFI_DRIVER_NORMAL 02 /**< Normal drivers */
49+
#define EFI_DRIVER_LATE 03 /**< Late drivers */
4350

4451
extern EFI_DEVICE_PATH_PROTOCOL *
4552
efi_devpath_end ( EFI_DEVICE_PATH_PROTOCOL *path );
46-
47-
extern int efi_driver_install ( struct efi_driver *efidrv );
48-
extern void efi_driver_uninstall ( struct efi_driver *efidrv );
53+
extern int efi_driver_install ( void );
54+
extern void efi_driver_uninstall ( void );
55+
extern int efi_driver_connect_all ( void );
56+
extern void efi_driver_disconnect_all ( void );
57+
extern void efi_driver_reconnect_all ( void );
4958

5059
#endif /* _IPXE_EFI_DRIVER_H */

src/include/ipxe/efi/efi_pci.h

+3-7
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ static inline EFIAPI uint64_t LShiftU64 ( UINT64 value, UINTN shift ) {
1717
return ( value << shift );
1818
}
1919

20-
struct efi_driver;
2120
struct device;
2221

2322
/** An EFI PCI device */
@@ -32,20 +31,17 @@ struct efi_pci_device {
3231
EFI_PCI_IO_PROTOCOL *pci_io;
3332
/** Device path */
3433
EFI_DEVICE_PATH_PROTOCOL *path;
35-
/** EFI driver */
36-
struct efi_driver *efidrv;
3734
};
3835

39-
extern struct efi_pci_device * efipci_create ( struct efi_driver *efidrv,
40-
EFI_HANDLE device );
36+
extern int efipci_create ( EFI_HANDLE device, UINT32 attributes,
37+
struct efi_pci_device **efipci );
4138
extern int efipci_enable ( struct efi_pci_device *efipci );
4239
extern struct efi_pci_device * efipci_find_efi ( EFI_HANDLE device );
4340
extern struct efi_pci_device * efipci_find ( struct device *dev );
4441
extern int efipci_child_add ( struct efi_pci_device *efipci,
4542
EFI_HANDLE device );
4643
extern void efipci_child_del ( struct efi_pci_device *efipci,
4744
EFI_HANDLE device );
48-
extern void efipci_destroy ( struct efi_driver *efidrv,
49-
struct efi_pci_device *efipci );
45+
extern void efipci_destroy ( struct efi_pci_device *efipci );
5046

5147
#endif /* _IPXE_EFI_PCI_H */

0 commit comments

Comments
 (0)