|
|
1.1 ! root 1: /* ! 2: * Copyright (C) 2008 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 <string.h> ! 22: #include <ipxe/efi/efi.h> ! 23: #include <ipxe/efi/Protocol/LoadedImage.h> ! 24: #include <ipxe/uuid.h> ! 25: #include <ipxe/init.h> ! 26: ! 27: /** Image handle passed to entry point */ ! 28: EFI_HANDLE efi_image_handle; ! 29: ! 30: /** Loaded image protocol for this image */ ! 31: EFI_LOADED_IMAGE_PROTOCOL *efi_loaded_image; ! 32: ! 33: /** System table passed to entry point */ ! 34: EFI_SYSTEM_TABLE *efi_systab; ! 35: ! 36: /** EFI loaded image protocol GUID */ ! 37: static EFI_GUID efi_loaded_image_protocol_guid ! 38: = EFI_LOADED_IMAGE_PROTOCOL_GUID; ! 39: ! 40: /** Event used to signal shutdown */ ! 41: static EFI_EVENT efi_shutdown_event; ! 42: ! 43: /** ! 44: * Shut down in preparation for booting an OS. ! 45: * ! 46: * This hook gets called at ExitBootServices time in order to make ! 47: * sure that everything is properly shut down before the OS takes ! 48: * over. ! 49: */ ! 50: static EFIAPI void efi_shutdown_hook ( EFI_EVENT event __unused, ! 51: void *context __unused ) { ! 52: shutdown_boot(); ! 53: } ! 54: ! 55: /** ! 56: * Look up EFI configuration table ! 57: * ! 58: * @v guid Configuration table GUID ! 59: * @ret table Configuration table, or NULL ! 60: */ ! 61: static void * efi_find_table ( EFI_GUID *guid ) { ! 62: unsigned int i; ! 63: ! 64: for ( i = 0 ; i < efi_systab->NumberOfTableEntries ; i++ ) { ! 65: if ( memcmp ( &efi_systab->ConfigurationTable[i].VendorGuid, ! 66: guid, sizeof ( *guid ) ) == 0 ) ! 67: return efi_systab->ConfigurationTable[i].VendorTable; ! 68: } ! 69: ! 70: return NULL; ! 71: } ! 72: ! 73: /** ! 74: * Initialise EFI environment ! 75: * ! 76: * @v image_handle Image handle ! 77: * @v systab System table ! 78: * @ret efirc EFI return status code ! 79: */ ! 80: EFI_STATUS efi_init ( EFI_HANDLE image_handle, ! 81: EFI_SYSTEM_TABLE *systab ) { ! 82: EFI_BOOT_SERVICES *bs; ! 83: struct efi_protocol *prot; ! 84: struct efi_config_table *tab; ! 85: EFI_STATUS efirc; ! 86: void *loaded_image; ! 87: ! 88: /* Store image handle and system table pointer for future use */ ! 89: efi_image_handle = image_handle; ! 90: efi_systab = systab; ! 91: ! 92: /* Sanity checks */ ! 93: if ( ! systab ) ! 94: return EFI_NOT_AVAILABLE_YET; ! 95: if ( ! systab->ConOut ) ! 96: return EFI_NOT_AVAILABLE_YET; ! 97: if ( ! systab->BootServices ) { ! 98: DBGC ( systab, "EFI provided no BootServices entry point\n" ); ! 99: return EFI_NOT_AVAILABLE_YET; ! 100: } ! 101: if ( ! systab->RuntimeServices ) { ! 102: DBGC ( systab, "EFI provided no RuntimeServices entry " ! 103: "point\n" ); ! 104: return EFI_NOT_AVAILABLE_YET; ! 105: } ! 106: DBGC ( systab, "EFI handle %p systab %p\n", image_handle, systab ); ! 107: ! 108: bs = systab->BootServices; ! 109: efirc = bs->OpenProtocol ( image_handle, ! 110: &efi_loaded_image_protocol_guid, ! 111: &loaded_image, image_handle, NULL, ! 112: EFI_OPEN_PROTOCOL_GET_PROTOCOL ); ! 113: if ( efirc ) { ! 114: DBGC ( systab, "Could not get loaded image protocol" ); ! 115: return efirc; ! 116: } ! 117: ! 118: efi_loaded_image = loaded_image; ! 119: DBG ( "Image base address = %p\n", efi_loaded_image->ImageBase ); ! 120: ! 121: /* Look up used protocols */ ! 122: for_each_table_entry ( prot, EFI_PROTOCOLS ) { ! 123: if ( ( efirc = bs->LocateProtocol ( &prot->u.guid, NULL, ! 124: prot->protocol ) ) == 0 ) { ! 125: DBGC ( systab, "EFI protocol %s is at %p\n", ! 126: uuid_ntoa ( &prot->u.uuid ), *(prot->protocol)); ! 127: } else { ! 128: DBGC ( systab, "EFI does not provide protocol %s\n", ! 129: uuid_ntoa ( &prot->u.uuid ) ); ! 130: /* All protocols are required */ ! 131: return efirc; ! 132: } ! 133: } ! 134: ! 135: /* Look up used configuration tables */ ! 136: for_each_table_entry ( tab, EFI_CONFIG_TABLES ) { ! 137: if ( ( *(tab->table) = efi_find_table ( &tab->u.guid ) ) ) { ! 138: DBGC ( systab, "EFI configuration table %s is at %p\n", ! 139: uuid_ntoa ( &tab->u.uuid ), *(tab->table) ); ! 140: } else { ! 141: DBGC ( systab, "EFI does not provide configuration " ! 142: "table %s\n", uuid_ntoa ( &tab->u.uuid ) ); ! 143: if ( tab->required ) ! 144: return EFI_NOT_AVAILABLE_YET; ! 145: } ! 146: } ! 147: ! 148: /* EFI is perfectly capable of gracefully shutting down any ! 149: * loaded devices if it decides to fall back to a legacy boot. ! 150: * For no particularly comprehensible reason, it doesn't ! 151: * bother doing so when ExitBootServices() is called. ! 152: */ ! 153: if ( ( efirc = bs->CreateEvent ( EVT_SIGNAL_EXIT_BOOT_SERVICES, ! 154: TPL_CALLBACK, efi_shutdown_hook, ! 155: NULL, &efi_shutdown_event ) ) != 0 ) { ! 156: DBGC ( systab, "EFI could not create ExitBootServices event: " ! 157: "%s\n", efi_strerror ( efirc ) ); ! 158: return efirc; ! 159: } ! 160: ! 161: return 0; ! 162: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.