Browse Source

[efi] Allow network devices to be created on top of arbitrary SNP devices

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 10 years ago
parent
commit
c7051d826b

+ 219
- 0
src/drivers/net/efi/snp.c View File

1
+/*
2
+ * Copyright (C) 2014 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., 51 Franklin Street, Fifth Floor, Boston, MA
17
+ * 02110-1301, USA.
18
+ */
19
+
20
+FILE_LICENCE ( GPL2_OR_LATER );
21
+
22
+#include <stdlib.h>
23
+#include <stdio.h>
24
+#include <string.h>
25
+#include <errno.h>
26
+#include <ipxe/efi/efi.h>
27
+#include <ipxe/efi/Protocol/SimpleNetwork.h>
28
+#include <ipxe/efi/efi_driver.h>
29
+#include <ipxe/efi/efi_snp.h>
30
+#include <ipxe/efi/efi_pci.h>
31
+#include "snpnet.h"
32
+#include "snp.h"
33
+
34
+/** @file
35
+ *
36
+ * SNP driver
37
+ *
38
+ */
39
+
40
+/** EFI simple network protocol GUID */
41
+static EFI_GUID efi_simple_network_protocol_guid
42
+	= EFI_SIMPLE_NETWORK_PROTOCOL_GUID;
43
+
44
+/** EFI PCI I/O protocol GUID */
45
+static EFI_GUID efi_pci_io_protocol_guid
46
+	= EFI_PCI_IO_PROTOCOL_GUID;
47
+
48
+/**
49
+ * Check to see if driver supports a device
50
+ *
51
+ * @v device		EFI device handle
52
+ * @ret rc		Return status code
53
+ */
54
+static int snp_supported ( EFI_HANDLE device ) {
55
+	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
56
+	EFI_STATUS efirc;
57
+
58
+	/* Check that this is not a device we are providing ourselves */
59
+	if ( find_snpdev ( device ) != NULL ) {
60
+		DBGCP ( device, "SNP %p %s is provided by this binary\n",
61
+			device, efi_handle_devpath_text ( device ) );
62
+		return -ENOTTY;
63
+	}
64
+
65
+	/* Test for presence of simple network protocol */
66
+	if ( ( efirc = bs->OpenProtocol ( device,
67
+					  &efi_simple_network_protocol_guid,
68
+					  NULL, efi_image_handle, device,
69
+					  EFI_OPEN_PROTOCOL_TEST_PROTOCOL))!=0){
70
+		DBGCP ( device, "SNP %p %s is not an SNP device\n",
71
+			device, efi_handle_devpath_text ( device ) );
72
+		return -EEFI ( efirc );
73
+	}
74
+	DBGC ( device, "SNP %p %s is an SNP device\n",
75
+	       device, efi_handle_devpath_text ( device ) );
76
+
77
+	return 0;
78
+}
79
+
80
+/**
81
+ * Get underlying PCI device information
82
+ *
83
+ * @v snpdev		SNP device
84
+ * @ret rc		Return status code
85
+ */
86
+static int snp_pci_info ( struct snp_device *snpdev ) {
87
+	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
88
+	struct efi_device *efidev = snpdev->efidev;
89
+	EFI_DEVICE_PATH_PROTOCOL *devpath = efidev->path;
90
+	struct pci_device pci;
91
+	EFI_HANDLE device;
92
+	EFI_STATUS efirc;
93
+	int rc;
94
+
95
+	/* Check for presence of PCI I/O protocol */
96
+	if ( ( efirc = bs->LocateDevicePath ( &efi_pci_io_protocol_guid,
97
+					      &devpath, &device ) ) != 0 ) {
98
+		DBGC ( efidev->device, "SNP %p %s is not a PCI device\n",
99
+		       efidev->device, efi_devpath_text ( efidev->path ) );
100
+		return -EEFI ( efirc );
101
+	}
102
+
103
+	/* Get PCI device information */
104
+	if ( ( rc = efipci_info ( device, &pci ) ) != 0 ) {
105
+		DBGC ( efidev->device, "SNP %p %s could not get PCI "
106
+		       "information: %s\n", efidev->device,
107
+		       efi_devpath_text ( efidev->path ), strerror ( rc ) );
108
+		return rc;
109
+	}
110
+
111
+	/* Populate SNP device information */
112
+	memcpy ( &snpdev->dev.desc, &pci.dev.desc, sizeof ( snpdev->dev.desc ));
113
+	snprintf ( snpdev->dev.name, sizeof ( snpdev->dev.name ), "SNP-%s",
114
+		   pci.dev.name );
115
+
116
+	return 0;
117
+}
118
+
119
+/**
120
+ * Attach driver to device
121
+ *
122
+ * @v efidev		EFI device
123
+ * @ret rc		Return status code
124
+ */
125
+static int snp_start ( struct efi_device *efidev ) {
126
+	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
127
+	EFI_HANDLE device = efidev->device;
128
+	struct snp_device *snpdev;
129
+	union {
130
+		EFI_SIMPLE_NETWORK_PROTOCOL *snp;
131
+		void *interface;
132
+	} snp;
133
+	EFI_STATUS efirc;
134
+	int rc;
135
+
136
+	/* Check that this is not a device we are providing ourselves */
137
+	if ( find_snpdev ( efidev->device ) != NULL ) {
138
+		DBGCP ( device, "SNP %p %s is provided by this binary\n",
139
+			device, efi_devpath_text ( efidev->path ) );
140
+		rc = -ENOTTY;
141
+		goto err_own;
142
+	}
143
+
144
+	/* Allocate and initialise structure */
145
+	snpdev = zalloc ( sizeof ( *snpdev ) );
146
+	if ( ! snpdev ) {
147
+		rc = -ENOMEM;
148
+		goto err_alloc;
149
+	}
150
+	snpdev->efidev = efidev;
151
+	snpdev->dev.driver_name = "SNP";
152
+	INIT_LIST_HEAD ( &snpdev->dev.children );
153
+
154
+	/* See if device is an SNP device */
155
+	if ( ( efirc = bs->OpenProtocol ( device,
156
+					  &efi_simple_network_protocol_guid,
157
+					  &snp.interface, efi_image_handle,
158
+					  device,
159
+					  ( EFI_OPEN_PROTOCOL_BY_DRIVER |
160
+					    EFI_OPEN_PROTOCOL_EXCLUSIVE )))!=0){
161
+		rc = -EEFI ( efirc );
162
+		DBGCP ( device, "SNP %p %s cannot open SNP protocol: %s\n",
163
+			device, efi_devpath_text ( efidev->path ),
164
+			strerror ( rc ) );
165
+		goto err_open_protocol;
166
+	}
167
+	snpdev->snp = snp.snp;
168
+
169
+	/* Get underlying device information */
170
+	if ( ( rc = snp_pci_info ( snpdev ) ) != 0 )
171
+		goto err_info;
172
+
173
+	/* Mark SNP device as a child of the EFI device */
174
+	snpdev->dev.parent = &efidev->dev;
175
+	list_add ( &snpdev->dev.siblings, &efidev->dev.children );
176
+
177
+	/* Create SNP network device */
178
+	if ( ( rc = snpnet_probe ( snpdev ) ) != 0 )
179
+		goto err_probe;
180
+
181
+	efidev_set_drvdata ( efidev, snpdev );
182
+	return 0;
183
+
184
+	snpnet_remove ( snpdev );
185
+ err_probe:
186
+	list_del ( &snpdev->dev.siblings );
187
+ err_info:
188
+	bs->CloseProtocol ( device, &efi_simple_network_protocol_guid,
189
+			    efi_image_handle, device );
190
+ err_open_protocol:
191
+	free ( snpdev );
192
+ err_alloc:
193
+ err_own:
194
+	return rc;
195
+}
196
+
197
+/**
198
+ * Detach driver from device
199
+ *
200
+ * @v efidev		EFI device
201
+  */
202
+static void snp_stop ( struct efi_device *efidev ) {
203
+	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
204
+	struct snp_device *snpdev = efidev_get_drvdata ( efidev );
205
+
206
+	snpnet_remove ( snpdev );
207
+	list_del ( &snpdev->dev.siblings );
208
+	bs->CloseProtocol ( efidev->device, &efi_simple_network_protocol_guid,
209
+			    efi_image_handle, efidev->device );
210
+	free ( snpdev );
211
+}
212
+
213
+/** EFI SNP driver */
214
+struct efi_driver snp_driver __efi_driver ( EFI_DRIVER_NORMAL ) = {
215
+	.name = "SNP",
216
+	.supported = snp_supported,
217
+	.start = snp_start,
218
+	.stop = snp_stop,
219
+};

+ 7
- 8
src/drivers/net/efi/snp.h View File

28
 FILE_LICENCE ( GPL2_OR_LATER );
28
 FILE_LICENCE ( GPL2_OR_LATER );
29
 
29
 
30
 #include <ipxe/device.h>
30
 #include <ipxe/device.h>
31
-#include <ipxe/netdevice.h>
31
+#include <ipxe/efi/efi.h>
32
 #include <ipxe/efi/Protocol/SimpleNetwork.h>
32
 #include <ipxe/efi/Protocol/SimpleNetwork.h>
33
 
33
 
34
-/** A network device that consumes the EFI Simple Network Protocol */
34
+/** An SNP device */
35
 struct snp_device {
35
 struct snp_device {
36
-	/** Underlying simple network protocol instance */
36
+	/** EFI device */
37
+	struct efi_device *efidev;
38
+	/** Simple network protocol */
37
 	EFI_SIMPLE_NETWORK_PROTOCOL *snp;
39
 	EFI_SIMPLE_NETWORK_PROTOCOL *snp;
38
-
39
 	/** Generic device */
40
 	/** Generic device */
40
 	struct device dev;
41
 	struct device dev;
41
-
42
 	/** Network device */
42
 	/** Network device */
43
 	struct net_device *netdev;
43
 	struct net_device *netdev;
44
-
45
-	/** State to put the snp in when removing the device */
46
-	uint32 removal_state;
44
+	/** State to restore when removing the device */
45
+	UINT32 removal_state;
47
 };
46
 };
48
 
47
 
49
 #endif /* _SNP_H */
48
 #endif /* _SNP_H */

+ 3
- 0
src/include/ipxe/device.h View File

