|
|
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.