Browse Source

[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>
tags/v1.20.1
Michael Brown 10 years ago
parent
commit
0e3ab6064e

+ 35
- 0
src/arch/x86/prefix/efiprefix.c View File

21
 
21
 
22
 #include <stdlib.h>
22
 #include <stdlib.h>
23
 #include <errno.h>
23
 #include <errno.h>
24
+#include <ipxe/device.h>
24
 #include <ipxe/efi/efi.h>
25
 #include <ipxe/efi/efi.h>
26
+#include <ipxe/efi/efi_driver.h>
25
 
27
 
26
 /**
28
 /**
27
  * EFI entry point
29
  * EFI entry point
47
 
49
 
48
  err_main:
50
  err_main:
49
 	efi_loaded_image->Unload ( image_handle );
51
 	efi_loaded_image->Unload ( image_handle );
52
+	efi_driver_reconnect_all();
50
  err_init:
53
  err_init:
51
 	return efirc;
54
 	return efirc;
52
 }
55
 }
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
+};

+ 35
- 26
src/include/ipxe/efi/efi_driver.h View File

8
 
8
 
9
 FILE_LICENCE ( GPL2_OR_LATER );
9
 FILE_LICENCE ( GPL2_OR_LATER );
10
 
10
 
11
+#include <ipxe/tables.h>
11
 #include <ipxe/efi/efi.h>
12
 #include <ipxe/efi/efi.h>
12
-#include <ipxe/efi/Protocol/DriverBinding.h>
13
-#include <ipxe/efi/Protocol/ComponentName2.h>
14
 #include <ipxe/efi/Protocol/DevicePath.h>
13
 #include <ipxe/efi/Protocol/DevicePath.h>
15
 
14
 
16
 /** An EFI driver */
15
 /** An EFI driver */
17
 struct efi_driver {
16
 struct efi_driver {
18
 	/** Name */
17
 	/** Name */
19
 	const char *name;
18
 	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 );
26
 };
39
 };
27
 
40
 
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 */
43
 
50
 
44
 extern EFI_DEVICE_PATH_PROTOCOL *
51
 extern EFI_DEVICE_PATH_PROTOCOL *
45
 efi_devpath_end ( EFI_DEVICE_PATH_PROTOCOL *path );
52
 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 );
49
 
58
 
50
 #endif /* _IPXE_EFI_DRIVER_H */
59
 #endif /* _IPXE_EFI_DRIVER_H */

+ 3
- 7
src/include/ipxe/efi/efi_pci.h View File

17
 	return ( value << shift );
17
 	return ( value << shift );
18
 }
18
 }
19
 
19
 
20
-struct efi_driver;
21
 struct device;
20
 struct device;
22
 
21
 
23
 /** An EFI PCI device */
22
 /** An EFI PCI device */
32
 	EFI_PCI_IO_PROTOCOL *pci_io;
31
 	EFI_PCI_IO_PROTOCOL *pci_io;
33
 	/** Device path */
32
 	/** Device path */
34
 	EFI_DEVICE_PATH_PROTOCOL *path;
33
 	EFI_DEVICE_PATH_PROTOCOL *path;
35
-	/** EFI driver */
36
-	struct efi_driver *efidrv;
37
 };
34
 };
38
 
35
 
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 );
41
 extern int efipci_enable ( struct efi_pci_device *efipci );
38
 extern int efipci_enable ( struct efi_pci_device *efipci );
42
 extern struct efi_pci_device * efipci_find_efi ( EFI_HANDLE device );
39
 extern struct efi_pci_device * efipci_find_efi ( EFI_HANDLE device );
43
 extern struct efi_pci_device * efipci_find ( struct device *dev );
40
 extern struct efi_pci_device * efipci_find ( struct device *dev );
45
 			      EFI_HANDLE device );
42
 			      EFI_HANDLE device );
46
 extern void efipci_child_del ( struct efi_pci_device *efipci,
43
 extern void efipci_child_del ( struct efi_pci_device *efipci,
47
 			       EFI_HANDLE device );
44
 			       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 );
50
 
46
 
51
 #endif /* _IPXE_EFI_PCI_H */
47
 #endif /* _IPXE_EFI_PCI_H */

+ 79
- 123
src/interface/efi/efi_bofm.c View File

21
 
21
 
22
 #include <errno.h>
22
 #include <errno.h>
23
 #include <ipxe/bofm.h>
23
 #include <ipxe/bofm.h>
24
-#include <ipxe/init.h>
25
 #include <ipxe/efi/efi.h>
24
 #include <ipxe/efi/efi.h>
26
 #include <ipxe/efi/efi_pci.h>
25
 #include <ipxe/efi/efi_pci.h>
27
 #include <ipxe/efi/efi_driver.h>
26
 #include <ipxe/efi/efi_driver.h>
156
 /**
155
 /**
157
  * Check if device is supported
156
  * Check if device is supported
158
  *
157
  *
159
- * @v driver		EFI driver
160
  * @v device		EFI device
158
  * @v device		EFI device
161
- * @v child		Path to child device, if any
162
- * @ret efirc		EFI status code
159
+ * @ret rc		Return status code
163
  */
160
  */
164
-static EFI_STATUS EFIAPI
165
-efi_bofm_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver,
166
-		     EFI_HANDLE device,
167
-		     EFI_DEVICE_PATH_PROTOCOL *child ) {
168
-	struct efi_driver *efidrv =
169
-		container_of ( driver, struct efi_driver, driver );
161
+static int efi_bofm_supported ( EFI_HANDLE device ) {
170
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
162
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
171
 	union {
163
 	union {
172
 		IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL *bofm1;
164
 		IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL *bofm1;
176
 	EFI_STATUS efirc;
168
 	EFI_STATUS efirc;
177
 	int rc;
169
 	int rc;
178
 
170
 
179
-	DBGCP ( efidrv, "EFIBOFM DRIVER_SUPPORTED %p (%p)\n", device, child );
171
+	/* Do nothing if we are already driving this device */
172
+	efipci = efipci_find_efi ( device );
173
+	if ( efipci ) {
174
+		DBGCP ( device, "EFIBOFM %p %s already started\n",
175
+			device, efi_devpath_text ( efipci->path ) );
176
+		rc = -EALREADY;
177
+		goto err_already_started;
178
+	}
180
 
179
 
181
 	/* Create corresponding PCI device, if any */
180
 	/* Create corresponding PCI device, if any */
182
-	efipci = efipci_create ( efidrv, device );
183
-	if ( ! efipci ) {
184
-		rc = -ENOTSUP;
185
-		goto err_not_pci;
186
-	}
181
+	if ( ( rc = efipci_create ( device, EFI_OPEN_PROTOCOL_GET_PROTOCOL,
182
+				    &efipci ) ) != 0 )
183
+		goto err_create;
187
 
184
 
188
 	/* Look for a BOFM driver */
185
 	/* Look for a BOFM driver */
189
 	if ( ( rc = bofm_find_driver ( &efipci->pci ) ) != 0 ) {
186
 	if ( ( rc = bofm_find_driver ( &efipci->pci ) ) != 0 ) {
190
-		DBGCP ( efidrv, "EFIBOFM " PCI_FMT " has no driver\n",
191
-			PCI_ARGS ( &efipci->pci ) );
187
+		DBGCP ( device, "EFIBOFM %p %s has no driver\n",
188
+			device, efi_devpath_text ( efipci->path ) );
192
 		goto err_no_driver;
189
 		goto err_no_driver;
193
 	}
190
 	}
194
 
191
 
196
 	if ( ( efirc = bs->LocateProtocol ( &bofm1_protocol_guid, NULL,
193
 	if ( ( efirc = bs->LocateProtocol ( &bofm1_protocol_guid, NULL,
197
 					    &bofm1.interface ) ) != 0 ) {
194
 					    &bofm1.interface ) ) != 0 ) {
198
 		rc = -EEFI ( efirc );
195
 		rc = -EEFI ( efirc );
199
-		DBGC ( efidrv, "EFIBOFM " PCI_FMT " cannot find BOFM "
200
-		       "protocol\n", PCI_ARGS ( &efipci->pci ) );
196
+		DBGC ( device, "EFIBOFM %p %s cannot find BOFM protocol\n",
197
+		       device, efi_devpath_text ( efipci->path ) );
201
 		goto err_not_bofm;
198
 		goto err_not_bofm;
202
 	}
199
 	}
203
 
200
 
207
 						      0x00 /* No iSCSI */,
204
 						      0x00 /* No iSCSI */,
208
 						      0x02 /* Version */ ))!=0){
205
 						      0x02 /* Version */ ))!=0){
209
 		rc = -EEFI ( efirc );
206
 		rc = -EEFI ( efirc );
210
-		DBGC ( efidrv, "EFIBOFM " PCI_FMT " could not register "
211
-		       "support: %s\n", PCI_ARGS ( &efipci->pci ),
207
+		DBGC ( device, "EFIBOFM %p %s could not register support: %s\n",
208
+		       device, efi_devpath_text ( efipci->path ),
212
 		       strerror ( rc ) );
209
 		       strerror ( rc ) );
213
 		goto err_cannot_register;
210
 		goto err_cannot_register;
214
 	}
211
 	}
215
 
212
 
216
-	DBGC ( efidrv, "EFIBOFM " PCI_FMT " is supported by driver \"%s\"\n",
217
-	       PCI_ARGS ( &efipci->pci ), efipci->pci.id->name );
213
+	DBGC ( device, "EFIBOFM %p %s has driver \"%s\"\n", device,
214
+	       efi_devpath_text ( efipci->path ), efipci->pci.id->name );
218
 
215
 
219
 	/* Destroy temporary PCI device */
216
 	/* Destroy temporary PCI device */
220
-	efipci_destroy ( efidrv, efipci );
217
+	efipci_destroy ( efipci );
221
 
218
 
222
 	return 0;
219
 	return 0;
223
 
220
 
224
  err_cannot_register:
221
  err_cannot_register:
225
  err_not_bofm:
222
  err_not_bofm:
226
  err_no_driver:
223
  err_no_driver:
227
-	efipci_destroy ( efidrv, efipci );
228
- err_not_pci:
229
-	return EFIRC ( rc );
224
+	efipci_destroy ( efipci );
225
+ err_create:
226
+ err_already_started:
227
+	return rc;
230
 }