57
 /** TAP bus type */
57
 /** TAP bus type */
58
 #define BUS_TYPE_TAP 6
58
 #define BUS_TYPE_TAP 6
59
 
59
 
60
+/** EFI bus type */
61
+#define BUS_TYPE_EFI 7
62
+
60
 /** A hardware device */
63
 /** A hardware device */
61
 struct device {
64
 struct device {
62
 	/** Name */
65
 	/** Name */

+ 44
- 5
src/include/ipxe/efi/efi_driver.h View File

8
 
8
 
9
 FILE_LICENCE ( GPL2_OR_LATER );
9
 FILE_LICENCE ( GPL2_OR_LATER );
10
 
10
 
11
+#include <ipxe/device.h>
11
 #include <ipxe/tables.h>
12
 #include <ipxe/tables.h>
12
 #include <ipxe/efi/efi.h>
13
 #include <ipxe/efi/efi.h>
13
 #include <ipxe/efi/Protocol/DevicePath.h>
14
 #include <ipxe/efi/Protocol/DevicePath.h>
14
 
15
 
16
+/** An EFI device */
17
+struct efi_device {
18
+	/** Generic device */
19
+	struct device dev;
20
+	/** EFI device handle */
21
+	EFI_HANDLE device;
22
+	/** Device path */
23
+	EFI_DEVICE_PATH_PROTOCOL *path;
24
+	/** Driver for this device */
25
+	struct efi_driver *driver;
26
+	/** Driver-private data */
27
+	void *priv;
28
+};
29
+
15
 /** An EFI driver */
30
 /** An EFI driver */
16
 struct efi_driver {
31
 struct efi_driver {
17
 	/** Name */
32
 	/** Name */
19
 	/**
34
 	/**
20
 	 * Check if driver supports device
35
 	 * Check if driver supports device
21
 	 *
36
 	 *
22
-	 * @v device		Device
37
+	 * @v device		EFI device handle
23
 	 * @ret rc		Return status code
38
 	 * @ret rc		Return status code
24
 	 */
39
 	 */
25
 	int ( * supported ) ( EFI_HANDLE device );
40
 	int ( * supported ) ( EFI_HANDLE device );
26
 	/**
41
 	/**
27
 	 * Attach driver to device
42
 	 * Attach driver to device
28
 	 *
43
 	 *
29
-	 * @v device		Device
44
+	 * @v efidev		EFI device
30
 	 * @ret rc		Return status code
45
 	 * @ret rc		Return status code
31
 	 */
46
 	 */
32
-	int ( * start ) ( EFI_HANDLE device );
47
+	int ( * start ) ( struct efi_device *efidev );
33
 	/**
48
 	/**
34
 	 * Detach driver from device
49
 	 * Detach driver from device
35
 	 *
50
 	 *
36
-	 * @v device		Device
51
+	 * @v efidev		EFI device
37
 	 */
52
 	 */
38
-	void ( * stop ) ( EFI_HANDLE device );
53
+	void ( * stop ) ( struct efi_device *efidev );
39
 };
54
 };
40
 
55
 
41
 /** EFI driver table */
56
 /** EFI driver table */
48
 #define EFI_DRIVER_NORMAL	02	/**< Normal drivers */
63
 #define EFI_DRIVER_NORMAL	02	/**< Normal drivers */
49
 #define EFI_DRIVER_LATE		03	/**< Late drivers */
64
 #define EFI_DRIVER_LATE		03	/**< Late drivers */
50
 
65
 
66
+/**
67
+ * Set EFI driver-private data
68
+ *
69
+ * @v efidev		EFI device
70
+ * @v priv		Private data
71
+ */
72
+static inline void efidev_set_drvdata ( struct efi_device *efidev,
73
+					void *priv ) {
74
+	efidev->priv = priv;
75
+}
76
+
77
+/**
78
+ * Get EFI driver-private data
79
+ *
80
+ * @v efidev		EFI device
81
+ * @ret priv		Private data
82
+ */
83
+static inline void * efidev_get_drvdata ( struct efi_device *efidev ) {
84
+	return efidev->priv;
85
+}
86
+
51
 extern EFI_DEVICE_PATH_PROTOCOL *
87
 extern EFI_DEVICE_PATH_PROTOCOL *
52
 efi_devpath_end ( EFI_DEVICE_PATH_PROTOCOL *path );
88
 efi_devpath_end ( EFI_DEVICE_PATH_PROTOCOL *path );
89
+extern struct efi_device * efidev_parent ( struct device *dev );
90
+extern int efidev_child_add ( struct efi_device *efidev, EFI_HANDLE device );
91
+extern void efidev_child_del ( struct efi_device *efidev, EFI_HANDLE device );
53
 extern int efi_driver_install ( void );
92
 extern int efi_driver_install ( void );
54
 extern void efi_driver_uninstall ( void );
93
 extern void efi_driver_uninstall ( void );
55
 extern int efi_driver_connect_all ( void );
94
 extern int efi_driver_connect_all ( void );

+ 5
- 27
src/include/ipxe/efi/efi_pci.h View File

8
 
8
 
9
 FILE_LICENCE ( GPL2_OR_LATER );
9
 FILE_LICENCE ( GPL2_OR_LATER );
10
 
10
 
11
+#include <ipxe/pci.h>
11
 #include <ipxe/efi/efi.h>
12
 #include <ipxe/efi/efi.h>
12
 #include <ipxe/efi/Protocol/PciIo.h>
13
 #include <ipxe/efi/Protocol/PciIo.h>
13
-#include <ipxe/efi/Protocol/DevicePath.h>
14
 
14
 
15
 /* PciRootBridgeIo.h uses LShiftU64(), which isn't defined anywhere else */
15
 /* PciRootBridgeIo.h uses LShiftU64(), which isn't defined anywhere else */
16
 static inline EFIAPI uint64_t LShiftU64 ( UINT64 value, UINTN shift ) {
16
 static inline EFIAPI uint64_t LShiftU64 ( UINT64 value, UINTN shift ) {
17
 	return ( value << shift );
17
 	return ( value << shift );
18
 }
18
 }
19
 
19
 
20
-struct device;
21
-
22
-/** An EFI PCI device */
23
-struct efi_pci_device {
24
-	/** List of EFI PCI devices */
25
-	struct list_head list;
26
-	/** iPXE PCI device */
27
-	struct pci_device pci;
28
-	/** Underlying EFI device */
29
-	EFI_HANDLE device;
30
-	/** PCI I/O protocol */
31
-	EFI_PCI_IO_PROTOCOL *pci_io;
32
-	/** Device path */
33
-	EFI_DEVICE_PATH_PROTOCOL *path;
34
-};
35
-
36
-extern int efipci_create ( EFI_HANDLE device, UINT32 attributes,
37
-			   struct efi_pci_device **efipci );
38
-extern int efipci_enable ( struct efi_pci_device *efipci );
39
-extern struct efi_pci_device * efipci_find_efi ( EFI_HANDLE device );
40
-extern struct efi_pci_device * efipci_find ( struct device *dev );
41
-extern int efipci_child_add ( struct efi_pci_device *efipci,
42
-			      EFI_HANDLE device );
43
-extern void efipci_child_del ( struct efi_pci_device *efipci,
44
-			       EFI_HANDLE device );
45
-extern void efipci_destroy ( struct efi_pci_device *efipci );
20
+extern int efipci_open ( EFI_HANDLE device, UINT32 attributes,
21
+			 struct pci_device *pci );
22
+extern void efipci_close ( EFI_HANDLE device );
23
+extern int efipci_info ( EFI_HANDLE device, struct pci_device *pci );
46
 
24
 
47
 #endif /* _IPXE_EFI_PCI_H */
25
 #endif /* _IPXE_EFI_PCI_H */

+ 3
- 2
src/include/ipxe/efi/efi_snp.h View File

24
 	struct list_head list;
24
 	struct list_head list;
25
 	/** The underlying iPXE network device */
25
 	/** The underlying iPXE network device */
26
 	struct net_device *netdev;
26
 	struct net_device *netdev;
27
-	/** The underlying EFI PCI device */
28
-	struct efi_pci_device *efipci;
27
+	/** The underlying EFI device */
28
+	struct efi_device *efidev;
29
 	/** EFI device handle */
29
 	/** EFI device handle */
30
 	EFI_HANDLE handle;
30
 	EFI_HANDLE handle;
31
 	/** The SNP structure itself */
31
 	/** The SNP structure itself */
76
 
76
 
77
 extern int efi_snp_hii_install ( struct efi_snp_device *snpdev );
77
 extern int efi_snp_hii_install ( struct efi_snp_device *snpdev );
78
 extern void efi_snp_hii_uninstall ( struct efi_snp_device *snpdev );
78
 extern void efi_snp_hii_uninstall ( struct efi_snp_device *snpdev );
79
+extern struct efi_snp_device * find_snpdev ( EFI_HANDLE handle );
79
 extern struct efi_snp_device * last_opened_snpdev ( void );
80
 extern struct efi_snp_device * last_opened_snpdev ( void );
80
 extern void efi_snp_claim ( void );
81
 extern void efi_snp_claim ( void );
81
 extern void efi_snp_release ( void );
82
 extern void efi_snp_release ( void );

+ 1
- 0
src/include/ipxe/errfile.h View File

154
 #define ERRFILE_intel		     ( ERRFILE_DRIVER | 0x00650000 )
154
 #define ERRFILE_intel		     ( ERRFILE_DRIVER | 0x00650000 )
155
 #define ERRFILE_myson		     ( ERRFILE_DRIVER | 0x00660000 )
155
 #define ERRFILE_myson		     ( ERRFILE_DRIVER | 0x00660000 )
156
 #define ERRFILE_intelx		     ( ERRFILE_DRIVER | 0x00670000 )
156
 #define ERRFILE_intelx		     ( ERRFILE_DRIVER | 0x00670000 )
157
+#define ERRFILE_snp		     ( ERRFILE_DRIVER | 0x00680000 )
157
 
158
 
158
 #define ERRFILE_scsi		     ( ERRFILE_DRIVER | 0x00700000 )
159
 #define ERRFILE_scsi		     ( ERRFILE_DRIVER | 0x00700000 )
159
 #define ERRFILE_arbel		     ( ERRFILE_DRIVER | 0x00710000 )
160
 #define ERRFILE_arbel		     ( ERRFILE_DRIVER | 0x00710000 )

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

155
 /**
155
 /**
156
  * Check if device is supported
156
  * Check if device is supported
157
  *
157
  *
158
- * @v device		EFI device
158
+ * @v device		EFI device handle
159
  * @ret rc		Return status code
159
  * @ret rc		Return status code
160
  */
160
  */
161
 static int efi_bofm_supported ( EFI_HANDLE device ) {
161
 static int efi_bofm_supported ( EFI_HANDLE device ) {
162
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
162
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
163
+	struct pci_device pci;
163
 	union {
164
 	union {
164
 		IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL *bofm1;
165
 		IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL *bofm1;
165
 		void *interface;
166
 		void *interface;
166
 	} bofm1;
167
 	} bofm1;
167
-	struct efi_pci_device *efipci;
168
 	EFI_STATUS efirc;
168
 	EFI_STATUS efirc;
169
 	int rc;
169
 	int rc;
170
 
170
 
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
-	}
179
-
180
-	/* Create corresponding PCI device, if any */
181
-	if ( ( rc = efipci_create ( device, EFI_OPEN_PROTOCOL_GET_PROTOCOL,
182
-				    &efipci ) ) != 0 )
183
-		goto err_create;
171
+	/* Get PCI device information */
172
+	if ( ( rc = efipci_info ( device, &pci ) ) != 0 )
173
+		return rc;
184
 
174
 
185
 	/* Look for a BOFM driver */
175
 	/* Look for a BOFM driver */
186
-	if ( ( rc = bofm_find_driver ( &efipci->pci ) ) != 0 ) {
176
+	if ( ( rc = bofm_find_driver ( &pci ) ) != 0 ) {
187
 		DBGCP ( device, "EFIBOFM %p %s has no driver\n",
177
 		DBGCP ( device, "EFIBOFM %p %s has no driver\n",
188
-			device, efi_devpath_text ( efipci->path ) );
189
-		goto err_no_driver;
178
+			device, efi_handle_devpath_text ( device ) );
179
+		return rc;
190
 	}
180
 	}
191
 
181
 
192
 	/* Locate BOFM protocol */
182
 	/* Locate BOFM protocol */
194
 					    &bofm1.interface ) ) != 0 ) {
184
 					    &bofm1.interface ) ) != 0 ) {
195
 		rc = -EEFI ( efirc );
185
 		rc = -EEFI ( efirc );
196
 		DBGC ( device, "EFIBOFM %p %s cannot find BOFM protocol\n",
186
 		DBGC ( device, "EFIBOFM %p %s cannot find BOFM protocol\n",
197
-		       device, efi_devpath_text ( efipci->path ) );
198
-		goto err_not_bofm;
187
+		       device, efi_handle_devpath_text ( device ) );
188
+		return rc;
199
 	}
