Procházet zdrojové kódy

[efi] Allow EFI to control PCI bus enumeration

EFI performs its own PCI bus enumeration.  Respect this, and start
controlling devices only when instructed to do so by EFI.

As a side benefit, we should now correctly create multiple SNP
instances for multi-port devices.

This should also fix the problem of failing to enumerate devices
because the PCI bridges have not yet been enabled at the time the iPXE
driver is loaded.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown před 13 roky
rodič
revize
d7736fbb7b

+ 3
- 2
src/arch/x86/prefix/efidrvprefix.c Zobrazit soubor

@@ -41,6 +41,7 @@ EFI_STATUS EFIAPI _efidrv_start ( EFI_HANDLE image_handle,
41 41
 	initialise();
42 42
 	startup();
43 43
 
44
-	/* Install SNP driver and return */
45
-	return RC_TO_EFIRC ( efi_snp_install () );
44
+	return 0;
46 45
 }
46
+
47
+REQUIRE_OBJECT ( efi_snp );

+ 0
- 1
src/include/ipxe/efi/efi.h Zobrazit soubor

@@ -142,6 +142,5 @@ extern EFI_SYSTEM_TABLE *efi_systab;
142 142
 extern const char * efi_strerror ( EFI_STATUS efirc );
143 143
 extern EFI_STATUS efi_init ( EFI_HANDLE image_handle,
144 144
 			     EFI_SYSTEM_TABLE *systab );
145
-extern int efi_snp_install ( void );
146 145
 
147 146
 #endif /* _IPXE_EFI_H */

+ 49
- 0
src/include/ipxe/efi/efi_driver.h Zobrazit soubor

@@ -0,0 +1,49 @@
1
+#ifndef _IPXE_EFI_DRIVER_H
2
+#define _IPXE_EFI_DRIVER_H
3
+
4
+/** @file
5
+ *
6
+ * EFI driver interface
7
+ */
8
+
9
+FILE_LICENCE ( GPL2_OR_LATER );
10
+
11
+#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>
15
+
16
+/** An EFI driver */
17
+struct efi_driver {
18
+	/** Name */
19
+	const char *name;
20
+	/** EFI name */
21
+	CHAR16 *wname;
22
+	/** EFI driver binding protocol */
23
+	EFI_DRIVER_BINDING_PROTOCOL driver;
24
+	/** EFI component name protocol */
25
+	EFI_COMPONENT_NAME2_PROTOCOL wtf;
26
+};
27
+
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
+	} }
43
+
44
+extern EFI_DEVICE_PATH_PROTOCOL *
45
+efi_devpath_end ( EFI_DEVICE_PATH_PROTOCOL *path );
46
+
47
+extern EFI_STATUS efi_driver_install ( struct efi_driver *efidrv );
48
+
49
+#endif /* _IPXE_EFI_DRIVER_H */

+ 40
- 0
src/include/ipxe/efi/efi_pci.h Zobrazit soubor

@@ -0,0 +1,40 @@
1
+#ifndef _IPXE_EFI_PCI_H
2
+#define _IPXE_EFI_PCI_H
3
+
4
+/** @file
5
+ *
6
+ * EFI driver interface
7
+ */
8
+
9
+FILE_LICENCE ( GPL2_OR_LATER );
10
+
11
+#include <ipxe/efi/efi.h>
12
+#include <ipxe/efi/Protocol/PciIo.h>
13
+#include <ipxe/efi/Protocol/DevicePath.h>
14
+
15
+struct efi_driver;
16
+struct device;
17
+
18
+/** An EFI PCI device */
19
+struct efi_pci_device {
20
+	/** List of EFI PCI devices */
21
+	struct list_head list;
22
+	/** iPXE PCI device */
23
+	struct pci_device pci;
24
+	/** Underlying EFI device */
25
+	EFI_HANDLE device;
26
+	/** PCI I/O protocol */
27
+	EFI_PCI_IO_PROTOCOL *pci_io;
28
+	/** Device path */
29
+	EFI_DEVICE_PATH_PROTOCOL *path;
30
+};
31
+
32
+extern struct efi_pci_device * efipci_create ( struct efi_driver *efidrv,
33
+					       EFI_HANDLE device );
34
+extern EFI_STATUS efipci_enable ( struct efi_pci_device *efipci );
35
+extern struct efi_pci_device * efipci_find_efi ( EFI_HANDLE device );
36
+extern struct efi_pci_device * efipci_find ( struct device *dev );
37
+extern void efipci_destroy ( struct efi_driver *efidrv,
38
+			     struct efi_pci_device *efipci );
39
+
40
+#endif /* _IPXE_EFI_PCI_H */

+ 143
- 0
src/interface/efi/efi_driver.c Zobrazit soubor