228
 }
231
 
229
 
232
 /**
230
 /**
233
  * Attach driver to device
231
  * Attach driver to device
234
  *
232
  *
235
- * @v driver		EFI driver
236
  * @v device		EFI device
233
  * @v device		EFI device
237
- * @v child		Path to child device, if any
238
- * @ret efirc		EFI status code
234
+ * @ret rc		Return status code
239
  */
235
  */
240
-static EFI_STATUS EFIAPI efi_bofm_start ( EFI_DRIVER_BINDING_PROTOCOL *driver,
241
-				   EFI_HANDLE device,
242
-				   EFI_DEVICE_PATH_PROTOCOL *child ) {
243
-	struct efi_driver *efidrv =
244
-		container_of ( driver, struct efi_driver, driver );
236
+static int efi_bofm_start ( EFI_HANDLE device ) {
245
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
237
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
246
 	union {
238
 	union {
247
 		IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL *bofm1;
239
 		IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL *bofm1;
258
 	EFI_STATUS efirc;
250
 	EFI_STATUS efirc;
259
 	int rc;
251
 	int rc;
260
 
252
 
261
-	DBGCP ( efidrv, "EFIBOFM DRIVER_START %p (%p)\n", device, child );
253
+	/* Do nothing if we are already driving this device */
254
+	efipci = efipci_find_efi ( device );
255
+	if ( efipci ) {
256
+		DBGCP ( device, "EFIPCI %p %s already started\n",
257
+			device, efi_devpath_text ( efipci->path ) );
258
+		rc = -EALREADY;
259
+		goto err_already_started;
260
+	}
262
 
261
 
263
 	/* Create corresponding PCI device */
262
 	/* Create corresponding PCI device */
264
-	efipci = efipci_create ( efidrv, device );
265
-	if ( ! efipci ) {
266
-		rc = -ENOMEM;
263
+	if ( ( rc = efipci_create ( device, EFI_OPEN_PROTOCOL_GET_PROTOCOL,
264
+				    &efipci ) ) != 0 )
267
 		goto err_create;
265
 		goto err_create;
268
-	}
269
 
266
 
270
 	/* Enable PCI device */
267
 	/* Enable PCI device */
271
 	if ( ( rc = efipci_enable ( efipci ) ) != 0 )
268
 	if ( ( rc = efipci_enable ( efipci ) ) != 0 )
275
 	if ( ( efirc = bs->LocateProtocol ( &bofm1_protocol_guid, NULL,
272
 	if ( ( efirc = bs->LocateProtocol ( &bofm1_protocol_guid, NULL,
276
 					    &bofm1.interface ) ) != 0 ) {
273
 					    &bofm1.interface ) ) != 0 ) {
277
 		rc = -EEFI ( efirc );
274
 		rc = -EEFI ( efirc );
278
-		DBGC ( efidrv, "EFIBOFM " PCI_FMT " cannot find BOFM "
279
-		       "protocol\n", PCI_ARGS ( &efipci->pci ) );
275
+		DBGC ( device, "EFIBOFM %p %s cannot find BOFM protocol\n",
276
+		       device, efi_devpath_text ( efipci->path ) );
280
 		goto err_locate_bofm;
277
 		goto err_locate_bofm;
281
 	}
278
 	}
282
 	bofmtab = &bofm1.bofm1->BofmTable;
279
 	bofmtab = &bofm1.bofm1->BofmTable;
283
-	DBGC ( efidrv, "EFIBOFM " PCI_FMT " found version 1 BOFM table at "
284
-	       "%p+%04x\n", PCI_ARGS ( &efipci->pci ), bofmtab,
280
+	DBGC ( device, "EFIBOFM %p %s found version 1 BOFM table at %p+%04x\n",
281
+	       device, efi_devpath_text ( efipci->path ), bofmtab,
285
 	       bofmtab->Parameters.Length );
282
 	       bofmtab->Parameters.Length );
286
 
283
 
287
 	/* Locate BOFM2 protocol, if available */
284
 	/* Locate BOFM2 protocol, if available */
288
 	if ( ( efirc = bs->LocateProtocol ( &bofm2_protocol_guid, NULL,
285
 	if ( ( efirc = bs->LocateProtocol ( &bofm2_protocol_guid, NULL,
289
 					    &bofm2.interface ) ) == 0 ) {
286
 					    &bofm2.interface ) ) == 0 ) {
290
 		bofmtab2 = &bofm2.bofm2->BofmTable;
287
 		bofmtab2 = &bofm2.bofm2->BofmTable;
291
-		DBGC ( efidrv, "EFIBOFM " PCI_FMT " found version 2 BOFM table "
292
-		       "at %p+%04x\n", PCI_ARGS ( &efipci->pci ), bofmtab2,
293
-		       bofmtab2->Parameters.Length );
288
+		DBGC ( device, "EFIBOFM %p %s found version 2 BOFM table at "
289
+		       "%p+%04x\n", device, efi_devpath_text ( efipci->path ),
290
+		       bofmtab2, bofmtab2->Parameters.Length );
294
 		assert ( bofm2.bofm2->RegisterSupport ==
291
 		assert ( bofm2.bofm2->RegisterSupport ==
295
 			 bofm1.bofm1->RegisterSupport );
292
 			 bofm1.bofm1->RegisterSupport );
296
 	} else {
293
 	} else {
297
-		DBGC ( efidrv, "EFIBOFM " PCI_FMT " cannot find BOFM2 "
298
-		       "protocol\n", PCI_ARGS ( &efipci->pci ) );
294
+		DBGC ( device, "EFIBOFM %p %s cannot find BOFM2 protocol\n",
295
+		       device, efi_devpath_text ( efipci->path ) );
299
 		/* Not a fatal error; may be a BOFM1-only system */
296
 		/* Not a fatal error; may be a BOFM1-only system */
300
 		bofmtab2 = NULL;
297
 		bofmtab2 = NULL;
301
 	}
298
 	}
302
 
299
 
303
 	/* Process BOFM table */
300
 	/* Process BOFM table */
304
-	DBGC2 ( efidrv, "EFIBOFM " PCI_FMT " version 1 before processing:\n",
305
-		PCI_ARGS ( &efipci->pci ) );
306
-	DBGC2_HD ( efidrv, bofmtab, bofmtab->Parameters.Length );
301
+	DBGC2 ( device, "EFIBOFM %p %s version 1 before processing:\n",
302
+		device, efi_devpath_text ( efipci->path ) );
303
+	DBGC2_HD ( device, bofmtab, bofmtab->Parameters.Length );
307
 	if ( bofmtab2 ) {
304
 	if ( bofmtab2 ) {
308
-		DBGC2 ( efidrv, "EFIBOFM " PCI_FMT " version 2 before "
309
-			"processing:\n", PCI_ARGS ( &efipci->pci ) );
310
-		DBGC2_HD ( efidrv, bofmtab2, bofmtab2->Parameters.Length );
305
+		DBGC2 ( device, "EFIBOFM %p %s version 2 before processing:\n",
306
+			device, efi_devpath_text ( efipci->path ) );
307
+		DBGC2_HD ( device, bofmtab2, bofmtab2->Parameters.Length );
311
 	}
308
 	}
312
 	bofmrc = bofm ( virt_to_user ( bofmtab2 ? bofmtab2 : bofmtab ),
309
 	bofmrc = bofm ( virt_to_user ( bofmtab2 ? bofmtab2 : bofmtab ),
313
 			&efipci->pci );
310
 			&efipci->pci );
314
-	DBGC ( efidrv, "EFIBOFM " PCI_FMT " status %08x\n",
315
-	       PCI_ARGS ( &efipci->pci ), bofmrc );
316
-	DBGC2 ( efidrv, "EFIBOFM " PCI_FMT " version 1 after processing:\n",
317
-		PCI_ARGS ( &efipci->pci ) );
318
-	DBGC2_HD ( efidrv, bofmtab, bofmtab->Parameters.Length );
311
+	DBGC ( device, "EFIBOFM %p %s status %08x\n",
312
+	       device, efi_devpath_text ( efipci->path ), bofmrc );
313
+	DBGC2 ( device, "EFIBOFM %p %s version 1 after processing:\n",
314
+		device, efi_devpath_text ( efipci->path ) );
315
+	DBGC2_HD ( device, bofmtab, bofmtab->Parameters.Length );
319
 	if ( bofmtab2 ) {
316
 	if ( bofmtab2 ) {
320
-		DBGC2 ( efidrv, "EFIBOFM " PCI_FMT " version 2 after "
321
-			"processing:\n", PCI_ARGS ( &efipci->pci ) );
322
-		DBGC2_HD ( efidrv, bofmtab2, bofmtab2->Parameters.Length );
317
+		DBGC2 ( device, "EFIBOFM %p %s version 2 after processing:\n",
318
+			device, efi_devpath_text ( efipci->path ) );
319
+		DBGC2_HD ( device, bofmtab2, bofmtab2->Parameters.Length );
323
 	}
320
 	}
324
 
321
 
325
 	/* Return BOFM status */
322
 	/* Return BOFM status */
327
 		if ( ( efirc = bofm2.bofm2->SetStatus ( bofm2.bofm2, device,
324
 		if ( ( efirc = bofm2.bofm2->SetStatus ( bofm2.bofm2, device,
328
 							FALSE, bofmrc ) ) != 0){
325
 							FALSE, bofmrc ) ) != 0){
329
 			rc = -EEFI ( efirc );
326
 			rc = -EEFI ( efirc );
330
-			DBGC ( efidrv, "EFIBOFM " PCI_FMT " could not set "
331
-			       "BOFM2 status: %s\n", PCI_ARGS ( &efipci->pci ),
327
+			DBGC ( device, "EFIBOFM %p %s could not set BOFM2 "
328
+			       "status: %s\n",
329
+			       device, efi_devpath_text ( efipci->path ),
332
 			       strerror ( rc ) );
330
 			       strerror ( rc ) );
333
 			goto err_set_status;
331
 			goto err_set_status;
334
 		}
332
 		}
336
 		if ( ( efirc = bofm1.bofm1->SetStatus ( bofm1.bofm1, device,
334
 		if ( ( efirc = bofm1.bofm1->SetStatus ( bofm1.bofm1, device,
337
 							FALSE, bofmrc ) ) != 0){
335
 							FALSE, bofmrc ) ) != 0){
338
 			rc = -EEFI ( efirc );
336
 			rc = -EEFI ( efirc );
339
-			DBGC ( efidrv, "EFIBOFM " PCI_FMT " could not set "
340
-			       "BOFM status: %s\n", PCI_ARGS ( &efipci->pci ),
337
+			DBGC ( device, "EFIBOFM %p %s could not set BOFM "
338
+			       "status: %s\n",
339
+			       device, efi_devpath_text ( efipci->path ),
341
 			       strerror ( rc ) );
340
 			       strerror ( rc ) );
342
 			goto err_set_status;
341
 			goto err_set_status;
343
 		}
342
 		}
344
 	}
343
 	}
345
 
344
 
346
 	/* Destroy the PCI device anyway; we have no further use for it */
345
 	/* Destroy the PCI device anyway; we have no further use for it */
347
-	efipci_destroy ( efidrv, efipci );
346
+	efipci_destroy ( efipci );
348
 
347
 
349
 	/* BOFM (ab)uses the "start" method to mean "process and exit" */
348
 	/* BOFM (ab)uses the "start" method to mean "process and exit" */
350
-	return EFI_NOT_READY;
349
+	return -EAGAIN;
351
 
350
 
352
  err_set_status:
351
  err_set_status:
353
  err_locate_bofm:
352
  err_locate_bofm:
354
  err_enable:
353
  err_enable:
355
-	efipci_destroy ( efidrv, efipci );
354
+	efipci_destroy ( efipci );
356
  err_create:
355
  err_create:
357
-	return EFIRC ( rc );
356
+ err_already_started:
357
+	return rc;
358
 }
358
 }
