Browse Source

[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 13 years ago
parent
commit
d7736fbb7b

+ 3
- 2
src/arch/x86/prefix/efidrvprefix.c View File

41
 	initialise();
41
 	initialise();
42
 	startup();
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 View File

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

+ 49
- 0
src/include/ipxe/efi/efi_driver.h View File

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 View File

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 View File

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 View File

18
 
18
 
19
 FILE_LICENCE ( GPL2_OR_LATER );
19
 FILE_LICENCE ( GPL2_OR_LATER );
20
 
20
 
21
+#include <stdlib.h>
21
 #include <errno.h>
22
 #include <errno.h>
22
 #include <ipxe/pci.h>
23
 #include <ipxe/pci.h>
24
+#include <ipxe/init.h>
23
 #include <ipxe/efi/efi.h>
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
 #include <ipxe/efi/Protocol/PciRootBridgeIo.h>
29
 #include <ipxe/efi/Protocol/PciRootBridgeIo.h>
25
 
30
 
26
 /** @file
31
 /** @file
29
  *
34
  *
30
  */
35
  */
31
 
36
 
37
+/******************************************************************************
38
+ *
39
+ * iPXE PCI API
40
+ *
41
+ ******************************************************************************
42
+ */
43
+
32
 /** PCI root bridge I/O protocol */
44
 /** PCI root bridge I/O protocol */
33
 static EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *efipci;
45
 static EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *efipci;
34
 EFI_REQUIRE_PROTOCOL ( EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL, &efipci );
46
 EFI_REQUIRE_PROTOCOL ( EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL, &efipci );
80
 PROVIDE_PCIAPI_INLINE ( efi, pci_write_config_byte );
92
 PROVIDE_PCIAPI_INLINE ( efi, pci_write_config_byte );
81
 PROVIDE_PCIAPI_INLINE ( efi, pci_write_config_word );
93
 PROVIDE_PCIAPI_INLINE ( efi, pci_write_config_word );
82
 PROVIDE_PCIAPI_INLINE ( efi, pci_write_config_dword );
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 View File

28
 #include <ipxe/in.h>
28
 #include <ipxe/in.h>
29
 #include <ipxe/pci.h>
29
 #include <ipxe/pci.h>
30
 #include <ipxe/efi/efi.h>
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
 #include <ipxe/efi/Protocol/SimpleNetwork.h>
33
 #include <ipxe/efi/Protocol/SimpleNetwork.h>
34
-#include <ipxe/efi/Protocol/ComponentName2.h>
35
 #include <ipxe/efi/Protocol/NetworkInterfaceIdentifier.h>
34
 #include <ipxe/efi/Protocol/NetworkInterfaceIdentifier.h>
36
-#include <config/general.h>
35
+#include <ipxe/efi/Protocol/DevicePath.h>
37
 
36
 
38
 /** @file
37
 /** @file
39
  *
38
  *
43
 
42
 
44
 /** An SNP device */
43
 /** An SNP device */
45
 struct efi_snp_device {
44
 struct efi_snp_device {
45
+	/** List of SNP devices */
46
+	struct list_head list;
46
 	/** The underlying iPXE network device */
47
 	/** The underlying iPXE network device */
47
 	struct net_device *netdev;
48
 	struct net_device *netdev;
48
 	/** EFI device handle */
49
 	/** EFI device handle */
81
 static EFI_GUID efi_simple_network_protocol_guid
82
 static EFI_GUID efi_simple_network_protocol_guid
82
 	= EFI_SIMPLE_NETWORK_PROTOCOL_GUID;
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
 /** EFI device path protocol GUID */
85
 /** EFI device path protocol GUID */
93
 static EFI_GUID efi_device_path_protocol_guid
86
 static EFI_GUID efi_device_path_protocol_guid
94
 	= EFI_DEVICE_PATH_PROTOCOL_GUID;
87
 	= EFI_DEVICE_PATH_PROTOCOL_GUID;
107
 	{ 0xBC, 0x81, 0x76, 0x7F, 0x1F, 0x97, 0x7A, 0x89 }
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
  * Set EFI SNP mode based on iPXE net device parameters
107
  * Set EFI SNP mode based on iPXE net device parameters
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
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
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
 	struct efi_snp_device *snpdev;
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
 	size_t path_prefix_len = 0;
772
 	size_t path_prefix_len = 0;
894
 	unsigned int i;
773
 	unsigned int i;
895
 	EFI_STATUS efirc;
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
 	/* Allocate the SNP device */
790
 	/* Allocate the SNP device */
920
 	snpdev = zalloc ( sizeof ( *snpdev ) + path_prefix_len +
791
 	snpdev = zalloc ( sizeof ( *snpdev ) + path_prefix_len +
921
 			  sizeof ( *macpath ) );
792
 			  sizeof ( *macpath ) );
922
 	if ( ! snpdev ) {
793
 	if ( ! snpdev ) {
923
-		efirc = EFI_OUT_OF_RESOURCES;
794
+		rc = -ENOMEM;
924
 		goto err_alloc_snp;
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
 	snpdev->netdev = netdev_get ( netdev );
797
 	snpdev->netdev = netdev_get ( netdev );
936
 
798
 
937
 	/* Sanity check */
799
 	/* Sanity check */
939
 		DBGC ( snpdev, "SNPDEV %p cannot support link-layer address "
801
 		DBGC ( snpdev, "SNPDEV %p cannot support link-layer address "
940
 		       "length %d for %s\n", snpdev,
802
 		       "length %d for %s\n", snpdev,
941
 		       netdev->ll_protocol->ll_addr_len, netdev->name );
803
 		       netdev->ll_protocol->ll_addr_len, netdev->name );
942
-		efirc = EFI_INVALID_PARAMETER;
804
+		rc = -ENOTSUP;
943
 		goto err_ll_addr_len;
805
 		goto err_ll_addr_len;
944
 	}
806
 	}
945
 
807
 
951
 					 &snpdev->snp.WaitForPacket ) ) != 0 ){
813
 					 &snpdev->snp.WaitForPacket ) ) != 0 ){
952
 		DBGC ( snpdev, "SNPDEV %p could not create event: %s\n",
814
 		DBGC ( snpdev, "SNPDEV %p could not create event: %s\n",
953
 		       snpdev, efi_strerror ( efirc ) );
815
 		       snpdev, efi_strerror ( efirc ) );
816
+		rc = EFIRC_TO_RC ( efirc );
954
 		goto err_create_event;
817
 		goto err_create_event;
955
 	}
