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