@@ -0,0 +1,143 @@
1
+/*
2
+ * Copyright (C) 2011 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+FILE_LICENCE ( GPL2_OR_LATER );
20
+
21
+#include <stddef.h>
22
+#include <stdio.h>
23
+#include <ipxe/efi/efi.h>
24
+#include <ipxe/efi/Protocol/DriverBinding.h>
25
+#include <ipxe/efi/Protocol/ComponentName2.h>
26
+#include <ipxe/efi/efi_driver.h>
27
+#include <config/general.h>
28
+
29
+/** @file
30
+ *
31
+ * EFI driver interface
32
+ *
33
+ */
34
+
35
+/** EFI driver binding protocol GUID */
36
+static EFI_GUID efi_driver_binding_protocol_guid
37
+	= EFI_DRIVER_BINDING_PROTOCOL_GUID;
38
+
39
+/** EFI component name protocol GUID */
40
+static EFI_GUID efi_component_name2_protocol_guid
41
+	= EFI_COMPONENT_NAME2_PROTOCOL_GUID;
42
+
43
+/**
44
+ * Find end of device path
45
+ *
46
+ * @v path		Path to device
47
+ * @ret path_end	End of device path
48
+ */
49
+EFI_DEVICE_PATH_PROTOCOL * efi_devpath_end ( EFI_DEVICE_PATH_PROTOCOL *path ) {
50
+
51
+	while ( path->Type != END_DEVICE_PATH_TYPE ) {
52
+		path = ( ( ( void * ) path ) +
53
+			 /* There's this amazing new-fangled thing known as
54
+			  * a UINT16, but who wants to use one of those? */
55
+			 ( ( path->Length[1] << 8 ) | path->Length[0] ) );
56
+	}
57
+
58
+	return path;
59
+}
60
+
61
+/**
62
+ * Look up driver name
63
+ *
64
+ * @v wtf		Component name protocol
65
+ * @v language		Language to use
66
+ * @v driver_name	Driver name to fill in
67
+ * @ret efirc		EFI status code
68
+ */
69
+static EFI_STATUS EFIAPI
70
+efi_driver_get_driver_name ( EFI_COMPONENT_NAME2_PROTOCOL *wtf,
71
+			     CHAR8 *language __unused, CHAR16 **driver_name ) {
72
+	struct efi_driver *efidrv =
73
+		container_of ( wtf, struct efi_driver, wtf );
74
+
75
+	*driver_name = efidrv->wname;
76
+	return 0;
77
+}
78
+
79
+/**
80
+ * Look up controller name
81
+ *
82
+ * @v wtf		Component name protocol
83
+ * @v device		Device
84
+ * @v child		Child device, or NULL
85
+ * @v language		Language to use
86
+ * @v driver_name	Device name to fill in
87
+ * @ret efirc		EFI status code
88
+ */
89
+static EFI_STATUS EFIAPI
90
+efi_driver_get_controller_name ( EFI_COMPONENT_NAME2_PROTOCOL *wtf __unused,
91
+				 EFI_HANDLE device __unused,
92
+				 EFI_HANDLE child __unused,
93
+				 CHAR8 *language __unused,
94
+				 CHAR16 **controller_name __unused ) {
95
+
96
+	/* Just let EFI use the default Device Path Name */
97
+	return EFI_UNSUPPORTED;
98
+}
99
+
100
+/**
101
+ * Install EFI driver
102
+ *
103
+ * @v efidrv		EFI driver
104
+ * @ret efirc		EFI status code
105
+ */
106
+EFI_STATUS efi_driver_install ( struct efi_driver *efidrv ) {
107
+	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
108
+	EFI_DRIVER_BINDING_PROTOCOL *driver = &efidrv->driver;
109
+	EFI_COMPONENT_NAME2_PROTOCOL *wtf = &efidrv->wtf;
110
+	char buf[ sizeof ( efidrv->wname ) / sizeof ( efidrv->wname[0] ) ];
111
+	unsigned int i;
112
+	EFI_STATUS efirc;
113
+
114
+	/* Configure driver binding protocol */
115
+	driver->ImageHandle = efi_image_handle;
116
+
117
+	/* Configure component name protocol */
118
+	wtf->GetDriverName = efi_driver_get_driver_name;
119
+	wtf->GetControllerName = efi_driver_get_controller_name;
120
+	wtf->SupportedLanguages = "en";
121
+
122
+	/* Fill in driver name */
123
+	snprintf ( buf, sizeof ( buf ), PRODUCT_SHORT_NAME " - %s",
124
+		   efidrv->name );
125
+	for ( i = 0 ; i < sizeof ( buf ) ; i++ ) {
126
+		/* Damn Unicode names */
127
+		efidrv->wname[i] = *( ( ( unsigned char * ) buf ) + i );
128
+	}
129
+
130
+	/* Install driver */
131
+	if ( ( efirc = bs->InstallMultipleProtocolInterfaces (
132
+			&driver->DriverBindingHandle,
133
+			&efi_driver_binding_protocol_guid, driver,
134
+			&efi_component_name2_protocol_guid, wtf,
135
+			NULL ) ) != 0 ) {
136
+		DBGC ( efidrv, "EFIDRV %s could not install protocol: %s\n",
137
+		       efidrv->name, efi_strerror ( efirc ) );
138
+		return efirc;
139
+	}
140
+
141
+	DBGC ( efidrv, "EFIDRV %s installed\n", efidrv->name );
142
+	return 0;
143
+}

+ 378
- 0
src/interface/efi/efi_pci.c Zobrazit soubor

@@ -18,9 +18,14 @@
18 18
 
19 19
 FILE_LICENCE ( GPL2_OR_LATER );
20 20
 
21
+#include <stdlib.h>
21 22
 #include <errno.h>
22 23
 #include <ipxe/pci.h>
24
+#include <ipxe/init.h>
23 25
 #include <ipxe/efi/efi.h>
26
+#include <ipxe/efi/efi_pci.h>
27
+#include <ipxe/efi/efi_driver.h>
28
+#include <ipxe/efi/Protocol/PciIo.h>
24 29
 #include <ipxe/efi/Protocol/PciRootBridgeIo.h>
25 30
 
26 31
 /** @file
@@ -29,6 +34,13 @@ FILE_LICENCE ( GPL2_OR_LATER );
29 34
  *
30 35
  */
31 36
 
37
+/******************************************************************************
38
+ *
39
+ * iPXE PCI API
40
+ *
41
+ ******************************************************************************
42
+ */
43
+
32 44
 /** PCI root bridge I/O protocol */
33 45
 static EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *efipci;
34 46
 EFI_REQUIRE_PROTOCOL ( EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL, &efipci );
@@ -80,3 +92,369 @@ PROVIDE_PCIAPI_INLINE ( efi, pci_read_config_dword );
80 92
 PROVIDE_PCIAPI_INLINE ( efi, pci_write_config_byte );
81 93
 PROVIDE_PCIAPI_INLINE ( efi, pci_write_config_word );
82 94
 PROVIDE_PCIAPI_INLINE ( efi, pci_write_config_dword );
