|
|
1.1 root 1: /*
2: * Copyright (C) 2011 Michael Brown <[email protected]>.
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: #define IBM_BOFM_DRIVER_CONFIGURATION2_PROTOCOL_GUID \
49: { 0xe82a9763, 0x0584, 0x4e41, \
50: { 0xbb, 0x39, 0xe0, 0xcd, 0xb8, 0xc1, 0xf0, 0xfc } }
51:
52: typedef struct {
53: UINT8 Id;
54: UINT8 ResultByte;
55: } __attribute__ (( packed )) BOFM_EPID_Results_t;
56:
57: typedef struct {
58: UINT8 Version;
59: UINT8 Level;
60: UINT16 Length;
61: UINT8 Checksum;
62: UINT8 Profile[32];
63: UINT8 GlobalOption0;
64: UINT8 GlobalOption1;
65: UINT8 GlobalOption2;
66: UINT8 GlobalOption3;
67: UINT32 SequenceStamp;
68: UINT8 Regions[911]; // For use by BOFM Driver
69: UINT32 Reserved1;
70: } __attribute__ (( packed )) BOFM_Parameters_t;
71:
72: typedef struct {
73: UINT32 Reserved1;
74: UINT8 Version;
75: UINT8 Level;
76: UINT8 Checksum;
77: UINT32 SequenceStamp;
78: UINT8 SUIDResults;
79: UINT8 EntryResults[32];
80: UINT8 Reserved2;
81: UINT8 Reserved3;
82: UINT8 FCTgtResults[2];
83: UINT8 SASTgtResults[2];
84: BOFM_EPID_Results_t EPIDResults[2];
85: UINT8 Results4[10];
86: } __attribute__ (( packed )) BOFM_Results_t;
87:
88: typedef struct {
89: UINT32 Signature;
90: UINT32 SubSignature;
91: BOFM_Parameters_t Parameters;
92: BOFM_Results_t Results;
93: } __attribute__ (( packed )) BOFM_DataStructure_t;
94:
95: #define IBM_BOFM_TABLE BOFM_DataStructure_t
96:
97: typedef struct _IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL
98: IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL;
99:
100: typedef EFI_STATUS ( EFIAPI *IBM_BOFM_DRIVER_CONFIGURATION_SUPPORT ) (
101: IN IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL *This,
102: EFI_HANDLE ControllerHandle,
103: UINT8 SupporttedOptions,
104: UINT8 iSCSI_Parameter_Version,
105: UINT8 BOFM_Parameter_Version
106: );
107:
108: typedef EFI_STATUS ( EFIAPI *IBM_BOFM_DRIVER_CONFIGURATION_STATUS ) (
109: IN IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL *This,
110: EFI_HANDLE ControllerHandle,
111: BOOLEAN ResetRequired,
112: UINT8 BOFMReturnCode
113: );
114:
115: struct _IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL {
116: IBM_BOFM_TABLE BofmTable;
117: IBM_BOFM_DRIVER_CONFIGURATION_STATUS SetStatus;
118: IBM_BOFM_DRIVER_CONFIGURATION_SUPPORT RegisterSupport;
119: };
120:
121: typedef struct _IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL2 {
122: UINT32 Signature;
123: UINT32 Reserved1;
124: UINT64 Reserved2;
125: IBM_BOFM_DRIVER_CONFIGURATION_STATUS SetStatus;
126: IBM_BOFM_DRIVER_CONFIGURATION_SUPPORT RegisterSupport;
127: IBM_BOFM_TABLE BofmTable;
128: } IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL2;
129:
130: /***************************************************************************
131: *
132: * EFI BOFM interface
133: *
134: ***************************************************************************
135: */
136:
137: /** BOFM1 protocol GUID */
138: static EFI_GUID bofm1_protocol_guid =
139: IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL_GUID;
140:
141: /** BOFM2 protocol GUID */
142: static EFI_GUID bofm2_protocol_guid =
143: IBM_BOFM_DRIVER_CONFIGURATION2_PROTOCOL_GUID;
144:
145: /**
146: * Check if device is supported
147: *
148: * @v driver EFI driver
149: * @v device EFI device
150: * @v child Path to child device, if any
151: * @ret efirc EFI status code
152: */
153: static EFI_STATUS EFIAPI
154: efi_bofm_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver,
155: EFI_HANDLE device,
156: EFI_DEVICE_PATH_PROTOCOL *child ) {
157: struct efi_driver *efidrv =
158: container_of ( driver, struct efi_driver, driver );
159: EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
160: union {
161: IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL *bofm1;
162: void *interface;
163: } bofm1;
164: struct efi_pci_device *efipci;
165: EFI_STATUS efirc;
166: int rc;
167:
168: DBGCP ( efidrv, "BOFM DRIVER_SUPPORTED %p (%p)\n", device, child );
169:
170: /* Create corresponding PCI device, if any */
171: efipci = efipci_create ( efidrv, device );
172: if ( ! efipci ) {
173: efirc = EFI_UNSUPPORTED;
174: goto err_not_pci;
175: }
176:
177: /* Look for a BOFM driver */
178: if ( ( rc = bofm_find_driver ( &efipci->pci ) ) != 0 ) {
179: DBGC2 ( efidrv, "BOFM " PCI_FMT " has no driver\n",
180: PCI_ARGS ( &efipci->pci ) );
181: efirc = EFI_UNSUPPORTED;
182: goto err_no_driver;
183: }
184:
185: /* Locate BOFM protocol */
186: if ( ( efirc = bs->LocateProtocol ( &bofm1_protocol_guid, NULL,
187: &bofm1.interface ) ) != 0 ) {
188: DBGC ( efidrv, "BOFM " PCI_FMT " cannot find BOFM protocol\n",
189: PCI_ARGS ( &efipci->pci ) );
190: efirc = EFI_UNSUPPORTED;
191: goto err_not_bofm;
192: }
193:
194: /* Register support for this device */
195: if ( ( efirc = bofm1.bofm1->RegisterSupport ( bofm1.bofm1, device,
196: 0x04 /* Can change MAC */,
197: 0x00 /* No iSCSI */,
198: 0x02 /* Version */ ))!=0){
199: DBGC ( efidrv, "BOFM " PCI_FMT " could not register support: "
200: "%s\n", PCI_ARGS ( &efipci->pci ),
201: efi_strerror ( efirc ) );
202: goto err_cannot_register;
203: }
204:
205: DBGC ( efidrv, "BOFM " PCI_FMT " is supported by driver \"%s\"\n",
206: PCI_ARGS ( &efipci->pci ), efipci->pci.id->name );
207:
208: /* Destroy temporary PCI device */
209: efipci_destroy ( efidrv, efipci );
210:
211: return 0;
212:
213: err_cannot_register:
214: err_not_bofm:
215: err_no_driver:
216: efipci_destroy ( efidrv, efipci );
217: err_not_pci:
218: return efirc;
219: }
220:
221: /**
222: * Attach driver to device
223: *
224: * @v driver EFI driver
225: * @v device EFI device
226: * @v child Path to child device, if any
227: * @ret efirc EFI status code
228: */
229: static EFI_STATUS EFIAPI efi_bofm_start ( EFI_DRIVER_BINDING_PROTOCOL *driver,
230: EFI_HANDLE device,
231: EFI_DEVICE_PATH_PROTOCOL *child ) {
232: struct efi_driver *efidrv =
233: container_of ( driver, struct efi_driver, driver );
234: EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
235: union {
236: IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL *bofm1;
237: void *interface;
238: } bofm1;
239: union {
240: IBM_BOFM_DRIVER_CONFIGURATION_PROTOCOL2 *bofm2;
241: void *interface;
242: } bofm2;
243: struct efi_pci_device *efipci;
244: userptr_t bofmtab;
245: EFI_STATUS efirc;
246: int bofmrc;
247:
248: DBGCP ( efidrv, "BOFM DRIVER_START %p (%p)\n", device, child );
249:
250: /* Create corresponding PCI device */
251: efipci = efipci_create ( efidrv, device );
252: if ( ! efipci ) {
253: efirc = EFI_OUT_OF_RESOURCES;
254: goto err_create;
255: }
256:
257: /* Enable PCI device */
258: if ( ( efirc = efipci_enable ( efipci ) ) != 0 )
259: goto err_enable;
260:
261: /* Locate BOFM protocol */
262: if ( ( efirc = bs->LocateProtocol ( &bofm1_protocol_guid, NULL,
263: &bofm1.interface ) ) != 0 ) {
264: DBGC ( efidrv, "BOFM " PCI_FMT " cannot find BOFM protocol\n",
265: PCI_ARGS ( &efipci->pci ) );
266: goto err_locate_bofm;
267: }
268:
269: /* Locate BOFM2 protocol, if available */
270: if ( ( efirc = bs->LocateProtocol ( &bofm2_protocol_guid, NULL,
271: &bofm2.interface ) ) != 0 ) {
272: DBGC ( efidrv, "BOFM " PCI_FMT " cannot find BOFM2 protocol\n",
273: PCI_ARGS ( &efipci->pci ) );
274: /* Not a fatal error; may be a BOFM1-only system */
275: bofm2.bofm2 = NULL;
276: }
277:
278: /* Select appropriate BOFM table (v1 or v2) to use */
279: if ( bofm2.bofm2 ) {
280: DBGC ( efidrv, "BOFM " PCI_FMT " using version 2 BOFM table\n",
281: PCI_ARGS ( &efipci->pci ) );
282: assert ( bofm2.bofm2->RegisterSupport ==
283: bofm1.bofm1->RegisterSupport );
284: assert ( bofm2.bofm2->SetStatus == bofm1.bofm1->SetStatus );
285: bofmtab = virt_to_user ( &bofm2.bofm2->BofmTable );
286: } else {
287: DBGC ( efidrv, "BOFM " PCI_FMT " using version 1 BOFM table\n",
288: PCI_ARGS ( &efipci->pci ) );
289: bofmtab = virt_to_user ( &bofm1.bofm1->BofmTable );
290: }
291:
292: /* Process BOFM table */
293: bofmrc = bofm ( bofmtab, &efipci->pci );
294: DBGC ( efidrv, "BOFM " PCI_FMT " status %08x\n",
295: PCI_ARGS ( &efipci->pci ), bofmrc );
296:
297: /* Return BOFM status */
298: if ( ( efirc = bofm1.bofm1->SetStatus ( bofm1.bofm1, device, FALSE,
299: bofmrc ) ) != 0 ) {
300: DBGC ( efidrv, "BOFM " PCI_FMT " could not set BOFM status: "
301: "%s\n", PCI_ARGS ( &efipci->pci ),
302: efi_strerror ( efirc ) );
303: goto err_set_status;
304: }
305:
306: /* Destroy the PCI device anyway; we have no further use for it */
307: efipci_destroy ( efidrv, efipci );
308:
309: /* BOFM (ab)uses the "start" method to mean "process and exit" */
310: return EFI_NOT_READY;
311:
312: err_set_status:
313: err_locate_bofm:
314: err_enable:
315: efipci_destroy ( efidrv, efipci );
316: err_create:
317: return efirc;
318: }
319:
320: /**
321: * Detach driver from device
322: *
323: * @v driver EFI driver
324: * @v device EFI device
325: * @v num_children Number of child devices
326: * @v children List of child devices
327: * @ret efirc EFI status code
328: */
329: static EFI_STATUS EFIAPI efi_bofm_stop ( EFI_DRIVER_BINDING_PROTOCOL *driver,
330: EFI_HANDLE device, UINTN num_children,
331: EFI_HANDLE *children ) {
332: struct efi_driver *efidrv =
333: container_of ( driver, struct efi_driver, driver );
334:
335: DBGCP ( efidrv, "BOFM DRIVER_STOP %p (%ld %p)\n",
336: device, ( ( unsigned long ) num_children ), children );
337:
338: return 0;
339: }
340:
341: /** EFI BOFM driver */
342: static struct efi_driver efi_bofm_driver =
343: EFI_DRIVER_INIT ( "BOFM",
344: efi_bofm_supported, efi_bofm_start, efi_bofm_stop );
345:
346: /**
347: * Install EFI BOFM driver
348: *
349: */
350: static void efi_bofm_driver_init ( void ) {
351: struct efi_driver *efidrv = &efi_bofm_driver;
352: EFI_STATUS efirc;
353:
354: /* Install driver */
355: if ( ( efirc = efi_driver_install ( efidrv ) ) != 0 ) {
356: DBGC ( efidrv, "BOFM could not install driver: %s\n",
357: efi_strerror ( efirc ) );
358: return;
359: }
360:
361: DBGC ( efidrv, "BOFM driver installed\n" );
362: }
363:
364: /** EFI BOFM startup function */
365: struct startup_fn startup_bofm __startup_fn ( STARTUP_EARLY ) = {
366: .startup = efi_bofm_driver_init,
367: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.