189
 	}
200
 
190
 
201
 	/* Register support for this device */
191
 	/* Register support for this device */
205
 						      0x02 /* Version */ ))!=0){
195
 						      0x02 /* Version */ ))!=0){
206
 		rc = -EEFI ( efirc );
196
 		rc = -EEFI ( efirc );
207
 		DBGC ( device, "EFIBOFM %p %s could not register support: %s\n",
197
 		DBGC ( device, "EFIBOFM %p %s could not register support: %s\n",
208
-		       device, efi_devpath_text ( efipci->path ),
198
+		       device, efi_handle_devpath_text ( device ),
209
 		       strerror ( rc ) );
199
 		       strerror ( rc ) );
210
-		goto err_cannot_register;
200
+		return rc;
211
 	}
201
 	}
212
 
202
 
213
-	DBGC ( device, "EFIBOFM %p %s has driver \"%s\"\n", device,
214
-	       efi_devpath_text ( efipci->path ), efipci->pci.id->name );
215
-
216
-	/* Destroy temporary PCI device */
217
-	efipci_destroy ( efipci );
218
-
203
+	DBGC ( device, "EFIBOFM %p %s has driver \"%s\"\n",
204
+	       device, efi_handle_devpath_text ( device ), pci.id->name );
219
 	return 0;
205
 	return 0;
220
-
221
- err_cannot_register:
222
- err_not_bofm:
223
- err_no_driver:
224
-	efipci_destroy ( efipci );
225
- err_create:
226
- err_already_started:
227
-	return rc;
228
 }
206
 }
229
 
207
 
230
 /**
208
 /**
231
  * Attach driver to device
209
  * Attach driver to device
232
  *
210
  *
233
- * @v device		EFI device
211
+ * @v efidev		EFI device
234
  * @ret rc		Return status code
212
  * @ret rc		Return status code
235
  */
213
  */
236
-static int efi_bofm_start ( EFI_HANDLE device ) {
214
+static int efi_bofm_start ( struct efi_device *efidev ) {
237
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
215
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
216
+	EFI_HANDLE device = efidev->device;
238
 	union {
217
 	union {
239
 		IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL *bofm1;
218
 		IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL *bofm1;
240
 		void *interface;
219
 		void *interface;
243
 		IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL2 *bofm2;
222
 		IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL2 *bofm2;
244
 		void *interface;
223
 		void *interface;
245
 	} bofm2;
224
 	} bofm2;
246
-	struct efi_pci_device *efipci;
225
+	struct pci_device pci;
247
 	IBM_BOFM_TABLE *bofmtab;
226
 	IBM_BOFM_TABLE *bofmtab;
248
 	IBM_BOFM_TABLE *bofmtab2;
227
 	IBM_BOFM_TABLE *bofmtab2;
249
 	int bofmrc;
228
 	int bofmrc;
250
 	EFI_STATUS efirc;
229
 	EFI_STATUS efirc;
251
 	int rc;
230
 	int rc;
252
 
231
 
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
-	}
261
-
262
-	/* Create corresponding PCI device */
263
-	if ( ( rc = efipci_create ( device, EFI_OPEN_PROTOCOL_GET_PROTOCOL,
264
-				    &efipci ) ) != 0 )
265
-		goto err_create;
266
-
267
-	/* Enable PCI device */
268
-	if ( ( rc = efipci_enable ( efipci ) ) != 0 )
269
-		goto err_enable;
232
+	/* Open PCI device, if possible */
233
+	if ( ( rc = efipci_open ( device, EFI_OPEN_PROTOCOL_GET_PROTOCOL,
234
+				  &pci ) ) != 0 )
235
+		goto err_open;
270
 
236
 
271
 	/* Locate BOFM protocol */
237
 	/* Locate BOFM protocol */
272
 	if ( ( efirc = bs->LocateProtocol ( &bofm1_protocol_guid, NULL,
238
 	if ( ( efirc = bs->LocateProtocol ( &bofm1_protocol_guid, NULL,
273
 					    &bofm1.interface ) ) != 0 ) {
239
 					    &bofm1.interface ) ) != 0 ) {
274
 		rc = -EEFI ( efirc );
240
 		rc = -EEFI ( efirc );
275
 		DBGC ( device, "EFIBOFM %p %s cannot find BOFM protocol\n",
241
 		DBGC ( device, "EFIBOFM %p %s cannot find BOFM protocol\n",
276
-		       device, efi_devpath_text ( efipci->path ) );
242
+		       device, efi_devpath_text ( efidev->path ) );
277
 		goto err_locate_bofm;
243
 		goto err_locate_bofm;
278
 	}
244
 	}
279
 	bofmtab = &bofm1.bofm1->BofmTable;
245
 	bofmtab = &bofm1.bofm1->BofmTable;
280
 	DBGC ( device, "EFIBOFM %p %s found version 1 BOFM table at %p+%04x\n",
246
 	DBGC ( device, "EFIBOFM %p %s found version 1 BOFM table at %p+%04x\n",
281
-	       device, efi_devpath_text ( efipci->path ), bofmtab,
247
+	       device, efi_devpath_text ( efidev->path ), bofmtab,
282
 	       bofmtab->Parameters.Length );
248
 	       bofmtab->Parameters.Length );
283
 
249
 
284
 	/* Locate BOFM2 protocol, if available */
250
 	/* Locate BOFM2 protocol, if available */
286
 					    &bofm2.interface ) ) == 0 ) {
252
 					    &bofm2.interface ) ) == 0 ) {
287
 		bofmtab2 = &bofm2.bofm2->BofmTable;
253
 		bofmtab2 = &bofm2.bofm2->BofmTable;
288
 		DBGC ( device, "EFIBOFM %p %s found version 2 BOFM table at "
254
 		DBGC ( device, "EFIBOFM %p %s found version 2 BOFM table at "
289
-		       "%p+%04x\n", device, efi_devpath_text ( efipci->path ),
255
+		       "%p+%04x\n", device, efi_devpath_text ( efidev->path ),
290
 		       bofmtab2, bofmtab2->Parameters.Length );
256
 		       bofmtab2, bofmtab2->Parameters.Length );
291
 		assert ( bofm2.bofm2->RegisterSupport ==
257
 		assert ( bofm2.bofm2->RegisterSupport ==
292
 			 bofm1.bofm1->RegisterSupport );
258
 			 bofm1.bofm1->RegisterSupport );
293
 	} else {
259
 	} else {
294
 		DBGC ( device, "EFIBOFM %p %s cannot find BOFM2 protocol\n",
260
 		DBGC ( device, "EFIBOFM %p %s cannot find BOFM2 protocol\n",
295
-		       device, efi_devpath_text ( efipci->path ) );
261
+		       device, efi_devpath_text ( efidev->path ) );
296
 		/* Not a fatal error; may be a BOFM1-only system */
262
 		/* Not a fatal error; may be a BOFM1-only system */
297
 		bofmtab2 = NULL;
263
 		bofmtab2 = NULL;
298
 	}
264
 	}
299
 
265
 
300
 	/* Process BOFM table */
266
 	/* Process BOFM table */
301
 	DBGC2 ( device, "EFIBOFM %p %s version 1 before processing:\n",
267
 	DBGC2 ( device, "EFIBOFM %p %s version 1 before processing:\n",
302
-		device, efi_devpath_text ( efipci->path ) );
268
+		device, efi_devpath_text ( efidev->path ) );
303
 	DBGC2_HD ( device, bofmtab, bofmtab->Parameters.Length );