818
 	}
956
 
819
 
973
 	}
836
 	}
974
 
837
 
975
 	/* Populate the device path */
838
 	/* Populate the device path */
976
-	memcpy ( &snpdev->path, path, path_prefix_len );
839
+	memcpy ( &snpdev->path, efipci->path, path_prefix_len );
977
 	macpath = ( ( ( void * ) &snpdev->path ) + path_prefix_len );
840
 	macpath = ( ( ( void * ) &snpdev->path ) + path_prefix_len );
978
-	subpath = ( ( void * ) ( macpath + 1 ) );
841
+	path_end = ( ( void * ) ( macpath + 1 ) );
979
 	memset ( macpath, 0, sizeof ( *macpath ) );
842
 	memset ( macpath, 0, sizeof ( *macpath ) );
980
 	macpath->Header.Type = MESSAGING_DEVICE_PATH;
843
 	macpath->Header.Type = MESSAGING_DEVICE_PATH;
981
 	macpath->Header.SubType = MSG_MAC_ADDR_DP;
844
 	macpath->Header.SubType = MSG_MAC_ADDR_DP;
983
 	memcpy ( &macpath->MacAddress, netdev->ll_addr,
846
 	memcpy ( &macpath->MacAddress, netdev->ll_addr,
984
 		 sizeof ( macpath->MacAddress ) );
847
 		 sizeof ( macpath->MacAddress ) );
985
 	macpath->IfType = ntohs ( netdev->ll_protocol->ll_proto );
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
 	/* Install the SNP */
854
 	/* Install the SNP */
992
 	if ( ( efirc = bs->InstallMultipleProtocolInterfaces (
855
 	if ( ( efirc = bs->InstallMultipleProtocolInterfaces (
998
 			NULL ) ) != 0 ) {
861
 			NULL ) ) != 0 ) {
999
 		DBGC ( snpdev, "SNPDEV %p could not install protocols: "
862
 		DBGC ( snpdev, "SNPDEV %p could not install protocols: "
1000
 		       "%s\n", snpdev, efi_strerror ( efirc ) );
863
 		       "%s\n", snpdev, efi_strerror ( efirc ) );
864
+		rc = EFIRC_TO_RC ( efirc );
1001
 		goto err_install_protocol_interface;
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
 	DBGC ( snpdev, "SNPDEV %p installed for %s as device %p\n",
871
 	DBGC ( snpdev, "SNPDEV %p installed for %s as device %p\n",
1005
 	       snpdev, netdev->name, snpdev->handle );
872
 	       snpdev, netdev->name, snpdev->handle );
1006
 	return 0;
873
 	return 0;
1017
  err_create_event:
884
  err_create_event:
1018
  err_ll_addr_len:
885
  err_ll_addr_len:
1019
 	netdev_put ( netdev );
886
 	netdev_put ( netdev );
1020
- err_no_netdev:
1021
 	free ( snpdev );
887
 	free ( snpdev );
1022
  err_alloc_snp:
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
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
908
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
1044
 	struct efi_snp_device *snpdev;
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
 	/* Locate SNP device */
911
 	/* Locate SNP device */
1050
-	snpdev = efi_snp_snpdev ( driver, device );
912
+	snpdev = efi_snp_demux ( netdev );
1051
 	if ( ! snpdev ) {
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
 	/* Uninstall the SNP */
918
 	/* Uninstall the SNP */
919
+	list_del ( &snpdev->list );
1058
 	bs->UninstallMultipleProtocolInterfaces (
920
 	bs->UninstallMultipleProtocolInterfaces (
1059
 			snpdev->handle,
921
 			snpdev->handle,
1060
 			&efi_simple_network_protocol_guid, &snpdev->snp,
922
 			&efi_simple_network_protocol_guid, &snpdev->snp,
1065
 	bs->CloseEvent ( snpdev->snp.WaitForPacket );
927
 	bs->CloseEvent ( snpdev->snp.WaitForPacket );
1066
 	netdev_put ( snpdev->netdev );
928
 	netdev_put ( snpdev->netdev );
1067
 	free ( snpdev );
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
-}

Loading…
Cancel
Save