[efi] Show memory map returned by wrapped calls to GetMemoryMap
[ipxe.git] / src / interface / efi / efi_init.c
1 /*
2 * Copyright (C) 2008 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., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 */
19
20 FILE_LICENCE ( GPL2_OR_LATER );
21
22 #include <string.h>
23 #include <errno.h>
24 #include <endian.h>
25 #include <ipxe/init.h>
26 #include <ipxe/rotate.h>
27 #include <ipxe/efi/efi.h>
28 #include <ipxe/efi/efi_driver.h>
29 #include <ipxe/efi/efi_utils.h>
30 #include <ipxe/efi/Protocol/LoadedImage.h>
31
32 /** Image handle passed to entry point */
33 EFI_HANDLE efi_image_handle;
34
35 /** Loaded image protocol for this image */
36 EFI_LOADED_IMAGE_PROTOCOL *efi_loaded_image;
37
38 /** Device path for the loaded image's device handle */
39 EFI_DEVICE_PATH_PROTOCOL *efi_loaded_image_path;
40
41 /** System table passed to entry point
42 *
43 * We construct the symbol name efi_systab via the PLATFORM macro.
44 * This ensures that the symbol is defined only in EFI builds, and so
45 * prevents EFI code from being incorrectly linked in to a non-EFI
46 * build.
47 */
48 EFI_SYSTEM_TABLE * _C2 ( PLATFORM, _systab );
49
50 /** EFI shutdown is in progress */
51 int efi_shutdown_in_progress;
52
53 /** Event used to signal shutdown */
54 static EFI_EVENT efi_shutdown_event;
55
56 /** Stack cookie */
57 unsigned long __stack_chk_guard;
58
59 /** Exit function
60 *
61 * Cached to minimise external dependencies when a stack check
62 * failure is triggered.
63 */
64 static EFI_EXIT efi_exit;
65
66 /* Forward declarations */
67 static EFI_STATUS EFIAPI efi_unload ( EFI_HANDLE image_handle );
68
69 /**
70 * Shut down in preparation for booting an OS.
71 *
72 * This hook gets called at ExitBootServices time in order to make
73 * sure that everything is properly shut down before the OS takes
74 * over.
75 */
76 static EFIAPI void efi_shutdown_hook ( EFI_EVENT event __unused,
77 void *context __unused ) {
78
79 /* Mark shutdown as being in progress, to indicate that large
80 * parts of the system (e.g. timers) are no longer functional.
81 */
82 efi_shutdown_in_progress = 1;
83
84 /* Shut down iPXE */
85 shutdown_boot();
86 }
87
88 /**
89 * Look up EFI configuration table
90 *
91 * @v guid Configuration table GUID
92 * @ret table Configuration table, or NULL
93 */
94 static void * efi_find_table ( EFI_GUID *guid ) {
95 unsigned int i;
96
97 for ( i = 0 ; i < efi_systab->NumberOfTableEntries ; i++ ) {
98 if ( memcmp ( &efi_systab->ConfigurationTable[i].VendorGuid,
99 guid, sizeof ( *guid ) ) == 0 )
100 return efi_systab->ConfigurationTable[i].VendorTable;
101 }
102
103 return NULL;
104 }
105
106 /**
107 * Construct a stack cookie value
108 *
109 * @v handle Image handle
110 * @ret cookie Stack cookie
111 */
112 __attribute__ (( noinline )) unsigned long
113 efi_stack_cookie ( EFI_HANDLE handle ) {
114 unsigned long cookie = 0;
115 unsigned int rotation = ( 8 * sizeof ( cookie ) / 4 );
116
117 /* There is no viable source of entropy available at this
118 * point. Construct a value that is at least likely to vary
119 * between platforms and invocations.
120 */
121 cookie ^= ( ( unsigned long ) handle );
122 cookie = roll ( cookie, rotation );
123 cookie ^= ( ( unsigned long ) &handle );
124 cookie = roll ( cookie, rotation );
125 cookie ^= profile_timestamp();
126 cookie = roll ( cookie, rotation );
127 cookie ^= build_id;
128
129 /* Ensure that the value contains a NUL byte, to act as a
130 * runaway string terminator. Construct the NUL using a shift
131 * rather than a mask, to avoid losing valuable entropy in the
132 * lower-order bits.
133 */
134 cookie <<= 8;
135
136 /* Ensure that the NUL byte is placed at the bottom of the
137 * stack cookie, to avoid potential disclosure via an
138 * unterminated string.
139 */
140 if ( __BYTE_ORDER == __BIG_ENDIAN )
141 cookie >>= 8;
142
143 return cookie;
144 }
145
146 /**
147 * Initialise EFI environment
148 *
149 * @v image_handle Image handle
150 * @v systab System table
151 * @ret efirc EFI return status code
152 */
153 EFI_STATUS efi_init ( EFI_HANDLE image_handle,
154 EFI_SYSTEM_TABLE *systab ) {
155 EFI_BOOT_SERVICES *bs;
156 struct efi_protocol *prot;
157 struct efi_config_table *tab;
158 void *loaded_image;
159 void *device_path;
160 void *device_path_copy;
161 size_t device_path_len;
162 EFI_STATUS efirc;
163 int rc;
164
165 /* Store image handle and system table pointer for future use */
166 efi_image_handle = image_handle;
167 efi_systab = systab;
168
169 /* Sanity checks */
170 if ( ! systab ) {
171 efirc = EFI_NOT_AVAILABLE_YET;
172 goto err_sanity;
173 }
174 if ( ! systab->ConOut ) {
175 efirc = EFI_NOT_AVAILABLE_YET;
176 goto err_sanity;
177 }
178 if ( ! systab->BootServices ) {
179 DBGC ( systab, "EFI provided no BootServices entry point\n" );
180 efirc = EFI_NOT_AVAILABLE_YET;
181 goto err_sanity;
182 }
183 if ( ! systab->RuntimeServices ) {
184 DBGC ( systab, "EFI provided no RuntimeServices entry "
185 "point\n" );
186 efirc = EFI_NOT_AVAILABLE_YET;
187 goto err_sanity;
188 }
189 DBGC ( systab, "EFI handle %p systab %p\n", image_handle, systab );
190 bs = systab->BootServices;
191
192 /* Store abort function pointer */
193 efi_exit = bs->Exit;
194
195 /* Look up used protocols */
196 for_each_table_entry ( prot, EFI_PROTOCOLS ) {
197 if ( ( efirc = bs->LocateProtocol ( &prot->guid, NULL,
198 prot->protocol ) ) == 0 ) {
199 DBGC ( systab, "EFI protocol %s is at %p\n",
200 efi_guid_ntoa ( &prot->guid ),
201 *(prot->protocol) );
202 } else {
203 DBGC ( systab, "EFI does not provide protocol %s\n",
204 efi_guid_ntoa ( &prot->guid ) );
205 /* Fail if protocol is required */
206 if ( prot->required )
207 goto err_missing_protocol;
208 }
209 }
210
211 /* Look up used configuration tables */
212 for_each_table_entry ( tab, EFI_CONFIG_TABLES ) {
213 if ( ( *(tab->table) = efi_find_table ( &tab->guid ) ) ) {
214 DBGC ( systab, "EFI configuration table %s is at %p\n",
215 efi_guid_ntoa ( &tab->guid ), *(tab->table) );
216 } else {
217 DBGC ( systab, "EFI does not provide configuration "
218 "table %s\n", efi_guid_ntoa ( &tab->guid ) );
219 if ( tab->required ) {
220 efirc = EFI_NOT_AVAILABLE_YET;
221 goto err_missing_table;
222 }
223 }
224 }
225
226 /* Get loaded image protocol */
227 if ( ( efirc = bs->OpenProtocol ( image_handle,
228 &efi_loaded_image_protocol_guid,
229 &loaded_image, image_handle, NULL,
230 EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ) != 0 ) {
231 rc = -EEFI ( efirc );
232 DBGC ( systab, "EFI could not get loaded image protocol: %s",
233 strerror ( rc ) );
234 goto err_no_loaded_image;
235 }
236 efi_loaded_image = loaded_image;
237 DBGC ( systab, "EFI image base address %p\n",
238 efi_loaded_image->ImageBase );
239
240 /* Get loaded image's device handle's device path */
241 if ( ( efirc = bs->OpenProtocol ( efi_loaded_image->DeviceHandle,
242 &efi_device_path_protocol_guid,
243 &device_path, image_handle, NULL,
244 EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ) != 0 ) {
245 rc = -EEFI ( efirc );
246 DBGC ( systab, "EFI could not get loaded image's device path: "
247 "%s", strerror ( rc ) );
248 goto err_no_device_path;
249 }
250
251 /* Make a copy of the loaded image's device handle's device
252 * path, since the device handle itself may become invalidated
253 * when we load our own drivers.
254 */
255 device_path_len = ( efi_devpath_len ( device_path ) +
256 sizeof ( EFI_DEVICE_PATH_PROTOCOL ) );
257 if ( ( efirc = bs->AllocatePool ( EfiBootServicesData, device_path_len,
258 &device_path_copy ) ) != 0 ) {
259 rc = -EEFI ( efirc );
260 goto err_alloc_device_path;
261 }
262 memcpy ( device_path_copy, device_path, device_path_len );
263 efi_loaded_image_path = device_path_copy;
264 DBGC ( systab, "EFI image device path %s\n",
265 efi_devpath_text ( efi_loaded_image_path ) );
266
267 /* EFI is perfectly capable of gracefully shutting down any
268 * loaded devices if it decides to fall back to a legacy boot.
269 * For no particularly comprehensible reason, it doesn't
270 * bother doing so when ExitBootServices() is called.
271 */
272 if ( ( efirc = bs->CreateEvent ( EVT_SIGNAL_EXIT_BOOT_SERVICES,
273 TPL_CALLBACK, efi_shutdown_hook,
274 NULL, &efi_shutdown_event ) ) != 0 ) {
275 rc = -EEFI ( efirc );
276 DBGC ( systab, "EFI could not create ExitBootServices event: "
277 "%s\n", strerror ( rc ) );
278 goto err_create_event;
279 }
280
281 /* Install driver binding protocol */
282 if ( ( rc = efi_driver_install() ) != 0 ) {
283 DBGC ( systab, "EFI could not install driver: %s\n",
284 strerror ( rc ) );
285 efirc = EFIRC ( rc );
286 goto err_driver_install;
287 }
288
289 /* Install image unload method */
290 efi_loaded_image->Unload = efi_unload;
291
292 return 0;
293
294 efi_driver_uninstall();
295 err_driver_install:
296 bs->CloseEvent ( efi_shutdown_event );
297 err_create_event:
298 bs->FreePool ( efi_loaded_image_path );
299 err_alloc_device_path:
300 err_no_device_path:
301 err_no_loaded_image:
302 err_missing_table:
303 err_missing_protocol:
304 err_sanity:
305 return efirc;
306 }
307
308 /**
309 * Shut down EFI environment
310 *
311 * @v image_handle Image handle
312 */
313 static EFI_STATUS EFIAPI efi_unload ( EFI_HANDLE image_handle __unused ) {
314 EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
315 EFI_SYSTEM_TABLE *systab = efi_systab;
316
317 DBGC ( systab, "EFI image unloading\n" );
318
319 /* Shut down */
320 shutdown_exit();
321
322 /* Disconnect any remaining devices */
323 efi_driver_disconnect_all();
324
325 /* Uninstall driver binding protocol */
326 efi_driver_uninstall();
327
328 /* Uninstall exit boot services event */
329 bs->CloseEvent ( efi_shutdown_event );
330
331 /* Free copy of loaded image's device handle's device path */
332 bs->FreePool ( efi_loaded_image_path );
333
334 DBGC ( systab, "EFI image unloaded\n" );
335
336 return 0;
337 }
338
339 /**
340 * Abort on stack check failure
341 *
342 */
343 __attribute__ (( noreturn )) void __stack_chk_fail ( void ) {
344 EFI_STATUS efirc;
345 int rc;
346
347 /* Report failure (when debugging) */
348 DBGC ( efi_systab, "EFI stack check failed (cookie %#lx); aborting\n",
349 __stack_chk_guard );
350
351 /* Attempt to exit cleanly with an error status */
352 if ( efi_exit ) {
353 efirc = efi_exit ( efi_image_handle, EFI_COMPROMISED_DATA,
354 0, NULL );
355 rc = -EEFI ( efirc );
356 DBGC ( efi_systab, "EFI stack check exit failed: %s\n",
357 strerror ( rc ) );
358 }
359
360 /* If the exit fails for any reason, lock the system */
361 while ( 1 ) {}
362
363 }