269
 	DBGC2_HD ( device, bofmtab, bofmtab->Parameters.Length );
304
 	if ( bofmtab2 ) {
270
 	if ( bofmtab2 ) {
305
 		DBGC2 ( device, "EFIBOFM %p %s version 2 before processing:\n",
271
 		DBGC2 ( device, "EFIBOFM %p %s version 2 before processing:\n",
306
-			device, efi_devpath_text ( efipci->path ) );
272
+			device, efi_devpath_text ( efidev->path ) );
307
 		DBGC2_HD ( device, bofmtab2, bofmtab2->Parameters.Length );
273
 		DBGC2_HD ( device, bofmtab2, bofmtab2->Parameters.Length );
308
 	}
274
 	}
309
-	bofmrc = bofm ( virt_to_user ( bofmtab2 ? bofmtab2 : bofmtab ),
310
-			&efipci->pci );
275
+	bofmrc = bofm ( virt_to_user ( bofmtab2 ? bofmtab2 : bofmtab ), &pci );
311
 	DBGC ( device, "EFIBOFM %p %s status %08x\n",
276
 	DBGC ( device, "EFIBOFM %p %s status %08x\n",
312
-	       device, efi_devpath_text ( efipci->path ), bofmrc );
277
+	       device, efi_devpath_text ( efidev->path ), bofmrc );
313
 	DBGC2 ( device, "EFIBOFM %p %s version 1 after processing:\n",
278
 	DBGC2 ( device, "EFIBOFM %p %s version 1 after processing:\n",
314
-		device, efi_devpath_text ( efipci->path ) );
279
+		device, efi_devpath_text ( efidev->path ) );
315
 	DBGC2_HD ( device, bofmtab, bofmtab->Parameters.Length );
280
 	DBGC2_HD ( device, bofmtab, bofmtab->Parameters.Length );
316
 	if ( bofmtab2 ) {
281
 	if ( bofmtab2 ) {
317
 		DBGC2 ( device, "EFIBOFM %p %s version 2 after processing:\n",
282
 		DBGC2 ( device, "EFIBOFM %p %s version 2 after processing:\n",
318
-			device, efi_devpath_text ( efipci->path ) );
283
+			device, efi_devpath_text ( efidev->path ) );
319
 		DBGC2_HD ( device, bofmtab2, bofmtab2->Parameters.Length );
284
 		DBGC2_HD ( device, bofmtab2, bofmtab2->Parameters.Length );
320
 	}
285
 	}
321
 
286
 
326
 			rc = -EEFI ( efirc );
291
 			rc = -EEFI ( efirc );
327
 			DBGC ( device, "EFIBOFM %p %s could not set BOFM2 "
292
 			DBGC ( device, "EFIBOFM %p %s could not set BOFM2 "
328
 			       "status: %s\n",
293
 			       "status: %s\n",
329
-			       device, efi_devpath_text ( efipci->path ),
294
+			       device, efi_devpath_text ( efidev->path ),
330
 			       strerror ( rc ) );
295
 			       strerror ( rc ) );
331
 			goto err_set_status;
296
 			goto err_set_status;
332
 		}
297
 		}
336
 			rc = -EEFI ( efirc );
301
 			rc = -EEFI ( efirc );
337
 			DBGC ( device, "EFIBOFM %p %s could not set BOFM "
302
 			DBGC ( device, "EFIBOFM %p %s could not set BOFM "
338
 			       "status: %s\n",
303
 			       "status: %s\n",
339
-			       device, efi_devpath_text ( efipci->path ),
304
+			       device, efi_devpath_text ( efidev->path ),
340
 			       strerror ( rc ) );
305
 			       strerror ( rc ) );
341
 			goto err_set_status;
306
 			goto err_set_status;
342
 		}
307
 		}
343
 	}
308
 	}
344
 
309
 
345
-	/* Destroy the PCI device anyway; we have no further use for it */
346
-	efipci_destroy ( efipci );
347
-
348
 	/* BOFM (ab)uses the "start" method to mean "process and exit" */
310
 	/* BOFM (ab)uses the "start" method to mean "process and exit" */
349
-	return -EAGAIN;
311
+	rc = -EAGAIN;
350
 
312
 
351
  err_set_status:
313
  err_set_status:
352
  err_locate_bofm:
314
  err_locate_bofm:
353
- err_enable:
354
-	efipci_destroy ( efipci );
355
- err_create:
356
- err_already_started:
315
+	efipci_close ( device );
316
+ err_open:
357
 	return rc;
317
 	return rc;
358
 }
318
 }
359
 
319
 
362
  *
322
  *
363
  * @v device		EFI device
323
  * @v device		EFI device
364
  */
324
  */
365
-static void efi_bofm_stop ( EFI_HANDLE device __unused ) {
366
-	/* Nothing to do */
325
+static void efi_bofm_stop ( struct efi_device *efidev __unused ) {
326
+
327
+	/* Should never happen */
328
+	assert ( 0 );
367
 }
329
 }
368
 
330
 
369
 /** EFI BOFM driver */
331
 /** EFI BOFM driver */

+ 181
- 9
src/interface/efi/efi_driver.c View File

20
 FILE_LICENCE ( GPL2_OR_LATER );
20
 FILE_LICENCE ( GPL2_OR_LATER );
21
 
21
 
22
 #include <stddef.h>
22
 #include <stddef.h>
23
+#include <stdlib.h>
23
 #include <stdio.h>
24
 #include <stdio.h>
24
 #include <string.h>
25
 #include <string.h>
25
 #include <errno.h>
26
 #include <errno.h>
27
 #include <ipxe/efi/efi.h>
28
 #include <ipxe/efi/efi.h>
28
 #include <ipxe/efi/Protocol/DriverBinding.h>
29
 #include <ipxe/efi/Protocol/DriverBinding.h>
29
 #include <ipxe/efi/Protocol/ComponentName2.h>
30
 #include <ipxe/efi/Protocol/ComponentName2.h>
31
+#include <ipxe/efi/Protocol/DevicePath.h>
30
 #include <ipxe/efi/efi_strings.h>
32
 #include <ipxe/efi/efi_strings.h>
31
 #include <ipxe/efi/efi_driver.h>
33
 #include <ipxe/efi/efi_driver.h>
32
 
34
 
46
 static EFI_GUID efi_component_name2_protocol_guid
48
 static EFI_GUID efi_component_name2_protocol_guid
47
 	= EFI_COMPONENT_NAME2_PROTOCOL_GUID;
49
 	= EFI_COMPONENT_NAME2_PROTOCOL_GUID;
48
 
50
 
51
+/** EFI device path protocol GUID */
52
+static EFI_GUID efi_device_path_protocol_guid
53
+	= EFI_DEVICE_PATH_PROTOCOL_GUID;
54
+
55
+/** List of controlled EFI devices */
56
+static LIST_HEAD ( efi_devices );
57
+
49
 /**
58
 /**
50
  * Find end of device path
59
  * Find end of device path
51
  *
60
  *
64
 	return path;
73
 	return path;
65
 }
74
 }
66
 
75
 
76
+/**
77
+ * Find EFI device
78
+ *
79
+ * @v device		EFI device handle
80
+ * @ret efidev		EFI device, or NULL if not found
81
+ */
82
+static struct efi_device * efidev_find ( EFI_HANDLE device ) {
83
+	struct efi_device *efidev;
84
+
85
+	/* Look for an existing EFI device */
86
+	list_for_each_entry ( efidev, &efi_devices, dev.siblings ) {
87
+		if ( efidev->device == device )
88
+			return efidev;
89
+	}
90
+
91
+	return NULL;
92
+}
93
+
94
+/**
95
+ * Get parent EFI device
96
+ *
97
+ * @v dev		Generic device
98
+ * @ret efidev		Parent EFI device, or NULL
99
+ */
100
+struct efi_device * efidev_parent ( struct device *dev ) {
101
+	struct device *parent = dev->parent;
102
+	struct efi_device *efidev;
103
+
104
+	/* Check that parent exists and is an EFI device */
105
+	if ( ! parent )
106
+		return NULL;
107
+	if ( parent->desc.bus_type != BUS_TYPE_EFI )
108
+		return NULL;
109
+
110
+	/* Get containing EFI device */
111
+	efidev = container_of ( parent, struct efi_device, dev );
112
+	return efidev;
113
+}
114
+
115
+/**
116
+ * Add EFI device as child of EFI device
117
+ *
118
+ * @v efidev		EFI device
119
+ * @v device		EFI child device handle
120
+ * @ret efirc		EFI status code
121
+ */
122
+int efidev_child_add ( struct efi_device *efidev, EFI_HANDLE device ) {
123
+	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
124
+	void *devpath;
125
+	EFI_STATUS efirc;
126
+	int rc;
127
+
128
+	/* Re-open the device path protocol */
129
+	if ( ( efirc = bs->OpenProtocol ( efidev->device,
130
+					  &efi_device_path_protocol_guid,
131
+					  &devpath,
132
+					  efi_image_handle, device,
133
+					  EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
134
+					  ) ) != 0 ) {
135
+		rc = -EEFI ( efirc );
136
+		DBGC ( efidev->device, "EFIDRV %p %s could not add child",
137
+		       efidev->device, efi_devpath_text ( efidev->path ) );
138
+		DBGC ( efidev->device, " %p %s: %s\n", device,
139
+		       efi_handle_devpath_text ( device ), strerror ( rc ) );
140
+		return rc;
141
+	}
142
+
143
+	DBGC2 ( efidev->device, "EFIDRV %p %s added child",
144
+		efidev->device, efi_devpath_text ( efidev->path ) );
145
+	DBGC2 ( efidev->device, " %p %s\n",
146
+		device, efi_handle_devpath_text ( device ) );
147
+	return 0;
148
+}
149
+
150
+/**
151
+ * Remove EFI device as child of EFI device
152
+ *
153
+ * @v efidev		EFI device
154
+ * @v device		EFI child device handle
155
+ * @ret efirc		EFI status code
156
+ */
157
+void efidev_child_del ( struct efi_device *efidev, EFI_HANDLE device ) {
158
+	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
159
+
160
+	bs->CloseProtocol ( efidev->device,
161
+			    &efi_device_path_protocol_guid,
162
+			    efi_image_handle, device );
163
+	DBGC2 ( efidev->device, "EFIDRV %p %s removed child",
164
+		efidev->device, efi_devpath_text ( efidev->path ) );
165
+	DBGC2 ( efidev->device, " %p %s\n",
166
+		device, efi_handle_devpath_text ( device ) );
167
+}
168
+
67
 /**
169
 /**
68
  * Check to see if driver supports a device
170
  * Check to see if driver supports a device
69
  *
171
  *
84
 		DBGCP ( device, " (child %s)", efi_devpath_text ( child ) );
186
 		DBGCP ( device, " (child %s)", efi_devpath_text ( child ) );
85
 	DBGCP ( device, "\n" );
187
 	DBGCP ( device, "\n" );
86
 
188
 
189
+	/* Do nothing if we are already driving this device */
190
+	if ( efidev_find ( device ) != NULL ) {
191
+		DBGCP ( device, "EFIDRV %p %s is already started\n",
192
+			device, efi_handle_devpath_text ( device ) );
193
+		return EFI_ALREADY_STARTED;
194
+	}
195
+
87
 	/* Look for a driver claiming to support this device */