95
+
96
+/******************************************************************************
97
+ *
98
+ * EFI PCI device instantiation
99
+ *
100
+ ******************************************************************************
101
+ */
102
+
103
+/** EFI PCI I/O protocol GUID */
104
+static EFI_GUID efi_pci_io_protocol_guid
105
+	= EFI_PCI_IO_PROTOCOL_GUID;
106
+
107
+/** EFI device path protocol GUID */
108
+static EFI_GUID efi_device_path_protocol_guid
109
+	= EFI_DEVICE_PATH_PROTOCOL_GUID;
110
+
111
+/** EFI PCI devices */
112
+static LIST_HEAD ( efi_pci_devices );
113
+
114
+/**
115
+ * Create EFI PCI device
116
+ *
117
+ * @v efidrv		EFI driver
118
+ * @v device		EFI device
119
+ * @ret efipci		EFI PCI device, or NULL
120
+ */
121
+struct efi_pci_device * efipci_create ( struct efi_driver *efidrv,
122
+					EFI_HANDLE device ) {
123
+	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
124
+	struct efi_pci_device *efipci;
125
+	union {
126
+		EFI_PCI_IO_PROTOCOL *pci_io;
127
+		void *interface;
128
+	} pci_io;
129
+	union {
130
+		EFI_DEVICE_PATH_PROTOCOL *path;
131
+		void *interface;
132
+	} path;
133
+	UINTN pci_segment, pci_bus, pci_dev, pci_fn;
134
+	EFI_STATUS efirc;
135
+	int rc;
136
+
137
+	/* Allocate PCI device */
138
+	efipci = zalloc ( sizeof ( *efipci ) );
139
+	if ( ! efipci )
140
+		goto err_zalloc;
141
+	efipci->device = device;
142
+
143
+	/* See if device is a PCI device */
144
+	if ( ( efirc = bs->OpenProtocol ( device,
145
+					  &efi_pci_io_protocol_guid,
146
+					  &pci_io.interface,
147
+					  efidrv->driver.DriverBindingHandle,
148
+					  device,
149
+					  EFI_OPEN_PROTOCOL_BY_DRIVER )) !=0 ){
150
+		DBGCP ( efipci, "EFIPCI device %p is not a PCI device\n",
151
+			device );
152
+		goto err_open_protocol;
153
+	}
154
+	efipci->pci_io = pci_io.pci_io;
155
+
156
+	/* Get PCI bus:dev.fn address */
157
+	if ( ( efirc = pci_io.pci_io->GetLocation ( pci_io.pci_io,
158
+						    &pci_segment,
159
+						    &pci_bus, &pci_dev,
160
+						    &pci_fn ) ) != 0 ) {
161
+		DBGC ( efipci, "EFIPCI device %p could not get PCI "
162
+		       "location: %s\n", device, efi_strerror ( efirc ) );
163
+		goto err_get_location;
164
+	}
165
+	DBGC2 ( efipci, "EFIPCI device %p is PCI %04lx:%02lx:%02lx.%lx\n",
166
+		device, ( ( unsigned long ) pci_segment ),
167
+		( ( unsigned long ) pci_bus ), ( ( unsigned long ) pci_dev ),
168
+		( ( unsigned long ) pci_fn ) );
169
+
170
+	/* Populate PCI device */
171
+	pci_init ( &efipci->pci, PCI_BUSDEVFN ( pci_bus, pci_dev, pci_fn ) );
172
+	if ( ( rc = pci_read_config ( &efipci->pci ) ) != 0 ) {
173
+		DBGC ( efipci, "EFIPCI " PCI_FMT " cannot read PCI "
174
+		       "configuration: %s\n",
175
+		       PCI_ARGS ( &efipci->pci ), strerror ( rc ) );
176
+		goto err_pci_read_config;
177
+	}
178
+
179
+	/* Retrieve device path */
180
+	if ( ( efirc = bs->OpenProtocol ( device,
181
+					  &efi_device_path_protocol_guid,
182
+					  &path.interface,
183
+					  efidrv->driver.DriverBindingHandle,
184
+					  device,
185
+					  EFI_OPEN_PROTOCOL_BY_DRIVER )) !=0 ){
186
+		DBGC ( efipci, "EFIPCI " PCI_FMT " has no device path\n",
187
+		       PCI_ARGS ( &efipci->pci ) );
188
+		goto err_no_device_path;
189
+	}
190
+	efipci->path = path.path;
191
+
192
+	/* Add to list of PCI devices */
193
+	list_add ( &efipci->list, &efi_pci_devices );
194
+
195
+	return efipci;
196
+
197
+	bs->CloseProtocol ( device, &efi_device_path_protocol_guid,
198
+			    efidrv->driver.DriverBindingHandle, device );
199
+ err_no_device_path:
200
+ err_pci_read_config:
201
+ err_get_location:
202
+	bs->CloseProtocol ( device, &efi_pci_io_protocol_guid,
203
+			    efidrv->driver.DriverBindingHandle, device );
204
+ err_open_protocol:
205
+	free ( efipci );
206
+ err_zalloc:
207
+	return NULL;
208
+}
209
+
210
+/**
211
+ * Enable EFI PCI device
212
+ *
213
+ * @v efipci		EFI PCI device
214
+ * @ret efirc		EFI status code
215
+ */
216
+EFI_STATUS efipci_enable ( struct efi_pci_device *efipci ) {
217
+	EFI_PCI_IO_PROTOCOL *pci_io = efipci->pci_io;
218
+	EFI_STATUS efirc;
219
+
220
+	/* Enable device */
221
+	if ( ( efirc = pci_io->Attributes ( pci_io,
222
+					    EfiPciIoAttributeOperationSet,
223
+					    EFI_PCI_DEVICE_ENABLE,
224
+					    NULL ) ) != 0 ) {
225
+		DBGC ( efipci, "EFIPCI " PCI_FMT " could not be enabled: %s\n",
226
+		       PCI_ARGS ( &efipci->pci ), efi_strerror ( efirc ) );
227
+		return efirc;
228
+	}
229
+
230
+	return 0;
231
+}
232
+
233
+/**
234
+ * Find EFI PCI device by EFI device
235
+ *
236
+ * @v device		EFI device
237
+ * @ret efipci		EFI PCI device, or NULL
238
+ */
239
+struct efi_pci_device * efipci_find_efi ( EFI_HANDLE device ) {
240
+	struct efi_pci_device *efipci;
241
+
242
+	list_for_each_entry ( efipci, &efi_pci_devices, list ) {
243
+		if ( efipci->device == device )
244
+			return efipci;
245
+	}
246
+	return NULL;
247
+}
248
+
249
+/**
250
+ * Find EFI PCI device by iPXE device
251
+ *
252
+ * @v dev		Device
253
+ * @ret efipci		EFI PCI device, or NULL
254
+ */
255
+struct efi_pci_device * efipci_find ( struct device *dev ) {
256
+	struct efi_pci_device *efipci;
257
+
258
+	list_for_each_entry ( efipci, &efi_pci_devices, list ) {
259
+		if ( &efipci->pci.dev == dev )
260
+			return efipci;
261
+	}
262
+	return NULL;
263
+}
264
+
265
+/**
266
+ * Destroy EFI PCI device
267
+ *
268
+ * @v efidrv		EFI driver
269
+ * @v efipci		EFI PCI device
270
+ */
271
+void efipci_destroy ( struct efi_driver *efidrv,
272
+		      struct efi_pci_device *efipci ) {
273
+	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
274
+
275
+	list_del ( &efipci->list );
276
+	bs->CloseProtocol ( efipci->device, &efi_device_path_protocol_guid,
277
+			    efidrv->driver.DriverBindingHandle,
278
+			    efipci->device );
279
+	bs->CloseProtocol ( efipci->device, &efi_pci_io_protocol_guid,
280
+			    efidrv->driver.DriverBindingHandle,
281
+			    efipci->device );
282
+	free ( efipci );
283
+}
284
+
285
+/******************************************************************************
286
+ *
287
+ * EFI PCI driver
288
+ *
289
+ ******************************************************************************
290
+ */
291
+
292
+/**
293
+ * Check to see if driver supports a device
294
+ *
295
+ * @v driver		EFI driver
296
+ * @v device		EFI device
297
+ * @v child		Path to child device, if any
298
+ * @ret efirc		EFI status code
299
+ */
300
+static EFI_STATUS EFIAPI
301
+efipci_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device,
302
+		   EFI_DEVICE_PATH_PROTOCOL *child ) {
303
+	struct efi_driver *efidrv =
304
+		container_of ( driver, struct efi_driver, driver );
305
+	struct efi_pci_device *efipci;
306
+	EFI_STATUS efirc;
307
+	int rc;
308
+
309
+	DBGCP ( efidrv, "EFIPCI DRIVER_SUPPORTED %p (%p)\n", device, child );
310
+
311
+	/* Create temporary corresponding PCI device, if any */
312
+	efipci = efipci_create ( efidrv, device );
313
+	if ( ! efipci ) {
314
+		/* Non-PCI devices are simply unsupported */
315
+		efirc = EFI_UNSUPPORTED;
316
+		goto err_not_pci;
317
+	}
318
+
319
+	/* Look for a driver */
320
+	if ( ( rc = pci_find_driver ( &efipci->pci ) ) != 0 ) {
321
+		DBGCP ( efipci, "EFIPCI " PCI_FMT " has no driver\n",
322
+			PCI_ARGS ( &efipci->pci ) );
323
+		efirc = EFI_UNSUPPORTED;
324
+		goto err_no_driver;
325
+	}
326
+
327
+	DBGC ( efipci, "EFIPCI " PCI_FMT " is supported by driver \"%s\"\n",
328
+	       PCI_ARGS ( &efipci->pci ), efipci->pci.id->name );
329
+
330
+	/* Destroy temporary PCI device */
331
+	efipci_destroy ( efidrv, efipci );
332
+
333
+	return 0;
334
+
335
+ err_no_driver:
336
+	efipci_destroy ( efidrv, efipci );
337
+ err_not_pci:
338
+	return efirc;
339
+}
340
+
341
+/**
342
+ * Attach driver to device
343
+ *
344
+ * @v driver		EFI driver
345
+ * @v device		EFI device
346
+ * @v child		Path to child device, if any
347
+ * @ret efirc		EFI status code
348
+ */
349
+static EFI_STATUS EFIAPI
350
+efipci_start ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device,
351
+	       EFI_DEVICE_PATH_PROTOCOL *child ) {
352
+	struct efi_driver *efidrv =
353
+		container_of ( driver, struct efi_driver, driver );
354
+	struct efi_pci_device *efipci;
355
+	EFI_STATUS efirc;
356
+	int rc;
357
+
358
+	DBGC ( efidrv, "EFIPCI DRIVER_START %p (%p)\n", device, child );
359
+
360
+	/* Create corresponding PCI device */
361
+	efipci = efipci_create ( efidrv, device );
362
+	if ( ! efipci ) {
363
+		efirc = EFI_OUT_OF_RESOURCES;
364
+		goto err_create;
365
+	}
366
+
367
+	/* Find driver */
368
+	if ( ( rc = pci_find_driver ( &efipci->pci ) ) != 0 ) {
369
+		DBGC ( efipci, "EFIPCI " PCI_FMT " has no driver\n",
370
+		       PCI_ARGS ( &efipci->pci ) );
371
+		efirc = RC_TO_EFIRC ( rc );
372
+		goto err_find_driver;
373
+	}
374
+
375
+	/* Enable PCI device */
376
+	if ( ( efirc = efipci_enable ( efipci ) ) != 0 )
377
+		goto err_enable;
378
+
379
+	/* Probe driver */
380
+	if ( ( rc = pci_probe ( &efipci->pci ) ) != 0 ) {
381
+		DBGC ( efipci, "EFIPCI " PCI_FMT " could not probe driver "
382
+		       "\"%s\": %s\n", PCI_ARGS ( &efipci->pci ),
383
+		       efipci->pci.id->name, strerror ( rc ) );
384
+		efirc = RC_TO_EFIRC ( rc );
385
+		goto err_probe;
386
+	}
387
+
388
+	return 0;
389
+
390
+	pci_remove ( &efipci->pci );
391
+ err_probe:
392
+ err_enable:
393
+ err_find_driver:
394
+	efipci_destroy ( efidrv, efipci );
395
+ err_create:
396
+	return efirc;
397
+}
398
+
399
+/**
400
+ * Detach driver from device
401
+ *
402
+ * @v driver		EFI driver
403
+ * @v device		EFI device
404
+ * @v pci		PCI device
405
+ * @v num_children	Number of child devices
406
+ * @v children		List of child devices
407
+ * @ret efirc		EFI status code
408
+ */
409
+static EFI_STATUS EFIAPI
410
+efipci_stop ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device,
411
+	      UINTN num_children, EFI_HANDLE *children ) {
412
+	struct efi_driver *efidrv =
413
+		container_of ( driver, struct efi_driver, driver );
414
+	struct efi_pci_device *efipci;
415
+
416
+	DBGC ( efidrv, "EFIPCI DRIVER_STOP %p (%ld %p)\n",
417
+	       device, ( ( unsigned long ) num_children ), children );
418
+
419
+	/* Find PCI device */
420
+	efipci = efipci_find_efi ( device );
421
+	if ( ! efipci ) {
422
+		DBGC ( efidrv, "EFIPCI device %p not started!\n", device );
423
+		return EFI_INVALID_PARAMETER;
424
+	}
425
+
426
+	/* Remove device */
427
+	pci_remove ( &efipci->pci );
428
+
429
+	/* Delete EFI PCI device */
430
+	efipci_destroy ( efidrv, efipci );
431
+
432
+	return 0;
433
+}
434
+
435
+/** EFI PCI driver */
436
+static struct efi_driver efipci_driver =
437
+	EFI_DRIVER_INIT ( "PCI", efipci_supported, efipci_start, efipci_stop );
438
+
439
+/**
440
+ * Install EFI PCI driver
441
+ *
442
+ */
443
+static void efipci_driver_init ( void ) {
444
+	struct efi_driver *efidrv = &efipci_driver;
445
+	EFI_STATUS efirc;
446
+
447
+	/* Install driver */
448
+	if ( ( efirc = efi_driver_install ( efidrv ) ) != 0 ) {
449
+		DBGC ( efidrv, "EFIPCI could not install driver: %s\n",
450
+		       efi_strerror ( efirc ) );
451
+		return;
452
+	}
453
+
454
+	DBGC ( efidrv, "EFIPCI driver installed\n" );
455
+}
456
+
457
+/** EFI PCI startup function */
458
+struct startup_fn startup_pci __startup_fn ( STARTUP_NORMAL ) = {
459
+	.startup = efipci_driver_init,
460
+};

