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,7 +21,9 @@ FILE_LICENCE ( GPL2_OR_LATER );
21 21
 
22 22
 #include <stdlib.h>
23 23
 #include <errno.h>
24
+#include <ipxe/device.h>
24 25
 #include <ipxe/efi/efi.h>
26
+#include <ipxe/efi/efi_driver.h>
25 27
 
26 28
 /**
27 29
  * EFI entry point
@@ -47,6 +49,39 @@ EFI_STATUS EFIAPI _efi_start ( EFI_HANDLE image_handle,
47 49
 
48 50
  err_main:
49 51
 	efi_loaded_image->Unload ( image_handle );
52
+	efi_driver_reconnect_all();
50 53
  err_init:
51 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,43 +8,52 @@
8 8
 
9 9
 FILE_LICENCE ( GPL2_OR_LATER );
10 10
 
11
+#include <ipxe/tables.h>
11 12
 #include <ipxe/efi/efi.h>
12
-#include <ipxe/efi/Protocol/DriverBinding.h>
13
-#include <ipxe/efi/Protocol/ComponentName2.h>
14 13
 #include <ipxe/efi/Protocol/DevicePath.h>
15 14
 
16 15
 /** An EFI driver */
17 16
 struct efi_driver {
18 17
 	/** Name */
19 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 51
 extern EFI_DEVICE_PATH_PROTOCOL *
45 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 59
 #endif /* _IPXE_EFI_DRIVER_H */

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

@@ -17,7 +17,6 @@ static inline EFIAPI uint64_t LShiftU64 ( UINT64 value, UINTN shift ) {
17 17
 	return ( value << shift );
18 18
 }
19 19
 
20
-struct efi_driver;
21 20
 struct device;
22 21
 
23 22
 /** An EFI PCI device */
@@ -32,12 +31,10 @@ struct efi_pci_device {
32 31
 	EFI_PCI_IO_PROTOCOL *pci_io;
33 32
 	/** Device path */
34 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 38
 extern int efipci_enable ( struct efi_pci_device *efipci );
42 39
 extern struct efi_pci_device * efipci_find_efi ( EFI_HANDLE device );
43 40
 extern struct efi_pci_device * efipci_find ( struct device *dev );
@@ -45,7 +42,6 @@ extern int efipci_child_add ( struct efi_pci_device *efipci,
45 42
 			      EFI_HANDLE device );
46 43
 extern void efipci_child_del ( struct efi_pci_device *efipci,
47 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 47
 #endif /* _IPXE_EFI_PCI_H */

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

@@ -21,7 +21,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
21 21
 
22 22
 #include <errno.h>
23 23
 #include <ipxe/bofm.h>
24
-#include <ipxe/init.h>
25 24
 #include <ipxe/efi/efi.h>
26 25
 #include <ipxe/efi/efi_pci.h>
27 26
 #include <ipxe/efi/efi_driver.h>
@@ -156,17 +155,10 @@ static EFI_GUID bofm2_protocol_guid =
156 155
 /**
157 156
  * Check if device is supported
158 157
  *
159
- * @v driver		EFI driver
160 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 162
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
171 163
 	union {
172 164
 		IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL *bofm1;
@@ -176,19 +168,24 @@ efi_bofm_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver,
176 168
 	EFI_STATUS efirc;
177 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 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 185
 	/* Look for a BOFM driver */
189 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 189
 		goto err_no_driver;
193 190
 	}
194 191
 
@@ -196,8 +193,8 @@ efi_bofm_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver,
196 193
 	if ( ( efirc = bs->LocateProtocol ( &bofm1_protocol_guid, NULL,
197 194
 					    &bofm1.interface ) ) != 0 ) {
198 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 198
 		goto err_not_bofm;
202 199
 	}
203 200
 
@@ -207,41 +204,36 @@ efi_bofm_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver,
207 204
 						      0x00 /* No iSCSI */,
208 205
 						      0x02 /* Version */ ))!=0){
209 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 209
 		       strerror ( rc ) );
213 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 216
 	/* Destroy temporary PCI device */
220
-	efipci_destroy ( efidrv, efipci );
217
+	efipci_destroy ( efipci );
221 218
 