359
 
359
 
360
 /**
360
 /**
361
  * Detach driver from device
361
  * Detach driver from device
362
  *
362
  *
363
- * @v driver		EFI driver
364
  * @v device		EFI device
363
  * @v device		EFI device
365
- * @v num_children	Number of child devices
366
- * @v children		List of child devices
367
- * @ret efirc		EFI status code
368
  */
364
  */
369
-static EFI_STATUS EFIAPI efi_bofm_stop ( EFI_DRIVER_BINDING_PROTOCOL *driver,
370
-					 EFI_HANDLE device, UINTN num_children,
371
-					 EFI_HANDLE *children ) {
372
-	struct efi_driver *efidrv =
373
-		container_of ( driver, struct efi_driver, driver );
374
-
375
-	DBGCP ( efidrv, "EFIBOFM DRIVER_STOP %p (%ld %p)\n",
376
-		device, ( ( unsigned long ) num_children ), children );
377
-
378
-	return 0;
365
+static void efi_bofm_stop ( EFI_HANDLE device __unused ) {
366
+	/* Nothing to do */
379
 }
367
 }
380
 
368
 
381
 /** EFI BOFM driver */
369
 /** EFI BOFM driver */
382
-static struct efi_driver efi_bofm_driver =
383
-	EFI_DRIVER_INIT ( "BOFM",
384
-			  efi_bofm_supported, efi_bofm_start, efi_bofm_stop );
385
-
386
-/**
387
- * Install EFI BOFM driver
388
- *
389
- */
390
-static void efi_bofm_driver_startup ( void ) {
391
-	struct efi_driver *efidrv = &efi_bofm_driver;
392
-	int rc;
393
-
394
-	/* Install driver */
395
-	if ( ( rc = efi_driver_install ( efidrv ) ) != 0 ) {
396
-		DBGC ( efidrv, "EFIBOFM could not install driver: %s\n",
397
-		       strerror ( rc ) );
398
-		return;
399
-	}
400
-
401
-	DBGC ( efidrv, "EFIBOFM driver installed\n" );
402
-}
403
-
404
-/**
405
- * Shut down EFI BOFM driver
406
- *
407
- * @v booting		System is shutting down for OS boot
408
- */
409
-static void efi_bofm_driver_shutdown ( int booting __unused ) {
410
-	struct efi_driver *efidrv = &efi_bofm_driver;
411
-
412
-	efi_driver_uninstall ( efidrv );
413
-}
414
-
415
-/** EFI BOFM startup function */
416
-struct startup_fn startup_bofm __startup_fn ( STARTUP_EARLY ) = {
417
-	.startup = efi_bofm_driver_startup,
418
-	.shutdown = efi_bofm_driver_shutdown,
370
+struct efi_driver efi_bofm_driver __efi_driver ( EFI_DRIVER_EARLY ) = {
371
+	.name = "BOFM",
372
+	.supported = efi_bofm_supported,
373
+	.start = efi_bofm_start,
374
+	.stop = efi_bofm_stop,
419
 };
375
 };

+ 261
- 85
src/interface/efi/efi_driver.c View File

36
  *
36
  *
37
  */
37
  */
38
 
38
 
39
+static EFI_DRIVER_BINDING_PROTOCOL efi_driver_binding;
40
+
39
 /** EFI driver binding protocol GUID */
41
 /** EFI driver binding protocol GUID */
40
 static EFI_GUID efi_driver_binding_protocol_guid
42
 static EFI_GUID efi_driver_binding_protocol_guid
41
 	= EFI_DRIVER_BINDING_PROTOCOL_GUID;
43
 	= EFI_DRIVER_BINDING_PROTOCOL_GUID;
62
 	return path;
64
 	return path;
63
 }
65
 }
64
 
66
 
67
+/**
68
+ * Check to see if driver supports a device
69
+ *
70
+ * @v driver		EFI driver
71
+ * @v device		EFI device
72
+ * @v child		Path to child device, if any
73
+ * @ret efirc		EFI status code
74
+ */
75
+static EFI_STATUS EFIAPI
76
+efi_driver_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused,
77
+		       EFI_HANDLE device, EFI_DEVICE_PATH_PROTOCOL *child ) {
78
+	struct efi_driver *efidrv;
79
+	int rc;
80
+
81
+	DBGCP ( device, "EFIDRV %p %s DRIVER_SUPPORTED",
82
+		device, efi_handle_devpath_text ( device ) );
83
+	if ( child )
84
+		DBGCP ( device, " (child %s)", efi_devpath_text ( child ) );
85
+	DBGCP ( device, "\n" );
86
+
87
+	/* Look for a driver claiming to support this device */
88
+	for_each_table_entry ( efidrv, EFI_DRIVERS ) {
89
+		if ( ( rc = efidrv->supported ( device ) ) == 0 ) {
90
+			DBGC ( device, "EFIDRV %p %s has driver \"%s\"\n",
91
+			       device, efi_handle_devpath_text ( device ),
92
+			       efidrv->name );
93
+			return 0;
94
+		}
95
+	}
96
+	DBGCP ( device, "EFIDRV %p %s has no driver\n",
97
+		device, efi_handle_devpath_text ( device ) );
98
+
99
+	return EFI_UNSUPPORTED;
100
+}
101
+
102
+/**
103
+ * Attach driver to device
104
+ *
105
+ * @v driver		EFI driver
106
+ * @v device		EFI device
107
+ * @v child		Path to child device, if any
108
+ * @ret efirc		EFI status code
109
+ */
110
+static EFI_STATUS EFIAPI
111
+efi_driver_start ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused,
112
+		   EFI_HANDLE device, EFI_DEVICE_PATH_PROTOCOL *child ) {
113
+	struct efi_driver *efidrv;
114
+	int rc;
115
+
116
+	DBGC ( device, "EFIDRV %p %s DRIVER_START",
117
+	       device, efi_handle_devpath_text ( device ) );
118
+	if ( child )
119
+		DBGC ( device, " (child %s)", efi_devpath_text ( child ) );
120
+	DBGC ( device, "\n" );
121
+
122
+	/* Try to start this device */
123
+	for_each_table_entry ( efidrv, EFI_DRIVERS ) {
124
+		if ( ( rc = efidrv->start ( device ) ) == 0 ) {
125
+			DBGC ( device, "EFIDRV %p %s using driver \"%s\"\n",
126
+			       device, efi_handle_devpath_text ( device ),
127
+			       efidrv->name );
128
+			return 0;
129
+		}
130
+		DBGC ( device, "EFIDRV %p %s could not start driver \"%s\": "
131
+		       "%s\n", device, efi_handle_devpath_text ( device ),
132
+		       efidrv->name, strerror ( rc ) );
133
+	}
134
+
135
+	return EFI_UNSUPPORTED;
136
+}
137
+
138
+/**
139
+ * Detach driver from device
140
+ *
141
+ * @v driver		EFI driver
142
+ * @v device		EFI device
143
+ * @v pci		PCI device
144
+ * @v num_children	Number of child devices
145
+ * @v children		List of child devices
146
+ * @ret efirc		EFI status code
147
+ */
148
+static EFI_STATUS EFIAPI
149
+efi_driver_stop ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused,
150
+		  EFI_HANDLE device, UINTN num_children,
151
+		  EFI_HANDLE *children ) {
152
+	struct efi_driver *efidrv;
153
+	UINTN i;
154
+
155
+	DBGC ( device, "EFIDRV %p %s DRIVER_STOP",
156
+	       device, efi_handle_devpath_text ( device ) );
157
+	for ( i = 0 ; i < num_children ; i++ ) {
158
+		DBGC ( device, "%s%p %s", ( i ? ", " : " child " ),
159
+		       children[i], efi_handle_devpath_text ( children[i] ) );
160
+	}
161
+	DBGC ( device, "\n" );
162
+
163
+	/* Try to stop this device */
164
+	for_each_table_entry ( efidrv, EFI_DRIVERS )
165
+		efidrv->stop ( device );
166
+
167
+	return 0;
168
+}
169
+
170
+/** EFI driver binding protocol */
171
+static EFI_DRIVER_BINDING_PROTOCOL efi_driver_binding = {
172
+	.Supported = efi_driver_supported,
173
+	.Start = efi_driver_start,
174
+	.Stop = efi_driver_stop,
175
+};
176
+
65
 /**
177
 /**
66
  * Look up driver name
178
  * Look up driver name
67
  *
179
  *
71
  * @ret efirc		EFI status code
183
  * @ret efirc		EFI status code
72
  */