196
 	/* Look for a driver claiming to support this device */
88
 	for_each_table_entry ( efidrv, EFI_DRIVERS ) {
197
 	for_each_table_entry ( efidrv, EFI_DRIVERS ) {
89
 		if ( ( rc = efidrv->supported ( device ) ) == 0 ) {
198
 		if ( ( rc = efidrv->supported ( device ) ) == 0 ) {
110
 static EFI_STATUS EFIAPI
219
 static EFI_STATUS EFIAPI
111
 efi_driver_start ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused,
220
 efi_driver_start ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused,
112
 		   EFI_HANDLE device, EFI_DEVICE_PATH_PROTOCOL *child ) {
221
 		   EFI_HANDLE device, EFI_DEVICE_PATH_PROTOCOL *child ) {
222
+	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
113
 	struct efi_driver *efidrv;
223
 	struct efi_driver *efidrv;
224
+	struct efi_device *efidev;
225
+	union {
226
+		EFI_DEVICE_PATH_PROTOCOL *devpath;
227
+		void *interface;
228
+	} devpath;
229
+	EFI_STATUS efirc;
114
 	int rc;
230
 	int rc;
115
 
231
 
116
 	DBGC ( device, "EFIDRV %p %s DRIVER_START",
232
 	DBGC ( device, "EFIDRV %p %s DRIVER_START",
119
 		DBGC ( device, " (child %s)", efi_devpath_text ( child ) );
235
 		DBGC ( device, " (child %s)", efi_devpath_text ( child ) );
120
 	DBGC ( device, "\n" );
236
 	DBGC ( device, "\n" );
121
 
237
 
238
+	/* Do nothing if we are already driving this device */
239
+	efidev = efidev_find ( device );
240
+	if ( efidev ) {
241
+		DBGCP ( device, "EFIDRV %p %s is already started\n",
242
+			device, efi_devpath_text ( efidev->path ) );
243
+		efirc = EFI_ALREADY_STARTED;
244
+		goto err_already_started;
245
+	}
246
+
247
+	/* Allocate and initialise structure */
248
+	efidev = zalloc ( sizeof ( *efidev ) );
249
+	if ( ! efidev ) {
250
+		efirc = EFI_OUT_OF_RESOURCES;
251
+		goto err_alloc;
252
+	}
253
+	efidev->device = device;
254
+	efidev->dev.desc.bus_type = BUS_TYPE_EFI;
255
+	INIT_LIST_HEAD ( &efidev->dev.children );
256
+	list_add ( &efidev->dev.siblings, &efi_devices );
257
+
258
+	/* Open device path protocol */
259
+	if ( ( efirc = bs->OpenProtocol ( device,
260
+					  &efi_device_path_protocol_guid,
261
+					  &devpath.interface,
262
+					  efi_image_handle, device,
263
+					  EFI_OPEN_PROTOCOL_BY_DRIVER ) ) != 0){
264
+		DBGCP ( device, "EFIDRV %p %s has no device path\n",
265
+			device, efi_handle_devpath_text ( device ) );
266
+		goto err_no_device_path;
267
+	}
268
+	efidev->path = devpath.devpath;
269
+
122
 	/* Try to start this device */
270
 	/* Try to start this device */
123
 	for_each_table_entry ( efidrv, EFI_DRIVERS ) {
271
 	for_each_table_entry ( efidrv, EFI_DRIVERS ) {
124
-		if ( ( rc = efidrv->start ( device ) ) == 0 ) {
272
+		if ( ( rc = efidrv->start ( efidev ) ) == 0 ) {
273
+			efidev->driver = efidrv;
125
 			DBGC ( device, "EFIDRV %p %s using driver \"%s\"\n",
274
 			DBGC ( device, "EFIDRV %p %s using driver \"%s\"\n",
126
-			       device, efi_handle_devpath_text ( device ),
127
-			       efidrv->name );
275
+			       device, efi_devpath_text ( efidev->path ),
276
+			       efidev->driver->name );
128
 			return 0;
277
 			return 0;
129
 		}
278
 		}
130
 		DBGC ( device, "EFIDRV %p %s could not start driver \"%s\": "
279
 		DBGC ( device, "EFIDRV %p %s could not start driver \"%s\": "
131
-		       "%s\n", device, efi_handle_devpath_text ( device ),
280
+		       "%s\n", device, efi_devpath_text ( efidev->path ),
132
 		       efidrv->name, strerror ( rc ) );
281
 		       efidrv->name, strerror ( rc ) );
133
 	}
282
 	}
134
-
135
-	return EFI_UNSUPPORTED;
283
+	efirc = EFI_UNSUPPORTED;
284
+
285
+	bs->CloseProtocol ( device, &efi_device_path_protocol_guid,
286
+			    efi_image_handle, device );
287
+ err_no_device_path:
288
+	list_del ( &efidev->dev.siblings );
289
+	free ( efidev );
290
+ err_alloc:
291
+ err_already_started:
292
+	return efirc;
136
 }
293
 }
137
 
294
 
138
 /**
295
 /**
149
 efi_driver_stop ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused,
306
 efi_driver_stop ( EFI_DRIVER_BINDING_PROTOCOL *driver __unused,
150
 		  EFI_HANDLE device, UINTN num_children,
307
 		  EFI_HANDLE device, UINTN num_children,
151
 		  EFI_HANDLE *children ) {
308
 		  EFI_HANDLE *children ) {
309
+	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
152
 	struct efi_driver *efidrv;
310
 	struct efi_driver *efidrv;
311
+	struct efi_device *efidev;
153
 	UINTN i;
312
 	UINTN i;
154
 
313
 
155
 	DBGC ( device, "EFIDRV %p %s DRIVER_STOP",
314
 	DBGC ( device, "EFIDRV %p %s DRIVER_STOP",
160
 	}
319
 	}
161
 	DBGC ( device, "\n" );
320
 	DBGC ( device, "\n" );
162
 
321
 
163
-	/* Try to stop this device */
164
-	for_each_table_entry ( efidrv, EFI_DRIVERS )
165
-		efidrv->stop ( device );
322
+	/* Do nothing unless we are driving this device */
323
+	efidev = efidev_find ( device );
324
+	if ( ! efidev ) {
325
+		DBGCP ( device, "EFIDRV %p %s is not started\n",
326
+			device, efi_devpath_text ( efidev->path ) );
327
+		return 0;
328
+	}
329
+
330
+	/* Stop this device */
331
+	efidrv = efidev->driver;
332
+	assert ( efidrv != NULL );
333
+	efidrv->stop ( efidev );
334
+	bs->CloseProtocol ( efidev->device, &efi_device_path_protocol_guid,
335
+			    efi_image_handle, efidev->device );
336
+	list_del ( &efidev->dev.siblings );
337
+	free ( efidev );
166
 
338
 
167
 	return 0;
339
 	return 0;
168
 }
340
 }

+ 99
- 242
src/interface/efi/efi_pci.c View File

37
 /* Disambiguate the various error causes */
37
 /* Disambiguate the various error causes */
38
 #define EINFO_EEFI_PCI							\
38
 #define EINFO_EEFI_PCI							\
39
 	__einfo_uniqify ( EINFO_EPLATFORM, 0x01,			\
39
 	__einfo_uniqify ( EINFO_EPLATFORM, 0x01,			\
40
-			  "Could not open PCI I/O protocols" )
40
+			  "Could not open PCI I/O protocol" )
41
 #define EINFO_EEFI_PCI_NOT_PCI						\
41
 #define EINFO_EEFI_PCI_NOT_PCI						\
42
 	__einfo_platformify ( EINFO_EEFI_PCI, EFI_UNSUPPORTED,		\
42
 	__einfo_platformify ( EINFO_EEFI_PCI, EFI_UNSUPPORTED,		\
43
 			      "Not a PCI device" )
43
 			      "Not a PCI device" )
124
 static EFI_GUID efi_pci_io_protocol_guid
124
 static EFI_GUID efi_pci_io_protocol_guid
125
 	= EFI_PCI_IO_PROTOCOL_GUID;
125
 	= EFI_PCI_IO_PROTOCOL_GUID;
126
 
126
 
127
-/** EFI device path protocol GUID */
128
-static EFI_GUID efi_device_path_protocol_guid
129
-	= EFI_DEVICE_PATH_PROTOCOL_GUID;
130
-
131
-/** EFI PCI devices */
132
-static LIST_HEAD ( efi_pci_devices );
133
-
134
 /**
127
 /**
135
- * Create EFI PCI device
128
+ * Open EFI PCI device
136
  *
129
  *
137
- * @v device		EFI device
130
+ * @v device		EFI device handle
138
  * @v attributes	Protocol opening attributes
131
  * @v attributes	Protocol opening attributes
139
- * @v efipci		EFI PCI device to fill in
132
+ * @v pci		PCI device to fill in
140
  * @ret rc		Return status code
133
  * @ret rc		Return status code
141
  */
134
  */
142
-int efipci_create ( EFI_HANDLE device, UINT32 attributes,
143
-		    struct efi_pci_device **efipci ) {
135
+int efipci_open ( EFI_HANDLE device, UINT32 attributes,
136
+		  struct pci_device *pci ) {
144
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
137
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
145
 	union {
138
 	union {
146
 		EFI_PCI_IO_PROTOCOL *pci_io;
139
 		EFI_PCI_IO_PROTOCOL *pci_io;
147
 		void *interface;
140
 		void *interface;
148
 	} pci_io;
141
 	} pci_io;
149
-	union {
150
-		EFI_DEVICE_PATH_PROTOCOL *path;
151
-		void *interface;
152
-	} path;
153
 	UINTN pci_segment, pci_bus, pci_dev, pci_fn;
142
 	UINTN pci_segment, pci_bus, pci_dev, pci_fn;
154
 	EFI_STATUS efirc;
143
 	EFI_STATUS efirc;
155
 	int rc;
144
 	int rc;
156
 
145
 
157
-	/* Allocate PCI device */
158
-	*efipci = zalloc ( sizeof ( **efipci ) );
159
-	if ( ! *efipci ) {
160
-		rc = -ENOMEM;
161
-		goto err_zalloc;
162
-	}
163
-	(*efipci)->device = device;
164
-
165
 	/* See if device is a PCI device */
146
 	/* See if device is a PCI device */
166
-	if ( ( efirc = bs->OpenProtocol ( device,
167
-					  &efi_pci_io_protocol_guid,
168
-					  &pci_io.interface,
169
-					  efi_image_handle,
147
+	if ( ( efirc = bs->OpenProtocol ( device, &efi_pci_io_protocol_guid,
148
+					  &pci_io.interface, efi_image_handle,
170
 					  device, attributes ) ) != 0 ) {
149
 					  device, attributes ) ) != 0 ) {
171
 		rc = -EEFI_PCI ( efirc );
150
 		rc = -EEFI_PCI ( efirc );
172
 		DBGCP ( device, "EFIPCI %p %s cannot open PCI protocols: %s\n",
151
 		DBGCP ( device, "EFIPCI %p %s cannot open PCI protocols: %s\n",
174
 			strerror ( rc ) );
153
 			strerror ( rc ) );
175
 		goto err_open_protocol;
154
 		goto err_open_protocol;
176
 	}
155
 	}
177
-	(*efipci)->pci_io = pci_io.pci_io;
178
 
156
 
179
 	/* Get PCI bus:dev.fn address */
157
 	/* Get PCI bus:dev.fn address */
180
-	if ( ( efirc = pci_io.pci_io->GetLocation ( pci_io.pci_io,
181
-						    &pci_segment,
158
+	if ( ( efirc = pci_io.pci_io->GetLocation ( pci_io.pci_io, &pci_segment,
182
 						    &pci_bus, &pci_dev,
159
 						    &pci_bus, &pci_dev,
183
 						    &pci_fn ) ) != 0 ) {
160
 						    &pci_fn ) ) != 0 ) {
184
 		rc = -EEFI ( efirc );
161
 		rc = -EEFI ( efirc );
185
-		DBGC ( device, "EFIPCI %p %s could not get PCI location: "
186
-		       "%s\n", device, efi_handle_devpath_text ( device ),
162
+		DBGC ( device, "EFIPCI %p %s could not get PCI location: %s\n",
163
+		       device, efi_handle_devpath_text ( device ),
187
 		       strerror ( rc ) );
164
 		       strerror ( rc ) );
188
 		goto err_get_location;
165
 		goto err_get_location;
189
 	}
166
 	}
192
 		( ( unsigned long ) pci_segment ), ( ( unsigned long ) pci_bus),
169
 		( ( unsigned long ) pci_segment ), ( ( unsigned long ) pci_bus),
193
 		( ( unsigned long ) pci_dev ), ( ( unsigned long ) pci_fn ) );
170
 		( ( unsigned long ) pci_dev ), ( ( unsigned long ) pci_fn ) );
194
 
171
 
172
+	/* Try to enable I/O cycles, memory cycles, and bus mastering.
173
+	 * Some platforms will 'helpfully' report errors if these bits
174
+	 * can't be enabled (for example, if the card doesn't actually
175
+	 * support I/O cycles).  Work around any such platforms by
176
+	 * enabling bits individually and simply ignoring any errors.
177
+	 */
178
+	pci_io.pci_io->Attributes ( pci_io.pci_io,
179
+				    EfiPciIoAttributeOperationEnable,
180
+				    EFI_PCI_IO_ATTRIBUTE_IO, NULL );
181
+	pci_io.pci_io->Attributes ( pci_io.pci_io,
182
+				    EfiPciIoAttributeOperationEnable,
183
+				    EFI_PCI_IO_ATTRIBUTE_MEMORY, NULL );
184
+	pci_io.pci_io->Attributes ( pci_io.pci_io,
185
+				    EfiPciIoAttributeOperationEnable,
186
+				    EFI_PCI_IO_ATTRIBUTE_BUS_MASTER, NULL );
187
+
195
 	/* Populate PCI device */
188
 	/* Populate PCI device */
196
-	pci_init ( &(*efipci)->pci, PCI_BUSDEVFN ( pci_bus, pci_dev, pci_fn ) );
197
-	if ( ( rc = pci_read_config ( &(*efipci)->pci ) ) != 0 ) {
189
+	pci_init ( pci, PCI_BUSDEVFN ( pci_bus, pci_dev, pci_fn ) );
190
+	if ( ( rc = pci_read_config ( pci ) ) != 0 ) {
198
 		DBGC ( device, "EFIPCI %p %s cannot read PCI configuration: "
191
 		DBGC ( device, "EFIPCI %p %s cannot read PCI configuration: "
199
 		       "%s\n", device, efi_handle_devpath_text ( device ),
192
 		       "%s\n", device, efi_handle_devpath_text ( device ),
200
 		       strerror ( rc ) );
193
 		       strerror ( rc ) );
201
 		goto err_pci_read_config;
194
 		goto err_pci_read_config;
202
 	}
195
 	}
203
 
196
 
204
-	/* Retrieve device path */
205
-	if ( ( efirc = bs->OpenProtocol ( device,
206
-					  &efi_device_path_protocol_guid,
207
-					  &path.interface, efi_image_handle,
208
-					  device, attributes ) ) != 0 ) {
209
-		rc = -EEFI ( efirc );
210
-		DBGC ( device, "EFIPCI %p %s has no device path\n",
211
-		       device, efi_handle_devpath_text ( device ) );
212
-		goto err_no_device_path;
213
-	}
214
-	(*efipci)->path = path.path;
215
-
216
-	/* Add to list of PCI devices */
217
-	list_add ( &(*efipci)->list, &efi_pci_devices );
218
-
219
 	return 0;
197
 	return 0;
220
 
198
 
221
-	bs->CloseProtocol ( device, &efi_device_path_protocol_guid,
222
-			    efi_image_handle, device );
223
- err_no_device_path:
224
  err_pci_read_config:
199
  err_pci_read_config:
225
  err_get_location:
200
  err_get_location:
226
 	bs->CloseProtocol ( device, &efi_pci_io_protocol_guid,
201
 	bs->CloseProtocol ( device, &efi_pci_io_protocol_guid,
227
 			    efi_image_handle, device );
202
 			    efi_image_handle, device );
228
  err_open_protocol:
203
  err_open_protocol:
229
-	free ( *efipci );
230
- err_zalloc:
231
 	return rc;
204
 	return rc;
232
 }
205
 }
