blob: 5dd9cc876e4375e2bfa27d581b7838bd385a2a1c [file] [log] [blame]
Ilias Apalodimas37c3ca52021-03-17 21:54:59 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (c) 2020, Linaro Limited
4 */
5
6#define LOG_CATEGORY LOGC_EFI
AKASHI Takahiro64228202024-01-17 13:39:41 +09007#include <bootm.h>
Ilias Apalodimas37c3ca52021-03-17 21:54:59 +02008#include <env.h>
AKASHI Takahiro64228202024-01-17 13:39:41 +09009#include <image.h>
10#include <log.h>
Ilias Apalodimas37c3ca52021-03-17 21:54:59 +020011#include <malloc.h>
AKASHI Takahiro64228202024-01-17 13:39:41 +090012#include <mapmem.h>
Ilias Apalodimas37c3ca52021-03-17 21:54:59 +020013#include <dm.h>
14#include <fs.h>
AKASHI Takahiro64228202024-01-17 13:39:41 +090015#include <efi_api.h>
Ilias Apalodimas37c3ca52021-03-17 21:54:59 +020016#include <efi_load_initrd.h>
17#include <efi_loader.h>
18#include <efi_variable.h>
AKASHI Takahiro64228202024-01-17 13:39:41 +090019#include <linux/libfdt.h>
20#include <linux/list.h>
Ilias Apalodimas37c3ca52021-03-17 21:54:59 +020021
Heinrich Schuchardt9ad37fe2021-10-15 02:33:33 +020022#if defined(CONFIG_CMD_EFIDEBUG) || defined(CONFIG_EFI_LOAD_FILE2_INITRD)
23/* GUID used by Linux to identify the LoadFile2 protocol with the initrd */
24const efi_guid_t efi_lf2_initrd_guid = EFI_INITRD_MEDIA_GUID;
25#endif
26
Ilias Apalodimas37c3ca52021-03-17 21:54:59 +020027/**
28 * efi_create_current_boot_var() - Return Boot#### name were #### is replaced by
29 * the value of BootCurrent
30 *
31 * @var_name: variable name
32 * @var_name_size: size of var_name
33 *
34 * Return: Status code
35 */
36static efi_status_t efi_create_current_boot_var(u16 var_name[],
37 size_t var_name_size)
38{
39 efi_uintn_t boot_current_size;
40 efi_status_t ret;
41 u16 boot_current;
42 u16 *pos;
43
44 boot_current_size = sizeof(boot_current);
Simon Glass156ccbc2022-01-23 12:55:12 -070045 ret = efi_get_variable_int(u"BootCurrent",
Ilias Apalodimas37c3ca52021-03-17 21:54:59 +020046 &efi_global_variable_guid, NULL,
47 &boot_current_size, &boot_current, NULL);
48 if (ret != EFI_SUCCESS)
49 goto out;
50
51 pos = efi_create_indexed_name(var_name, var_name_size, "Boot",
52 boot_current);
53 if (!pos) {
54 ret = EFI_OUT_OF_RESOURCES;
55 goto out;
56 }
57
58out:
59 return ret;
60}
61
62/**
63 * efi_get_dp_from_boot() - Retrieve and return a device path from an EFI
64 * Boot### variable.
65 * A boot option may contain an array of device paths.
66 * We use a VenMedia() with a specific GUID to identify
67 * the usage of the array members. This function is
68 * used to extract a specific device path
69 *
70 * @guid: vendor GUID of the VenMedia() device path node identifying the
71 * device path
72 *
73 * Return: device path or NULL. Caller must free the returned value
74 */
75struct efi_device_path *efi_get_dp_from_boot(const efi_guid_t guid)
76{
Ilias Apalodimas37c3ca52021-03-17 21:54:59 +020077 struct efi_load_option lo;
Heinrich Schuchardtdb61e702021-10-15 02:59:15 +020078 void *var_value;
Ilias Apalodimas37c3ca52021-03-17 21:54:59 +020079 efi_uintn_t size;
80 efi_status_t ret;
81 u16 var_name[16];
82
83 ret = efi_create_current_boot_var(var_name, sizeof(var_name));
84 if (ret != EFI_SUCCESS)
85 return NULL;
86
87 var_value = efi_get_var(var_name, &efi_global_variable_guid, &size);
88 if (!var_value)
89 return NULL;
90
91 ret = efi_deserialize_load_option(&lo, var_value, &size);
92 if (ret != EFI_SUCCESS)
Heinrich Schuchardtdb61e702021-10-15 02:59:15 +020093 goto err;
Ilias Apalodimas37c3ca52021-03-17 21:54:59 +020094
Heinrich Schuchardtdb61e702021-10-15 02:59:15 +020095 return efi_dp_from_lo(&lo, &guid);
Ilias Apalodimas37c3ca52021-03-17 21:54:59 +020096
Heinrich Schuchardtdb61e702021-10-15 02:59:15 +020097err:
Ilias Apalodimas37c3ca52021-03-17 21:54:59 +020098 free(var_value);
Heinrich Schuchardtdb61e702021-10-15 02:59:15 +020099 return NULL;
Ilias Apalodimas37c3ca52021-03-17 21:54:59 +0200100}
Ilias Apalodimasb436cc62022-05-06 15:36:00 +0300101
102const struct guid_to_hash_map {
103 efi_guid_t guid;
104 const char algo[32];
105 u32 bits;
106} guid_to_hash[] = {
107 {
108 EFI_CERT_X509_SHA256_GUID,
109 "sha256",
110 SHA256_SUM_LEN * 8,
111 },
112 {
113 EFI_CERT_SHA256_GUID,
114 "sha256",
115 SHA256_SUM_LEN * 8,
116 },
117 {
118 EFI_CERT_X509_SHA384_GUID,
119 "sha384",
120 SHA384_SUM_LEN * 8,
121 },
122 {
123 EFI_CERT_X509_SHA512_GUID,
124 "sha512",
125 SHA512_SUM_LEN * 8,
126 },
127};
128
129#define MAX_GUID_TO_HASH_COUNT ARRAY_SIZE(guid_to_hash)
130
131/** guid_to_sha_str - return the sha string e.g "sha256" for a given guid
132 * used on EFI security databases
133 *
134 * @guid: guid to check
135 *
136 * Return: len or 0 if no match is found
137 */
138const char *guid_to_sha_str(const efi_guid_t *guid)
139{
140 size_t i;
141
142 for (i = 0; i < MAX_GUID_TO_HASH_COUNT; i++) {
143 if (!guidcmp(guid, &guid_to_hash[i].guid))
144 return guid_to_hash[i].algo;
145 }
146
147 return NULL;
148}
149
150/** algo_to_len - return the sha size in bytes for a given string
151 *
152 * @algo: string indicating hashing algorithm to check
153 *
154 * Return: length of hash in bytes or 0 if no match is found
155 */
156int algo_to_len(const char *algo)
157{
158 size_t i;
159
160 for (i = 0; i < MAX_GUID_TO_HASH_COUNT; i++) {
161 if (!strcmp(algo, guid_to_hash[i].algo))
162 return guid_to_hash[i].bits / 8;
163 }
164
165 return 0;
166}
Masahisa Kojimaee576662022-07-22 11:39:10 +0900167
168/** efi_link_dev - link the efi_handle_t and udevice
169 *
170 * @handle: efi handle to associate with udevice
171 * @dev: udevice to associate with efi handle
172 *
173 * Return: 0 on success, negative on failure
174 */
175int efi_link_dev(efi_handle_t handle, struct udevice *dev)
176{
177 handle->dev = dev;
178 return dev_tag_set_ptr(dev, DM_TAG_EFI, handle);
179}
Heinrich Schuchardt16b27b62022-10-03 09:47:51 +0200180
181/**
182 * efi_unlink_dev() - unlink udevice and handle
183 *
184 * @handle: EFI handle to unlink
185 *
186 * Return: 0 on success, negative on failure
187 */
188int efi_unlink_dev(efi_handle_t handle)
189{
190 int ret;
191
192 ret = dev_tag_del(handle->dev, DM_TAG_EFI);
193 if (ret)
194 return ret;
195 handle->dev = NULL;
196
197 return 0;
198}
Masahisa Kojima3ac026a2022-12-02 13:59:35 +0900199
200static int u16_tohex(u16 c)
201{
202 if (c >= '0' && c <= '9')
203 return c - '0';
204 if (c >= 'A' && c <= 'F')
205 return c - 'A' + 10;
206
207 /* not hexadecimal */
208 return -1;
209}
210
211bool efi_varname_is_load_option(u16 *var_name16, int *index)
212{
213 int id, i, digit;
214
215 if (memcmp(var_name16, u"Boot", 8))
216 return false;
217
218 for (id = 0, i = 0; i < 4; i++) {
219 digit = u16_tohex(var_name16[4 + i]);
220 if (digit < 0)
221 break;
222 id = (id << 4) + digit;
223 }
224 if (i == 4 && !var_name16[8]) {
225 if (index)
226 *index = id;
227 return true;
228 }
229
230 return false;
231}
Masahisa Kojimace327082022-12-19 11:33:12 +0900232
233/**
234 * efi_next_variable_name() - get next variable name
235 *
236 * This function is a wrapper of efi_get_next_variable_name_int().
237 * If efi_get_next_variable_name_int() returns EFI_BUFFER_TOO_SMALL,
238 * @size and @buf are updated by new buffer size and realloced buffer.
239 *
240 * @size: pointer to the buffer size
241 * @buf: pointer to the buffer
242 * @guid: pointer to the guid
243 * Return: status code
244 */
245efi_status_t efi_next_variable_name(efi_uintn_t *size, u16 **buf, efi_guid_t *guid)
246{
247 u16 *p;
248 efi_status_t ret;
249 efi_uintn_t buf_size = *size;
250
251 ret = efi_get_next_variable_name_int(&buf_size, *buf, guid);
252 if (ret == EFI_NOT_FOUND)
253 return ret;
254 if (ret == EFI_BUFFER_TOO_SMALL) {
255 p = realloc(*buf, buf_size);
256 if (!p)
257 return EFI_OUT_OF_RESOURCES;
258
259 *buf = p;
260 *size = buf_size;
261 ret = efi_get_next_variable_name_int(&buf_size, *buf, guid);
262 }
263
264 return ret;
265}
Raymond Mao339b5272023-06-19 14:22:58 -0700266
267/**
268 * efi_search_bootorder() - search the boot option index in BootOrder
269 *
270 * @bootorder: pointer to the BootOrder variable
271 * @num: number of BootOrder entry
272 * @target: target boot option index to search
273 * @index: pointer to store the index of BootOrder variable
274 * Return: true if exists, false otherwise
275 */
276bool efi_search_bootorder(u16 *bootorder, efi_uintn_t num, u32 target, u32 *index)
277{
278 u32 i;
279
280 for (i = 0; i < num; i++) {
281 if (target == bootorder[i]) {
282 if (index)
283 *index = i;
284
285 return true;
286 }
287 }
288
289 return false;
290}
AKASHI Takahiro64228202024-01-17 13:39:41 +0900291
292/**
293 * efi_env_set_load_options() - set load options from environment variable
294 *
295 * @handle: the image handle
296 * @env_var: name of the environment variable
297 * @load_options: pointer to load options (output)
298 * Return: status code
299 */
300efi_status_t efi_env_set_load_options(efi_handle_t handle,
301 const char *env_var,
302 u16 **load_options)
303{
304 const char *env = env_get(env_var);
305 size_t size;
306 u16 *pos;
307 efi_status_t ret;
308
309 *load_options = NULL;
310 if (!env)
311 return EFI_SUCCESS;
312 size = sizeof(u16) * (utf8_utf16_strlen(env) + 1);
313 pos = calloc(size, 1);
314 if (!pos)
315 return EFI_OUT_OF_RESOURCES;
316 *load_options = pos;
317 utf8_utf16_strcpy(&pos, env);
318 ret = efi_set_load_options(handle, size, *load_options);
319 if (ret != EFI_SUCCESS) {
320 free(*load_options);
321 *load_options = NULL;
322 }
323 return ret;
324}
325
326/**
327 * copy_fdt() - Copy the device tree to a new location available to EFI
328 *
329 * The FDT is copied to a suitable location within the EFI memory map.
330 * Additional 12 KiB are added to the space in case the device tree needs to be
331 * expanded later with fdt_open_into().
332 *
333 * @fdtp: On entry a pointer to the flattened device tree.
334 * On exit a pointer to the copy of the flattened device tree.
335 * FDT start
336 * Return: status code
337 */
338static efi_status_t copy_fdt(void **fdtp)
339{
340 unsigned long fdt_ram_start = -1L, fdt_pages;
341 efi_status_t ret = 0;
342 void *fdt, *new_fdt;
343 u64 new_fdt_addr;
344 uint fdt_size;
345 int i;
346
347 for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
348 u64 ram_start = gd->bd->bi_dram[i].start;
349 u64 ram_size = gd->bd->bi_dram[i].size;
350
351 if (!ram_size)
352 continue;
353
354 if (ram_start < fdt_ram_start)
355 fdt_ram_start = ram_start;
356 }
357
358 /*
359 * Give us at least 12 KiB of breathing room in case the device tree
360 * needs to be expanded later.
361 */
362 fdt = *fdtp;
363 fdt_pages = efi_size_in_pages(fdt_totalsize(fdt) + 0x3000);
364 fdt_size = fdt_pages << EFI_PAGE_SHIFT;
365
366 ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
367 EFI_ACPI_RECLAIM_MEMORY, fdt_pages,
368 &new_fdt_addr);
369 if (ret != EFI_SUCCESS) {
370 log_err("ERROR: Failed to reserve space for FDT\n");
371 goto done;
372 }
373 new_fdt = (void *)(uintptr_t)new_fdt_addr;
374 memcpy(new_fdt, fdt, fdt_totalsize(fdt));
375 fdt_set_totalsize(new_fdt, fdt_size);
376
377 *fdtp = (void *)(uintptr_t)new_fdt_addr;
378done:
379 return ret;
380}
381
382/**
Heinrich Schuchardtfa077212024-01-26 08:54:30 +0100383 * efi_get_configuration_table() - get configuration table
AKASHI Takahiro64228202024-01-17 13:39:41 +0900384 *
385 * @guid: GUID of the configuration table
386 * Return: pointer to configuration table or NULL
387 */
Heinrich Schuchardtfa077212024-01-26 08:54:30 +0100388void *efi_get_configuration_table(const efi_guid_t *guid)
AKASHI Takahiro64228202024-01-17 13:39:41 +0900389{
390 size_t i;
391
392 for (i = 0; i < systab.nr_tables; i++) {
393 if (!guidcmp(guid, &systab.tables[i].guid))
394 return systab.tables[i].table;
395 }
396 return NULL;
397}
398
399/**
400 * efi_install_fdt() - install device tree
401 *
402 * If fdt is not EFI_FDT_USE_INTERNAL, the device tree located at that memory
403 * address will be installed as configuration table, otherwise the device
404 * tree located at the address indicated by environment variable fdt_addr or as
405 * fallback fdtcontroladdr will be used.
406 *
407 * On architectures using ACPI tables device trees shall not be installed as
408 * configuration table.
409 *
410 * @fdt: address of device tree or EFI_FDT_USE_INTERNAL to use
411 * the hardware device tree as indicated by environment variable
412 * fdt_addr or as fallback the internal device tree as indicated by
413 * the environment variable fdtcontroladdr
414 * Return: status code
415 */
416efi_status_t efi_install_fdt(void *fdt)
417{
418 struct bootm_headers img = { 0 };
419 efi_status_t ret;
420
421 /*
422 * The EBBR spec requires that we have either an FDT or an ACPI table
423 * but not both.
424 */
425 if (CONFIG_IS_ENABLED(GENERATE_ACPI_TABLE) && fdt)
426 log_warning("WARNING: Can't have ACPI table and device tree - ignoring DT.\n");
427
428 if (fdt == EFI_FDT_USE_INTERNAL) {
429 const char *fdt_opt;
430 uintptr_t fdt_addr;
431
432 /* Look for device tree that is already installed */
Heinrich Schuchardtfa077212024-01-26 08:54:30 +0100433 if (efi_get_configuration_table(&efi_guid_fdt))
AKASHI Takahiro64228202024-01-17 13:39:41 +0900434 return EFI_SUCCESS;
435 /* Check if there is a hardware device tree */
436 fdt_opt = env_get("fdt_addr");
437 /* Use our own device tree as fallback */
438 if (!fdt_opt) {
439 fdt_opt = env_get("fdtcontroladdr");
440 if (!fdt_opt) {
441 log_err("ERROR: need device tree\n");
442 return EFI_NOT_FOUND;
443 }
444 }
445 fdt_addr = hextoul(fdt_opt, NULL);
446 if (!fdt_addr) {
447 log_err("ERROR: invalid $fdt_addr or $fdtcontroladdr\n");
448 return EFI_LOAD_ERROR;
449 }
450 fdt = map_sysmem(fdt_addr, 0);
451 }
452
453 /* Install device tree */
454 if (fdt_check_header(fdt)) {
455 log_err("ERROR: invalid device tree\n");
456 return EFI_LOAD_ERROR;
457 }
458
459 /* Create memory reservations as indicated by the device tree */
460 efi_carve_out_dt_rsv(fdt);
461
462 if (CONFIG_IS_ENABLED(GENERATE_ACPI_TABLE))
463 return EFI_SUCCESS;
464
465 /* Prepare device tree for payload */
466 ret = copy_fdt(&fdt);
467 if (ret) {
468 log_err("ERROR: out of memory\n");
469 return EFI_OUT_OF_RESOURCES;
470 }
471
472 if (image_setup_libfdt(&img, fdt, NULL)) {
473 log_err("ERROR: failed to process device tree\n");
474 return EFI_LOAD_ERROR;
475 }
476
477 efi_try_purge_kaslr_seed(fdt);
478
479 if (CONFIG_IS_ENABLED(EFI_TCG2_PROTOCOL_MEASURE_DTB)) {
480 ret = efi_tcg2_measure_dtb(fdt);
481 if (ret == EFI_SECURITY_VIOLATION) {
482 log_err("ERROR: failed to measure DTB\n");
483 return ret;
484 }
485 }
486
487 /* Install device tree as UEFI table */
488 ret = efi_install_configuration_table(&efi_guid_fdt, fdt);
489 if (ret != EFI_SUCCESS) {
490 log_err("ERROR: failed to install device tree\n");
491 return ret;
492 }
493
494 return EFI_SUCCESS;
495}
496
497/**
498 * do_bootefi_exec() - execute EFI binary
499 *
500 * The image indicated by @handle is started. When it returns the allocated
501 * memory for the @load_options is freed.
502 *
503 * @handle: handle of loaded image
504 * @load_options: load options
505 * Return: status code
506 *
507 * Load the EFI binary into a newly assigned memory unwinding the relocation
508 * information, install the loaded image protocol, and call the binary.
509 */
510efi_status_t do_bootefi_exec(efi_handle_t handle, void *load_options)
511{
512 efi_status_t ret;
513 efi_uintn_t exit_data_size = 0;
514 u16 *exit_data = NULL;
515 struct efi_event *evt;
516
517 /* On ARM switch from EL3 or secure mode to EL2 or non-secure mode */
518 switch_to_non_secure_mode();
519
520 /*
521 * The UEFI standard requires that the watchdog timer is set to five
522 * minutes when invoking an EFI boot option.
523 *
524 * Unified Extensible Firmware Interface (UEFI), version 2.7 Errata A
525 * 7.5. Miscellaneous Boot Services - EFI_BOOT_SERVICES.SetWatchdogTimer
526 */
527 ret = efi_set_watchdog(300);
528 if (ret != EFI_SUCCESS) {
529 log_err("ERROR: Failed to set watchdog timer\n");
530 goto out;
531 }
532
533 /* Call our payload! */
534 ret = EFI_CALL(efi_start_image(handle, &exit_data_size, &exit_data));
535 if (ret != EFI_SUCCESS) {
536 log_err("## Application failed, r = %lu\n",
537 ret & ~EFI_ERROR_MASK);
538 if (exit_data) {
539 log_err("## %ls\n", exit_data);
540 efi_free_pool(exit_data);
541 }
542 }
543
544 efi_restore_gd();
545
546out:
547 free(load_options);
548
549 if (IS_ENABLED(CONFIG_EFI_LOAD_FILE2_INITRD)) {
550 if (efi_initrd_deregister() != EFI_SUCCESS)
551 log_err("Failed to remove loadfile2 for initrd\n");
552 }
553
554 /* Notify EFI_EVENT_GROUP_RETURN_TO_EFIBOOTMGR event group. */
555 list_for_each_entry(evt, &efi_events, link) {
556 if (evt->group &&
557 !guidcmp(evt->group,
558 &efi_guid_event_group_return_to_efibootmgr)) {
559 efi_signal_event(evt);
560 EFI_CALL(systab.boottime->close_event(evt));
561 break;
562 }
563 }
564
565 /* Control is returned to U-Boot, disable EFI watchdog */
566 efi_set_watchdog(0);
567
568 return ret;
569}