184
  */
73
 static EFI_STATUS EFIAPI
185
 static EFI_STATUS EFIAPI
74
-efi_driver_get_driver_name ( EFI_COMPONENT_NAME2_PROTOCOL *wtf,
75
-			     CHAR8 *language __unused, CHAR16 **driver_name ) {
76
-	struct efi_driver *efidrv =
77
-		container_of ( wtf, struct efi_driver, wtf );
186
+efi_driver_name ( EFI_COMPONENT_NAME2_PROTOCOL *wtf __unused,
187
+		  CHAR8 *language __unused, CHAR16 **driver_name ) {
188
+	const wchar_t *name;
78
 
189
 
79
-	*driver_name = efidrv->wname;
190
+	name = ( product_wname[0] ? product_wname : build_wname );
191
+	*driver_name = ( ( wchar_t * ) name );
80
 	return 0;
192
 	return 0;
81
 }
193
 }
82
 
194
 
91
  * @ret efirc		EFI status code
203
  * @ret efirc		EFI status code
92
  */
204
  */
93
 static EFI_STATUS EFIAPI
205
 static EFI_STATUS EFIAPI
94
-efi_driver_get_controller_name ( EFI_COMPONENT_NAME2_PROTOCOL *wtf __unused,
95
-				 EFI_HANDLE device, EFI_HANDLE child,
96
-				 CHAR8 *language, CHAR16 **controller_name ) {
206
+efi_driver_controller_name ( EFI_COMPONENT_NAME2_PROTOCOL *wtf __unused,
207
+			     EFI_HANDLE device, EFI_HANDLE child,
208
+			     CHAR8 *language, CHAR16 **controller_name ) {
97
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
209
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
98
 	union {
210
 	union {
99
 		EFI_COMPONENT_NAME2_PROTOCOL *name2;
211
 		EFI_COMPONENT_NAME2_PROTOCOL *name2;
118
 	return EFI_UNSUPPORTED;
230
 	return EFI_UNSUPPORTED;
119
 }
231
 }
120
 
232
 
233
+/** EFI component name protocol */
234
+static EFI_COMPONENT_NAME2_PROTOCOL efi_wtf = {
235
+	.GetDriverName = efi_driver_name,
236
+	.GetControllerName = efi_driver_controller_name,
237
+	.SupportedLanguages = "en",
238
+};
239
+
240
+/**
241
+ * Install EFI driver
242
+ *
243
+ * @ret rc		Return status code
244
+ */
245
+int efi_driver_install ( void ) {
246
+	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
247
+	EFI_STATUS efirc;
248
+	int rc;
249
+
250
+	/* Calculate driver version number.  We use the build
251
+	 * timestamp (in seconds since the Epoch) shifted right by six
252
+	 * bits: this gives us an approximately one-minute resolution
253
+	 * and a scheme which will last until the year 10680.
254
+	 */
255
+	efi_driver_binding.Version = ( build_timestamp >> 6 );
256
+
257
+	/* Install protocols on image handle */
258
+	efi_driver_binding.ImageHandle = efi_image_handle;
259
+	efi_driver_binding.DriverBindingHandle = efi_image_handle;
260
+	if ( ( efirc = bs->InstallMultipleProtocolInterfaces (
261
+			&efi_image_handle,
262
+			&efi_driver_binding_protocol_guid, &efi_driver_binding,
263
+			&efi_component_name2_protocol_guid, &efi_wtf,
264
+			NULL ) ) != 0 ) {
265
+		rc = -EEFI ( efirc );
266
+		DBGC ( &efi_driver_binding, "EFIDRV could not install "
267
+		       "protocols: %s\n", strerror ( rc ) );
268
+		return rc;
269
+	}
270
+
271
+	return 0;
272
+}
273
+
274
+/**
275
+ * Uninstall EFI driver
276
+ *
277
+ */
278
+void efi_driver_uninstall ( void ) {
279
+	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
280
+
281
+	/* Uninstall protocols */
282
+	bs->UninstallMultipleProtocolInterfaces (
283
+		efi_image_handle,
284
+		&efi_driver_binding_protocol_guid, &efi_driver_binding,
285
+		&efi_component_name2_protocol_guid, &efi_wtf, NULL );
286
+}
287
+
121
 /**
288
 /**
122
  * Try to connect EFI driver
289
  * Try to connect EFI driver
123
  *
290
  *
124
- * @v efidrv		EFI driver
125
- * @v handle		Controller handle
291
+ * @v device		EFI device
292
+ * @ret rc		Return status code
126
  */
293
  */
127
-static void efi_driver_connect ( struct efi_driver *efidrv, EFI_HANDLE handle ){
294
+static int efi_driver_connect ( EFI_HANDLE device ) {
128
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
295
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
129
-	EFI_HANDLE drivers[2] = { efidrv->driver.DriverBindingHandle, NULL };
296
+	EFI_HANDLE drivers[2] =
297
+		{ efi_driver_binding.DriverBindingHandle, NULL };
298
+	EFI_STATUS efirc;
299
+	int rc;
300
+
301
+	/* Check if we want to drive this device */
302
+	if ( ( efirc = efi_driver_supported ( &efi_driver_binding, device,
303
+					      NULL ) ) != 0 ) {
304
+		/* Not supported; not an error */
305
+		return 0;
306
+	}
307
+
308
+	/* Disconnect any existing drivers */
309
+	DBGC ( device, "EFIDRV %p %s disconnecting existing drivers\n",
310
+	       device, efi_handle_devpath_text ( device ) );
311
+	bs->DisconnectController ( device, NULL, NULL );
130
 
312
 
131
-	bs->ConnectController ( handle, drivers, NULL, FALSE );
313
+	/* Connect our driver */
314
+	DBGC ( device, "EFIDRV %p %s connecting new drivers\n",
315
+	       device, efi_handle_devpath_text ( device ) );
316
+	if ( ( efirc = bs->ConnectController ( device, drivers, NULL,
317
+					       FALSE ) ) != 0 ) {
318
+		rc = -EEFI ( efirc );
319
+		DBGC ( device, "EFIDRV %p %s could not connect new drivers: "
320
+		       "%s\n", device, efi_handle_devpath_text ( device ),
321
+		       strerror ( rc ) );
322
+		return rc;
323
+	}
324
+
325
+	return 0;
132
 }
326
 }
133
 
327
 
134
 /**
328
 /**
135
  * Try to disconnect EFI driver
329
  * Try to disconnect EFI driver
136
  *
330
  *
137
- * @v efidrv		EFI driver
138
- * @v handle		Controller handle
331
+ * @v device		EFI device
332
+ * @ret rc		Return status code
139
  */
333
  */
140
-static void efi_driver_disconnect ( struct efi_driver *efidrv,
141
-				    EFI_HANDLE handle ) {
334
+static int efi_driver_disconnect ( EFI_HANDLE device ) {
142
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
335
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
143
 
336
 
144
-	bs->DisconnectController ( handle, efidrv->driver.DriverBindingHandle,
337
+	/* Disconnect our driver */
338
+	bs->DisconnectController ( device,
339
+				   efi_driver_binding.DriverBindingHandle,
145
 				   NULL );
340
 				   NULL );
341
+	return 0;
342
+}
343
+
344
+/**
345
+ * Reconnect original EFI driver
346
+ *
347
+ * @v device		EFI device
348
+ * @ret rc		Return status code
349
+ */
350
+static int efi_driver_reconnect ( EFI_HANDLE device ) {
351
+	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
352
+
353
+	/* Reconnect any available driver */
354
+	bs->ConnectController ( device, NULL, NULL, FALSE );
355
+
356
+	return 0;
146
 }
357
 }
147
 
358
 
148
 /**
359
 /**
149
  * Connect/disconnect EFI driver from all handles
360
  * Connect/disconnect EFI driver from all handles
150
  *
361
  *
151
- * @v efidrv		EFI driver
152
  * @v method		Connect/disconnect method
362
  * @v method		Connect/disconnect method
153
  * @ret rc		Return status code
363
  * @ret rc		Return status code
154
  */
364
  */
155
-static int efi_driver_handles ( struct efi_driver *efidrv,
156
-				void ( * method ) ( struct efi_driver *efidrv,
157
-						    EFI_HANDLE handle ) ) {
365
+static int efi_driver_handles ( int ( * method ) ( EFI_HANDLE handle ) ) {
158
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
366
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
159
 	EFI_HANDLE *handles;
367
 	EFI_HANDLE *handles;
160
 	UINTN num_handles;
368
 	UINTN num_handles;
167
 						&num_handles,
375
 						&num_handles,
168
 						&handles ) ) != 0 ) {
376
 						&handles ) ) != 0 ) {
169
 		rc = -EEFI ( efirc );
377
 		rc = -EEFI ( efirc );
170
-		DBGC ( efidrv, "EFIDRV %s could not list handles: %s\n",
171
-		       efidrv->name, strerror ( rc ) );
172
-		return rc;
378
+		DBGC ( &efi_driver_binding, "EFIDRV could not list handles: "
379
+		       "%s\n", strerror ( rc ) );
380
+		goto err_locate;
173
 	}
381
 	}
174
 
382
 
175
 	/* Connect/disconnect driver from all handles */
383
 	/* Connect/disconnect driver from all handles */
176
-	for ( i = 0 ; i < num_handles ; i++ )
177
-		method ( efidrv, handles[i] );
384
+	for ( i = 0 ; i < num_handles ; i++ ) {
385
+		if ( ( rc = method ( handles[i] ) ) != 0 )
386
+			goto err_method;
387
+	}
178
 
388
 
179
-	/* Free list of handles */
180
-	bs->FreePool ( handles );
389
+	/* Success */
390
+	rc = 0;
181
 
391
 
182
-	return 0;
392
+ err_method:
393
+	bs->FreePool ( handles );
394
+ err_locate:
395
+	return rc;
183
 }
396
 }
184
 
397
 
185
 /**
398
 /**
186
- * Install EFI driver
399
+ * Connect EFI driver to all possible devices
187
  *
400
  *
188
- * @v efidrv		EFI driver
189
  * @ret rc		Return status code
401
  * @ret rc		Return status code
190
  */