233
 
206
 
234
 /**
207
 /**
235
- * Enable EFI PCI device
236
- *
237
- * @v efipci		EFI PCI device
238
- * @ret rc		Return status code
239
- */
240
-int efipci_enable ( struct efi_pci_device *efipci ) {
241
-	EFI_PCI_IO_PROTOCOL *pci_io = efipci->pci_io;
242
-
243
-	/* Try to enable I/O cycles, memory cycles, and bus mastering.
244
-	 * Some platforms will 'helpfully' report errors if these bits
245
-	 * can't be enabled (for example, if the card doesn't actually
246
-	 * support I/O cycles).  Work around any such platforms by
247
-	 * enabling bits individually and simply ignoring any errors.
248
-	 */
249
-	pci_io->Attributes ( pci_io, EfiPciIoAttributeOperationEnable,
250
-			     EFI_PCI_IO_ATTRIBUTE_IO, NULL );
251
-	pci_io->Attributes ( pci_io, EfiPciIoAttributeOperationEnable,
252
-			     EFI_PCI_IO_ATTRIBUTE_MEMORY, NULL );
253
-	pci_io->Attributes ( pci_io, EfiPciIoAttributeOperationEnable,
254
-			     EFI_PCI_IO_ATTRIBUTE_BUS_MASTER, NULL );
255
-
256
-	return 0;
257
-}
258
-
259
-/**
260
- * Find EFI PCI device by EFI device
261
- *
262
- * @v device		EFI device
263
- * @ret efipci		EFI PCI device, or NULL
264
- */
265
-struct efi_pci_device * efipci_find_efi ( EFI_HANDLE device ) {
266
-	struct efi_pci_device *efipci;
267
-
268
-	list_for_each_entry ( efipci, &efi_pci_devices, list ) {
269
-		if ( efipci->device == device )
270
-			return efipci;
271
-	}
272
-	return NULL;
273
-}
274
-
275
-/**
276
- * Find EFI PCI device by iPXE device
208
+ * Close EFI PCI device
277
  *
209
  *
278
- * @v dev		Device
279
- * @ret efipci		EFI PCI device, or NULL
210
+ * @v device		EFI device handle
280
  */
211
  */
281
-struct efi_pci_device * efipci_find ( struct device *dev ) {
282
-	struct efi_pci_device *efipci;
212
+void efipci_close ( EFI_HANDLE device ) {
213
+	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
283
 
214
 
284
-	list_for_each_entry ( efipci, &efi_pci_devices, list ) {
285
-		if ( &efipci->pci.dev == dev )
286
-			return efipci;
287
-	}
288
-	return NULL;
215
+	bs->CloseProtocol ( device, &efi_pci_io_protocol_guid,
216
+			    efi_image_handle, device );
289
 }
217
 }
290
 
218
 
291
 /**
219
 /**
292
- * Add EFI device as child of EFI PCI device
220
+ * Get EFI PCI device information
293
  *
221
  *
294
- * @v efipci		EFI PCI device
295
- * @v device		EFI child device
296
- * @ret efirc		EFI status code
222
+ * @v device		EFI device handle
223
+ * @v pci		PCI device to fill in
224
+ * @ret rc		Return status code
297
  */