222 219
 	return 0;
223 220
 
224 221
  err_cannot_register:
225 222
  err_not_bofm:
226 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 231
  * Attach driver to device
234 232
  *
235
- * @v driver		EFI driver
236 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 237
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
246 238
 	union {
247 239
 		IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL *bofm1;
@@ -258,14 +250,19 @@ static EFI_STATUS EFIAPI efi_bofm_start ( EFI_DRIVER_BINDING_PROTOCOL *driver,
258 250
 	EFI_STATUS efirc;
259 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 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 265
 		goto err_create;
268
-	}
269 266
 
270 267
 	/* Enable PCI device */
271 268
 	if ( ( rc = efipci_enable ( efipci ) ) != 0 )
@@ -275,51 +272,51 @@ static EFI_STATUS EFIAPI efi_bofm_start ( EFI_DRIVER_BINDING_PROTOCOL *driver,
275 272
 	if ( ( efirc = bs->LocateProtocol ( &bofm1_protocol_guid, NULL,
276 273
 					    &bofm1.interface ) ) != 0 ) {
277 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 277
 		goto err_locate_bofm;
281 278
 	}
282 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 282
 	       bofmtab->Parameters.Length );
286 283
 
287 284
 	/* Locate BOFM2 protocol, if available */
288 285
 	if ( ( efirc = bs->LocateProtocol ( &bofm2_protocol_guid, NULL,
289 286
 					    &bofm2.interface ) ) == 0 ) {
290 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 291
 		assert ( bofm2.bofm2->RegisterSupport ==
295 292
 			 bofm1.bofm1->RegisterSupport );
296 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 296
 		/* Not a fatal error; may be a BOFM1-only system */
300 297
 		bofmtab2 = NULL;
301 298
 	}
302 299
 
303 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 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 309
 	bofmrc = bofm ( virt_to_user ( bofmtab2 ? bofmtab2 : bofmtab ),
313 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 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 322
 	/* Return BOFM status */
@@ -327,8 +324,9 @@ static EFI_STATUS EFIAPI efi_bofm_start ( EFI_DRIVER_BINDING_PROTOCOL *driver,
327 324
 		if ( ( efirc = bofm2.bofm2->SetStatus ( bofm2.bofm2, device,
328 325
 							FALSE, bofmrc ) ) != 0){
329 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 330
 			       strerror ( rc ) );
333 331
 			goto err_set_status;
334 332
 		}
@@ -336,84 +334,42 @@ static EFI_STATUS EFIAPI efi_bofm_start ( EFI_DRIVER_BINDING_PROTOCOL *driver,
336 334
 		if ( ( efirc = bofm1.bofm1->SetStatus ( bofm1.bofm1, device,
337 335
 							FALSE, bofmrc ) ) != 0){
338 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 340
 			       strerror ( rc ) );
342 341
 			goto err_set_status;
343 342
 		}
344 343
 	}
345 344
 
346 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 348
 	/* BOFM (ab)uses the "start" method to mean "process and exit" */
350
-	return EFI_NOT_READY;
349
+	return -EAGAIN;
351 350
 
352 351
  err_set_status:
353 352
  err_locate_bofm:
354 353
  err_enable:
355
-	efipci_destroy ( efidrv, efipci );
354
+	efipci_destroy ( efipci );
356 355
  err_create:
357
-	return EFIRC ( rc );
356
+ err_already_started:
357
+	return rc;
358 358
 }
359 359
 
360 360
 /**
361 361
  * Detach driver from device
362 362
  *
363
- * @v driver		EFI driver
364 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 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,6 +36,8 @@ FILE_LICENCE ( GPL2_OR_LATER );
36 36
  *
37 37
  */
38 38
 
39
+static EFI_DRIVER_BINDING_PROTOCOL efi_driver_binding;
40
+
39 41
 /** EFI driver binding protocol GUID */
40 42
 static EFI_GUID efi_driver_binding_protocol_guid
41 43
 	= EFI_DRIVER_BINDING_PROTOCOL_GUID;