402
  */
191
-int efi_driver_install ( struct efi_driver *efidrv ) {
192
-	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
193
-	EFI_DRIVER_BINDING_PROTOCOL *driver = &efidrv->driver;
194
-	EFI_COMPONENT_NAME2_PROTOCOL *wtf = &efidrv->wtf;
195
-	EFI_STATUS efirc;
196
-	int rc;
197
-
198
-	/* Configure driver binding protocol */
199
-	driver->ImageHandle = efi_image_handle;
200
-
201
-	/* Configure component name protocol */
202
-	wtf->GetDriverName = efi_driver_get_driver_name;
203
-	wtf->GetControllerName = efi_driver_get_controller_name;
204
-	wtf->SupportedLanguages = "en";
403
+int efi_driver_connect_all ( void ) {
205
 
404
 
206
-	/* Fill in driver name */
207
-	efi_snprintf ( efidrv->wname,
208
-		       ( sizeof ( efidrv->wname ) /
209
-			 sizeof ( efidrv->wname[0] ) ),
210
-		       "%s%s%s", product_short_name,
211
-		       ( efidrv->name ? " - " : "" ),
212
-		       ( efidrv->name ? efidrv->name : "" ) );
213
-
214
-	/* Install driver */
215
-	if ( ( efirc = bs->InstallMultipleProtocolInterfaces (
216
-			&driver->DriverBindingHandle,
217
-			&efi_driver_binding_protocol_guid, driver,
218
-			&efi_component_name2_protocol_guid, wtf,
219
-			NULL ) ) != 0 ) {
220
-		rc = -EEFI ( efirc );
221
-		DBGC ( efidrv, "EFIDRV %s could not install protocol: %s\n",
222
-		       efidrv->name, strerror ( rc ) );
223
-		return rc;
224
-	}
405
+	DBGC ( &efi_driver_binding, "EFIDRV connecting our drivers\n" );
406
+	return efi_driver_handles ( efi_driver_connect );
407
+}
225
 
408
 
226
-	/* Connect devices */
227
-	DBGC ( efidrv, "EFIDRV %s connecting devices\n", efidrv->name );
228
-	efi_driver_handles ( efidrv, efi_driver_connect );
409
+/**
410
+ * Disconnect EFI driver from all possible devices
411
+ *
412
+ * @ret rc		Return status code
413
+ */
414
+void efi_driver_disconnect_all ( void ) {
229
 
415
 
230
-	DBGC ( efidrv, "EFIDRV %s installed\n", efidrv->name );
231
-	return 0;
416
+	DBGC ( &efi_driver_binding, "EFIDRV disconnecting our drivers\n" );
417
+	efi_driver_handles ( efi_driver_disconnect );
232
 }
418
 }
233
 
419
 
234
 /**
420
 /**
235
- * Uninstall EFI driver
421
+ * Reconnect original EFI drivers to all possible devices
236
  *
422
  *
237
- * @v efidrv		EFI driver
423
+ * @ret rc		Return status code
238
  */
424
  */
239
-void efi_driver_uninstall ( struct efi_driver *efidrv ) {
240
-	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
241
-
242
-	/* Disconnect the driver from its devices */
243
-	DBGC ( efidrv, "EFIDRV %s disconnecting devices\n", efidrv->name );
244
-	efi_driver_handles ( efidrv, efi_driver_disconnect );
425
+void efi_driver_reconnect_all ( void ) {
245
 
426
 
246
-	/* Uninstall the driver */
247
-	bs->UninstallMultipleProtocolInterfaces (
248
-			efidrv->driver.DriverBindingHandle,
249
-			&efi_driver_binding_protocol_guid, &efidrv->driver,
250
-			&efi_component_name2_protocol_guid, &efidrv->wtf,
251
-			NULL );
252
-	DBGC ( efidrv, "EFIDRV %s uninstalled\n", efidrv->name );
427
+	DBGC ( &efi_driver_binding, "EFIDRV reconnecting old drivers\n" );
428
+	efi_driver_handles ( efi_driver_reconnect );
253
 }
429
 }

+ 42
- 80
src/interface/efi/efi_init.c View File

21
 
21
 
22
 #include <string.h>
22
 #include <string.h>
23
 #include <errno.h>
23
 #include <errno.h>
24
+#include <ipxe/init.h>
24
 #include <ipxe/efi/efi.h>
25
 #include <ipxe/efi/efi.h>
25
 #include <ipxe/efi/efi_driver.h>
26
 #include <ipxe/efi/efi_driver.h>
26
 #include <ipxe/efi/Protocol/LoadedImage.h>
27
 #include <ipxe/efi/Protocol/LoadedImage.h>
27
-#include <ipxe/efi/Protocol/DevicePath.h>
28
-#include <ipxe/uuid.h>
29
-#include <ipxe/init.h>
30
 
28
 
31
 /** Image handle passed to entry point */
29
 /** Image handle passed to entry point */
32
 EFI_HANDLE efi_image_handle;
30
 EFI_HANDLE efi_image_handle;
47
 /* Forward declarations */
45
 /* Forward declarations */
48
 static EFI_STATUS EFIAPI efi_unload ( EFI_HANDLE image_handle );
46
 static EFI_STATUS EFIAPI efi_unload ( EFI_HANDLE image_handle );
49
 
47
 
50
-/**
51
- * Check to see if driver supports a device
52
- *
53
- * @v driver		EFI driver
54
- * @v device		EFI device
55
- * @v child		Path to child device, if any
56
- * @ret efirc		EFI status code
57
- */
58
-static EFI_STATUS EFIAPI
59
-efi_image_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused,
60
-		    EFI_HANDLE device __unused,
61
-		    EFI_DEVICE_PATH_PROTOCOL *child __unused ) {
62
-
63
-	return EFI_UNSUPPORTED;
64
-}
65
-
66
-/**
67
- * Attach driver to device
68
- *
69
- * @v driver		EFI driver
70
- * @v device		EFI device
71
- * @v child		Path to child device, if any
72
- * @ret efirc		EFI status code
73
- */
74
-static EFI_STATUS EFIAPI
75
-efi_image_start ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused,
76
-		EFI_HANDLE device __unused,
77
-		EFI_DEVICE_PATH_PROTOCOL *child __unused ) {
78
-
79
-	return EFI_UNSUPPORTED;
80
-}
81
-
82
-/**
83
- * Detach driver from device
84
- *
85
- * @v driver		EFI driver
86
- * @v device		EFI device
87
- * @v pci		PCI device
88
- * @v num_children	Number of child devices
89
- * @v children		List of child devices
90
- * @ret efirc		EFI status code
91
- */
92
-static EFI_STATUS EFIAPI
93
-efi_image_stop ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused,
94
-	       EFI_HANDLE device __unused, UINTN num_children __unused,
95
-	       EFI_HANDLE *children __unused ) {
96
-
97
-	return EFI_UNSUPPORTED;
98
-}
99
-
100
-/** EFI loaded image driver */
101
-static struct efi_driver efi_image_driver =
102
-	EFI_DRIVER_INIT ( NULL, efi_image_supported, efi_image_start,
103
-			  efi_image_stop );
104
-
105
 /**
48
 /**
106
  * Shut down in preparation for booting an OS.
49
  * Shut down in preparation for booting an OS.
107
  *
50
  *
153
 	efi_systab = systab;
96
 	efi_systab = systab;
154
 
97
 
155
 	/* Sanity checks */
98
 	/* Sanity checks */
156
-	if ( ! systab )
157
-		return EFI_NOT_AVAILABLE_YET;
158
-	if ( ! systab->ConOut )
159
-		return EFI_NOT_AVAILABLE_YET;
99
+	if ( ! systab ) {
100
+		efirc = EFI_NOT_AVAILABLE_YET;
101
+		goto err_sanity;
102
+	}
103
+	if ( ! systab->ConOut ) {
104
+		efirc = EFI_NOT_AVAILABLE_YET;
105
+		goto err_sanity;
106
+	}
160
 	if ( ! systab->BootServices ) {
107
 	if ( ! systab->BootServices ) {
161
 		DBGC ( systab, "EFI provided no BootServices entry point\n" );
108
 		DBGC ( systab, "EFI provided no BootServices entry point\n" );
162
-		return EFI_NOT_AVAILABLE_YET;
109
+		efirc = EFI_NOT_AVAILABLE_YET;
110
+		goto err_sanity;
163
 	}
111
 	}
164
 	if ( ! systab->RuntimeServices ) {
112
 	if ( ! systab->RuntimeServices ) {
165
 		DBGC ( systab, "EFI provided no RuntimeServices entry "
113
 		DBGC ( systab, "EFI provided no RuntimeServices entry "
166
 		       "point\n" );
114
 		       "point\n" );
167
-		return EFI_NOT_AVAILABLE_YET;
115
+		efirc = EFI_NOT_AVAILABLE_YET;
116
+		goto err_sanity;
168
 	}
117
 	}
169
 	DBGC ( systab, "EFI handle %p systab %p\n", image_handle, systab );
118
 	DBGC ( systab, "EFI handle %p systab %p\n", image_handle, systab );
170
 	bs = systab->BootServices;
119
 	bs = systab->BootServices;
181
 			       efi_guid_ntoa ( &prot->guid ) );
130
 			       efi_guid_ntoa ( &prot->guid ) );
182
 			/* Fail if protocol is required */
131
 			/* Fail if protocol is required */
183
 			if ( prot->required )
132
 			if ( prot->required )
184
-				return efirc;
133
+				goto err_missing_protocol;
185
 		}
134
 		}
186
 	}
135
 	}
187
 
136
 
193
 		} else {
142
 		} else {
194
 			DBGC ( systab, "EFI does not provide configuration "
143
 			DBGC ( systab, "EFI does not provide configuration "
195
 			       "table %s\n", efi_guid_ntoa ( &tab->guid ) );
144
 			       "table %s\n", efi_guid_ntoa ( &tab->guid ) );
196
-			if ( tab->required )
197
-				return EFI_NOT_AVAILABLE_YET;
145
+			if ( tab->required ) {
146
+				efirc = EFI_NOT_AVAILABLE_YET;
147
+				goto err_missing_table;
148
+			}
198
 		}
