瀏覽代碼

[bofm] Add support for BOFM under EFI

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 14 年之前
父節點
當前提交
85eefad90c
共有 4 個文件被更改,包括 347 次插入0 次删除
  1. 10
    0
      src/config/config.c
  2. 1
    0
      src/config/defaults/efi.h
  3. 14
    0
      src/config/sideband.h
  4. 322
    0
      src/interface/efi/efi_bofm.c

+ 10
- 0
src/config/config.c 查看文件

@@ -9,6 +9,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
9 9
 
10 10
 #include <config/general.h>
11 11
 #include <config/console.h>
12
+#include <config/sideband.h>
12 13
 
13 14
 /** @file
14 15
  *
@@ -271,3 +272,12 @@ REQUIRE_OBJECT ( embedded );
271 272
 #ifdef DRIVERS_LINUX
272 273
 REQUIRE_OBJECT ( tap );
273 274
 #endif
275
+
276
+/*
277
+ * Drag in relevant BOFM entry points
278
+ */
279
+#ifdef CONFIG_BOFM
280
+#ifdef BOFM_EFI
281
+REQUIRE_OBJECT ( efi_bofm );
282
+#endif /* BOFM_EFI */
283
+#endif /* CONFIG_BOFM */

+ 1
- 0
src/config/defaults/efi.h 查看文件

@@ -16,6 +16,7 @@
16 16
 #define UMALLOC_EFI
17 17
 #define SMBIOS_EFI
18 18
 #define SANBOOT_NULL
19
+#define BOFM_EFI
19 20
 
20 21
 #define	IMAGE_EFI		/* EFI image support */
21 22
 #define	IMAGE_SCRIPT		/* iPXE script image support */

+ 14
- 0
src/config/sideband.h 查看文件

@@ -0,0 +1,14 @@
1
+#ifndef CONFIG_SIDEBAND_H
2
+#define CONFIG_SIDEBAND_H
3
+
4
+/** @file
5
+ *
6
+ * Sideband access by platform firmware
7
+ *
8
+ */
9
+
10
+FILE_LICENCE ( GPL2_OR_LATER );
11
+
12
+//#define	CONFIG_BOFM	/* IBM's BladeCenter Open Fabric Manager */
13
+
14
+#endif /* CONFIG_SIDEBAND_H */

+ 322
- 0
src/interface/efi/efi_bofm.c 查看文件

