blob: f6fbcdffe8260451c329e9b92ec59f348e158edd [file] [log] [blame]
Ilias Apalodimasaa0f7552021-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
Heinrich Schuchardt955a3212025-01-16 20:26:59 +01007
AKASHI Takahiro9b08b9a2024-01-17 13:39:41 +09008#include <bootm.h>
Ilias Apalodimasaa0f7552021-03-17 21:54:59 +02009#include <env.h>
AKASHI Takahiro9b08b9a2024-01-17 13:39:41 +090010#include <image.h>
11#include <log.h>
Ilias Apalodimasaa0f7552021-03-17 21:54:59 +020012#include <malloc.h>
AKASHI Takahiro9b08b9a2024-01-17 13:39:41 +090013#include <mapmem.h>
Ilias Apalodimasaa0f7552021-03-17 21:54:59 +020014#include <dm.h>
15#include <fs.h>
Simon Glass3b1e60b2024-11-07 14:31:43 -070016#include <efi.h>
AKASHI Takahiro9b08b9a2024-01-17 13:39:41 +090017#include <efi_api.h>
Ilias Apalodimasaa0f7552021-03-17 21:54:59 +020018#include <efi_load_initrd.h>
19#include <efi_loader.h>
20#include <efi_variable.h>
Simon Glass3b1e60b2024-11-07 14:31:43 -070021#include <host_arch.h>
AKASHI Takahiro9b08b9a2024-01-17 13:39:41 +090022#include <linux/libfdt.h>
23#include <linux/list.h>
Ilias Apalodimasaa0f7552021-03-17 21:54:59 +020024
Simon Glass1824bf62024-11-07 14:31:44 -070025#undef BOOTEFI_NAME
26
Simon Glass3b1e60b2024-11-07 14:31:43 -070027#if HOST_ARCH == HOST_ARCH_X86_64
Simon Glass52b53af2024-11-07 14:31:46 -070028#define HOST_BOOTEFI_NAME "BOOTX64.EFI"
29#define HOST_PXE_ARCH 0x6
Simon Glass3b1e60b2024-11-07 14:31:43 -070030#elif HOST_ARCH == HOST_ARCH_X86
Simon Glass52b53af2024-11-07 14:31:46 -070031#define HOST_BOOTEFI_NAME "BOOTIA32.EFI"
32#define HOST_PXE_ARCH 0x7
Simon Glass3b1e60b2024-11-07 14:31:43 -070033#elif HOST_ARCH == HOST_ARCH_AARCH64
Simon Glass52b53af2024-11-07 14:31:46 -070034#define HOST_BOOTEFI_NAME "BOOTAA64.EFI"
35#define HOST_PXE_ARCH 0xb
Simon Glass3b1e60b2024-11-07 14:31:43 -070036#elif HOST_ARCH == HOST_ARCH_ARM
Simon Glass52b53af2024-11-07 14:31:46 -070037#define HOST_BOOTEFI_NAME "BOOTARM.EFI"
38#define HOST_PXE_ARCH 0xa
Simon Glass3b1e60b2024-11-07 14:31:43 -070039#elif HOST_ARCH == HOST_ARCH_RISCV32
Simon Glass52b53af2024-11-07 14:31:46 -070040#define HOST_BOOTEFI_NAME "BOOTRISCV32.EFI"
41#define HOST_PXE_ARCH 0x19
Simon Glass3b1e60b2024-11-07 14:31:43 -070042#elif HOST_ARCH == HOST_ARCH_RISCV64
Simon Glass52b53af2024-11-07 14:31:46 -070043#define HOST_BOOTEFI_NAME "BOOTRISCV64.EFI"
44#define HOST_PXE_ARCH 0x1b
Simon Glass3b1e60b2024-11-07 14:31:43 -070045#else
Simon Glass52b53af2024-11-07 14:31:46 -070046#error Unsupported Host architecture
Simon Glass3b1e60b2024-11-07 14:31:43 -070047#endif
48
Simon Glass52b53af2024-11-07 14:31:46 -070049#if defined(CONFIG_SANDBOX)
50#define BOOTEFI_NAME "BOOTSBOX.EFI"
51#elif defined(CONFIG_ARM64)
Simon Glass3b1e60b2024-11-07 14:31:43 -070052#define BOOTEFI_NAME "BOOTAA64.EFI"
53#elif defined(CONFIG_ARM)
54#define BOOTEFI_NAME "BOOTARM.EFI"
55#elif defined(CONFIG_X86_64)
56#define BOOTEFI_NAME "BOOTX64.EFI"
57#elif defined(CONFIG_X86)
58#define BOOTEFI_NAME "BOOTIA32.EFI"
59#elif defined(CONFIG_ARCH_RV32I)
60#define BOOTEFI_NAME "BOOTRISCV32.EFI"
61#elif defined(CONFIG_ARCH_RV64I)
62#define BOOTEFI_NAME "BOOTRISCV64.EFI"
63#else
64#error Unsupported UEFI architecture
65#endif
66
Heinrich Schuchardt6c405cb2021-10-15 02:33:33 +020067#if defined(CONFIG_CMD_EFIDEBUG) || defined(CONFIG_EFI_LOAD_FILE2_INITRD)
68/* GUID used by Linux to identify the LoadFile2 protocol with the initrd */
69const efi_guid_t efi_lf2_initrd_guid = EFI_INITRD_MEDIA_GUID;
70#endif
71
Simon Glass3b1e60b2024-11-07 14:31:43 -070072const char *efi_get_basename(void)
73{
Simon Glass52b53af2024-11-07 14:31:46 -070074 return efi_use_host_arch() ? HOST_BOOTEFI_NAME : BOOTEFI_NAME;
Simon Glass3b1e60b2024-11-07 14:31:43 -070075}
76
Simon Glass1824bf62024-11-07 14:31:44 -070077int efi_get_pxe_arch(void)
78{
Simon Glass52b53af2024-11-07 14:31:46 -070079 if (efi_use_host_arch())
80 return HOST_PXE_ARCH;
81
Simon Glass1824bf62024-11-07 14:31:44 -070082 /* http://www.iana.org/assignments/dhcpv6-parameters/dhcpv6-parameters.xml */
83 if (IS_ENABLED(CONFIG_ARM64))
84 return 0xb;
85 else if (IS_ENABLED(CONFIG_ARM))
86 return 0xa;
87 else if (IS_ENABLED(CONFIG_X86_64))
88 return 0x6;
89 else if (IS_ENABLED(CONFIG_X86))
90 return 0x7;
91 else if (IS_ENABLED(CONFIG_ARCH_RV32I))
92 return 0x19;
93 else if (IS_ENABLED(CONFIG_ARCH_RV64I))
94 return 0x1b;
Simon Glass1824bf62024-11-07 14:31:44 -070095
96 return -EINVAL;
97}
98
Ilias Apalodimasaa0f7552021-03-17 21:54:59 +020099/**
100 * efi_create_current_boot_var() - Return Boot#### name were #### is replaced by
101 * the value of BootCurrent
102 *
103 * @var_name: variable name
104 * @var_name_size: size of var_name
105 *
106 * Return: Status code
107 */
108static efi_status_t efi_create_current_boot_var(u16 var_name[],
109 size_t var_name_size)
110{
111 efi_uintn_t boot_current_size;
112 efi_status_t ret;
113 u16 boot_current;
114 u16 *pos;
115
116 boot_current_size = sizeof(boot_current);
Simon Glass90975372022-01-23 12:55:12 -0700117 ret = efi_get_variable_int(u"BootCurrent",
Ilias Apalodimasaa0f7552021-03-17 21:54:59 +0200118 &efi_global_variable_guid, NULL,
119 &boot_current_size, &boot_current, NULL);
120 if (ret != EFI_SUCCESS)
121 goto out;
122
123 pos = efi_create_indexed_name(var_name, var_name_size, "Boot",
124 boot_current);
125 if (!pos) {
126 ret = EFI_OUT_OF_RESOURCES;
127 goto out;
128 }
129
130out:
131 return ret;
132}
133
134/**
135 * efi_get_dp_from_boot() - Retrieve and return a device path from an EFI
136 * Boot### variable.
137 * A boot option may contain an array of device paths.
138 * We use a VenMedia() with a specific GUID to identify
139 * the usage of the array members. This function is
140 * used to extract a specific device path
141 *
142 * @guid: vendor GUID of the VenMedia() device path node identifying the
143 * device path
144 *
145 * Return: device path or NULL. Caller must free the returned value
146 */
Heinrich Schuchardtefd90d72024-04-26 16:13:08 +0200147struct efi_device_path *efi_get_dp_from_boot(const efi_guid_t *guid)
Ilias Apalodimasaa0f7552021-03-17 21:54:59 +0200148{
Ilias Apalodimasb92f7ba2024-08-12 23:57:59 +0300149 struct efi_device_path *file_path = NULL;
Ilias Apalodimasaa0f7552021-03-17 21:54:59 +0200150 struct efi_load_option lo;
Heinrich Schuchardt35dd3222021-10-15 02:59:15 +0200151 void *var_value;
Ilias Apalodimasaa0f7552021-03-17 21:54:59 +0200152 efi_uintn_t size;
153 efi_status_t ret;
154 u16 var_name[16];
155
156 ret = efi_create_current_boot_var(var_name, sizeof(var_name));
157 if (ret != EFI_SUCCESS)
158 return NULL;
159
160 var_value = efi_get_var(var_name, &efi_global_variable_guid, &size);
161 if (!var_value)
162 return NULL;
163
164 ret = efi_deserialize_load_option(&lo, var_value, &size);
165 if (ret != EFI_SUCCESS)
Heinrich Schuchardt35dd3222021-10-15 02:59:15 +0200166 goto err;
Ilias Apalodimasaa0f7552021-03-17 21:54:59 +0200167
Ilias Apalodimasb92f7ba2024-08-12 23:57:59 +0300168 file_path = efi_dp_from_lo(&lo, guid);
Ilias Apalodimasaa0f7552021-03-17 21:54:59 +0200169
Heinrich Schuchardt35dd3222021-10-15 02:59:15 +0200170err:
Ilias Apalodimasaa0f7552021-03-17 21:54:59 +0200171 free(var_value);
Ilias Apalodimasb92f7ba2024-08-12 23:57:59 +0300172 return file_path;
Ilias Apalodimasaa0f7552021-03-17 21:54:59 +0200173}
Ilias Apalodimas34db9b12022-05-06 15:36:00 +0300174
Heinrich Schuchardtf7529f72024-04-26 16:13:11 +0200175/**
176 * efi_load_option_dp_join() - join device-paths for load option
177 *
178 * @dp: in: binary device-path, out: joined device-path
179 * @dp_size: size of joined device-path
180 * @initrd_dp: initrd device-path or NULL
181 * @fdt_dp: device-tree device-path or NULL
182 * Return: status_code
183 */
184efi_status_t efi_load_option_dp_join(struct efi_device_path **dp,
185 size_t *dp_size,
186 struct efi_device_path *initrd_dp,
187 struct efi_device_path *fdt_dp)
188{
189 if (!dp)
190 return EFI_INVALID_PARAMETER;
191
192 *dp_size = efi_dp_size(*dp);
193
194 if (initrd_dp) {
195 struct efi_device_path *tmp_dp = *dp;
196
197 *dp = efi_dp_concat(tmp_dp, initrd_dp, *dp_size);
198 efi_free_pool(tmp_dp);
199 if (!*dp)
200 return EFI_OUT_OF_RESOURCES;
201 *dp_size += efi_dp_size(initrd_dp) + sizeof(END);
202 }
203
204 if (fdt_dp) {
205 struct efi_device_path *tmp_dp = *dp;
206
207 *dp = efi_dp_concat(tmp_dp, fdt_dp, *dp_size);
208 efi_free_pool(tmp_dp);
Heinrich Schuchardt9b4e1f52024-07-24 15:26:04 +0200209 if (!*dp)
Heinrich Schuchardtf7529f72024-04-26 16:13:11 +0200210 return EFI_OUT_OF_RESOURCES;
211 *dp_size += efi_dp_size(fdt_dp) + sizeof(END);
212 }
213
214 *dp_size += sizeof(END);
215
216 return EFI_SUCCESS;
217}
218
Ilias Apalodimas34db9b12022-05-06 15:36:00 +0300219const struct guid_to_hash_map {
220 efi_guid_t guid;
221 const char algo[32];
222 u32 bits;
223} guid_to_hash[] = {
224 {
225 EFI_CERT_X509_SHA256_GUID,
226 "sha256",
227 SHA256_SUM_LEN * 8,
228 },
229 {
230 EFI_CERT_SHA256_GUID,
231 "sha256",
232 SHA256_SUM_LEN * 8,
233 },
234 {
235 EFI_CERT_X509_SHA384_GUID,
236 "sha384",
237 SHA384_SUM_LEN * 8,
238 },
239 {
240 EFI_CERT_X509_SHA512_GUID,
241 "sha512",
242 SHA512_SUM_LEN * 8,
243 },
244};
245
246#define MAX_GUID_TO_HASH_COUNT ARRAY_SIZE(guid_to_hash)
247
248/** guid_to_sha_str - return the sha string e.g "sha256" for a given guid
249 * used on EFI security databases
250 *
251 * @guid: guid to check
252 *
253 * Return: len or 0 if no match is found
254 */
255const char *guid_to_sha_str(const efi_guid_t *guid)
256{
257 size_t i;
258
259 for (i = 0; i < MAX_GUID_TO_HASH_COUNT; i++) {
260 if (!guidcmp(guid, &guid_to_hash[i].guid))
261 return guid_to_hash[i].algo;
262 }
263
264 return NULL;
265}
266
267/** algo_to_len - return the sha size in bytes for a given string
268 *
269 * @algo: string indicating hashing algorithm to check
270 *
271 * Return: length of hash in bytes or 0 if no match is found
272 */
273int algo_to_len(const char *algo)
274{
275 size_t i;
276
277 for (i = 0; i < MAX_GUID_TO_HASH_COUNT; i++) {
278 if (!strcmp(algo, guid_to_hash[i].algo))
279 return guid_to_hash[i].bits / 8;
280 }
281
282 return 0;
283}
Masahisa Kojimac9611082022-07-22 11:39:10 +0900284
285/** efi_link_dev - link the efi_handle_t and udevice
286 *
287 * @handle: efi handle to associate with udevice
288 * @dev: udevice to associate with efi handle
289 *
290 * Return: 0 on success, negative on failure
291 */
292int efi_link_dev(efi_handle_t handle, struct udevice *dev)
293{
294 handle->dev = dev;
295 return dev_tag_set_ptr(dev, DM_TAG_EFI, handle);
296}
Heinrich Schuchardt34f34622022-10-03 09:47:51 +0200297
298/**
299 * efi_unlink_dev() - unlink udevice and handle
300 *
301 * @handle: EFI handle to unlink
302 *
303 * Return: 0 on success, negative on failure
304 */
305int efi_unlink_dev(efi_handle_t handle)
306{
307 int ret;
308
309 ret = dev_tag_del(handle->dev, DM_TAG_EFI);
310 if (ret)
311 return ret;
312 handle->dev = NULL;
313
314 return 0;
315}
Masahisa Kojima2f407f02022-12-02 13:59:35 +0900316
317static int u16_tohex(u16 c)
318{
319 if (c >= '0' && c <= '9')
320 return c - '0';
321 if (c >= 'A' && c <= 'F')
322 return c - 'A' + 10;
323
324 /* not hexadecimal */
325 return -1;
326}
327
328bool efi_varname_is_load_option(u16 *var_name16, int *index)
329{
330 int id, i, digit;
331
332 if (memcmp(var_name16, u"Boot", 8))
333 return false;
334
335 for (id = 0, i = 0; i < 4; i++) {
336 digit = u16_tohex(var_name16[4 + i]);
337 if (digit < 0)
338 break;
339 id = (id << 4) + digit;
340 }
341 if (i == 4 && !var_name16[8]) {
342 if (index)
343 *index = id;
344 return true;
345 }
346
347 return false;
348}
Masahisa Kojima7ec3c6f2022-12-19 11:33:12 +0900349
350/**
351 * efi_next_variable_name() - get next variable name
352 *
353 * This function is a wrapper of efi_get_next_variable_name_int().
354 * If efi_get_next_variable_name_int() returns EFI_BUFFER_TOO_SMALL,
355 * @size and @buf are updated by new buffer size and realloced buffer.
356 *
357 * @size: pointer to the buffer size
358 * @buf: pointer to the buffer
359 * @guid: pointer to the guid
360 * Return: status code
361 */
362efi_status_t efi_next_variable_name(efi_uintn_t *size, u16 **buf, efi_guid_t *guid)
363{
364 u16 *p;
365 efi_status_t ret;
366 efi_uintn_t buf_size = *size;
367
368 ret = efi_get_next_variable_name_int(&buf_size, *buf, guid);
369 if (ret == EFI_NOT_FOUND)
370 return ret;
371 if (ret == EFI_BUFFER_TOO_SMALL) {
372 p = realloc(*buf, buf_size);
373 if (!p)
374 return EFI_OUT_OF_RESOURCES;
375
376 *buf = p;
377 *size = buf_size;
378 ret = efi_get_next_variable_name_int(&buf_size, *buf, guid);
379 }
380
381 return ret;
382}
Raymond Mao70a76c52023-06-19 14:22:58 -0700383
384/**
385 * efi_search_bootorder() - search the boot option index in BootOrder
386 *
387 * @bootorder: pointer to the BootOrder variable
388 * @num: number of BootOrder entry
389 * @target: target boot option index to search
390 * @index: pointer to store the index of BootOrder variable
391 * Return: true if exists, false otherwise
392 */
393bool efi_search_bootorder(u16 *bootorder, efi_uintn_t num, u32 target, u32 *index)
394{
395 u32 i;
396
397 for (i = 0; i < num; i++) {
398 if (target == bootorder[i]) {
399 if (index)
400 *index = i;
401
402 return true;
403 }
404 }
405
406 return false;
407}
AKASHI Takahiro9b08b9a2024-01-17 13:39:41 +0900408
409/**
410 * efi_env_set_load_options() - set load options from environment variable
411 *
412 * @handle: the image handle
413 * @env_var: name of the environment variable
414 * @load_options: pointer to load options (output)
415 * Return: status code
416 */
417efi_status_t efi_env_set_load_options(efi_handle_t handle,
418 const char *env_var,
419 u16 **load_options)
420{
421 const char *env = env_get(env_var);
422 size_t size;
423 u16 *pos;
424 efi_status_t ret;
425
426 *load_options = NULL;
427 if (!env)
428 return EFI_SUCCESS;
429 size = sizeof(u16) * (utf8_utf16_strlen(env) + 1);
430 pos = calloc(size, 1);
431 if (!pos)
432 return EFI_OUT_OF_RESOURCES;
433 *load_options = pos;
434 utf8_utf16_strcpy(&pos, env);
435 ret = efi_set_load_options(handle, size, *load_options);
436 if (ret != EFI_SUCCESS) {
437 free(*load_options);
438 *load_options = NULL;
439 }
440 return ret;
441}
442
443/**
444 * copy_fdt() - Copy the device tree to a new location available to EFI
445 *
446 * The FDT is copied to a suitable location within the EFI memory map.
447 * Additional 12 KiB are added to the space in case the device tree needs to be
448 * expanded later with fdt_open_into().
449 *
450 * @fdtp: On entry a pointer to the flattened device tree.
451 * On exit a pointer to the copy of the flattened device tree.
452 * FDT start
453 * Return: status code
454 */
455static efi_status_t copy_fdt(void **fdtp)
456{
AKASHI Takahiro9b08b9a2024-01-17 13:39:41 +0900457 efi_status_t ret = 0;
458 void *fdt, *new_fdt;
Sughosh Ganu007604e2025-03-17 14:03:56 +0530459 static u64 new_fdt_addr;
460 static efi_uintn_t fdt_pages;
461 ulong fdt_size;
AKASHI Takahiro9b08b9a2024-01-17 13:39:41 +0900462
463 /*
Sughosh Ganu007604e2025-03-17 14:03:56 +0530464 * Remove the configuration table that might already be
465 * installed, ignoring EFI_NOT_FOUND if no device-tree
466 * is installed
467 */
468 efi_install_configuration_table(&efi_guid_fdt, NULL);
469
470 if (new_fdt_addr) {
471 log_debug("%s: Found allocated memory at %#llx, with %#zx pages\n",
472 __func__, new_fdt_addr, fdt_pages);
473
474 ret = efi_free_pages(new_fdt_addr, fdt_pages);
475 if (ret != EFI_SUCCESS)
476 log_err("Unable to free up existing FDT memory region\n");
477
478 new_fdt_addr = 0;
479 fdt_pages = 0;
480 }
481
482 /*
AKASHI Takahiro9b08b9a2024-01-17 13:39:41 +0900483 * Give us at least 12 KiB of breathing room in case the device tree
484 * needs to be expanded later.
485 */
486 fdt = *fdtp;
487 fdt_pages = efi_size_in_pages(fdt_totalsize(fdt) + 0x3000);
488 fdt_size = fdt_pages << EFI_PAGE_SHIFT;
489
490 ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
491 EFI_ACPI_RECLAIM_MEMORY, fdt_pages,
492 &new_fdt_addr);
493 if (ret != EFI_SUCCESS) {
Heinrich Schuchardt353db822024-10-17 20:13:05 +0200494 log_err("Failed to reserve space for FDT\n");
Sughosh Ganu007604e2025-03-17 14:03:56 +0530495 return ret;
AKASHI Takahiro9b08b9a2024-01-17 13:39:41 +0900496 }
Sughosh Ganu007604e2025-03-17 14:03:56 +0530497 log_debug("%s: Allocated memory at %#llx, with %#zx pages\n",
498 __func__, new_fdt_addr, fdt_pages);
499
AKASHI Takahiro9b08b9a2024-01-17 13:39:41 +0900500 new_fdt = (void *)(uintptr_t)new_fdt_addr;
501 memcpy(new_fdt, fdt, fdt_totalsize(fdt));
502 fdt_set_totalsize(new_fdt, fdt_size);
503
Sughosh Ganu007604e2025-03-17 14:03:56 +0530504 *fdtp = new_fdt;
505
506 return EFI_SUCCESS;
AKASHI Takahiro9b08b9a2024-01-17 13:39:41 +0900507}
508
509/**
Heinrich Schuchardt0a4a2f32024-01-26 08:54:30 +0100510 * efi_get_configuration_table() - get configuration table
AKASHI Takahiro9b08b9a2024-01-17 13:39:41 +0900511 *
512 * @guid: GUID of the configuration table
513 * Return: pointer to configuration table or NULL
514 */
Heinrich Schuchardt0a4a2f32024-01-26 08:54:30 +0100515void *efi_get_configuration_table(const efi_guid_t *guid)
AKASHI Takahiro9b08b9a2024-01-17 13:39:41 +0900516{
517 size_t i;
518
519 for (i = 0; i < systab.nr_tables; i++) {
520 if (!guidcmp(guid, &systab.tables[i].guid))
521 return systab.tables[i].table;
522 }
523 return NULL;
524}
525
526/**
527 * efi_install_fdt() - install device tree
528 *
529 * If fdt is not EFI_FDT_USE_INTERNAL, the device tree located at that memory
530 * address will be installed as configuration table, otherwise the device
531 * tree located at the address indicated by environment variable fdt_addr or as
532 * fallback fdtcontroladdr will be used.
533 *
534 * On architectures using ACPI tables device trees shall not be installed as
535 * configuration table.
536 *
537 * @fdt: address of device tree or EFI_FDT_USE_INTERNAL to use
538 * the hardware device tree as indicated by environment variable
539 * fdt_addr or as fallback the internal device tree as indicated by
540 * the environment variable fdtcontroladdr
541 * Return: status code
542 */
543efi_status_t efi_install_fdt(void *fdt)
544{
545 struct bootm_headers img = { 0 };
546 efi_status_t ret;
547
548 /*
549 * The EBBR spec requires that we have either an FDT or an ACPI table
550 * but not both.
551 */
552 if (CONFIG_IS_ENABLED(GENERATE_ACPI_TABLE) && fdt)
Heinrich Schuchardt353db822024-10-17 20:13:05 +0200553 log_warning("Can't have ACPI table and device tree - ignoring DT.\n");
AKASHI Takahiro9b08b9a2024-01-17 13:39:41 +0900554
555 if (fdt == EFI_FDT_USE_INTERNAL) {
556 const char *fdt_opt;
557 uintptr_t fdt_addr;
558
AKASHI Takahiro9b08b9a2024-01-17 13:39:41 +0900559 /* Check if there is a hardware device tree */
560 fdt_opt = env_get("fdt_addr");
561 /* Use our own device tree as fallback */
562 if (!fdt_opt) {
563 fdt_opt = env_get("fdtcontroladdr");
564 if (!fdt_opt) {
Heinrich Schuchardt353db822024-10-17 20:13:05 +0200565 log_err("need device tree\n");
AKASHI Takahiro9b08b9a2024-01-17 13:39:41 +0900566 return EFI_NOT_FOUND;
567 }
568 }
569 fdt_addr = hextoul(fdt_opt, NULL);
570 if (!fdt_addr) {
Heinrich Schuchardt353db822024-10-17 20:13:05 +0200571 log_err("invalid $fdt_addr or $fdtcontroladdr\n");
AKASHI Takahiro9b08b9a2024-01-17 13:39:41 +0900572 return EFI_LOAD_ERROR;
573 }
574 fdt = map_sysmem(fdt_addr, 0);
575 }
576
577 /* Install device tree */
578 if (fdt_check_header(fdt)) {
Heinrich Schuchardt353db822024-10-17 20:13:05 +0200579 log_err("invalid device tree\n");
AKASHI Takahiro9b08b9a2024-01-17 13:39:41 +0900580 return EFI_LOAD_ERROR;
581 }
582
Mark Kettenis98c598c2024-02-16 00:25:34 +0100583 if (CONFIG_IS_ENABLED(GENERATE_ACPI_TABLE)) {
584 /* Create memory reservations as indicated by the device tree */
585 efi_carve_out_dt_rsv(fdt);
AKASHI Takahiro9b08b9a2024-01-17 13:39:41 +0900586 return EFI_SUCCESS;
Mark Kettenis98c598c2024-02-16 00:25:34 +0100587 }
AKASHI Takahiro9b08b9a2024-01-17 13:39:41 +0900588
589 /* Prepare device tree for payload */
590 ret = copy_fdt(&fdt);
591 if (ret) {
Heinrich Schuchardt353db822024-10-17 20:13:05 +0200592 log_err("out of memory\n");
AKASHI Takahiro9b08b9a2024-01-17 13:39:41 +0900593 return EFI_OUT_OF_RESOURCES;
594 }
595
Sughosh Ganu291bf9c2024-08-26 17:29:18 +0530596 if (image_setup_libfdt(&img, fdt, false)) {
Heinrich Schuchardt353db822024-10-17 20:13:05 +0200597 log_err("failed to process device tree\n");
AKASHI Takahiro9b08b9a2024-01-17 13:39:41 +0900598 return EFI_LOAD_ERROR;
599 }
600
Mark Kettenis98c598c2024-02-16 00:25:34 +0100601 /* Create memory reservations as indicated by the device tree */
602 efi_carve_out_dt_rsv(fdt);
603
Heinrich Schuchardt069079c2024-09-17 10:49:29 +0200604 efi_try_purge_rng_seed(fdt);
AKASHI Takahiro9b08b9a2024-01-17 13:39:41 +0900605
606 if (CONFIG_IS_ENABLED(EFI_TCG2_PROTOCOL_MEASURE_DTB)) {
607 ret = efi_tcg2_measure_dtb(fdt);
608 if (ret == EFI_SECURITY_VIOLATION) {
Heinrich Schuchardt353db822024-10-17 20:13:05 +0200609 log_err("failed to measure DTB\n");
AKASHI Takahiro9b08b9a2024-01-17 13:39:41 +0900610 return ret;
611 }
612 }
613
614 /* Install device tree as UEFI table */
615 ret = efi_install_configuration_table(&efi_guid_fdt, fdt);
616 if (ret != EFI_SUCCESS) {
Heinrich Schuchardt353db822024-10-17 20:13:05 +0200617 log_err("failed to install device tree\n");
AKASHI Takahiro9b08b9a2024-01-17 13:39:41 +0900618 return ret;
619 }
620
621 return EFI_SUCCESS;
622}
623
624/**
625 * do_bootefi_exec() - execute EFI binary
626 *
627 * The image indicated by @handle is started. When it returns the allocated
628 * memory for the @load_options is freed.
629 *
630 * @handle: handle of loaded image
631 * @load_options: load options
632 * Return: status code
633 *
634 * Load the EFI binary into a newly assigned memory unwinding the relocation
635 * information, install the loaded image protocol, and call the binary.
636 */
637efi_status_t do_bootefi_exec(efi_handle_t handle, void *load_options)
638{
639 efi_status_t ret;
640 efi_uintn_t exit_data_size = 0;
641 u16 *exit_data = NULL;
642 struct efi_event *evt;
643
644 /* On ARM switch from EL3 or secure mode to EL2 or non-secure mode */
645 switch_to_non_secure_mode();
646
647 /*
648 * The UEFI standard requires that the watchdog timer is set to five
649 * minutes when invoking an EFI boot option.
650 *
651 * Unified Extensible Firmware Interface (UEFI), version 2.7 Errata A
652 * 7.5. Miscellaneous Boot Services - EFI_BOOT_SERVICES.SetWatchdogTimer
653 */
654 ret = efi_set_watchdog(300);
655 if (ret != EFI_SUCCESS) {
Heinrich Schuchardt353db822024-10-17 20:13:05 +0200656 log_err("failed to set watchdog timer\n");
AKASHI Takahiro9b08b9a2024-01-17 13:39:41 +0900657 goto out;
658 }
659
660 /* Call our payload! */
661 ret = EFI_CALL(efi_start_image(handle, &exit_data_size, &exit_data));
662 if (ret != EFI_SUCCESS) {
663 log_err("## Application failed, r = %lu\n",
664 ret & ~EFI_ERROR_MASK);
665 if (exit_data) {
666 log_err("## %ls\n", exit_data);
667 efi_free_pool(exit_data);
668 }
669 }
670
AKASHI Takahiro9b08b9a2024-01-17 13:39:41 +0900671out:
672 free(load_options);
673
AKASHI Takahiro9b08b9a2024-01-17 13:39:41 +0900674 /* Notify EFI_EVENT_GROUP_RETURN_TO_EFIBOOTMGR event group. */
675 list_for_each_entry(evt, &efi_events, link) {
676 if (evt->group &&
677 !guidcmp(evt->group,
678 &efi_guid_event_group_return_to_efibootmgr)) {
679 efi_signal_event(evt);
680 EFI_CALL(systab.boottime->close_event(evt));
681 break;
682 }
683 }
684
685 /* Control is returned to U-Boot, disable EFI watchdog */
686 efi_set_watchdog(0);
687
688 return ret;
689}