+ 72
- 285
src/interface/efi/efi_snp.c Zobrazit soubor

@@ -28,12 +28,11 @@ FILE_LICENCE ( GPL2_OR_LATER );
28 28
 #include <ipxe/in.h>
29 29
 #include <ipxe/pci.h>
30 30
 #include <ipxe/efi/efi.h>
31
-#include <ipxe/efi/Protocol/DriverBinding.h>
32
-#include <ipxe/efi/Protocol/PciIo.h>
31
+#include <ipxe/efi/efi_pci.h>
32
+#include <ipxe/efi/efi_driver.h>
33 33
 #include <ipxe/efi/Protocol/SimpleNetwork.h>
34
-#include <ipxe/efi/Protocol/ComponentName2.h>
35 34
 #include <ipxe/efi/Protocol/NetworkInterfaceIdentifier.h>
36
-#include <config/general.h>
35
+#include <ipxe/efi/Protocol/DevicePath.h>
37 36
 
38 37
 /** @file
39 38
  *
@@ -43,6 +42,8 @@ FILE_LICENCE ( GPL2_OR_LATER );
43 42
 
44 43
 /** An SNP device */
45 44
 struct efi_snp_device {
45
+	/** List of SNP devices */
46
+	struct list_head list;
46 47
 	/** The underlying iPXE network device */
47 48
 	struct net_device *netdev;
48 49
 	/** EFI device handle */
@@ -81,14 +82,6 @@ struct efi_snp_device {
81 82
 static EFI_GUID efi_simple_network_protocol_guid
82 83
 	= EFI_SIMPLE_NETWORK_PROTOCOL_GUID;
83 84
 
84
-/** EFI driver binding protocol GUID */
85
-static EFI_GUID efi_driver_binding_protocol_guid
86
-	= EFI_DRIVER_BINDING_PROTOCOL_GUID;
87
-
88
-/** EFI component name protocol GUID */
89
-static EFI_GUID efi_component_name2_protocol_guid
90
-	= EFI_COMPONENT_NAME2_PROTOCOL_GUID;
91
-
92 85
 /** EFI device path protocol GUID */
93 86
 static EFI_GUID efi_device_path_protocol_guid
94 87
 	= EFI_DEVICE_PATH_PROTOCOL_GUID;
@@ -107,9 +100,8 @@ static EFI_GUID efi_nii31_protocol_guid = {
107 100
 	{ 0xBC, 0x81, 0x76, 0x7F, 0x1F, 0x97, 0x7A, 0x89 }
108 101
 };
109 102
 
110
-/** EFI PCI I/O protocol GUID */
111
-static EFI_GUID efi_pci_io_protocol_guid
112
-	= EFI_PCI_IO_PROTOCOL_GUID;
103
+/** List of SNP devices */
104
+static LIST_HEAD ( efi_snp_devices );
113 105
 
114 106
 /**
115 107
  * Set EFI SNP mode based on iPXE net device parameters
@@ -750,188 +742,58 @@ static EFI_SIMPLE_NETWORK_PROTOCOL efi_snp_device_snp = {
750 742
 };
751 743
 
752 744
 /**
753
- * Locate net device corresponding to EFI device
754
- *
755
- * @v driver		EFI driver
756
- * @v device		EFI device
757
- * @ret netdev		Net device, or NULL if not found
758
- */
759
-static struct net_device *
760
-efi_snp_netdev ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device ) {
761
-	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
762
-	union {
763
-		EFI_PCI_IO_PROTOCOL *pci;
764
-		void *interface;
765
-	} u;
766
-	UINTN pci_segment, pci_bus, pci_dev, pci_fn;
767
-	unsigned int pci_busdevfn;
768
-	struct net_device *netdev = NULL;
769
-	EFI_STATUS efirc;
770
-
771
-	/* See if device is a PCI device */
772
-	if ( ( efirc = bs->OpenProtocol ( device,
773
-					  &efi_pci_io_protocol_guid,
774
-					  &u.interface,
775
-					  driver->DriverBindingHandle,
776
-					  device,
777
-					  EFI_OPEN_PROTOCOL_BY_DRIVER )) !=0 ){
778
-		DBGCP ( driver, "SNPDRV %p device %p is not a PCI device\n",
779
-			driver, device );
780
-		goto out_no_pci_io;
781
-	}
782
-
783
-	/* Get PCI bus:dev.fn address */
784
-	if ( ( efirc = u.pci->GetLocation ( u.pci, &pci_segment, &pci_bus,
785
-					    &pci_dev, &pci_fn ) ) != 0 ) {
786
-		DBGC ( driver, "SNPDRV %p device %p could not get PCI "
787
-		       "location: %s\n",
788
-		       driver, device, efi_strerror ( efirc ) );
789
-		goto out_no_pci_location;
790
-	}
791
-	DBGCP ( driver, "SNPDRV %p device %p is PCI %04lx:%02lx:%02lx.%lx\n",
792
-		driver, device, ( ( unsigned long ) pci_segment ),
793
-		( ( unsigned long ) pci_bus ), ( ( unsigned long ) pci_dev ),
794
-		( ( unsigned long ) pci_fn ) );
795
-
796
-	/* Look up corresponding network device */
797
-	pci_busdevfn = PCI_BUSDEVFN ( pci_bus, pci_dev, pci_fn );
798
-	if ( ( netdev = find_netdev_by_location ( BUS_TYPE_PCI,
799
-						  pci_busdevfn ) ) == NULL ) {
800
-		DBGCP ( driver, "SNPDRV %p device %p is not a iPXE network "
801
-			"device\n", driver, device );
802
-		goto out_no_netdev;
803
-	}
804
-	DBGC ( driver, "SNPDRV %p device %p is %s\n",
805
-	       driver, device, netdev->name );
806
-
807
- out_no_netdev:
808
- out_no_pci_location:
809
-	bs->CloseProtocol ( device, &efi_pci_io_protocol_guid,
810
-			    driver->DriverBindingHandle, device );
811
- out_no_pci_io:
812
-	return netdev;
813
-}
814
-
815
-/**
816
- * Locate SNP corresponding to EFI device
745
+ * Locate SNP device corresponding to network device
817 746
  *
818
- * @v driver		EFI driver
819
- * @v device		EFI device
820
- * @ret snp		EFI SNP, or NULL if not found
747
+ * @v netdev		Network device
748
+ * @ret snp		SNP device, or NULL if not found
821 749
  */
822
-static struct efi_snp_device *
823
-efi_snp_snpdev ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device ) {
824
-	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
825
-	union {
826
-		EFI_SIMPLE_NETWORK_PROTOCOL *snp;
827
-		void *interface;
828
-	} u;
829
-	struct efi_snp_device *snpdev = NULL;
830
-	EFI_STATUS efirc;
750
+static struct efi_snp_device * efi_snp_demux ( struct net_device *netdev ) {
751
+	struct efi_snp_device *snpdev;
831 752
 
832
-	if ( ( efirc = bs->OpenProtocol ( device,
833
-					  &efi_simple_network_protocol_guid,
834
-					  &u.interface,
835
-					  driver->DriverBindingHandle,
836
-					  device,
837
-					  EFI_OPEN_PROTOCOL_GET_PROTOCOL))!=0){
838
-		DBGC ( driver, "SNPDRV %p device %p could not locate SNP: "
839
-		       "%s\n", driver, device, efi_strerror ( efirc ) );
840
-		goto err_no_snp;
753
+	list_for_each_entry ( snpdev, &efi_snp_devices, list ) {
754
+		if ( snpdev->netdev == netdev )
755
+			return snpdev;
841 756
 	}
842
-
843
-	snpdev =  container_of ( u.snp, struct efi_snp_device, snp );
844
-	DBGCP ( driver, "SNPDRV %p device %p is SNPDEV %p\n",
845
-		driver, device, snpdev );
846
-
847
-	bs->CloseProtocol ( device, &efi_simple_network_protocol_guid,
848
-			    driver->DriverBindingHandle, device );
849
- err_no_snp:
850
-	return snpdev;
757
+	return NULL;
851 758
 }
852 759
 
853 760
 /**
854
- * Check to see if driver supports a device
761
+ * Create SNP device
855 762
  *
856
- * @v driver		EFI driver
857
- * @v device		EFI device
858
- * @v child		Path to child device, if any
859
- * @ret efirc		EFI status code
860
- */
861
-static EFI_STATUS EFIAPI
862
-efi_snp_driver_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver,
863
-			   EFI_HANDLE device,
864
-			   EFI_DEVICE_PATH_PROTOCOL *child ) {
865
-	struct net_device *netdev;
866
-
867
-	DBGCP ( driver, "SNPDRV %p DRIVER_SUPPORTED %p (%p)\n",
868
-		driver, device, child );
869
-
870
-	netdev = efi_snp_netdev ( driver, device );
871
-	return ( netdev ? 0 : EFI_UNSUPPORTED );
872
-}
873
-
874
-/**
875
- * Attach driver to device
876
- *
877
- * @v driver		EFI driver
878
- * @v device		EFI device
879
- * @v child		Path to child device, if any
880
- * @ret efirc		EFI status code
763
+ * @v netdev		Network device
764
+ * @ret rc		Return status code
881 765
  */
882
-static EFI_STATUS EFIAPI
883
-efi_snp_driver_start ( EFI_DRIVER_BINDING_PROTOCOL *driver,
884
-		       EFI_HANDLE device,
885
-		       EFI_DEVICE_PATH_PROTOCOL *child ) {
766
+static int efi_snp_probe ( struct net_device *netdev ) {
886 767
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
887
-	EFI_DEVICE_PATH_PROTOCOL *path;
888
-	EFI_DEVICE_PATH_PROTOCOL *subpath;
889
-	MAC_ADDR_DEVICE_PATH *macpath;
768
+	struct efi_pci_device *efipci;
890 769
 	struct efi_snp_device *snpdev;
891
-	struct net_device *netdev;
892
-	size_t subpath_len;
770
+	EFI_DEVICE_PATH_PROTOCOL *path_end;
771
+	MAC_ADDR_DEVICE_PATH *macpath;
893 772
 	size_t path_prefix_len = 0;
894 773
 	unsigned int i;
895 774
 	EFI_STATUS efirc;
775
+	int rc;
896 776
 
897
-	DBGCP ( driver, "SNPDRV %p DRIVER_START %p (%p)\n",
898
-		driver, device, child );
899
-
900
-	/* Determine device path prefix length */
901
-	if ( ( efirc = bs->OpenProtocol ( device,
902
-					  &efi_device_path_protocol_guid,
903
-					  ( void * ) &path,
904
-					  driver->DriverBindingHandle,
905
-					  device,
906
-					  EFI_OPEN_PROTOCOL_BY_DRIVER )) !=0 ){
907
-		DBGCP ( driver, "SNPDRV %p device %p has no device path\n",
908
-			driver, device );
909
-		goto err_no_device_path;
910
-	}
911
-	subpath = path;
912
-	while ( subpath->Type != END_DEVICE_PATH_TYPE ) {
913
-		subpath_len = ( ( subpath->Length[1] << 8 ) |
914
-				subpath->Length[0] );
915
-		path_prefix_len += subpath_len;
916
-		subpath = ( ( ( void * ) subpath ) + subpath_len );
777
+	/* Find EFI PCI device */
778
+	efipci = efipci_find ( netdev->dev );
779
+	if ( ! efipci ) {
780
+		DBG ( "SNP skipping non-PCI device %s\n", netdev->name );
781
+		rc = 0;
782
+		goto err_no_pci;
917 783
 	}
918 784
 
785
+	/* Calculate device path prefix length */
786
+	path_end = efi_devpath_end ( efipci->path );
787
+	path_prefix_len = ( ( ( void * ) path_end ) -
788
+			    ( ( void * ) efipci->path ) );
789
+
919 790
 	/* Allocate the SNP device */
920 791
 	snpdev = zalloc ( sizeof ( *snpdev ) + path_prefix_len +
921 792
 			  sizeof ( *macpath ) );
922 793
 	if ( ! snpdev ) {
923
-		efirc = EFI_OUT_OF_RESOURCES;
794
+		rc = -ENOMEM;
924 795
 		goto err_alloc_snp;
925 796
 	}
926
-
927
-	/* Identify the net device */
928
-	netdev = efi_snp_netdev ( driver, device );
929
-	if ( ! netdev ) {
930
-		DBGC ( snpdev, "SNPDEV %p cannot find netdev for device %p\n",
931
-		       snpdev, device );
932
-		efirc = EFI_UNSUPPORTED;
933
-		goto err_no_netdev;
934
-	}
935 797
 	snpdev->netdev = netdev_get ( netdev );
936 798
 
937 799
 	/* Sanity check */
@@ -939,7 +801,7 @@ efi_snp_driver_start ( EFI_DRIVER_BINDING_PROTOCOL *driver,
939 801
 		DBGC ( snpdev, "SNPDEV %p cannot support link-layer address "
940 802
 		       "length %d for %s\n", snpdev,
941 803
 		       netdev->ll_protocol->ll_addr_len, netdev->name );
942
-		efirc = EFI_INVALID_PARAMETER;
804
+		rc = -ENOTSUP;
943 805
 		goto err_ll_addr_len;
944 806
 	}
945 807
 
@@ -951,6 +813,7 @@ efi_snp_driver_start ( EFI_DRIVER_BINDING_PROTOCOL *driver,
951 813
 					 &snpdev->snp.WaitForPacket ) ) != 0 ){
952 814
 		DBGC ( snpdev, "SNPDEV %p could not create event: %s\n",
953 815
 		       snpdev, efi_strerror ( efirc ) );
816
+		rc = EFIRC_TO_RC ( efirc );
954 817
 		goto err_create_event;
955 818
 	}
956 819
 
@@ -973,9 +836,9 @@ efi_snp_driver_start ( EFI_DRIVER_BINDING_PROTOCOL *driver,
973 836
 	}
974 837
 
975 838
 	/* Populate the device path */
976
-	memcpy ( &snpdev->path, path, path_prefix_len );
839
+	memcpy ( &snpdev->path, efipci->path, path_prefix_len );
977 840
 	macpath = ( ( ( void * ) &snpdev->path ) + path_prefix_len );
978
-	subpath = ( ( void * ) ( macpath + 1 ) );
841
+	path_end = ( ( void * ) ( macpath + 1 ) );
979 842
 	memset ( macpath, 0, sizeof ( *macpath ) );
980 843
 	macpath->Header.Type = MESSAGING_DEVICE_PATH;
981 844
 	macpath->Header.SubType = MSG_MAC_ADDR_DP;
@@ -983,10 +846,10 @@ efi_snp_driver_start ( EFI_DRIVER_BINDING_PROTOCOL *driver,
983 846
 	memcpy ( &macpath->MacAddress, netdev->ll_addr,
984 847
 		 sizeof ( macpath->MacAddress ) );
985 848
 	macpath->IfType = ntohs ( netdev->ll_protocol->ll_proto );
986
-	memset ( subpath, 0, sizeof ( *subpath ) );
987
-	subpath->Type = END_DEVICE_PATH_TYPE;
988
-	subpath->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
989
-	subpath->Length[0] = sizeof ( *subpath );
849
+	memset ( path_end, 0, sizeof ( *path_end ) );
850
+	path_end->Type = END_DEVICE_PATH_TYPE;
851
+	path_end->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
852
+	path_end->Length[0] = sizeof ( *path_end );
990 853
 
991 854
 	/* Install the SNP */
992 855
 	if ( ( efirc = bs->InstallMultipleProtocolInterfaces (
@@ -998,9 +861,13 @@ efi_snp_driver_start ( EFI_DRIVER_BINDING_PROTOCOL *driver,
998 861
 			NULL ) ) != 0 ) {
999 862
 		DBGC ( snpdev, "SNPDEV %p could not install protocols: "
1000 863
 		       "%s\n", snpdev, efi_strerror ( efirc ) );
864
+		rc = EFIRC_TO_RC ( efirc );
1001 865
 		goto err_install_protocol_interface;
1002 866
 	}
1003 867
 
868
+	/* Add to list of SNP devices */
869
+	list_add ( &snpdev->list, &efi_snp_devices );
870
+
1004 871
 	DBGC ( snpdev, "SNPDEV %p installed for %s as device %p\n",
1005 872
 	       snpdev, netdev->name, snpdev->handle );
1006 873
 	return 0;
@@ -1017,44 +884,39 @@ efi_snp_driver_start ( EFI_DRIVER_BINDING_PROTOCOL *driver,
1017 884
  err_create_event:
1018 885
  err_ll_addr_len:
1019 886
 	netdev_put ( netdev );
1020
- err_no_netdev:
1021 887
 	free ( snpdev );
1022 888
  err_alloc_snp:
1023
-	bs->CloseProtocol ( device, &efi_device_path_protocol_guid,
1024
-			    driver->DriverBindingHandle, device );
1025
- err_no_device_path:
1026
-	return efirc;
889
+ err_no_pci:
890
+	return rc;
1027 891
 }
1028 892
 
1029 893
 /**
1030
- * Detach driver from device
894
+ * Handle SNP device or link state change
1031 895
  *
1032
- * @v driver		EFI driver
1033
- * @v device		EFI device
1034
- * @v num_children	Number of child devices
1035
- * @v children		List of child devices
1036
- * @ret efirc		EFI status code
896
+ * @v netdev		Network device
1037 897
  */
1038
-static EFI_STATUS EFIAPI
1039
-efi_snp_driver_stop ( EFI_DRIVER_BINDING_PROTOCOL *driver,
1040
-		      EFI_HANDLE device,
1041
-		      UINTN num_children,
1042
-		      EFI_HANDLE *children ) {
898
+static void efi_snp_notify ( struct net_device *netdev __unused ) {
899
+	/* Nothing to do */
900
+}
901
+
902
+/**
903
+ * Destroy SNP device
904
+ *
905
+ * @v netdev		Network device
906
+ */
907
+static void efi_snp_remove ( struct net_device *netdev ) {
1043 908
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
1044 909
 	struct efi_snp_device *snpdev;
1045 910
 
1046
-	DBGCP ( driver, "SNPDRV %p DRIVER_STOP %p (%ld %p)\n",
1047
-		driver, device, ( ( unsigned long ) num_children ), children );
1048
-
1049 911
 	/* Locate SNP device */
1050
-	snpdev = efi_snp_snpdev ( driver, device );
912
+	snpdev = efi_snp_demux ( netdev );
1051 913
 	if ( ! snpdev ) {
1052
-		DBGC ( driver, "SNPDRV %p device %p could not find SNPDEV\n",
1053
-		       driver, device );
1054
-		return EFI_DEVICE_ERROR;
914
+		DBG ( "SNP skipping non-SNP device %s\n", netdev->name );
915
+		return;
1055 916
 	}
1056 917
 
1057 918
 	/* Uninstall the SNP */
919
+	list_del ( &snpdev->list );
1058 920
 	bs->UninstallMultipleProtocolInterfaces (
1059 921
 			snpdev->handle,
1060 922
 			&efi_simple_network_protocol_guid, &snpdev->snp,
@@ -1065,87 +927,12 @@ efi_snp_driver_stop ( EFI_DRIVER_BINDING_PROTOCOL *driver,
1065 927
 	bs->CloseEvent ( snpdev->snp.WaitForPacket );
1066 928
 	netdev_put ( snpdev->netdev );
1067 929
 	free ( snpdev );
1068
-	bs->CloseProtocol ( device, &efi_device_path_protocol_guid,
1069
-			    driver->DriverBindingHandle, device );
1070
-	return 0;
1071 930
 }
1072 931
 
1073
-/** EFI SNP driver binding */
1074
-static EFI_DRIVER_BINDING_PROTOCOL efi_snp_binding = {
1075
-	efi_snp_driver_supported,
1076
-	efi_snp_driver_start,
1077
-	efi_snp_driver_stop,
1078
-	0x10,
1079
-	NULL,
1080
-	NULL
932
+/** SNP driver */
933
+struct net_driver efi_snp_driver __net_driver = {
934
+	.name = "SNP",
935
+	.probe = efi_snp_probe,
936
+	.notify = efi_snp_notify,
937
+	.remove = efi_snp_remove,
1081 938
 };
1082
-
1083
-/**
1084
- * Look up driver name
1085
- *
1086
- * @v wtf		Component name protocol
1087
- * @v language		Language to use
1088
- * @v driver_name	Driver name to fill in
1089
- * @ret efirc		EFI status code
1090
- */
1091
-static EFI_STATUS EFIAPI
1092
-efi_snp_get_driver_name ( EFI_COMPONENT_NAME2_PROTOCOL *wtf __unused,
1093
-			  CHAR8 *language __unused, CHAR16 **driver_name ) {
1094
-
1095
-	*driver_name = L"" PRODUCT_SHORT_NAME " Driver";
1096
-	return 0;
1097
-}
1098
-
1099
-/**
1100
- * Look up controller name
1101
- *
1102
- * @v wtf		Component name protocol
1103
- * @v device		Device
1104
- * @v child		Child device, or NULL
1105
- * @v language		Language to use
1106
- * @v driver_name	Device name to fill in
1107
- * @ret efirc		EFI status code
1108
- */
1109
-static EFI_STATUS EFIAPI
1110
-efi_snp_get_controller_name ( EFI_COMPONENT_NAME2_PROTOCOL *wtf __unused,
1111
-			      EFI_HANDLE device __unused,
1112
-			      EFI_HANDLE child __unused,
1113
-			      CHAR8 *language __unused,
1114
-			      CHAR16 **controller_name __unused ) {
1115
-
1116
-	/* Just let EFI use the default Device Path Name */
1117
-	return EFI_UNSUPPORTED;
1118
-}
1119
-
1120
-/** EFI SNP component name protocol */
1121
-static EFI_COMPONENT_NAME2_PROTOCOL efi_snp_name = {
1122
-	efi_snp_get_driver_name,
1123
-	efi_snp_get_controller_name,
1124
-	"en"
1125
-};
1126
-
1127
-/**
1128
- * Install EFI SNP driver
1129
- *
1130
- * @ret rc		Return status code
1131
- */
1132
-int efi_snp_install ( void ) {
1133
-	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
1134
-	EFI_DRIVER_BINDING_PROTOCOL *driver = &efi_snp_binding;
1135
-	EFI_STATUS efirc;
1136
-
1137
-	driver->ImageHandle = efi_image_handle;
1138
-	if ( ( efirc = bs->InstallMultipleProtocolInterfaces (
1139
-			&driver->DriverBindingHandle,
1140
-			&efi_driver_binding_protocol_guid, driver,
1141
-			&efi_component_name2_protocol_guid, &efi_snp_name,
1142
-			NULL ) ) != 0 ) {
1143
-		DBGC ( driver, "SNPDRV %p could not install protocols: "
1144
-		       "%s\n", driver, efi_strerror ( efirc ) );
1145
-		return EFIRC_TO_RC ( efirc );
1146
-	}
1147
-
1148
-	DBGC ( driver, "SNPDRV %p driver binding installed as %p\n",
1149
-	       driver, driver->DriverBindingHandle );
1150
-	return 0;
1151
-}

Načítá se…
Zrušit
Uložit