225
  */
298
-int efipci_child_add ( struct efi_pci_device *efipci, EFI_HANDLE device ) {
299
-	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
300
-	union {
301
-		EFI_PCI_IO_PROTOCOL *pci_io;
302
-		void *interface;
303
-	} pci_io;
304
-	EFI_STATUS efirc;
226
+int efipci_info ( EFI_HANDLE device, struct pci_device *pci ) {
305
 	int rc;
227
 	int rc;
306
 
228
 
307
-	/* Re-open the PCI_IO_PROTOCOL */
308
-	if ( ( efirc = bs->OpenProtocol ( efipci->device,
309
-					  &efi_pci_io_protocol_guid,
310
-					  &pci_io.interface,
311
-					  efi_image_handle, device,
312
-					  EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
313
-					  ) ) != 0 ) {
314
-		rc = -EEFI ( efirc );
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 ) );
229
+	/* Open PCI device, if possible */
230
+	if ( ( rc = efipci_open ( device, EFI_OPEN_PROTOCOL_GET_PROTOCOL,
231
+				  pci ) ) != 0 )
319
 		return rc;
232
 		return rc;
320
-	}
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 ) );
326
-	return 0;
327
-}
328
-
329
-/**
330
- * Remove EFI device as child of PCI device
331
- *
332
- * @v efipci		EFI PCI device
333
- * @v device		EFI child device
334
- * @ret efirc		EFI status code
335
- */
336
-void efipci_child_del ( struct efi_pci_device *efipci, EFI_HANDLE device ) {
337
-	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
338
-
339
-	bs->CloseProtocol ( efipci->device, &efi_pci_io_protocol_guid,
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 ) );
345
-}
346
 
233
 
347
-/**
348
- * Destroy EFI PCI device
349
- *
350
- * @v efipci		EFI PCI device
351
- */
352
-void efipci_destroy ( struct efi_pci_device *efipci ) {
353
-	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
234
+	/* Close PCI device */
235
+	efipci_close ( device );
354
 
236
 
355
-	list_del ( &efipci->list );
356
-	bs->CloseProtocol ( efipci->device, &efi_device_path_protocol_guid,
357
-			    efi_image_handle, efipci->device );
358
-	bs->CloseProtocol ( efipci->device, &efi_pci_io_protocol_guid,
359
-			    efi_image_handle, efipci->device );
360
-	free ( efipci );
237
+	return 0;
361
 }
238
 }
362
 
239
 
363
 /******************************************************************************
240
 /******************************************************************************
370
 /**
247
 /**
371
  * Check to see if driver supports a device
248
  * Check to see if driver supports a device
372
  *
249
  *
373
- * @v device		EFI device
250
+ * @v device		EFI device handle
374
  * @ret rc		Return status code
251
  * @ret rc		Return status code
375
  */
252
  */
376
 static int efipci_supported ( EFI_HANDLE device ) {
253
 static int efipci_supported ( EFI_HANDLE device ) {
377
-	struct efi_pci_device *efipci;
254
+	struct pci_device pci;
378
 	int rc;
255
 	int rc;
379
 
256
 
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
-	}
388
-
389
-	/* Create temporary corresponding PCI device, if any */
390
-	if ( ( rc = efipci_create ( device, EFI_OPEN_PROTOCOL_GET_PROTOCOL,
391
-				    &efipci ) ) != 0 )
392
-		goto err_create;
257
+	/* Get PCI device information */
258
+	if ( ( rc = efipci_info ( device, &pci ) ) != 0 )
259
+		return rc;
393
 
260
 
394
 	/* Look for a driver */
261
 	/* Look for a driver */
395
-	if ( ( rc = pci_find_driver ( &efipci->pci ) ) != 0 ) {
262
+	if ( ( rc = pci_find_driver ( &pci ) ) != 0 ) {
396
 		DBGCP ( device, "EFIPCI %p %s has no driver\n",
263
 		DBGCP ( device, "EFIPCI %p %s has no driver\n",
397
-			device, efi_devpath_text ( efipci->path ) );
398
-		goto err_no_driver;
264
+			device, efi_handle_devpath_text ( device ) );
265
+		return rc;
399
 	}
266
 	}
400
-
401
-	DBGC ( device, "EFIPCI %p %s has driver \"%s\"\n", device,
402
-	       efi_devpath_text ( efipci->path ), efipci->pci.id->name );
403
-
404
-	/* Destroy temporary PCI device */
405
-	efipci_destroy ( efipci );
267
+	DBGC ( device, "EFIPCI %p %s has driver \"%s\"\n",
268
+	       device, efi_handle_devpath_text ( device ), pci.id->name );
406
 
269
 
407
 	return 0;
270
 	return 0;
408
-
409
- err_no_driver:
410
-	efipci_destroy ( efipci );
411
- err_create:
412
- err_already_started:
413
-	return rc;
414
 }
271
 }
415
 
272
 
416
 /**
273
 /**
417
  * Attach driver to device
274
  * Attach driver to device
418
  *
275
  *
419
- * @v device		EFI device
276
+ * @v efidev		EFI device
420
  * @ret rc		Return status code
277
  * @ret rc		Return status code
421
  */
278
  */
422
-static int efipci_start ( EFI_HANDLE device ) {
423
-	struct efi_pci_device *efipci;
279
+static int efipci_start ( struct efi_device *efidev ) {
280
+	EFI_HANDLE device = efidev->device;
281
+	struct pci_device *pci;
424
 	int rc;
282
 	int rc;
425
 
283
 
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;
284
+	/* Allocate PCI device */
285
+	pci = zalloc ( sizeof ( *pci ) );
286
+	if ( ! pci ) {
287
+		rc = -ENOMEM;
288
+		goto err_alloc;
433
 	}
289
 	}
434
 
290
 
435
-	/* Create corresponding PCI device */
436
-	if ( ( rc = efipci_create ( device, ( EFI_OPEN_PROTOCOL_BY_DRIVER |
437
-					      EFI_OPEN_PROTOCOL_EXCLUSIVE ),
438
-				    &efipci ) ) != 0 )
439
-		goto err_create;
291
+	/* Open PCI device */
292
+	if ( ( rc = efipci_open ( device, ( EFI_OPEN_PROTOCOL_BY_DRIVER |
293
+					    EFI_OPEN_PROTOCOL_EXCLUSIVE ),
294
+				  pci ) ) != 0 ) {
295
+		DBGC ( device, "EFIPCI %p %s could not open PCI device: %s\n",
296
+		       device, efi_devpath_text ( efidev->path ),
297
+		       strerror ( rc ) );
298
+		goto err_open;
299
+	}
440
 
300
 
441
 	/* Find driver */
301
 	/* Find driver */
442
-	if ( ( rc = pci_find_driver ( &efipci->pci ) ) != 0 ) {
302
+	if ( ( rc = pci_find_driver ( pci ) ) != 0 ) {
443
 		DBGC ( device, "EFIPCI %p %s has no driver\n",
303
 		DBGC ( device, "EFIPCI %p %s has no driver\n",
444
-		       device, efi_devpath_text ( efipci->path ) );
304
+		       device, efi_devpath_text ( efidev->path ) );
445
 		goto err_find_driver;
305
 		goto err_find_driver;
446
 	}
306
 	}
447
 
307
 
448
-	/* Enable PCI device */
449
-	if ( ( rc = efipci_enable ( efipci ) ) != 0 )
450
-		goto err_enable;
308
+	/* Mark PCI device as a child of the EFI device */
309
+	pci->dev.parent = &efidev->dev;
310
+	list_add ( &pci->dev.siblings, &efidev->dev.children );
451
 
311
 
452
 	/* Probe driver */
312
 	/* Probe driver */
453
-	if ( ( rc = pci_probe ( &efipci->pci ) ) != 0 ) {
313
+	if ( ( rc = pci_probe ( pci ) ) != 0 ) {
454
 		DBGC ( device, "EFIPCI %p %s could not probe driver \"%s\": "
314
 		DBGC ( device, "EFIPCI %p %s could not probe driver \"%s\": "
455
-		       "%s\n", device, efi_devpath_text ( efipci->path ),
456
-		       efipci->pci.id->name, strerror ( rc ) );
315
+		       "%s\n", device, efi_devpath_text ( efidev->path ),
316
+		       pci->id->name, strerror ( rc ) );
457
 		goto err_probe;
317
 		goto err_probe;
458
 	}
318
 	}
459
 	DBGC ( device, "EFIPCI %p %s using driver \"%s\"\n", device,
319
 	DBGC ( device, "EFIPCI %p %s using driver \"%s\"\n", device,
460
-	       efi_devpath_text ( efipci->path ), efipci->pci.id->name );
320
+	       efi_devpath_text ( efidev->path ), pci->id->name );
461
 
321
 
322
+	efidev_set_drvdata ( efidev, pci );
462
 	return 0;
323
 	return 0;
463
 
324
 
464
-	pci_remove ( &efipci->pci );
325
+	pci_remove ( pci );
465
  err_probe:
326
  err_probe:
466
- err_enable:
327
+	list_del ( &pci->dev.siblings );
467
  err_find_driver:
328
  err_find_driver:
468
-	efipci_destroy ( efipci );
469
- err_create:
470
- err_already_started:
329
+	efipci_close ( device );
330
+ err_open:
331
+	free ( pci );
332
+ err_alloc:
471
 	return rc;
333
 	return rc;
472
 }
334
 }
473
 
335
 
474
 /**
336
 /**
475
  * Detach driver from device
337
  * Detach driver from device
476
  *
338
  *
477
- * @v device		EFI device
339
+ * @v efidev		EFI device
478
   */
340
   */
479
-static void efipci_stop ( EFI_HANDLE device ) {
480
-	struct efi_pci_device *efipci;
481
-
482
-	/* Find PCI device */
483
-	efipci = efipci_find_efi ( device );
484
-	if ( ! efipci )
485
-		return;
486
-
487
-	/* Remove device */
488
-	pci_remove ( &efipci->pci );
489
-
490
-	/* Delete EFI PCI device */
491
-	efipci_destroy ( efipci );
341
+static void efipci_stop ( struct efi_device *efidev ) {
342
+	struct pci_device *pci = efidev_get_drvdata ( efidev );
343
+	EFI_HANDLE device = efidev->device;
344
+
345
+	pci_remove ( pci );
346
+	list_del ( &pci->dev.siblings );
347
+	efipci_close ( device );
348
+	free ( pci );
492
 }
349
 }