149
 		}
199
 	}
150
 	}
200
 
151
 
206
 		rc = -EEFI ( efirc );
157
 		rc = -EEFI ( efirc );
207
 		DBGC ( systab, "EFI could not get loaded image protocol: %s",
158
 		DBGC ( systab, "EFI could not get loaded image protocol: %s",
208
 		       strerror ( rc ) );
159
 		       strerror ( rc ) );
209
-		return efirc;
160
+		goto err_no_loaded_image;
210
 	}
161
 	}
211
 	efi_loaded_image = loaded_image;
162
 	efi_loaded_image = loaded_image;
212
 	DBGC ( systab, "EFI image base address %p\n",
163
 	DBGC ( systab, "EFI image base address %p\n",
223
 		rc = -EEFI ( efirc );
174
 		rc = -EEFI ( efirc );
224
 		DBGC ( systab, "EFI could not create ExitBootServices event: "
175
 		DBGC ( systab, "EFI could not create ExitBootServices event: "
225
 		       "%s\n", strerror ( rc ) );
176
 		       "%s\n", strerror ( rc ) );
226
-		return efirc;
177
+		goto err_create_event;
227
 	}
178
 	}
228
 
179
 
229
-	/* Install an EFI driver on the image handle, to allow the
230
-	 * driver to be subsequently unloaded.
231
-	 */
232
-	efi_image_driver.driver.DriverBindingHandle = image_handle;
233
-	if ( ( rc = efi_driver_install ( &efi_image_driver ) ) != 0 ) {
234
-		DBGC ( systab, "EFI could not install loaded image driver: "
235
-		       "%s\n", strerror ( rc ) );
236
-		return EFIRC ( rc );
180
+	/* Install driver binding protocol */
181
+	if ( ( rc = efi_driver_install() ) != 0 ) {
182
+		DBGC ( systab, "EFI could not install driver: %s\n",
183
+		       strerror ( rc ) );
184
+		efirc = EFIRC ( rc );
185
+		goto err_driver_install;
237
 	}
186
 	}
238
 
187
 
239
 	/* Install image unload method */
188
 	/* Install image unload method */
240
 	efi_loaded_image->Unload = efi_unload;
189
 	efi_loaded_image->Unload = efi_unload;
241
 
190
 
242
 	return 0;
191
 	return 0;
192
+
193
+	efi_driver_uninstall();
194
+ err_driver_install:
195
+	bs->CloseEvent ( efi_shutdown_event );
196
+ err_create_event:
197
+ err_no_loaded_image:
198
+ err_missing_table:
199
+ err_missing_protocol:
200
+ err_sanity:
201
+	return efirc;
243
 }
202
 }
244
 
203
 
245
 /**
204
 /**
256
 	/* Shut down */
215
 	/* Shut down */
257
 	shutdown_exit();
216
 	shutdown_exit();
258
 
217
 
218
+	/* Disconnect any remaining devices */
219
+	efi_driver_disconnect_all();
220
+
221
+	/* Uninstall driver binding protocol */
222
+	efi_driver_uninstall();
223
+
259
 	/* Uninstall exit boot services event */
224
 	/* Uninstall exit boot services event */
260
 	bs->CloseEvent ( efi_shutdown_event );
225
 	bs->CloseEvent ( efi_shutdown_event );
261
 
226
 
262
-	/* Uninstall loaded image driver */
263
-	efi_driver_uninstall ( &efi_image_driver );
264
-
265
 	DBGC ( systab, "EFI image unloaded\n" );
227
 	DBGC ( systab, "EFI image unloaded\n" );
266
 
228
 
267
 	return 0;
229
 	return 0;

+ 127
- 165
src/interface/efi/efi_pci.c View File

22
 #include <stdlib.h>
22
 #include <stdlib.h>
23
 #include <errno.h>
23
 #include <errno.h>
24
 #include <ipxe/pci.h>
24
 #include <ipxe/pci.h>
25
-#include <ipxe/init.h>
26
 #include <ipxe/efi/efi.h>
25
 #include <ipxe/efi/efi.h>
27
 #include <ipxe/efi/efi_pci.h>
26
 #include <ipxe/efi/efi_pci.h>
28
 #include <ipxe/efi/efi_driver.h>
27
 #include <ipxe/efi/efi_driver.h>
35
  *
34
  *
36
  */
35
  */
37
 
36
 
37
+/* Disambiguate the various error causes */
38
+#define EINFO_EEFI_PCI							\
39
+	__einfo_uniqify ( EINFO_EPLATFORM, 0x01,			\
40
+			  "Could not open PCI I/O protocols" )
41
+#define EINFO_EEFI_PCI_NOT_PCI						\
42
+	__einfo_platformify ( EINFO_EEFI_PCI, EFI_UNSUPPORTED,		\
43
+			      "Not a PCI device" )
44
+#define EEFI_PCI_NOT_PCI __einfo_error ( EINFO_EEFI_PCI_NOT_PCI )
45
+#define EINFO_EEFI_PCI_IN_USE						\
46
+	__einfo_platformify ( EINFO_EEFI_PCI, EFI_ACCESS_DENIED,	\
47
+			      "PCI device already has a driver" )
48
+#define EEFI_PCI_IN_USE __einfo_error ( EINFO_EEFI_PCI_IN_USE )
49
+#define EEFI_PCI( efirc )						\
50
+	EPLATFORM ( EINFO_EEFI_PCI, efirc,				\
51
+		    EEFI_PCI_NOT_PCI, EEFI_PCI_IN_USE )
52
+
38
 /******************************************************************************
53
 /******************************************************************************
39
  *
54
  *
40
  * iPXE PCI API
55
  * iPXE PCI API
119
 /**
134
 /**
120
  * Create EFI PCI device
135
  * Create EFI PCI device
121
  *
136
  *
122
- * @v efidrv		EFI driver
123
  * @v device		EFI device
137
  * @v device		EFI device
124
- * @ret efipci		EFI PCI device, or NULL
138
+ * @v attributes	Protocol opening attributes
139
+ * @v efipci		EFI PCI device to fill in
140
+ * @ret rc		Return status code
125
  */
141
  */