@@ -0,0 +1,322 @@
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 <errno.h>
22
+#include <ipxe/bofm.h>
23
+#include <ipxe/init.h>
24
+#include <ipxe/efi/efi.h>
25
+#include <ipxe/efi/efi_pci.h>
26
+#include <ipxe/efi/efi_driver.h>
27
+
28
+/** @file
29
+ *
30
+ * IBM BladeCenter Open Fabric Manager (BOFM) EFI interface
31
+ *
32
+ */
33
+
34
+/***************************************************************************
35
+ *
36
+ * EFI BOFM definitions
37
+ *
38
+ ***************************************************************************
39
+ *
40
+ * Taken from the BOFM UEFI Vendor Specification document
41
+ *
42
+ */
43
+
44
+#define IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL_GUID			\
45
+	{ 0x03207ce2, 0xd9c7, 0x11dc,					\
46
+	  { 0xa9, 0x4d, 0x00, 0x19, 0x7d, 0x89, 0x02, 0x38 } }
47
+
48
+typedef struct {
49
+	UINT8 Id;
50
+	UINT8 ResultByte;
51
+} __attribute__ (( packed )) BOFM_EPID_Results_t;
52
+
53
+typedef struct {
54
+	UINT8 Version;
55
+	UINT8 Level;
56
+	UINT16 Length;
57
+	UINT8 Checksum;
58
+	UINT8 Profile[32];
59
+	UINT8 GlobalOption0;
60
+	UINT8 GlobalOption1;
61
+	UINT8 GlobalOption2;
62
+	UINT8 GlobalOption3;
63
+	UINT32 SequenceStamp;
64
+	UINT8 Regions[911]; // For use by BOFM Driver
65
+	UINT32 Reserved1;
66
+} __attribute__ (( packed )) BOFM_Parameters_t;
67
+
68
+typedef struct {
69
+	UINT32 Reserved1;
70
+	UINT8 Version;
71
+	UINT8 Level;
72
+	UINT8 Checksum;
73
+	UINT32 SequenceStamp;
74
+	UINT8 SUIDResults;
75
+	UINT8 EntryResults[32];
76
+	UINT8 Reserved2;
77
+	UINT8 Reserved3;
78
+	UINT8 FCTgtResults[2];
79
+	UINT8 SASTgtResults[2];
80
+	BOFM_EPID_Results_t EPIDResults[2];
81
+	UINT8 Results4[10];
82
+} __attribute__ (( packed )) BOFM_Results_t;
83
+
84
+typedef struct {
85
+	UINT32 Signature;
86
+	UINT32 SubSignature;
87
+	BOFM_Parameters_t Parameters;
88
+	BOFM_Results_t Results;
89
+} __attribute__ (( packed )) BOFM_DataStructure_t;
90
+
91
+#define IBM_BOFM_TABLE BOFM_DataStructure_t
92
+
93
+typedef struct _IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL
94
+	IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL;
95
+
96
+typedef EFI_STATUS ( EFIAPI *IBM_BOFM_DRIVER_CONFIGURATION_SUPPORT ) (
97
+	IN IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL *This,
98
+	EFI_HANDLE ControllerHandle,
99
+	UINT8 SupporttedOptions,
100
+	UINT8 iSCSI_Parameter_Version,
101
+	UINT8 BOFM_Parameter_Version
102
+);
103
+
104
+typedef EFI_STATUS ( EFIAPI *IBM_BOFM_DRIVER_CONFIGURATION_STATUS ) (
105
+	IN IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL *This,
106
+	EFI_HANDLE ControllerHandle,
107
+	BOOLEAN ResetRequired,
108
+	UINT8 BOFMReturnCode
109
+);
110
+
111
+struct _IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL {
112
+	IBM_BOFM_TABLE BofmTable;
113
+	IBM_BOFM_DRIVER_CONFIGURATION_STATUS SetStatus;
114
+	IBM_BOFM_DRIVER_CONFIGURATION_SUPPORT RegisterSupport;
115
+};
116
+
117
+/***************************************************************************
118
+ *
119
+ * EFI BOFM interface
120
+ *
121
+ ***************************************************************************
122
+ */
123
+
124
+/** BOFM protocol GUID */
125
+static EFI_GUID bofm_protocol_guid =
126
+	IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL_GUID;
127
+
128
+/**
129
+ * Check if device is supported
130
+ *
131
+ * @v driver		EFI driver
132
+ * @v device		EFI device
133
+ * @v child		Path to child device, if any
134
+ * @ret efirc		EFI status code
135
+ */
136
+static EFI_STATUS EFIAPI
137
+efi_bofm_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver,
138
+		     EFI_HANDLE device,
139
+		     EFI_DEVICE_PATH_PROTOCOL *child ) {
140
+	struct efi_driver *efidrv =
141
+		container_of ( driver, struct efi_driver, driver );
142
+	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
143
+	union {
144
+		IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL *bofm;
145
+		void *interface;
146
+	} u;
147
+	struct efi_pci_device *efipci;
148
+	EFI_STATUS efirc;
149
+	int rc;
150
+
151
+	DBGCP ( efidrv, "BOFM DRIVER_SUPPORTED %p (%p)\n", device, child );
152
+
153
+	/* Create corresponding PCI device, if any */
154
+	efipci = efipci_create ( efidrv, device );
155
+	if ( ! efipci ) {
156
+		efirc = EFI_UNSUPPORTED;
157
+		goto err_not_pci;
158
+	}
159
+
160
+	/* Look for a BOFM driver */
161
+	if ( ( rc = bofm_find_driver ( &efipci->pci ) ) != 0 ) {
162
+		DBGC2 ( efidrv, "BOFM " PCI_FMT " has no driver\n",
163
+			PCI_ARGS ( &efipci->pci ) );
164
+		efirc = EFI_UNSUPPORTED;
165
+		goto err_no_driver;
166
+	}
167
+
168
+	/* Locate BOFM protocol */
169
+	if ( ( efirc = bs->LocateProtocol ( &bofm_protocol_guid, NULL,
170
+					    &u.interface ) ) != 0 ) {
171
+		DBGC ( efidrv, "BOFM " PCI_FMT " cannot find BOFM protocol\n",
172
+		       PCI_ARGS ( &efipci->pci ) );
173
+		efirc = EFI_UNSUPPORTED;
174
+		goto err_not_bofm;
175
+	}
176
+
177
+	/* Register support for this device */
178
+	if ( ( efirc = u.bofm->RegisterSupport ( u.bofm, device,
179
+						 0x04 /* Can change MAC */,
180
+						 0x00 /* No iSCSI */,
181
+						 0x01 /* Version */ ) ) != 0 ) {
182
+		DBGC ( efidrv, "BOFM " PCI_FMT " could not register support: "
183
+		       "%s\n", PCI_ARGS ( &efipci->pci ),
184
+		       efi_strerror ( efirc ) );
185
+		goto err_cannot_register;
186
+	}
187
+
188
+	DBGC ( efidrv, "BOFM " PCI_FMT " is supported by driver \"%s\"\n",
189
+	       PCI_ARGS ( &efipci->pci ), efipci->pci.id->name );
190
+
191
+	/* Destroy temporary PCI device */
192
+	efipci_destroy ( efidrv, efipci );
193
+
194
+	return 0;
195
+
196
+ err_cannot_register:
197
+ err_not_bofm:
198
+ err_no_driver:
199
+	efipci_destroy ( efidrv, efipci );
200
+ err_not_pci:
201
+	return efirc;
202
+}
203
+
204
+/**
205
+ * Attach driver to device
206
+ *
207
+ * @v driver		EFI driver
208
+ * @v device		EFI device
209
+ * @v child		Path to child device, if any
210
+ * @ret efirc		EFI status code
211
+ */
212
+static EFI_STATUS EFIAPI efi_bofm_start ( EFI_DRIVER_BINDING_PROTOCOL *driver,
213
+				   EFI_HANDLE device,
214
+				   EFI_DEVICE_PATH_PROTOCOL *child ) {
215
+	struct efi_driver *efidrv =
216
+		container_of ( driver, struct efi_driver, driver );
217
+	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
218
+	union {
219
+		IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL *bofm;
220
+		void *interface;
221
+	} u;
222
+	struct efi_pci_device *efipci;
223
+	EFI_STATUS efirc;
224
+	int bofmrc;
225
+
226
+	DBGCP ( efidrv, "BOFM DRIVER_START %p (%p)\n", device, child );
227
+
228
+	/* Create corresponding PCI device */
229
+	efipci = efipci_create ( efidrv, device );
230
+	if ( ! efipci ) {
231
+		efirc = EFI_OUT_OF_RESOURCES;
232
+		goto err_create;
233
+	}
234
+
235
+	/* Enable PCI device */
236
+	if ( ( efirc = efipci_enable ( efipci ) ) != 0 )
237
+		goto err_enable;
238
+
239
+	/* Locate BOFM protocol */
240
+	if ( ( efirc = bs->LocateProtocol ( &bofm_protocol_guid, NULL,
241
+					    &u.interface ) ) != 0 ) {
242
+		DBGC ( efidrv, "BOFM " PCI_FMT " cannot find BOFM protocol\n",
243
+		       PCI_ARGS ( &efipci->pci ) );
244
+		goto err_locate_bofm;
245
+	}
246
+
247
+	/* Process BOFM table */
248
+        bofmrc = bofm ( virt_to_user ( &u.bofm->BofmTable ), &efipci->pci );
249
+	DBGC ( efidrv, "BOFM " PCI_FMT " status %08x\n",
250
+	       PCI_ARGS ( &efipci->pci ), bofmrc );
251
+
252
+	/* Return BOFM status */
253
+	if ( ( efirc = u.bofm->SetStatus ( u.bofm, device, FALSE,
254
+					   bofmrc ) ) != 0 ) {
255
+		DBGC ( efidrv, "BOFM " PCI_FMT " could not set BOFM status: "
256
+		       "%s\n", PCI_ARGS ( &efipci->pci ),
257
+		       efi_strerror ( efirc ) );
258
+		goto err_set_status;
259
+	}
260
+
261
+	/* Destroy the PCI device anyway; we have no further use for it */
262
+	efipci_destroy ( efidrv, efipci );
263
+
264
+	/* BOFM (ab)uses the "start" method to mean "process and exit" */
265
+	return EFI_NOT_READY;
266
+
267
+ err_set_status:
268
+ err_locate_bofm:
269
+ err_enable:
270
+	efipci_destroy ( efidrv, efipci );
271
+ err_create:
272
+	return efirc;
273
+}
274
+
275
+/**
276
+ * Detach driver from device
277
+ *
278
+ * @v driver		EFI driver
279
+ * @v device		EFI device
280
+ * @v num_children	Number of child devices
281
+ * @v children		List of child devices
282
+ * @ret efirc		EFI status code
283
+ */
284
+static EFI_STATUS EFIAPI efi_bofm_stop ( EFI_DRIVER_BINDING_PROTOCOL *driver,
285
+					 EFI_HANDLE device, UINTN num_children,
286
+					 EFI_HANDLE *children ) {
287
+	struct efi_driver *efidrv =
288
+		container_of ( driver, struct efi_driver, driver );
289
+
290
+	DBGCP ( efidrv, "BOFM DRIVER_STOP %p (%ld %p)\n",
291
+		device, ( ( unsigned long ) num_children ), children );
292
+
293
+	return 0;
294
+}
295
+
296
+/** EFI BOFM driver */
297
+static struct efi_driver efi_bofm_driver =
298
+	EFI_DRIVER_INIT ( "BOFM",
299
+			  efi_bofm_supported, efi_bofm_start, efi_bofm_stop );
300
+
301
+/**
302
+ * Install EFI BOFM driver
303
+ *
304
+ */
305
+static void efi_bofm_driver_init ( void ) {
306
+	struct efi_driver *efidrv = &efi_bofm_driver;
307
+	EFI_STATUS efirc;
308
+
309
+	/* Install driver */
310
+	if ( ( efirc = efi_driver_install ( efidrv ) ) != 0 ) {
311
+		DBGC ( efidrv, "BOFM could not install driver: %s\n",
312
+		       efi_strerror ( efirc ) );
313
+		return;
314
+	}
315
+
316
+	DBGC ( efidrv, "BOFM driver installed\n" );
317
+}
318
+
319
+/** EFI BOFM startup function */
320
+struct startup_fn startup_bofm __startup_fn ( STARTUP_EARLY ) = {
321
+	.startup = efi_bofm_driver_init,
322
+};

Loading…
取消
儲存