493
 
350
 
494
 /** EFI PCI driver */
351
 /** EFI PCI driver */

+ 40
- 25
src/interface/efi/efi_snp.c View File

27
 #include <ipxe/netdevice.h>
27
 #include <ipxe/netdevice.h>
28
 #include <ipxe/iobuf.h>
28
 #include <ipxe/iobuf.h>
29
 #include <ipxe/in.h>
29
 #include <ipxe/in.h>
30
-#include <ipxe/pci.h>
31
 #include <ipxe/version.h>
30
 #include <ipxe/version.h>
32
 #include <ipxe/efi/efi.h>
31
 #include <ipxe/efi/efi.h>
33
-#include <ipxe/efi/efi_pci.h>
34
 #include <ipxe/efi/efi_driver.h>
32
 #include <ipxe/efi/efi_driver.h>
35
 #include <ipxe/efi/efi_strings.h>
33
 #include <ipxe/efi/efi_strings.h>
36
 #include <ipxe/efi/efi_snp.h>
34
 #include <ipxe/efi/efi_snp.h>
348
 	/* MAC address changes take effect only on netdev_open() */
346
 	/* MAC address changes take effect only on netdev_open() */
349
 	if ( netdev_is_open ( snpdev->netdev ) ) {
347
 	if ( netdev_is_open ( snpdev->netdev ) ) {
350
 		DBGC ( snpdev, "SNPDEV %p MAC address changed while net "
348
 		DBGC ( snpdev, "SNPDEV %p MAC address changed while net "
351
-		       "devive open\n", snpdev );
349
+		       "device open\n", snpdev );
352
 	}
350
 	}
353
 
351
 
354
 	return 0;
352
 	return 0;
922
  */
920
  */
923
 static int efi_snp_probe ( struct net_device *netdev ) {
921
 static int efi_snp_probe ( struct net_device *netdev ) {
924
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
922
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
925
-	struct efi_pci_device *efipci;
923
+	struct efi_device *efidev;
926
 	struct efi_snp_device *snpdev;
924
 	struct efi_snp_device *snpdev;
927
 	EFI_DEVICE_PATH_PROTOCOL *path_end;
925
 	EFI_DEVICE_PATH_PROTOCOL *path_end;
928
 	MAC_ADDR_DEVICE_PATH *macpath;
926
 	MAC_ADDR_DEVICE_PATH *macpath;
930
 	EFI_STATUS efirc;
928
 	EFI_STATUS efirc;
931
 	int rc;
929
 	int rc;
932
 
930
 
933
-	/* Find EFI PCI device */
934
-	efipci = efipci_find ( netdev->dev );
935
-	if ( ! efipci ) {
936
-		DBG ( "SNP skipping non-PCI device %s\n", netdev->name );
931
+	/* Find parent EFI device */
932
+	efidev = efidev_parent ( netdev->dev );
933
+	if ( ! efidev ) {
934
+		DBG ( "SNP skipping non-EFI device %s\n", netdev->name );
937
 		rc = 0;
935
 		rc = 0;
938
-		goto err_no_pci;
936
+		goto err_no_efidev;
939
 	}
937
 	}
940
 
938
 
941
 	/* Calculate device path prefix length */
939
 	/* Calculate device path prefix length */
942
-	path_end = efi_devpath_end ( efipci->path );
940
+	path_end = efi_devpath_end ( efidev->path );
943
 	path_prefix_len = ( ( ( void * ) path_end ) -
941
 	path_prefix_len = ( ( ( void * ) path_end ) -
944
-			    ( ( void * ) efipci->path ) );
942
+			    ( ( void * ) efidev->path ) );
945
 
943
 
946
 	/* Allocate the SNP device */
944
 	/* Allocate the SNP device */
947
 	snpdev = zalloc ( sizeof ( *snpdev ) + path_prefix_len +
945
 	snpdev = zalloc ( sizeof ( *snpdev ) + path_prefix_len +
951
 		goto err_alloc_snp;
949
 		goto err_alloc_snp;
952
 	}
950
 	}
953
 	snpdev->netdev = netdev_get ( netdev );
951
 	snpdev->netdev = netdev_get ( netdev );
954
-	snpdev->efipci = efipci;
952
+	snpdev->efidev = efidev;
955
 
953
 
956
 	/* Sanity check */
954
 	/* Sanity check */
957
 	if ( netdev->ll_protocol->ll_addr_len > sizeof ( EFI_MAC_ADDRESS ) ) {
955
 	if ( netdev->ll_protocol->ll_addr_len > sizeof ( EFI_MAC_ADDRESS ) ) {
1009
 		       "%s", netdev->name );
1007
 		       "%s", netdev->name );
1010
 
1008
 
1011
 	/* Populate the device path */
1009
 	/* Populate the device path */
1012
-	memcpy ( &snpdev->path, efipci->path, path_prefix_len );
1010
+	memcpy ( &snpdev->path, efidev->path, path_prefix_len );
1013
 	macpath = ( ( ( void * ) &snpdev->path ) + path_prefix_len );
1011
 	macpath = ( ( ( void * ) &snpdev->path ) + path_prefix_len );
1014
 	path_end = ( ( void * ) ( macpath + 1 ) );
1012
 	path_end = ( ( void * ) ( macpath + 1 ) );
1015
 	memset ( macpath, 0, sizeof ( *macpath ) );
1013
 	memset ( macpath, 0, sizeof ( *macpath ) );
1040
 		goto err_install_protocol_interface;
1038
 		goto err_install_protocol_interface;
1041
 	}
1039
 	}
1042
 
1040
 
1043
-	/* Add as child of PCI device */
1044
-	if ( ( rc = efipci_child_add ( efipci, snpdev->handle ) ) != 0 ) {
1045
-		DBGC ( snpdev, "SNPDEV %p could not become child of " PCI_FMT
1046
-		       ": %s\n", snpdev, PCI_ARGS ( &efipci->pci ),
1047
-		       strerror ( rc ) );
1048
-		goto err_efipci_child_add;
1041
+	/* Add as child of EFI parent device */
1042
+	if ( ( rc = efidev_child_add ( efidev, snpdev->handle ) ) != 0 ) {
1043
+		DBGC ( snpdev, "SNPDEV %p could not become child of %p %s: "
1044
+		       "%s\n", snpdev, efidev->device,
1045
+		       efi_devpath_text ( efidev->path ), strerror ( rc ) );
1046
+		goto err_efidev_child_add;
1049
 	}
1047
 	}
1050
 
1048
 
1051
 	/* Install HII */
1049
 	/* Install HII */
1058
 	/* Add to list of SNP devices */
1056
 	/* Add to list of SNP devices */
1059
 	list_add ( &snpdev->list, &efi_snp_devices );
1057
 	list_add ( &snpdev->list, &efi_snp_devices );
1060
 
1058
 
1061
-	DBGC ( snpdev, "SNPDEV %p installed for %s as device %p\n",
1062
-	       snpdev, netdev->name, snpdev->handle );
1059
+	DBGC ( snpdev, "SNPDEV %p installed for %s as device %p %s\n",
1060
+	       snpdev, netdev->name, snpdev->handle,
1061
+	       efi_devpath_text ( &snpdev->path ) );
1063
 	return 0;
1062
 	return 0;
1064
 
1063
 
1065
 	efi_snp_hii_uninstall ( snpdev );
1064
 	efi_snp_hii_uninstall ( snpdev );
1066
  err_hii_install:
1065
  err_hii_install:
1067
-	efipci_child_del ( efipci, snpdev->handle );
1068
- err_efipci_child_add:
1066
+	efidev_child_del ( efidev, snpdev->handle );
1067
+ err_efidev_child_add:
1069
 	bs->UninstallMultipleProtocolInterfaces (
1068
 	bs->UninstallMultipleProtocolInterfaces (
1070
 			snpdev->handle,
1069
 			snpdev->handle,
1071
 			&efi_simple_network_protocol_guid, &snpdev->snp,
1070
 			&efi_simple_network_protocol_guid, &snpdev->snp,
1082
 	netdev_put ( netdev );
1081
 	netdev_put ( netdev );
1083
 	free ( snpdev );
1082
 	free ( snpdev );
1084
  err_alloc_snp:
1083
  err_alloc_snp:
1085
- err_no_pci:
1084
+ err_no_efidev:
1086
 	return rc;
1085
 	return rc;
1087
 }
1086
 }
1088
 
1087
 
1129
 
1128
 
1130
 	/* Uninstall the SNP */
1129
 	/* Uninstall the SNP */
1131
 	efi_snp_hii_uninstall ( snpdev );
1130
 	efi_snp_hii_uninstall ( snpdev );
1132
-	efipci_child_del ( snpdev->efipci, snpdev->handle );
1131
+	efidev_child_del ( snpdev->efidev, snpdev->handle );
1133
 	list_del ( &snpdev->list );
1132
 	list_del ( &snpdev->list );
1134
 	bs->UninstallMultipleProtocolInterfaces (
1133
 	bs->UninstallMultipleProtocolInterfaces (
1135
 			snpdev->handle,
1134
 			snpdev->handle,
1153
 	.remove = efi_snp_remove,
1152
 	.remove = efi_snp_remove,
1154
 };
1153
 };
1155
 
1154
 
1155
+/**
1156
+ * Find SNP device by EFI device handle
1157
+ *
1158
+ * @v handle		EFI device handle
1159
+ * @ret snpdev		SNP device, or NULL
1160
+ */
1161
+struct efi_snp_device * find_snpdev ( EFI_HANDLE handle ) {
1162
+	struct efi_snp_device *snpdev;
1163
+
1164
+	list_for_each_entry ( snpdev, &efi_snp_devices, list ) {
1165
+		if ( snpdev->handle == handle )
1166
+			return snpdev;
1167
+	}
1168
+	return NULL;
1169
+}
1170
+
1156
 /**
1171
 /**
1157
  * Get most recently opened SNP device
1172
  * Get most recently opened SNP device
1158
  *
1173
  *

Loading…
Cancel
Save