126
-struct efi_pci_device * efipci_create ( struct efi_driver *efidrv,
127
-					EFI_HANDLE device ) {
142
+int efipci_create ( EFI_HANDLE device, UINT32 attributes,
143
+		    struct efi_pci_device **efipci ) {
128
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
144
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
129
-	struct efi_pci_device *efipci;
130
 	union {
145
 	union {
131
 		EFI_PCI_IO_PROTOCOL *pci_io;
146
 		EFI_PCI_IO_PROTOCOL *pci_io;
132
 		void *interface;
147
 		void *interface;
140
 	int rc;
155
 	int rc;
141
 
156
 
142
 	/* Allocate PCI device */
157
 	/* Allocate PCI device */
143
-	efipci = zalloc ( sizeof ( *efipci ) );
144
-	if ( ! efipci )
158
+	*efipci = zalloc ( sizeof ( **efipci ) );
159
+	if ( ! *efipci ) {
160
+		rc = -ENOMEM;
145
 		goto err_zalloc;
161
 		goto err_zalloc;
146
-	efipci->device = device;
147
-	efipci->efidrv = efidrv;
162
+	}
163
+	(*efipci)->device = device;
148
 
164
 
149
 	/* See if device is a PCI device */
165
 	/* See if device is a PCI device */
150
 	if ( ( efirc = bs->OpenProtocol ( device,
166
 	if ( ( efirc = bs->OpenProtocol ( device,
151
 					  &efi_pci_io_protocol_guid,
167
 					  &efi_pci_io_protocol_guid,
152
 					  &pci_io.interface,
168
 					  &pci_io.interface,
153
-					  efidrv->driver.DriverBindingHandle,
154
-					  device,
155
-					  EFI_OPEN_PROTOCOL_BY_DRIVER )) !=0 ){
156
-		rc = -EEFI ( efirc );
157
-		DBGCP ( efipci, "EFIPCI device %p is not a PCI device\n",
158
-			device );
169
+					  efi_image_handle,
170
+					  device, attributes ) ) != 0 ) {
171
+		rc = -EEFI_PCI ( efirc );
172
+		DBGCP ( device, "EFIPCI %p %s cannot open PCI protocols: %s\n",
173
+			device, efi_handle_devpath_text ( device ),
174
+			strerror ( rc ) );
159
 		goto err_open_protocol;
175
 		goto err_open_protocol;
160
 	}
176
 	}
161
-	efipci->pci_io = pci_io.pci_io;
177
+	(*efipci)->pci_io = pci_io.pci_io;
162
 
178
 
163
 	/* Get PCI bus:dev.fn address */
179
 	/* Get PCI bus:dev.fn address */
164
 	if ( ( efirc = pci_io.pci_io->GetLocation ( pci_io.pci_io,
180
 	if ( ( efirc = pci_io.pci_io->GetLocation ( pci_io.pci_io,
166
 						    &pci_bus, &pci_dev,
182
 						    &pci_bus, &pci_dev,
167
 						    &pci_fn ) ) != 0 ) {
183
 						    &pci_fn ) ) != 0 ) {
168
 		rc = -EEFI ( efirc );
184
 		rc = -EEFI ( efirc );
169
-		DBGC ( efipci, "EFIPCI device %p could not get PCI "
170
-		       "location: %s\n", device, strerror ( rc ) );
185
+		DBGC ( device, "EFIPCI %p %s could not get PCI location: "
186
+		       "%s\n", device, efi_handle_devpath_text ( device ),
187
+		       strerror ( rc ) );
171
 		goto err_get_location;
188
 		goto err_get_location;
172
 	}
189
 	}
173
-	DBGC2 ( efipci, "EFIPCI device %p is PCI %04lx:%02lx:%02lx.%lx\n",
174
-		device, ( ( unsigned long ) pci_segment ),
175
-		( ( unsigned long ) pci_bus ), ( ( unsigned long ) pci_dev ),
176
-		( ( unsigned long ) pci_fn ) );
190
+	DBGC2 ( device, "EFIPCI %p %s is PCI %04lx:%02lx:%02lx.%lx\n",
191
+		device, efi_handle_devpath_text ( device ),
192
+		( ( unsigned long ) pci_segment ), ( ( unsigned long ) pci_bus),
193
+		( ( unsigned long ) pci_dev ), ( ( unsigned long ) pci_fn ) );
177
 
194
 
178
 	/* Populate PCI device */
195
 	/* Populate PCI device */
179
-	pci_init ( &efipci->pci, PCI_BUSDEVFN ( pci_bus, pci_dev, pci_fn ) );
180
-	if ( ( rc = pci_read_config ( &efipci->pci ) ) != 0 ) {
181
-		DBGC ( efipci, "EFIPCI " PCI_FMT " cannot read PCI "
182
-		       "configuration: %s\n",
183
-		       PCI_ARGS ( &efipci->pci ), strerror ( rc ) );
196
+	pci_init ( &(*efipci)->pci, PCI_BUSDEVFN ( pci_bus, pci_dev, pci_fn ) );
197
+	if ( ( rc = pci_read_config ( &(*efipci)->pci ) ) != 0 ) {
198
+		DBGC ( device, "EFIPCI %p %s cannot read PCI configuration: "
199
+		       "%s\n", device, efi_handle_devpath_text ( device ),
200
+		       strerror ( rc ) );
184
 		goto err_pci_read_config;
201
 		goto err_pci_read_config;
185
 	}
202
 	}
186
 
203
 
187
 	/* Retrieve device path */
204
 	/* Retrieve device path */
188
 	if ( ( efirc = bs->OpenProtocol ( device,
205
 	if ( ( efirc = bs->OpenProtocol ( device,
189
 					  &efi_device_path_protocol_guid,
206
 					  &efi_device_path_protocol_guid,
190
-					  &path.interface,
191
-					  efidrv->driver.DriverBindingHandle,
192
-					  device,
193
-					  EFI_OPEN_PROTOCOL_BY_DRIVER )) !=0 ){
207
+					  &path.interface, efi_image_handle,
208
+					  device, attributes ) ) != 0 ) {
194
 		rc = -EEFI ( efirc );
209
 		rc = -EEFI ( efirc );
195
-		DBGC ( efipci, "EFIPCI " PCI_FMT " has no device path\n",
196
-		       PCI_ARGS ( &efipci->pci ) );
210
+		DBGC ( device, "EFIPCI %p %s has no device path\n",
211
+		       device, efi_handle_devpath_text ( device ) );
197
 		goto err_no_device_path;
212
 		goto err_no_device_path;
198
 	}
213
 	}
199
-	efipci->path = path.path;
214
+	(*efipci)->path = path.path;
200
 
215
 
201
 	/* Add to list of PCI devices */
216
 	/* Add to list of PCI devices */
202
-	list_add ( &efipci->list, &efi_pci_devices );
217
+	list_add ( &(*efipci)->list, &efi_pci_devices );
203
 
218
 
204
-	return efipci;
219
+	return 0;
205
 
220
 
206
 	bs->CloseProtocol ( device, &efi_device_path_protocol_guid,
221
 	bs->CloseProtocol ( device, &efi_device_path_protocol_guid,
207
-			    efidrv->driver.DriverBindingHandle, device );
222
+			    efi_image_handle, device );
208
  err_no_device_path:
223
  err_no_device_path:
209
  err_pci_read_config:
224
  err_pci_read_config:
210
  err_get_location:
225
  err_get_location:
211
 	bs->CloseProtocol ( device, &efi_pci_io_protocol_guid,
226
 	bs->CloseProtocol ( device, &efi_pci_io_protocol_guid,
212
-			    efidrv->driver.DriverBindingHandle, device );
227
+			    efi_image_handle, device );
213
  err_open_protocol:
228
  err_open_protocol:
214
-	free ( efipci );
229
+	free ( *efipci );
215
  err_zalloc:
230
  err_zalloc:
216
-	return NULL;
231
+	return rc;
217
 }
232
 }
218
 
233
 
219
 /**
234
 /**
282
  */
297
  */
283
 int efipci_child_add ( struct efi_pci_device *efipci, EFI_HANDLE device ) {
298
 int efipci_child_add ( struct efi_pci_device *efipci, EFI_HANDLE device ) {
284
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
299
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
285
-	struct efi_driver *efidrv = efipci->efidrv;
286
 	union {
300
 	union {
287
 		EFI_PCI_IO_PROTOCOL *pci_io;
301
 		EFI_PCI_IO_PROTOCOL *pci_io;
288
 		void *interface;
302
 		void *interface;
294
 	if ( ( efirc = bs->OpenProtocol ( efipci->device,
308
 	if ( ( efirc = bs->OpenProtocol ( efipci->device,
295
 					  &efi_pci_io_protocol_guid,
309
 					  &efi_pci_io_protocol_guid,
296
 					  &pci_io.interface,
310
 					  &pci_io.interface,
297
-					  efidrv->driver.DriverBindingHandle,
298
-					  device,
311
+					  efi_image_handle, device,
299
 					  EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
312
 					  EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
300
 					  ) ) != 0 ) {
313
 					  ) ) != 0 ) {
301
 		rc = -EEFI ( efirc );
314
 		rc = -EEFI ( efirc );
302
-		DBGC ( efipci, "EFIPCI " PCI_FMT " could not add child: %s\n",
303
-		       PCI_ARGS ( &efipci->pci ), strerror ( rc ) );
315
+		DBGC ( efipci->device, "EFIPCI %p %s could not add child",
316
+		       efipci->device, efi_devpath_text ( efipci->path ) );
317
+		DBGC ( efipci->device, " %p %s: %s\n", device,
318
+		       efi_handle_devpath_text ( device ), strerror ( rc ) );
304
 		return rc;
319
 		return rc;
305
 	}
320
 	}
306
 
321
 
322
+	DBGC2 ( efipci->device, "EFIPCI %p %s added child",
323
+		efipci->device, efi_devpath_text ( efipci->path ) );
324
+	DBGC2 ( efipci->device, " %p %s\n",
325
+		device, efi_handle_devpath_text ( device ) );
307
 	return 0;
326
 	return 0;
308
 }
327
 }
309
 
328
 
316
  */
335
  */
317
 void efipci_child_del ( struct efi_pci_device *efipci, EFI_HANDLE device ) {
336
 void efipci_child_del ( struct efi_pci_device *efipci, EFI_HANDLE device ) {
318
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
337
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
319
-	struct efi_driver *efidrv = efipci->efidrv;
320
 
338
 
321
 	bs->CloseProtocol ( efipci->device, &efi_pci_io_protocol_guid,
339
 	bs->CloseProtocol ( efipci->device, &efi_pci_io_protocol_guid,
322
-			    efidrv->driver.DriverBindingHandle, device );
340
+			    efi_image_handle, device );
341
+	DBGC2 ( efipci->device, "EFIPCI %p %s removed child",
342
+		efipci->device, efi_devpath_text ( efipci->path ) );
343
+	DBGC2 ( efipci->device, " %p %s\n",
344
+		device, efi_handle_devpath_text ( device ) );
323
 }
345
 }
324
 
346
 
325
 /**
347
 /**
326
  * Destroy EFI PCI device
348
  * Destroy EFI PCI device
327
  *
349
  *
328
- * @v efidrv		EFI driver
329
  * @v efipci		EFI PCI device
350
  * @v efipci		EFI PCI device
330
  */
351
  */
331
-void efipci_destroy ( struct efi_driver *efidrv,
332
-		      struct efi_pci_device *efipci ) {
352
+void efipci_destroy ( struct efi_pci_device *efipci ) {
333
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
353
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
334
 
354
 
335
 	list_del ( &efipci->list );
355
 	list_del ( &efipci->list );
336
 	bs->CloseProtocol ( efipci->device, &efi_device_path_protocol_guid,
356
 	bs->CloseProtocol ( efipci->device, &efi_device_path_protocol_guid,
337
-			    efidrv->driver.DriverBindingHandle,
338
-			    efipci->device );
357
+			    efi_image_handle, efipci->device );
339
 	bs->CloseProtocol ( efipci->device, &efi_pci_io_protocol_guid,
358
 	bs->CloseProtocol ( efipci->device, &efi_pci_io_protocol_guid,
340
-			    efidrv->driver.DriverBindingHandle,
341
-			    efipci->device );
359
+			    efi_image_handle, efipci->device );
342
 	free ( efipci );
360
 	free ( efipci );
343
 }
361
 }
344
 
362
 
352
 /**
370
 /**
353
  * Check to see if driver supports a device
371
  * Check to see if driver supports a device
354
  *
372
  *
355
- * @v driver		EFI driver
356
  * @v device		EFI device
373
  * @v device		EFI device
357
- * @v child		Path to child device, if any
358
- * @ret efirc		EFI status code
374
+ * @ret rc		Return status code
359
  */
375
  */
360
-static EFI_STATUS EFIAPI
361
-efipci_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device,
362
-		   EFI_DEVICE_PATH_PROTOCOL *child ) {
363
-	struct efi_driver *efidrv =
364
-		container_of ( driver, struct efi_driver, driver );
376
+static int efipci_supported ( EFI_HANDLE device ) {
365
 	struct efi_pci_device *efipci;
377
 	struct efi_pci_device *efipci;
366
 	int rc;
378
 	int rc;
367
 
379
 
368
-	DBGCP ( efidrv, "EFIPCI DRIVER_SUPPORTED %p (%p)\n", device, child );
380
+	/* Do nothing if we are already driving this device */
381
+	efipci = efipci_find_efi ( device );
382
+	if ( efipci ) {
383
+		DBGCP ( device, "EFIPCI %p %s already started\n",
384
+			device, efi_devpath_text ( efipci->path ) );
385
+		rc = -EALREADY;
386
+		goto err_already_started;
387
+	}
369
 
388
 
370
 	/* Create temporary corresponding PCI device, if any */
389
 	/* Create temporary corresponding PCI device, if any */
371
-	efipci = efipci_create ( efidrv, device );
372
-	if ( ! efipci ) {
373
-		/* Non-PCI devices are simply unsupported */
374
-		rc = -ENOTSUP;
375
-		goto err_not_pci;
376
-	}
390
+	if ( ( rc = efipci_create ( device, EFI_OPEN_PROTOCOL_GET_PROTOCOL,
391
+				    &efipci ) ) != 0 )
392
+		goto err_create;
377
 
393
 
378
 	/* Look for a driver */
394
 	/* Look for a driver */
379
 	if ( ( rc = pci_find_driver ( &efipci->pci ) ) != 0 ) {
395
 	if ( ( rc = pci_find_driver ( &efipci->pci ) ) != 0 ) {
380
-		DBGCP ( efipci, "EFIPCI " PCI_FMT " has no driver\n",
381
-			PCI_ARGS ( &efipci->pci ) );
396
+		DBGCP ( device, "EFIPCI %p %s has no driver\n",
397
+			device, efi_devpath_text ( efipci->path ) );
382
 		goto err_no_driver;
398
 		goto err_no_driver;
383
 	}
399
 	}
384
 
400
 
385
-	DBGC ( efipci, "EFIPCI " PCI_FMT " is supported by driver \"%s\"\n",
386
-	       PCI_ARGS ( &efipci->pci ), efipci->pci.id->name );
401
+	DBGC ( device, "EFIPCI %p %s has driver \"%s\"\n", device,
402
+	       efi_devpath_text ( efipci->path ), efipci->pci.id->name );
387
 
403
 
388
 	/* Destroy temporary PCI device */
404
 	/* Destroy temporary PCI device */
389
-	efipci_destroy ( efidrv, efipci );
405
+	efipci_destroy ( efipci );
390
 
406
 
391
 	return 0;
407
 	return 0;
392
 
408
 
393
  err_no_driver:
409
  err_no_driver:
394
-	efipci_destroy ( efidrv, efipci );
395
- err_not_pci:
396
-	return EFIRC ( rc );
410
+	efipci_destroy ( efipci );
411
+ err_create:
412
+ err_already_started:
413
+	return rc;
397
 }
414
 }
398
 
415
 
399
 /**
416
 /**
400
  * Attach driver to device
417
  * Attach driver to device
401
  *
418
  *
402
- * @v driver		EFI driver
403
  * @v device		EFI device
419
  * @v device		EFI device
404
- * @v child		Path to child device, if any
405
- * @ret efirc		EFI status code
420
+ * @ret rc		Return status code
406
  */
421
  */
407
-static EFI_STATUS EFIAPI
408
-efipci_start ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device,
409
-	       EFI_DEVICE_PATH_PROTOCOL *child ) {
410
-	struct efi_driver *efidrv =
411
-		container_of ( driver, struct efi_driver, driver );
422
+static int efipci_start ( EFI_HANDLE device ) {
412
 	struct efi_pci_device *efipci;
423
 	struct efi_pci_device *efipci;
413
 	int rc;
424
 	int rc;
414
 
425
 
415
-	DBGC ( efidrv, "EFIPCI DRIVER_START %p (%p)\n", device, child );
426
+	/* Do nothing if we are already driving this device */
427
+	efipci = efipci_find_efi ( device );
428
+	if ( efipci ) {
429
+		DBGCP ( device, "EFIPCI %p %s already started\n",
430
+			device, efi_devpath_text ( efipci->path ) );
431
+		rc = -EALREADY;
432
+		goto err_already_started;
433
+	}
416
 
434
 
417
 	/* Create corresponding PCI device */
435
 	/* Create corresponding PCI device */
418
-	efipci = efipci_create ( efidrv, device );
419
-	if ( ! efipci ) {
420
-		rc = -ENOMEM;
436
+	if ( ( rc = efipci_create ( device, ( EFI_OPEN_PROTOCOL_BY_DRIVER |
437
+					      EFI_OPEN_PROTOCOL_EXCLUSIVE ),
438
+				    &efipci ) ) != 0 )
421
 		goto err_create;
439
 		goto err_create;
422
-	}
423
 
440
 
424
 	/* Find driver */
441
 	/* Find driver */
425
 	if ( ( rc = pci_find_driver ( &efipci->pci ) ) != 0 ) {
442
 	if ( ( rc = pci_find_driver ( &efipci->pci ) ) != 0 ) {
426
-		DBGC ( efipci, "EFIPCI " PCI_FMT " has no driver\n",
427
-		       PCI_ARGS ( &efipci->pci ) );
443
+		DBGC ( device, "EFIPCI %p %s has no driver\n",
444
+		       device, efi_devpath_text ( efipci->path ) );
428
 		goto err_find_driver;
445
 		goto err_find_driver;
429
 	}
446
 	}
430
 
447
 
434
 
451
 
435
 	/* Probe driver */
452
 	/* Probe driver */
436
 	if ( ( rc = pci_probe ( &efipci->pci ) ) != 0 ) {
453
 	if ( ( rc = pci_probe ( &efipci->pci ) ) != 0 ) {
437
-		DBGC ( efipci, "EFIPCI " PCI_FMT " could not probe driver "
438
-		       "\"%s\": %s\n", PCI_ARGS ( &efipci->pci ),
454
+		DBGC ( device, "EFIPCI %p %s could not probe driver \"%s\": "
455
+		       "%s\n", device, efi_devpath_text ( efipci->path ),
439
 		       efipci->pci.id->name, strerror ( rc ) );
456
 		       efipci->pci.id->name, strerror ( rc ) );
440
 		goto err_probe;
457
 		goto err_probe;
441
 	}
458
 	}
459
+	DBGC ( device, "EFIPCI %p %s using driver \"%s\"\n", device,
460
+	       efi_devpath_text ( efipci->path ), efipci->pci.id->name );
442
 
461
 
443
 	return 0;
462
 	return 0;
444
 
463
 
446
  err_probe:
465
  err_probe:
447
  err_enable:
466
  err_enable:
448
  err_find_driver:
467
  err_find_driver:
449
-	efipci_destroy ( efidrv, efipci );
468
+	efipci_destroy ( efipci );
450
  err_create:
469
  err_create:
451
-	return EFIRC ( rc );
470
+ err_already_started:
471
+	return rc;
452
 }
472
 }
453
 
473
 
454
 /**
474
 /**
455
  * Detach driver from device
475
  * Detach driver from device
456
  *
476
  *
457
- * @v driver		EFI driver
458
  * @v device		EFI device
477
  * @v device		EFI device
459
- * @v pci		PCI device
460
- * @v num_children	Number of child devices
461
- * @v children		List of child devices
462
- * @ret efirc		EFI status code
463
- */
464
-static EFI_STATUS EFIAPI
465
-efipci_stop ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device,
466
-	      UINTN num_children, EFI_HANDLE *children ) {
467
-	struct efi_driver *efidrv =
468
-		container_of ( driver, struct efi_driver, driver );
478
+  */
479
+static void efipci_stop ( EFI_HANDLE device ) {
469
 	struct efi_pci_device *efipci;
480
 	struct efi_pci_device *efipci;
470
 
481
 
471
-	DBGC ( efidrv, "EFIPCI DRIVER_STOP %p (%ld %p)\n",
472
-	       device, ( ( unsigned long ) num_children ), children );
473
-
474
 	/* Find PCI device */
482
 	/* Find PCI device */
475
 	efipci = efipci_find_efi ( device );
483
 	efipci = efipci_find_efi ( device );
476
-	if ( ! efipci ) {
477
-		DBGC ( efidrv, "EFIPCI device %p not started!\n", device );
478
-		return EFI_INVALID_PARAMETER;
479
-	}
484
+	if ( ! efipci )
485
+		return;
480
 
486
 
481
 	/* Remove device */
487
 	/* Remove device */
482
 	pci_remove ( &efipci->pci );
488
 	pci_remove ( &efipci->pci );
483
 
489
 
484
 	/* Delete EFI PCI device */
490
 	/* Delete EFI PCI device */
485
-	efipci_destroy ( efidrv, efipci );
486
-
487
-	return 0;
491
+	efipci_destroy ( efipci );
488
 }
492
 }
489
 
493
 
490
 /** EFI PCI driver */
494
 /** EFI PCI driver */
491
-static struct efi_driver efipci_driver =
492
-	EFI_DRIVER_INIT ( "PCI", efipci_supported, efipci_start, efipci_stop );
493
-
494
-/**
495
- * Install EFI PCI driver
496
- *
497
- */
498
-static void efipci_driver_startup ( void ) {
499
-	struct efi_driver *efidrv = &efipci_driver;
500
-	int rc;
501
-
502
-	/* Install driver */
503
-	if ( ( rc = efi_driver_install ( efidrv ) ) != 0 ) {
504
-		DBGC ( efidrv, "EFIPCI could not install driver: %s\n",
505
-		       strerror ( rc ) );
506
-		return;
507
-	}
508
-
509
-	DBGC ( efidrv, "EFIPCI driver installed\n" );
510
-}
511
-
512
-/**
513
- * Shut down EFI PCI driver
514
- *
515
- * @v booting		System is shutting down for OS boot
516
- */
517
-static void efipci_driver_shutdown ( int booting __unused ) {
518
-	struct efi_driver *efidrv = &efipci_driver;
519
-	struct efi_pci_device *efipci;
520
-	struct efi_pci_device *tmp;
521
-
522
-	/* Uninstall driver */
523
-	efi_driver_uninstall ( efidrv );
524
-
525
-	/* Shut down any remaining devices */
526
-	list_for_each_entry_safe ( efipci, tmp, &efi_pci_devices, list ) {
527
-		DBGC ( efipci, "EFIPCI " PCI_FMT " still active at shutdown; "
528
-		       "forcing close\n", PCI_ARGS ( &efipci->pci ) );
529
-		pci_remove ( &efipci->pci );
530
-		efipci_destroy ( efidrv, efipci );
531
-	}
532
-}
533
-
534
-/** EFI PCI startup function */
535
-struct startup_fn startup_pci __startup_fn ( STARTUP_NORMAL ) = {
536
-	.startup = efipci_driver_startup,
537
-	.shutdown = efipci_driver_shutdown,
495
+struct efi_driver efipci_driver __efi_driver ( EFI_DRIVER_NORMAL ) = {
496
+	.name = "PCI",
497
+	.supported = efipci_supported,
498
+	.start = efipci_start,
499
+	.stop = efipci_stop,
538
 };
500
 };

Loading…
Cancel
Save