@@ -62,6 +64,116 @@ EFI_DEVICE_PATH_PROTOCOL * efi_devpath_end ( EFI_DEVICE_PATH_PROTOCOL *path ) {
62 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 178
  * Look up driver name
67 179
  *
@@ -71,12 +183,12 @@ EFI_DEVICE_PATH_PROTOCOL * efi_devpath_end ( EFI_DEVICE_PATH_PROTOCOL *path ) {
71 183
  * @ret efirc		EFI status code
72 184
  */
73 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 192
 	return 0;
81 193
 }
82 194
 
@@ -91,9 +203,9 @@ efi_driver_get_driver_name ( EFI_COMPONENT_NAME2_PROTOCOL *wtf,
91 203
  * @ret efirc		EFI status code
92 204
  */
93 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 209
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
98 210
 	union {
99 211
 		EFI_COMPONENT_NAME2_PROTOCOL *name2;
@@ -118,43 +230,139 @@ efi_driver_get_controller_name ( EFI_COMPONENT_NAME2_PROTOCOL *wtf __unused,
118 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 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 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 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 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 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 360
  * Connect/disconnect EFI driver from all handles
150 361
  *
151
- * @v efidrv		EFI driver
152 362
  * @v method		Connect/disconnect method
153 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 366
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
159 367
 	EFI_HANDLE *handles;
160 368
 	UINTN num_handles;
@@ -167,87 +375,55 @@ static int efi_driver_handles ( struct efi_driver *efidrv,
167 375
 						&num_handles,
168 376
 						&handles ) ) != 0 ) {
169 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 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 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,12 +21,10 @@ FILE_LICENCE ( GPL2_OR_LATER );
21 21
 
22 22
 #include <string.h>
23 23
 #include <errno.h>
24
+#include <ipxe/init.h>
24 25
 #include <ipxe/efi/efi.h>
25 26
 #include <ipxe/efi/efi_driver.h>
26 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 29
 /** Image handle passed to entry point */
32 30
 EFI_HANDLE efi_image_handle;
@@ -47,61 +45,6 @@ static EFI_EVENT efi_shutdown_event;
47 45
 /* Forward declarations */
48 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 49
  * Shut down in preparation for booting an OS.
107 50
  *
@@ -153,18 +96,24 @@ EFI_STATUS efi_init ( EFI_HANDLE image_handle,
153 96
 	efi_systab = systab;
154 97
 
155 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 107
 	if ( ! systab->BootServices ) {
161 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 112
 	if ( ! systab->RuntimeServices ) {
165 113
 		DBGC ( systab, "EFI provided no RuntimeServices entry "
166 114
 		       "point\n" );
167
-		return EFI_NOT_AVAILABLE_YET;
115
+		efirc = EFI_NOT_AVAILABLE_YET;
116
+		goto err_sanity;
168 117
 	}
169 118
 	DBGC ( systab, "EFI handle %p systab %p\n", image_handle, systab );
170 119
 	bs = systab->BootServices;
@@ -181,7 +130,7 @@ EFI_STATUS efi_init ( EFI_HANDLE image_handle,
181 130
 			       efi_guid_ntoa ( &prot->guid ) );
182 131
 			/* Fail if protocol is required */
183 132
 			if ( prot->required )
184
-				return efirc;
133
+				goto err_missing_protocol;
185 134
 		}
186 135
 	}
187 136
 
@@ -193,8 +142,10 @@ EFI_STATUS efi_init ( EFI_HANDLE image_handle,
193 142
 		} else {
194 143
 			DBGC ( systab, "EFI does not provide configuration "
195 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,7 +157,7 @@ EFI_STATUS efi_init ( EFI_HANDLE image_handle,
206 157
 		rc = -EEFI ( efirc );
207 158
 		DBGC ( systab, "EFI could not get loaded image protocol: %s",
208 159
 		       strerror ( rc ) );
209
-		return efirc;
160
+		goto err_no_loaded_image;
210 161
 	}
211 162
 	efi_loaded_image = loaded_image;
212 163
 	DBGC ( systab, "EFI image base address %p\n",
@@ -223,23 +174,31 @@ EFI_STATUS efi_init ( EFI_HANDLE image_handle,
223 174
 		rc = -EEFI ( efirc );
224 175
 		DBGC ( systab, "EFI could not create ExitBootServices event: "
225 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 188
 	/* Install image unload method */
240 189
 	efi_loaded_image->Unload = efi_unload;
241 190
 
242 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,12 +215,15 @@ static EFI_STATUS EFIAPI efi_unload ( EFI_HANDLE image_handle __unused ) {
256 215
 	/* Shut down */
257 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 224
 	/* Uninstall exit boot services event */
260 225
 	bs->CloseEvent ( efi_shutdown_event );
261 226
 
262
-	/* Uninstall loaded image driver */
263
-	efi_driver_uninstall ( &efi_image_driver );
264
-
265 227
 	DBGC ( systab, "EFI image unloaded\n" );
266 228
 
267 229
 	return 0;

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

@@ -22,7 +22,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
22 22
 #include <stdlib.h>
23 23
 #include <errno.h>
24 24
 #include <ipxe/pci.h>
25
-#include <ipxe/init.h>
26 25
 #include <ipxe/efi/efi.h>
27 26
 #include <ipxe/efi/efi_pci.h>
28 27
 #include <ipxe/efi/efi_driver.h>
@@ -35,6 +34,22 @@ FILE_LICENCE ( GPL2_OR_LATER );
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 55
  * iPXE PCI API
@@ -119,14 +134,14 @@ static LIST_HEAD ( efi_pci_devices );
119 134
 /**
120 135
  * Create EFI PCI device
121 136
  *
122
- * @v efidrv		EFI driver
123 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 144
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
129
-	struct efi_pci_device *efipci;
130 145
 	union {
131 146
 		EFI_PCI_IO_PROTOCOL *pci_io;
132 147
 		void *interface;
@@ -140,25 +155,26 @@ struct efi_pci_device * efipci_create ( struct efi_driver *efidrv,
140 155
 	int rc;
141 156
 
142 157
 	/* Allocate PCI device */
143
-	efipci = zalloc ( sizeof ( *efipci ) );
144
-	if ( ! efipci )
158
+	*efipci = zalloc ( sizeof ( **efipci ) );
159
+	if ( ! *efipci ) {
160
+		rc = -ENOMEM;
145 161
 		goto err_zalloc;
146
-	efipci->device = device;
147
-	efipci->efidrv = efidrv;
162
+	}
163
+	(*efipci)->device = device;
148 164
 
149 165
 	/* See if device is a PCI device */
150 166
 	if ( ( efirc = bs->OpenProtocol ( device,
151 167
 					  &efi_pci_io_protocol_guid,
152 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 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 179
 	/* Get PCI bus:dev.fn address */
164 180
 	if ( ( efirc = pci_io.pci_io->GetLocation ( pci_io.pci_io,
@@ -166,54 +182,53 @@ struct efi_pci_device * efipci_create ( struct efi_driver *efidrv,
166 182
 						    &pci_bus, &pci_dev,
167 183
 						    &pci_fn ) ) != 0 ) {
168 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 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 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 201
 		goto err_pci_read_config;
185 202
 	}
186 203
 
187 204
 	/* Retrieve device path */
188 205
 	if ( ( efirc = bs->OpenProtocol ( device,
189 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 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 212
 		goto err_no_device_path;
198 213
 	}
199
-	efipci->path = path.path;
214
+	(*efipci)->path = path.path;
200 215
 
201 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 221
 	bs->CloseProtocol ( device, &efi_device_path_protocol_guid,
207
-			    efidrv->driver.DriverBindingHandle, device );
222
+			    efi_image_handle, device );
208 223
  err_no_device_path:
209 224
  err_pci_read_config:
210 225
  err_get_location:
211 226
 	bs->CloseProtocol ( device, &efi_pci_io_protocol_guid,
212
-			    efidrv->driver.DriverBindingHandle, device );
227
+			    efi_image_handle, device );
213 228
  err_open_protocol:
214
-	free ( efipci );
229
+	free ( *efipci );
215 230
  err_zalloc:
216
-	return NULL;
231
+	return rc;
217 232
 }
218 233
 
219 234
 /**
@@ -282,7 +297,6 @@ struct efi_pci_device * efipci_find ( struct device *dev ) {
282 297
  */
283 298
 int efipci_child_add ( struct efi_pci_device *efipci, EFI_HANDLE device ) {
284 299
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
285
-	struct efi_driver *efidrv = efipci->efidrv;
286 300
 	union {
287 301
 		EFI_PCI_IO_PROTOCOL *pci_io;
288 302
 		void *interface;
@@ -294,16 +308,21 @@ int efipci_child_add ( struct efi_pci_device *efipci, EFI_HANDLE device ) {
294 308
 	if ( ( efirc = bs->OpenProtocol ( efipci->device,
295 309
 					  &efi_pci_io_protocol_guid,
296 310
 					  &pci_io.interface,
297
-					  efidrv->driver.DriverBindingHandle,
298
-					  device,
311
+					  efi_image_handle, device,
299 312
 					  EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
300 313
 					  ) ) != 0 ) {
301 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 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 326
 	return 0;
308 327
 }
309 328
 
@@ -316,29 +335,28 @@ int efipci_child_add ( struct efi_pci_device *efipci, EFI_HANDLE device ) {
316 335
  */
317 336
 void efipci_child_del ( struct efi_pci_device *efipci, EFI_HANDLE device ) {
318 337
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
319
-	struct efi_driver *efidrv = efipci->efidrv;
320 338
 
321 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 348
  * Destroy EFI PCI device
327 349
  *
328
- * @v efidrv		EFI driver
329 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 353
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
334 354
 
335 355
 	list_del ( &efipci->list );
336 356
 	bs->CloseProtocol ( efipci->device, &efi_device_path_protocol_guid,
337
-			    efidrv->driver.DriverBindingHandle,
338
-			    efipci->device );
357
+			    efi_image_handle, efipci->device );
339 358
 	bs->CloseProtocol ( efipci->device, &efi_pci_io_protocol_guid,
340
-			    efidrv->driver.DriverBindingHandle,
341
-			    efipci->device );
359
+			    efi_image_handle, efipci->device );
342 360
 	free ( efipci );
343 361
 }
344 362
 
@@ -352,79 +370,78 @@ void efipci_destroy ( struct efi_driver *efidrv,
352 370
 /**
353 371
  * Check to see if driver supports a device
354 372
  *
355
- * @v driver		EFI driver
356 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 377
 	struct efi_pci_device *efipci;
366 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 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 394
 	/* Look for a driver */
379 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 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 404
 	/* Destroy temporary PCI device */
389
-	efipci_destroy ( efidrv, efipci );
405
+	efipci_destroy ( efipci );
390 406
 
391 407
 	return 0;
392 408
 
393 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 417
  * Attach driver to device
401 418
  *
402
- * @v driver		EFI driver
403 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 423
 	struct efi_pci_device *efipci;
413 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 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 439
 		goto err_create;
422
-	}
423 440
 
424 441
 	/* Find driver */
425 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 445
 		goto err_find_driver;
429 446
 	}
430 447
 
@@ -434,11 +451,13 @@ efipci_start ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device,
434 451
 
435 452
 	/* Probe driver */
436 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 456
 		       efipci->pci.id->name, strerror ( rc ) );
440 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 462
 	return 0;
444 463
 
@@ -446,93 +465,36 @@ efipci_start ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device,
446 465
  err_probe:
447 466
  err_enable:
448 467
  err_find_driver:
449
-	efipci_destroy ( efidrv, efipci );
468
+	efipci_destroy ( efipci );
450 469
  err_create:
451
-	return EFIRC ( rc );
470
+ err_already_started:
471
+	return rc;
452 472
 }
453 473
 
454 474
 /**
455 475
  * Detach driver from device
456 476
  *
457
- * @v driver		EFI driver
458 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 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 482
 	/* Find PCI device */
475 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 487
 	/* Remove device */
482 488
 	pci_remove ( &efipci->pci );
483 489
 
484 490
 	/* Delete EFI PCI device */
485
-	efipci_destroy ( efidrv, efipci );
486
-
487
-	return 0;
491
+	efipci_destroy ( efipci );
488 492
 }
489 493
 
490 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