aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--boot/Kconfig4
-rw-r--r--boot/Makefile2
-rw-r--r--boot/bootm_os.c32
-rw-r--r--boot/bootmeth_efi.c8
-rw-r--r--boot/bootmeth_efi_mgr.c2
-rw-r--r--cmd/Kconfig16
-rw-r--r--cmd/bootefi.c670
-rw-r--r--cmd/efidebug.c4
-rw-r--r--doc/chromium/files/chromebook_jerry.its4
-rw-r--r--doc/chromium/files/nyan-big.its4
-rw-r--r--doc/usage/cmd/imxtract.rst6
-rw-r--r--doc/usage/fit/beaglebone_vboot.rst74
-rw-r--r--doc/usage/fit/howto.rst40
-rw-r--r--doc/usage/fit/kernel.rst6
-rw-r--r--doc/usage/fit/kernel_fdt.rst4
-rw-r--r--doc/usage/fit/kernel_fdts_compressed.rst6
-rw-r--r--doc/usage/fit/multi-with-fpga.rst6
-rw-r--r--doc/usage/fit/multi-with-loadables.rst8
-rw-r--r--doc/usage/fit/multi.rst12
-rw-r--r--doc/usage/fit/sign-configs.rst6
-rw-r--r--doc/usage/fit/sign-images.rst4
-rw-r--r--doc/usage/fit/signature.rst22
-rw-r--r--doc/usage/fit/update3.rst6
-rw-r--r--doc/usage/fit/update_uboot.rst2
-rw-r--r--doc/usage/fit/x86-fit-boot.rst8
-rw-r--r--include/efi_loader.h12
-rw-r--r--lib/efi_loader/efi_bootmgr.c530
-rw-r--r--test/boot/bootflow.c2
28 files changed, 771 insertions, 729 deletions
diff --git a/boot/Kconfig b/boot/Kconfig
index b438002..987ca73 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -523,7 +523,7 @@ config BOOTMETH_EXTLINUX_PXE
config BOOTMETH_EFILOADER
bool "Bootdev support for EFI boot"
- depends on CMD_BOOTEFI
+ depends on BOOTEFI_BOOTMGR
default y
help
Enables support for EFI boot using bootdevs. This makes the
@@ -558,7 +558,7 @@ config BOOTMETH_DISTRO
select BOOTMETH_SCRIPT if CMDLINE # E.g. Armbian uses scripts
select BOOTMETH_EXTLINUX # E.g. Debian uses these
select BOOTMETH_EXTLINUX_PXE if CMD_PXE && CMD_NET && DM_ETH
- select BOOTMETH_EFILOADER if CMD_BOOTEFI # E.g. Ubuntu uses this
+ select BOOTMETH_EFILOADER if BOOTEFI_BOOTMGR # E.g. Ubuntu uses this
config SPL_BOOTMETH_VBE
bool "Bootdev support for Verified Boot for Embedded (SPL)"
diff --git a/boot/Makefile b/boot/Makefile
index de0eafe..a90ebea 100644
--- a/boot/Makefile
+++ b/boot/Makefile
@@ -34,7 +34,7 @@ obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_CROS) += bootm.o bootm_os.o bootmeth_cros.o
obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_SANDBOX) += bootmeth_sandbox.o
obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_SCRIPT) += bootmeth_script.o
ifdef CONFIG_$(SPL_TPL_)BOOTSTD_FULL
-obj-$(CONFIG_CMD_BOOTEFI_BOOTMGR) += bootmeth_efi_mgr.o
+obj-$(CONFIG_BOOTEFI_BOOTMGR) += bootmeth_efi_mgr.o
obj-$(CONFIG_$(SPL_TPL_)EXPO) += bootflow_menu.o
obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootflow_menu.o
obj-$(CONFIG_$(SPL_TPL_)CEDIT) += cedit.o
diff --git a/boot/bootm_os.c b/boot/bootm_os.c
index b924221..dc4046a 100644
--- a/boot/bootm_os.c
+++ b/boot/bootm_os.c
@@ -476,43 +476,27 @@ static int do_bootm_tee(int flag, int argc, char *const argv[],
static int do_bootm_efi(int flag, int argc, char *const argv[],
struct bootm_headers *images)
{
- efi_status_t efi_ret;
+ int ret;
void *image_buf;
if (flag != BOOTM_STATE_OS_GO)
return 0;
- /* Initialize EFI drivers */
- efi_ret = efi_init_obj_list();
- if (efi_ret != EFI_SUCCESS) {
- printf("## Failed to initialize UEFI sub-system: r = %lu\n",
- efi_ret & ~EFI_ERROR_MASK);
- return 1;
- }
+ /* We expect to return */
+ images->os.type = IH_TYPE_STANDALONE;
- /* Install device tree */
- efi_ret = efi_install_fdt(images->ft_len
- ? images->ft_addr : EFI_FDT_USE_INTERNAL);
- if (efi_ret != EFI_SUCCESS) {
- printf("## Failed to install device tree: r = %lu\n",
- efi_ret & ~EFI_ERROR_MASK);
- return 1;
- }
+ image_buf = map_sysmem(images->ep, images->os.image_len);
/* Run EFI image */
printf("## Transferring control to EFI (at address %08lx) ...\n",
images->ep);
bootstage_mark(BOOTSTAGE_ID_RUN_OS);
- /* We expect to return */
- images->os.type = IH_TYPE_STANDALONE;
+ ret = efi_binary_run(image_buf, images->os.image_len,
+ images->ft_len
+ ? images->ft_addr : EFI_FDT_USE_INTERNAL);
- image_buf = map_sysmem(images->ep, images->os.image_len);
-
- efi_ret = efi_run_image(image_buf, images->os.image_len);
- if (efi_ret != EFI_SUCCESS)
- return 1;
- return 0;
+ return ret;
}
#endif
diff --git a/boot/bootmeth_efi.c b/boot/bootmeth_efi.c
index 9ba7734..d46bff5 100644
--- a/boot/bootmeth_efi.c
+++ b/boot/bootmeth_efi.c
@@ -413,7 +413,6 @@ static int distro_efi_read_bootflow(struct udevice *dev, struct bootflow *bflow)
static int distro_efi_boot(struct udevice *dev, struct bootflow *bflow)
{
ulong kernel, fdt;
- char cmd[50];
int ret;
kernel = env_get_hex("kernel_addr_r", 0);
@@ -442,12 +441,7 @@ static int distro_efi_boot(struct udevice *dev, struct bootflow *bflow)
fdt = env_get_hex("fdt_addr_r", 0);
}
- /*
- * At some point we can add a real interface to bootefi so we can call
- * this directly. For now, go through the CLI, like distro boot.
- */
- snprintf(cmd, sizeof(cmd), "bootefi %lx %lx", kernel, fdt);
- if (run_command(cmd, 0))
+ if (efi_binary_run(map_sysmem(kernel, 0), 0, map_sysmem(fdt, 0)))
return log_msg_ret("run", -EINVAL);
return 0;
diff --git a/boot/bootmeth_efi_mgr.c b/boot/bootmeth_efi_mgr.c
index 6428c09..ed29d7e 100644
--- a/boot/bootmeth_efi_mgr.c
+++ b/boot/bootmeth_efi_mgr.c
@@ -87,7 +87,7 @@ static int efi_mgr_boot(struct udevice *dev, struct bootflow *bflow)
int ret;
/* Booting is handled by the 'bootefi bootmgr' command */
- ret = run_command("bootefi bootmgr", 0);
+ ret = efi_bootmgr_run(EFI_FDT_USE_INTERNAL);
return 0;
}
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 748b959..24bfbe5 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -273,7 +273,7 @@ config CMD_BOOTMETH
config BOOTM_EFI
bool "Support booting UEFI FIT images"
- depends on CMD_BOOTEFI && CMD_BOOTM && FIT
+ depends on BOOTEFI_BOOTMGR && CMD_BOOTM && FIT
default y
help
Support booting UEFI FIT images via the bootm command.
@@ -362,9 +362,19 @@ config CMD_BOOTEFI
help
Boot an EFI image from memory.
+if CMD_BOOTEFI
+config CMD_BOOTEFI_BINARY
+ bool "Allow booting an EFI binary directly"
+ depends on BOOTEFI_BOOTMGR
+ default y
+ help
+ Select this option to enable direct execution of binary at 'bootefi'.
+ This subcommand will allow you to load the UEFI binary using
+ other U-Boot commands or external methods and then run it.
+
config CMD_BOOTEFI_BOOTMGR
bool "UEFI Boot Manager command"
- depends on BOOTEFI_BOOTMGR && CMD_BOOTEFI
+ depends on BOOTEFI_BOOTMGR
default y
help
Select this option to enable the 'bootmgr' subcommand of 'bootefi'.
@@ -373,7 +383,6 @@ config CMD_BOOTEFI_BOOTMGR
config CMD_BOOTEFI_HELLO_COMPILE
bool "Compile a standard EFI hello world binary for testing"
- depends on CMD_BOOTEFI && !CPU_V7M
default y
help
This compiles a standard EFI hello world application with U-Boot so
@@ -395,6 +404,7 @@ config CMD_BOOTEFI_HELLO
up EFI support on a new architecture.
source lib/efi_selftest/Kconfig
+endif
config CMD_BOOTMENU
bool "bootmenu"
diff --git a/cmd/bootefi.c b/cmd/bootefi.c
index 2ed29ad..9cf9027 100644
--- a/cmd/bootefi.c
+++ b/cmd/bootefi.c
@@ -7,555 +7,23 @@
#define LOG_CATEGORY LOGC_EFI
-#include <common.h>
-#include <bootm.h>
-#include <charset.h>
#include <command.h>
-#include <dm.h>
+#include <efi.h>
#include <efi_loader.h>
-#include <efi_selftest.h>
-#include <env.h>
-#include <errno.h>
-#include <image.h>
+#include <exports.h>
#include <log.h>
#include <malloc.h>
-#include <asm/global_data.h>
-#include <linux/libfdt.h>
-#include <linux/libfdt_env.h>
#include <mapmem.h>
-#include <memalign.h>
+#include <vsprintf.h>
#include <asm-generic/sections.h>
-#include <linux/linkage.h>
+#include <asm/global_data.h>
+#include <linux/string.h>
DECLARE_GLOBAL_DATA_PTR;
-static struct efi_device_path *bootefi_image_path;
-static struct efi_device_path *bootefi_device_path;
-static void *image_addr;
-static size_t image_size;
-
-/**
- * efi_get_image_parameters() - return image parameters
- *
- * @img_addr: address of loaded image in memory
- * @img_size: size of loaded image
- */
-void efi_get_image_parameters(void **img_addr, size_t *img_size)
-{
- *img_addr = image_addr;
- *img_size = image_size;
-}
-
-/**
- * efi_clear_bootdev() - clear boot device
- */
-static void efi_clear_bootdev(void)
-{
- efi_free_pool(bootefi_device_path);
- efi_free_pool(bootefi_image_path);
- bootefi_device_path = NULL;
- bootefi_image_path = NULL;
- image_addr = NULL;
- image_size = 0;
-}
-
-/**
- * efi_set_bootdev() - set boot device
- *
- * This function is called when a file is loaded, e.g. via the 'load' command.
- * We use the path to this file to inform the UEFI binary about the boot device.
- *
- * @dev: device, e.g. "MMC"
- * @devnr: number of the device, e.g. "1:2"
- * @path: path to file loaded
- * @buffer: buffer with file loaded
- * @buffer_size: size of file loaded
- */
-void efi_set_bootdev(const char *dev, const char *devnr, const char *path,
- void *buffer, size_t buffer_size)
-{
- struct efi_device_path *device, *image;
- efi_status_t ret;
-
- log_debug("dev=%s, devnr=%s, path=%s, buffer=%p, size=%zx\n", dev,
- devnr, path, buffer, buffer_size);
-
- /* Forget overwritten image */
- if (buffer + buffer_size >= image_addr &&
- image_addr + image_size >= buffer)
- efi_clear_bootdev();
-
- /* Remember only PE-COFF and FIT images */
- if (efi_check_pe(buffer, buffer_size, NULL) != EFI_SUCCESS) {
- if (IS_ENABLED(CONFIG_FIT) &&
- !fit_check_format(buffer, IMAGE_SIZE_INVAL)) {
- /*
- * FIT images of type EFI_OS are started via command
- * bootm. We should not use their boot device with the
- * bootefi command.
- */
- buffer = 0;
- buffer_size = 0;
- } else {
- log_debug("- not remembering image\n");
- return;
- }
- }
-
- /* efi_set_bootdev() is typically called repeatedly, recover memory */
- efi_clear_bootdev();
-
- image_addr = buffer;
- image_size = buffer_size;
-
- ret = efi_dp_from_name(dev, devnr, path, &device, &image);
- if (ret == EFI_SUCCESS) {
- bootefi_device_path = device;
- if (image) {
- /* FIXME: image should not contain device */
- struct efi_device_path *image_tmp = image;
-
- efi_dp_split_file_path(image, &device, &image);
- efi_free_pool(image_tmp);
- }
- bootefi_image_path = image;
- log_debug("- boot device %pD\n", device);
- if (image)
- log_debug("- image %pD\n", image);
- } else {
- log_debug("- efi_dp_from_name() failed, err=%lx\n", ret);
- efi_clear_bootdev();
- }
-}
-
-/**
- * efi_env_set_load_options() - set load options from environment variable
- *
- * @handle: the image handle
- * @env_var: name of the environment variable
- * @load_options: pointer to load options (output)
- * Return: status code
- */
-static efi_status_t efi_env_set_load_options(efi_handle_t handle,
- const char *env_var,
- u16 **load_options)
-{
- const char *env = env_get(env_var);
- size_t size;
- u16 *pos;
- efi_status_t ret;
-
- *load_options = NULL;
- if (!env)
- return EFI_SUCCESS;
- size = sizeof(u16) * (utf8_utf16_strlen(env) + 1);
- pos = calloc(size, 1);
- if (!pos)
- return EFI_OUT_OF_RESOURCES;
- *load_options = pos;
- utf8_utf16_strcpy(&pos, env);
- ret = efi_set_load_options(handle, size, *load_options);
- if (ret != EFI_SUCCESS) {
- free(*load_options);
- *load_options = NULL;
- }
- return ret;
-}
-
-#if !CONFIG_IS_ENABLED(GENERATE_ACPI_TABLE)
-
-/**
- * copy_fdt() - Copy the device tree to a new location available to EFI
- *
- * The FDT is copied to a suitable location within the EFI memory map.
- * Additional 12 KiB are added to the space in case the device tree needs to be
- * expanded later with fdt_open_into().
- *
- * @fdtp: On entry a pointer to the flattened device tree.
- * On exit a pointer to the copy of the flattened device tree.
- * FDT start
- * Return: status code
- */
-static efi_status_t copy_fdt(void **fdtp)
-{
- unsigned long fdt_ram_start = -1L, fdt_pages;
- efi_status_t ret = 0;
- void *fdt, *new_fdt;
- u64 new_fdt_addr;
- uint fdt_size;
- int i;
-
- for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
- u64 ram_start = gd->bd->bi_dram[i].start;
- u64 ram_size = gd->bd->bi_dram[i].size;
-
- if (!ram_size)
- continue;
-
- if (ram_start < fdt_ram_start)
- fdt_ram_start = ram_start;
- }
-
- /*
- * Give us at least 12 KiB of breathing room in case the device tree
- * needs to be expanded later.
- */
- fdt = *fdtp;
- fdt_pages = efi_size_in_pages(fdt_totalsize(fdt) + 0x3000);
- fdt_size = fdt_pages << EFI_PAGE_SHIFT;
-
- ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
- EFI_ACPI_RECLAIM_MEMORY, fdt_pages,
- &new_fdt_addr);
- if (ret != EFI_SUCCESS) {
- log_err("ERROR: Failed to reserve space for FDT\n");
- goto done;
- }
- new_fdt = (void *)(uintptr_t)new_fdt_addr;
- memcpy(new_fdt, fdt, fdt_totalsize(fdt));
- fdt_set_totalsize(new_fdt, fdt_size);
-
- *fdtp = (void *)(uintptr_t)new_fdt_addr;
-done:
- return ret;
-}
-
-/**
- * get_config_table() - get configuration table
- *
- * @guid: GUID of the configuration table
- * Return: pointer to configuration table or NULL
- */
-static void *get_config_table(const efi_guid_t *guid)
-{
- size_t i;
-
- for (i = 0; i < systab.nr_tables; i++) {
- if (!guidcmp(guid, &systab.tables[i].guid))
- return systab.tables[i].table;
- }
- return NULL;
-}
-
-#endif /* !CONFIG_IS_ENABLED(GENERATE_ACPI_TABLE) */
-
-/**
- * efi_install_fdt() - install device tree
- *
- * If fdt is not EFI_FDT_USE_INTERNAL, the device tree located at that memory
- * address will will be installed as configuration table, otherwise the device
- * tree located at the address indicated by environment variable fdt_addr or as
- * fallback fdtcontroladdr will be used.
- *
- * On architectures using ACPI tables device trees shall not be installed as
- * configuration table.
- *
- * @fdt: address of device tree or EFI_FDT_USE_INTERNAL to use the
- * the hardware device tree as indicated by environment variable
- * fdt_addr or as fallback the internal device tree as indicated by
- * the environment variable fdtcontroladdr
- * Return: status code
- */
-efi_status_t efi_install_fdt(void *fdt)
-{
- /*
- * The EBBR spec requires that we have either an FDT or an ACPI table
- * but not both.
- */
-#if CONFIG_IS_ENABLED(GENERATE_ACPI_TABLE)
- if (fdt) {
- log_warning("WARNING: Can't have ACPI table and device tree - ignoring DT.\n");
- return EFI_SUCCESS;
- }
-#else
- struct bootm_headers img = { 0 };
- efi_status_t ret;
-
- if (fdt == EFI_FDT_USE_INTERNAL) {
- const char *fdt_opt;
- uintptr_t fdt_addr;
-
- /* Look for device tree that is already installed */
- if (get_config_table(&efi_guid_fdt))
- return EFI_SUCCESS;
- /* Check if there is a hardware device tree */
- fdt_opt = env_get("fdt_addr");
- /* Use our own device tree as fallback */
- if (!fdt_opt) {
- fdt_opt = env_get("fdtcontroladdr");
- if (!fdt_opt) {
- log_err("ERROR: need device tree\n");
- return EFI_NOT_FOUND;
- }
- }
- fdt_addr = hextoul(fdt_opt, NULL);
- if (!fdt_addr) {
- log_err("ERROR: invalid $fdt_addr or $fdtcontroladdr\n");
- return EFI_LOAD_ERROR;
- }
- fdt = map_sysmem(fdt_addr, 0);
- }
-
- /* Install device tree */
- if (fdt_check_header(fdt)) {
- log_err("ERROR: invalid device tree\n");
- return EFI_LOAD_ERROR;
- }
-
- /* Prepare device tree for payload */
- ret = copy_fdt(&fdt);
- if (ret) {
- log_err("ERROR: out of memory\n");
- return EFI_OUT_OF_RESOURCES;
- }
-
- if (image_setup_libfdt(&img, fdt, NULL)) {
- log_err("ERROR: failed to process device tree\n");
- return EFI_LOAD_ERROR;
- }
-
- /* Create memory reservations as indicated by the device tree */
- efi_carve_out_dt_rsv(fdt);
-
- efi_try_purge_kaslr_seed(fdt);
-
- if (CONFIG_IS_ENABLED(EFI_TCG2_PROTOCOL_MEASURE_DTB)) {
- ret = efi_tcg2_measure_dtb(fdt);
- if (ret == EFI_SECURITY_VIOLATION) {
- log_err("ERROR: failed to measure DTB\n");
- return ret;
- }
- }
-
- /* Install device tree as UEFI table */
- ret = efi_install_configuration_table(&efi_guid_fdt, fdt);
- if (ret != EFI_SUCCESS) {
- log_err("ERROR: failed to install device tree\n");
- return ret;
- }
-#endif /* GENERATE_ACPI_TABLE */
-
- return EFI_SUCCESS;
-}
-
-/**
- * do_bootefi_exec() - execute EFI binary
- *
- * The image indicated by @handle is started. When it returns the allocated
- * memory for the @load_options is freed.
- *
- * @handle: handle of loaded image
- * @load_options: load options
- * Return: status code
- *
- * Load the EFI binary into a newly assigned memory unwinding the relocation
- * information, install the loaded image protocol, and call the binary.
- */
-static efi_status_t do_bootefi_exec(efi_handle_t handle, void *load_options)
-{
- efi_status_t ret;
- efi_uintn_t exit_data_size = 0;
- u16 *exit_data = NULL;
- struct efi_event *evt;
-
- /* On ARM switch from EL3 or secure mode to EL2 or non-secure mode */
- switch_to_non_secure_mode();
-
- /*
- * The UEFI standard requires that the watchdog timer is set to five
- * minutes when invoking an EFI boot option.
- *
- * Unified Extensible Firmware Interface (UEFI), version 2.7 Errata A
- * 7.5. Miscellaneous Boot Services - EFI_BOOT_SERVICES.SetWatchdogTimer
- */
- ret = efi_set_watchdog(300);
- if (ret != EFI_SUCCESS) {
- log_err("ERROR: Failed to set watchdog timer\n");
- goto out;
- }
-
- /* Call our payload! */
- ret = EFI_CALL(efi_start_image(handle, &exit_data_size, &exit_data));
- if (ret != EFI_SUCCESS) {
- log_err("## Application failed, r = %lu\n",
- ret & ~EFI_ERROR_MASK);
- if (exit_data) {
- log_err("## %ls\n", exit_data);
- efi_free_pool(exit_data);
- }
- }
-
- efi_restore_gd();
-
-out:
- free(load_options);
-
- if (IS_ENABLED(CONFIG_EFI_LOAD_FILE2_INITRD)) {
- if (efi_initrd_deregister() != EFI_SUCCESS)
- log_err("Failed to remove loadfile2 for initrd\n");
- }
-
- /* Notify EFI_EVENT_GROUP_RETURN_TO_EFIBOOTMGR event group. */
- list_for_each_entry(evt, &efi_events, link) {
- if (evt->group &&
- !guidcmp(evt->group,
- &efi_guid_event_group_return_to_efibootmgr)) {
- efi_signal_event(evt);
- EFI_CALL(systab.boottime->close_event(evt));
- break;
- }
- }
-
- /* Control is returned to U-Boot, disable EFI watchdog */
- efi_set_watchdog(0);
-
- return ret;
-}
-
-/**
- * do_efibootmgr() - execute EFI boot manager
- *
- * Return: status code
- */
-static int do_efibootmgr(void)
-{
- efi_handle_t handle;
- efi_status_t ret;
- void *load_options;
-
- ret = efi_bootmgr_load(&handle, &load_options);
- if (ret != EFI_SUCCESS) {
- log_notice("EFI boot manager: Cannot load any image\n");
- return CMD_RET_FAILURE;
- }
-
- ret = do_bootefi_exec(handle, load_options);
-
- if (ret != EFI_SUCCESS)
- return CMD_RET_FAILURE;
-
- return CMD_RET_SUCCESS;
-}
-
-/**
- * do_bootefi_image() - execute EFI binary
- *
- * Set up memory image for the binary to be loaded, prepare device path, and
- * then call do_bootefi_exec() to execute it.
- *
- * @image_opt: string with image start address
- * @size_opt: string with image size or NULL
- * Return: status code
- */
-static int do_bootefi_image(const char *image_opt, const char *size_opt)
-{
- void *image_buf;
- unsigned long addr, size;
- efi_status_t ret;
-
-#ifdef CONFIG_CMD_BOOTEFI_HELLO
- if (!strcmp(image_opt, "hello")) {
- image_buf = __efi_helloworld_begin;
- size = __efi_helloworld_end - __efi_helloworld_begin;
- efi_clear_bootdev();
- } else
-#endif
- {
- addr = strtoul(image_opt, NULL, 16);
- /* Check that a numeric value was passed */
- if (!addr)
- return CMD_RET_USAGE;
- image_buf = map_sysmem(addr, 0);
-
- if (size_opt) {
- size = strtoul(size_opt, NULL, 16);
- if (!size)
- return CMD_RET_USAGE;
- efi_clear_bootdev();
- } else {
- if (image_buf != image_addr) {
- log_err("No UEFI binary known at %s\n",
- image_opt);
- return CMD_RET_FAILURE;
- }
- size = image_size;
- }
- }
- ret = efi_run_image(image_buf, size);
-
- if (ret != EFI_SUCCESS)
- return CMD_RET_FAILURE;
+static struct efi_device_path *test_image_path;
+static struct efi_device_path *test_device_path;
- return CMD_RET_SUCCESS;
-}
-
-/**
- * efi_run_image() - run loaded UEFI image
- *
- * @source_buffer: memory address of the UEFI image
- * @source_size: size of the UEFI image
- * Return: status code
- */
-efi_status_t efi_run_image(void *source_buffer, efi_uintn_t source_size)
-{
- efi_handle_t mem_handle = NULL, handle;
- struct efi_device_path *file_path = NULL;
- struct efi_device_path *msg_path;
- efi_status_t ret, ret2;
- u16 *load_options;
-
- if (!bootefi_device_path || !bootefi_image_path) {
- log_debug("Not loaded from disk\n");
- /*
- * Special case for efi payload not loaded from disk,
- * such as 'bootefi hello' or for example payload
- * loaded directly into memory via JTAG, etc:
- */
- file_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE,
- (uintptr_t)source_buffer,
- source_size);
- /*
- * Make sure that device for device_path exist
- * in load_image(). Otherwise, shell and grub will fail.
- */
- ret = efi_install_multiple_protocol_interfaces(&mem_handle,
- &efi_guid_device_path,
- file_path, NULL);
- if (ret != EFI_SUCCESS)
- goto out;
- msg_path = file_path;
- } else {
- file_path = efi_dp_append(bootefi_device_path,
- bootefi_image_path);
- msg_path = bootefi_image_path;
- log_debug("Loaded from disk\n");
- }
-
- log_info("Booting %pD\n", msg_path);
-
- ret = EFI_CALL(efi_load_image(false, efi_root, file_path, source_buffer,
- source_size, &handle));
- if (ret != EFI_SUCCESS) {
- log_err("Loading image failed\n");
- goto out;
- }
-
- /* Transfer environment variable as load options */
- ret = efi_env_set_load_options(handle, "bootargs", &load_options);
- if (ret != EFI_SUCCESS)
- goto out;
-
- ret = do_bootefi_exec(handle, load_options);
-
-out:
- ret2 = efi_uninstall_multiple_protocol_interfaces(mem_handle,
- &efi_guid_device_path,
- file_path, NULL);
- efi_free_pool(file_path);
- return (ret != EFI_SUCCESS) ? ret : ret2;
-}
-
-#ifdef CONFIG_CMD_BOOTEFI_SELFTEST
static efi_status_t bootefi_run_prepare(const char *load_options_path,
struct efi_device_path *device_path,
struct efi_device_path *image_path,
@@ -597,23 +65,26 @@ static efi_status_t bootefi_test_prepare
efi_status_t ret;
/* Construct a dummy device path */
- bootefi_device_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE, 0, 0);
- if (!bootefi_device_path)
+ test_device_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE, 0, 0);
+ if (!test_device_path)
return EFI_OUT_OF_RESOURCES;
- bootefi_image_path = efi_dp_from_file(NULL, path);
- if (!bootefi_image_path) {
+ test_image_path = efi_dp_from_file(NULL, path);
+ if (!test_image_path) {
ret = EFI_OUT_OF_RESOURCES;
goto failure;
}
- ret = bootefi_run_prepare(load_options_path, bootefi_device_path,
- bootefi_image_path, image_objp,
+ ret = bootefi_run_prepare(load_options_path, test_device_path,
+ test_image_path, image_objp,
loaded_image_infop);
if (ret == EFI_SUCCESS)
return ret;
failure:
+ efi_free_pool(test_device_path);
+ efi_free_pool(test_image_path);
+ /* TODO: not sure calling clear function is necessary */
efi_clear_bootdev();
return ret;
}
@@ -638,6 +109,8 @@ static int do_efi_selftest(void)
ret = EFI_CALL(efi_selftest(&image_obj->header, &systab));
efi_restore_gd();
free(loaded_image_info->load_options);
+ efi_free_pool(test_device_path);
+ efi_free_pool(test_image_path);
if (ret != EFI_SUCCESS)
efi_delete_handle(&image_obj->header);
else
@@ -645,7 +118,6 @@ static int do_efi_selftest(void)
return ret != EFI_SUCCESS;
}
-#endif /* CONFIG_CMD_BOOTEFI_SELFTEST */
/**
* do_bootefi() - execute `bootefi` command
@@ -660,20 +132,15 @@ static int do_bootefi(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
{
efi_status_t ret;
- char *img_addr, *img_size, *str_copy, *pos;
- void *fdt;
+ char *p;
+ void *fdt, *image_buf;
+ unsigned long addr, size;
+ void *image_addr;
+ size_t image_size;
if (argc < 2)
return CMD_RET_USAGE;
- /* Initialize EFI drivers */
- ret = efi_init_obj_list();
- if (ret != EFI_SUCCESS) {
- log_err("Error: Cannot initialize UEFI sub-system, r = %lu\n",
- ret & ~EFI_ERROR_MASK);
- return CMD_RET_FAILURE;
- }
-
if (argc > 2) {
uintptr_t fdt_addr;
@@ -682,32 +149,81 @@ static int do_bootefi(struct cmd_tbl *cmdtp, int flag, int argc,
} else {
fdt = EFI_FDT_USE_INTERNAL;
}
- ret = efi_install_fdt(fdt);
- if (ret == EFI_INVALID_PARAMETER)
- return CMD_RET_USAGE;
- else if (ret != EFI_SUCCESS)
- return CMD_RET_FAILURE;
- if (IS_ENABLED(CONFIG_CMD_BOOTEFI_BOOTMGR)) {
- if (!strcmp(argv[1], "bootmgr"))
- return do_efibootmgr();
+ if (IS_ENABLED(CONFIG_CMD_BOOTEFI_BOOTMGR) &&
+ !strcmp(argv[1], "bootmgr")) {
+ ret = efi_bootmgr_run(fdt);
+
+ if (ret == EFI_INVALID_PARAMETER)
+ return CMD_RET_USAGE;
+ else if (ret)
+ return CMD_RET_FAILURE;
+
+ return CMD_RET_SUCCESS;
}
-#ifdef CONFIG_CMD_BOOTEFI_SELFTEST
- if (!strcmp(argv[1], "selftest"))
+
+ if (IS_ENABLED(CONFIG_CMD_BOOTEFI_SELFTEST) &&
+ !strcmp(argv[1], "selftest")) {
+ /* Initialize EFI drivers */
+ ret = efi_init_obj_list();
+ if (ret != EFI_SUCCESS) {
+ log_err("Error: Cannot initialize UEFI sub-system, r = %lu\n",
+ ret & ~EFI_ERROR_MASK);
+ return CMD_RET_FAILURE;
+ }
+
+ ret = efi_install_fdt(fdt);
+ if (ret == EFI_INVALID_PARAMETER)
+ return CMD_RET_USAGE;
+ else if (ret != EFI_SUCCESS)
+ return CMD_RET_FAILURE;
+
return do_efi_selftest();
-#endif
- str_copy = strdup(argv[1]);
- if (!str_copy) {
- log_err("Out of memory\n");
- return CMD_RET_FAILURE;
}
- pos = str_copy;
- img_addr = strsep(&pos, ":");
- img_size = strsep(&pos, ":");
- ret = do_bootefi_image(img_addr, img_size);
- free(str_copy);
- return ret;
+ if (!IS_ENABLED(CONFIG_CMD_BOOTEFI_BINARY))
+ return CMD_RET_SUCCESS;
+
+ if (IS_ENABLED(CONFIG_CMD_BOOTEFI_HELLO) &&
+ !strcmp(argv[1], "hello")) {
+ image_buf = __efi_helloworld_begin;
+ size = __efi_helloworld_end - __efi_helloworld_begin;
+ /* TODO: not sure calling clear function is necessary */
+ efi_clear_bootdev();
+ } else {
+ addr = strtoul(argv[1], NULL, 16);
+ /* Check that a numeric value was passed */
+ if (!addr)
+ return CMD_RET_USAGE;
+ image_buf = map_sysmem(addr, 0);
+
+ p = strchr(argv[1], ':');
+ if (p) {
+ size = strtoul(++p, NULL, 16);
+ if (!size)
+ return CMD_RET_USAGE;
+ efi_clear_bootdev();
+ } else {
+ /* Image should be already loaded */
+ efi_get_image_parameters(&image_addr, &image_size);
+
+ if (image_buf != image_addr) {
+ log_err("No UEFI binary known at %s\n",
+ argv[1]);
+ return CMD_RET_FAILURE;
+ }
+ size = image_size;
+ }
+ }
+
+ ret = efi_binary_run(image_buf, size, fdt);
+
+ if (ret == EFI_INVALID_PARAMETER)
+ return CMD_RET_USAGE;
+ else if (ret)
+ return CMD_RET_FAILURE;
+
+ return CMD_RET_SUCCESS;
}
U_BOOT_LONGHELP(bootefi,
diff --git a/cmd/efidebug.c b/cmd/efidebug.c
index 78ef16f..e10fbf8 100644
--- a/cmd/efidebug.c
+++ b/cmd/efidebug.c
@@ -1410,7 +1410,7 @@ static __maybe_unused int do_efi_test_bootmgr(struct cmd_tbl *cmdtp, int flag,
}
static struct cmd_tbl cmd_efidebug_test_sub[] = {
-#ifdef CONFIG_CMD_BOOTEFI_BOOTMGR
+#ifdef CONFIG_BOOTEFI_BOOTMGR
U_BOOT_CMD_MKENT(bootmgr, CONFIG_SYS_MAXARGS, 1, do_efi_test_bootmgr,
"", ""),
#endif
@@ -1604,7 +1604,7 @@ U_BOOT_LONGHELP(efidebug,
" - show UEFI memory map\n"
"efidebug tables\n"
" - show UEFI configuration tables\n"
-#ifdef CONFIG_CMD_BOOTEFI_BOOTMGR
+#ifdef CONFIG_BOOTEFI_BOOTMGR
"efidebug test bootmgr\n"
" - run simple bootmgr for test\n"
#endif
diff --git a/doc/chromium/files/chromebook_jerry.its b/doc/chromium/files/chromebook_jerry.its
index 7505a20..02e5e13 100644
--- a/doc/chromium/files/chromebook_jerry.its
+++ b/doc/chromium/files/chromebook_jerry.its
@@ -15,7 +15,7 @@
load = <0>;
entry = <0>;
hash-2 {
- algo = "sha1";
+ algo = "sha256";
};
};
@@ -26,7 +26,7 @@
arch = "arm";
compression = "none";
hash-1{
- algo = "sha1";
+ algo = "sha256";
};
};
};
diff --git a/doc/chromium/files/nyan-big.its b/doc/chromium/files/nyan-big.its
index bd41291..60bdffb 100644
--- a/doc/chromium/files/nyan-big.its
+++ b/doc/chromium/files/nyan-big.its
@@ -15,7 +15,7 @@
load = <0>;
entry = <0>;
hash-2 {
- algo = "sha1";
+ algo = "sha256";
};
};
@@ -26,7 +26,7 @@
arch = "arm";
compression = "none";
hash-1{
- algo = "sha1";
+ algo = "sha256";
};
};
};
diff --git a/doc/usage/cmd/imxtract.rst b/doc/usage/cmd/imxtract.rst
index eb64b1c..16be60b 100644
--- a/doc/usage/cmd/imxtract.rst
+++ b/doc/usage/cmd/imxtract.rst
@@ -45,14 +45,14 @@ Examples
With verify=no incorrect hashes, signatures, or check sums don't stop the
extraction. But correct hashes are still indicated in the output
-(here: md5, sha1).
+(here: sha256, sha512).
.. code-block:: console
=> setenv verify no
=> imxtract $loadaddr kernel-1 $kernel_addr_r
## Copying 'kernel-1' subimage from FIT image at 40200000 ...
- md5+ sha1+ Loading part 0 ... OK
+ sha256+ sha512+ Loading part 0 ... OK
=>
With verify=yes incorrect hashes, signatures, or check sums stop the extraction.
@@ -62,7 +62,7 @@ With verify=yes incorrect hashes, signatures, or check sums stop the extraction.
=> setenv verify yes
=> imxtract $loadaddr kernel-1 $kernel_addr_r
## Copying 'kernel-1' subimage from FIT image at 40200000 ...
- md5 error!
+ sha256 error!
Bad hash value for 'hash-1' hash node in 'kernel-1' image node
Bad Data Hash
=>
diff --git a/doc/usage/fit/beaglebone_vboot.rst b/doc/usage/fit/beaglebone_vboot.rst
index a102be1..cd6bb14 100644
--- a/doc/usage/fit/beaglebone_vboot.rst
+++ b/doc/usage/fit/beaglebone_vboot.rst
@@ -145,7 +145,7 @@ Put this into a file in that directory called sign.its::
load = <0x80008000>;
entry = <0x80008000>;
hash-1 {
- algo = "sha1";
+ algo = "sha256";
};
};
fdt-1 {
@@ -155,7 +155,7 @@ Put this into a file in that directory called sign.its::
arch = "arm";
compression = "none";
hash-1 {
- algo = "sha1";
+ algo = "sha256";
};
};
};
@@ -165,7 +165,7 @@ Put this into a file in that directory called sign.its::
kernel = "kernel";
fdt = "fdt-1";
signature-1 {
- algo = "sha1,rsa2048";
+ algo = "sha256,rsa2048";
key-name-hint = "dev";
sign-images = "fdt", "kernel";
};
@@ -227,8 +227,8 @@ You should see something like this::
OS: Linux
Load Address: 0x80008000
Entry Point: 0x80008000
- Hash algo: sha1
- Hash value: c94364646427e10f423837e559898ef02c97b988
+ Hash algo: sha256
+ Hash value: 51b2adf9c1016ed46f424d85dcc6c34c46a20b9bee7227e06a6b6320ca5d35c1
Image 1 (fdt-1)
Description: beaglebone-black
Created: Sun Jun 1 12:50:30 2014
@@ -236,8 +236,8 @@ You should see something like this::
Compression: uncompressed
Data Size: 31547 Bytes = 30.81 kB = 0.03 MB
Architecture: ARM
- Hash algo: sha1
- Hash value: cb09202f889d824f23b8e4404b781be5ad38a68d
+ Hash algo: sha256
+ Hash value: 807d5842a04132261ba092373bd40c78991bc7ce173d1175cd976ec37858e7cd
Default Configuration: 'conf-1'
Configuration 0 (conf-1)
Description: unavailable
@@ -255,11 +255,11 @@ You can also run fit_check_sign to check it::
which results in::
- Verifying Hash Integrity ... sha1,rsa2048:dev+
+ Verifying Hash Integrity ... sha256,rsa2048:dev+
## Loading kernel from FIT Image at 7fc6ee469000 ...
Using 'conf-1' configuration
Verifying Hash Integrity ...
- sha1,rsa2048:dev+
+ sha256,rsa2048:dev+
OK
Trying 'kernel' kernel subimage
@@ -272,10 +272,10 @@ which results in::
OS: Linux
Load Address: 0x80008000
Entry Point: 0x80008000
- Hash algo: sha1
- Hash value: c94364646427e10f423837e559898ef02c97b988
+ Hash algo: sha256
+ Hash value: 51b2adf9c1016ed46f424d85dcc6c34c46a20b9bee7227e06a6b6320ca5d35c1
Verifying Hash Integrity ...
- sha1+
+ sha256+
OK
Unimplemented compression type 4
@@ -288,10 +288,10 @@ which results in::
Compression: uncompressed
Data Size: 31547 Bytes = 30.81 kB = 0.03 MB
Architecture: ARM
- Hash algo: sha1
- Hash value: cb09202f889d824f23b8e4404b781be5ad38a68d
+ Hash algo: sha256
+ Hash value: 807d5842a04132261ba092373bd40c78991bc7ce173d1175cd976ec37858e7cd
Verifying Hash Integrity ...
- sha1+
+ sha256+
OK
Loading Flat Device Tree ... OK
@@ -303,14 +303,14 @@ which results in::
Signature check OK
-At the top, you see "sha1,rsa2048:dev+". This means that it checked an RSA key
-of size 2048 bits using SHA1 as the hash algorithm. The key name checked was
+At the top, you see "sha256,rsa2048:dev+". This means that it checked an RSA key
+of size 2048 bits using SHA256 as the hash algorithm. The key name checked was
'dev' and the '+' means that it verified. If it showed '-' that would be bad.
Once the configuration is verified it is then possible to rely on the hashes
in each image referenced by that configuration. So fit_check_sign goes on to
load each of the images. We have a kernel and an FDT but no ramkdisk. In each
-case fit_check_sign checks the hash and prints sha1+ meaning that the SHA1
+case fit_check_sign checks the hash and prints sha256+ meaning that the SHA256
hash verified. This means that none of the images has been tampered with.
There is a test in test/vboot which uses U-Boot's sandbox build to verify that
@@ -328,11 +328,11 @@ This tells us that the kernel starts at byte offset 168 (decimal) in image.fit
and extends for about 7MB. Try changing a byte at 0x2000 (say) and run
fit_check_sign again. You should see something like::
- Verifying Hash Integrity ... sha1,rsa2048:dev+
+ Verifying Hash Integrity ... sha256,rsa2048:dev+
## Loading kernel from FIT Image at 7f5a39571000 ...
Using 'conf-1' configuration
Verifying Hash Integrity ...
- sha1,rsa2048:dev+
+ sha256,rsa2048:dev+
OK
Trying 'kernel' kernel subimage
@@ -345,10 +345,10 @@ fit_check_sign again. You should see something like::
OS: Linux
Load Address: 0x80008000
Entry Point: 0x80008000
- Hash algo: sha1
- Hash value: c94364646427e10f423837e559898ef02c97b988
+ Hash algo: sha256
+ Hash value: 51b2adf9c1016ed46f424d85dcc6c34c46a20b9bee7227e06a6b6320ca5d35c1
Verifying Hash Integrity ...
- sha1 error
+ sha256 error
Bad hash value for 'hash-1' hash node in 'kernel' image node
Bad Data Hash
@@ -361,10 +361,10 @@ fit_check_sign again. You should see something like::
Compression: uncompressed
Data Size: 31547 Bytes = 30.81 kB = 0.03 MB
Architecture: ARM
- Hash algo: sha1
- Hash value: cb09202f889d824f23b8e4404b781be5ad38a68d
+ Hash algo: sha256
+ Hash value: 807d5842a04132261ba092373bd40c78991bc7ce173d1175cd976ec37858e7cd
Verifying Hash Integrity ...
- sha1+
+ sha256+
OK
Loading Flat Device Tree ... OK
@@ -419,13 +419,13 @@ need to change the hash to match. Let's simulate that by changing a byte of
the hash::
fdtget -tx image.fit /images/kernel/hash-1 value
- c9436464 6427e10f 423837e5 59898ef0 2c97b988
- fdtput -tx image.fit /images/kernel/hash-1 value c9436464 6427e10f 423837e5 59898ef0 2c97b981
+ 51b2adf9 c1016ed4 6f424d85 dcc6c34c 46a20b9b ee7227e0 6a6b6320 ca5d35c1
+ fdtput -tx image.fit /images/kernel/hash-1 value 51b2adf9 c1016ed4 6f424d85 dcc6c34c 46a20b9b ee7227e0 6a6b6320 ca5d35c8
Now check it again::
$UOUT/tools/fit_check_sign -f image.fit -k am335x-boneblack-pubkey.dtb
- Verifying Hash Integrity ... sha1,rsa2048:devrsa_verify_with_keynode: RSA failed to verify: -13
+ Verifying Hash Integrity ... sha256,rsa2048:devrsa_verify_with_keynode: RSA failed to verify: -13
rsa_verify_with_keynode: RSA failed to verify: -13
-
Failed to verify required signature 'key-dev'
@@ -446,7 +446,7 @@ running the mkimage link again. Then::
fdtput -p image.fit /configurations/conf-1/signature-1 value fred
$UOUT/tools/fit_check_sign -f image.fit -k am335x-boneblack-pubkey.dtb
Verifying Hash Integrity ... -
- sha1,rsa2048:devrsa_verify_with_keynode: RSA failed to verify: -13
+ sha256,rsa2048:devrsa_verify_with_keynode: RSA failed to verify: -13
rsa_verify_with_keynode: RSA failed to verify: -13
-
Failed to verify required signature 'key-dev'
@@ -528,7 +528,7 @@ You should then see something like this::
U-Boot# bootm 82000000
## Loading kernel from FIT Image at 82000000 ...
Using 'conf-1' configuration
- Verifying Hash Integrity ... sha1,rsa2048:dev+ OK
+ Verifying Hash Integrity ... sha256,rsa2048:dev+ OK
Trying 'kernel' kernel subimage
Description: unavailable
Created: 2014-06-01 19:32:54 UTC
@@ -540,9 +540,9 @@ You should then see something like this::
OS: Linux
Load Address: 0x80008000
Entry Point: 0x80008000
- Hash algo: sha1
- Hash value: c94364646427e10f423837e559898ef02c97b988
- Verifying Hash Integrity ... sha1+ OK
+ Hash algo: sha256
+ Hash value: 51b2adf9c1016ed46f424d85dcc6c34c46a20b9bee7227e06a6b6320ca5d35c1
+ Verifying Hash Integrity ... sha256+ OK
## Loading fdt from FIT Image at 82000000 ...
Using 'conf-1' configuration
Trying 'fdt-1' fdt subimage
@@ -553,9 +553,9 @@ You should then see something like this::
Data Start: 0x8276e2ec
Data Size: 31547 Bytes = 30.8 KiB
Architecture: ARM
- Hash algo: sha1
- Hash value: cb09202f889d824f23b8e4404b781be5ad38a68d
- Verifying Hash Integrity ... sha1+ OK
+ Hash algo: sha256
+ Hash value: 807d5842a04132261ba092373bd40c78991bc7ce173d1175cd976ec37858e7cd
+ Verifying Hash Integrity ... sha256+ OK
Booting using the fdt blob at 0x8276e2ec
Uncompressing Kernel Image ... OK
Loading Device Tree to 8fff5000, end 8ffffb3a ... OK
diff --git a/doc/usage/fit/howto.rst b/doc/usage/fit/howto.rst
index def12a7..b5097d4 100644
--- a/doc/usage/fit/howto.rst
+++ b/doc/usage/fit/howto.rst
@@ -8,7 +8,7 @@ Overview
The new uImage format allows more flexibility in handling images of various
types (kernel, ramdisk, etc.), it also enhances integrity protection of images
-with sha1 and md5 checksums.
+with cryptographic checksums.
Two auxiliary tools are needed on the development host system in order to
create an uImage in the new format: mkimage and dtc, although only one
@@ -99,7 +99,7 @@ started by ATF where SPL is loading U-Boot (as loadables) and ATF (as firmware).
load = <0x8 0x8000000>;
entry = <0x8 0x8000000>;
hash {
- algo = "md5";
+ algo = "sha256";
};
};
atf {
@@ -112,7 +112,7 @@ started by ATF where SPL is loading U-Boot (as loadables) and ATF (as firmware).
load = <0xfffea000>;
entry = <0xfffea000>;
hash {
- algo = "md5";
+ algo = "sha256";
};
};
fdt_1 {
@@ -123,7 +123,7 @@ started by ATF where SPL is loading U-Boot (as loadables) and ATF (as firmware).
compression = "none";
load = <0x100000>;
hash {
- algo = "md5";
+ algo = "sha256";
};
};
};
@@ -190,8 +190,8 @@ its contents:
Entry Point: 0x00000000
Hash algo: crc32
Hash value: 2ae2bb40
- Hash algo: sha1
- Hash value: 3c200f34e2c226ddc789240cca0c59fc54a67cf4
+ Hash algo: sha256
+ Hash value: c22f6bb5a3f96942507a37e7d6a9333ebdc7da57971bc4c082113fe082fdc40f
Default Configuration: 'config-1'
Configuration 0 (config-1)
Description: Boot Linux kernel
@@ -236,8 +236,8 @@ specific to the new image format).
Entry Point: 0x00000000
Hash algo: crc32
Hash value: 2ae2bb40
- Hash algo: sha1
- Hash value: 3c200f34e2c226ddc789240cca0c59fc54a67cf4
+ Hash algo: sha256
+ Hash value: c22f6bb5a3f96942507a37e7d6a9333ebdc7da57971bc4c082113fe082fdc40f
Default Configuration: 'config-1'
Configuration 0 (config-1)
Description: Boot Linux kernel
@@ -258,8 +258,8 @@ specific to the new image format).
Entry Point: 0x00000000
Hash algo: crc32
Hash value: 2ae2bb40
- Hash algo: sha1
- Hash value: 3c200f34e2c226ddc789240cca0c59fc54a67cf4
+ Hash algo: sha256
+ Hash value: c22f6bb5a3f96942507a37e7d6a9333ebdc7da57971bc4c082113fe082fdc40f
Verifying Hash Integrity ... crc32+ sha1+ OK
Uncompressing Kernel Image ... OK
Memory BAT mapping: BAT2=256Mb, BAT3=0Mb, residual: 0Mb
@@ -302,8 +302,8 @@ modified to take the files from some other location if needed):
Entry Point: 0x00000000
Hash algo: crc32
Hash value: 2c0cc807
- Hash algo: sha1
- Hash value: 264b59935470e42c418744f83935d44cdf59a3bb
+ Hash algo: sha256
+ Hash value: a3e9e18b793873827d27c97edfbca67c404a1972d9f36cf48e73ff85d69a422c
Image 1 (fdt-1)
Description: Flattened Device Tree blob
Type: Flat Device Tree
@@ -312,8 +312,8 @@ modified to take the files from some other location if needed):
Architecture: PowerPC
Hash algo: crc32
Hash value: 0d655d71
- Hash algo: sha1
- Hash value: 25ab4e15cd4b8a5144610394560d9c318ce52def
+ Hash algo: sha256
+ Hash value: e9b9a40c5e2e12213ac819e7ccad7271ef43eb5edf9b421f0fa0b4b51bfdb214
Default Configuration: 'conf-1'
Configuration 0 (conf-1)
Description: Boot Linux kernel with FDT blob
@@ -353,8 +353,8 @@ inspected and booted:
Entry Point: 0x00000000
Hash algo: crc32
Hash value: 2c0cc807
- Hash algo: sha1
- Hash value: 264b59935470e42c418744f83935d44cdf59a3bb
+ Hash algo: sha256
+ Hash value: a3e9e18b793873827d27c97edfbca67c404a1972d9f36cf48e73ff85d69a422c
Image 1 (fdt-1)
Description: Flattened Device Tree blob
Type: Flat Device Tree
@@ -364,8 +364,8 @@ inspected and booted:
Architecture: PowerPC
Hash algo: crc32
Hash value: 0d655d71
- Hash algo: sha1
- Hash value: 25ab4e15cd4b8a5144610394560d9c318ce52def
+ Hash algo: sha256
+ Hash value: e9b9a40c5e2e12213ac819e7ccad7271ef43eb5edf9b421f0fa0b4b51bfdb214
Default Configuration: 'conf-1'
Configuration 0 (conf-1)
Description: Boot Linux kernel with FDT blob
@@ -387,7 +387,7 @@ inspected and booted:
Hash algo: crc32
Hash value: 2c0cc807
Hash algo: sha1
- Hash value: 264b59935470e42c418744f83935d44cdf59a3bb
+ Hash value: a3e9e18b793873827d27c97edfbca67c404a1972d9f36cf48e73ff85d69a422c
Verifying Hash Integrity ... crc32+ sha1+ OK
Uncompressing Kernel Image ... OK
## Flattened Device Tree from FIT Image at 00900000
@@ -402,7 +402,7 @@ inspected and booted:
Hash algo: crc32
Hash value: 0d655d71
Hash algo: sha1
- Hash value: 25ab4e15cd4b8a5144610394560d9c318ce52def
+ Hash value: e9b9a40c5e2e12213ac819e7ccad7271ef43eb5edf9b421f0fa0b4b51bfdb214
Verifying Hash Integrity ... crc32+ sha1+ OK
Booting using the fdt blob at 0xa0abdc
Loading Device Tree to 007fc000, end 007fffff ... OK
diff --git a/doc/usage/fit/kernel.rst b/doc/usage/fit/kernel.rst
index 012a81e..e560179 100644
--- a/doc/usage/fit/kernel.rst
+++ b/doc/usage/fit/kernel.rst
@@ -25,7 +25,7 @@ Single kernel
algo = "crc32";
};
hash-2 {
- algo = "sha1";
+ algo = "sha256";
};
};
};
@@ -59,7 +59,7 @@ For x86 a setup node is also required: see x86-fit-boot::
load = <0x01000000>;
entry = <0x00000000>;
hash-2 {
- algo = "sha1";
+ algo = "sha256";
};
};
@@ -73,7 +73,7 @@ For x86 a setup node is also required: see x86-fit-boot::
load = <0x00090000>;
entry = <0x00090000>;
hash-2 {
- algo = "sha1";
+ algo = "sha256";
};
};
};
diff --git a/doc/usage/fit/kernel_fdt.rst b/doc/usage/fit/kernel_fdt.rst
index 8eee13a..9cc26fb 100644
--- a/doc/usage/fit/kernel_fdt.rst
+++ b/doc/usage/fit/kernel_fdt.rst
@@ -25,7 +25,7 @@ Single kernel and FDT blob
algo = "crc32";
};
hash-2 {
- algo = "sha1";
+ algo = "sha256";
};
};
fdt-1 {
@@ -38,7 +38,7 @@ Single kernel and FDT blob
algo = "crc32";
};
hash-2 {
- algo = "sha1";
+ algo = "sha256";
};
};
};
diff --git a/doc/usage/fit/kernel_fdts_compressed.rst b/doc/usage/fit/kernel_fdts_compressed.rst
index 0b169c7..b57871d 100644
--- a/doc/usage/fit/kernel_fdts_compressed.rst
+++ b/doc/usage/fit/kernel_fdts_compressed.rst
@@ -28,7 +28,7 @@ string to match directly.
algo = "crc32";
};
hash-2 {
- algo = "sha1";
+ algo = "sha256";
};
};
fdt@1 {
@@ -41,7 +41,7 @@ string to match directly.
algo = "crc32";
};
hash-2 {
- algo = "sha1";
+ algo = "sha256";
};
};
fdt@2 {
@@ -54,7 +54,7 @@ string to match directly.
algo = "crc32";
};
hash-2 {
- algo = "sha1";
+ algo = "sha256";
};
};
};
diff --git a/doc/usage/fit/multi-with-fpga.rst b/doc/usage/fit/multi-with-fpga.rst
index 28d7d5d..4c7f1be 100644
--- a/doc/usage/fit/multi-with-fpga.rst
+++ b/doc/usage/fit/multi-with-fpga.rst
@@ -20,7 +20,7 @@ This example makes use of the 'loadables' field::
compression = "none";
load = <0x10000000>;
hash-1 {
- algo = "md5";
+ algo = "sha256";
};
};
@@ -33,7 +33,7 @@ This example makes use of the 'loadables' field::
load = <0x30000000>;
compatible = "u-boot,fpga-legacy"
hash-1 {
- algo = "md5";
+ algo = "sha256";
};
};
@@ -47,7 +47,7 @@ This example makes use of the 'loadables' field::
load = <0x8000>;
entry = <0x8000>;
hash-1 {
- algo = "md5";
+ algo = "sha256";
};
};
};
diff --git a/doc/usage/fit/multi-with-loadables.rst b/doc/usage/fit/multi-with-loadables.rst
index a0241df..7849cb5 100644
--- a/doc/usage/fit/multi-with-loadables.rst
+++ b/doc/usage/fit/multi-with-loadables.rst
@@ -22,7 +22,7 @@ This example makes use of the 'loadables' field::
load = <0xa0000000>;
entry = <0xa0000000>;
hash-1 {
- algo = "md5";
+ algo = "sha256";
};
};
@@ -34,7 +34,7 @@ This example makes use of the 'loadables' field::
compression = "none";
load = <0xb0000000>;
hash-1 {
- algo = "md5";
+ algo = "sha256";
};
};
@@ -46,7 +46,7 @@ This example makes use of the 'loadables' field::
compression = "none";
load = <0xb0400000>;
hash-1 {
- algo = "md5";
+ algo = "sha256";
};
};
@@ -60,7 +60,7 @@ This example makes use of the 'loadables' field::
load = <0xa0000000>;
entry = <0xa0000000>;
hash-1 {
- algo = "md5";
+ algo = "sha256";
};
};
};
diff --git a/doc/usage/fit/multi.rst b/doc/usage/fit/multi.rst
index 2e6ae58..e68752b 100644
--- a/doc/usage/fit/multi.rst
+++ b/doc/usage/fit/multi.rst
@@ -22,10 +22,10 @@ Multiple kernels, ramdisks and FDT blobs
load = <00000000>;
entry = <00000000>;
hash-1 {
- algo = "md5";
+ algo = "sha256";
};
hash-2 {
- algo = "sha1";
+ algo = "sha512";
};
};
@@ -39,7 +39,7 @@ Multiple kernels, ramdisks and FDT blobs
load = <00000000>;
entry = <00000000>;
hash-1 {
- algo = "sha1";
+ algo = "sha256";
};
};
@@ -53,7 +53,7 @@ Multiple kernels, ramdisks and FDT blobs
load = <00000000>;
entry = <00000000>;
hash-1 {
- algo = "md5";
+ algo = "sha256";
};
};
@@ -67,7 +67,7 @@ Multiple kernels, ramdisks and FDT blobs
load = <00000000>;
entry = <00000000>;
hash-1 {
- algo = "sha1";
+ algo = "sha256";
};
};
@@ -104,7 +104,7 @@ Multiple kernels, ramdisks and FDT blobs
compression = "none";
load = <00700000>;
hash-1 {
- algo = "sha1";
+ algo = "sha256";
};
};
diff --git a/doc/usage/fit/sign-configs.rst b/doc/usage/fit/sign-configs.rst
index 6a3df8f..6d98d44 100644
--- a/doc/usage/fit/sign-configs.rst
+++ b/doc/usage/fit/sign-configs.rst
@@ -22,7 +22,7 @@ Signed configurations
entry = <0x8>;
kernel-version = <1>;
hash-1 {
- algo = "sha1";
+ algo = "sha256";
};
};
fdt-1 {
@@ -33,7 +33,7 @@ Signed configurations
compression = "none";
fdt-version = <1>;
hash-1 {
- algo = "sha1";
+ algo = "sha256";
};
};
};
@@ -43,7 +43,7 @@ Signed configurations
kernel = "kernel";
fdt = "fdt-1";
signature {
- algo = "sha1,rsa2048";
+ algo = "sha256,rsa2048";
key-name-hint = "dev";
sign-images = "fdt", "kernel";
};
diff --git a/doc/usage/fit/sign-images.rst b/doc/usage/fit/sign-images.rst
index 7d54d70..ca7d10f 100644
--- a/doc/usage/fit/sign-images.rst
+++ b/doc/usage/fit/sign-images.rst
@@ -22,7 +22,7 @@ Signed Images
entry = <0x8>;
kernel-version = <1>;
signature {
- algo = "sha1,rsa2048";
+ algo = "sha256,rsa2048";
key-name-hint = "dev";
};
};
@@ -34,7 +34,7 @@ Signed Images
compression = "none";
fdt-version = <1>;
signature {
- algo = "sha1,rsa2048";
+ algo = "sha256,rsa2048";
key-name-hint = "dev";
};
};
diff --git a/doc/usage/fit/signature.rst b/doc/usage/fit/signature.rst
index 0804bff..39edba1 100644
--- a/doc/usage/fit/signature.rst
+++ b/doc/usage/fit/signature.rst
@@ -93,7 +93,7 @@ Public keys should be stored as sub-nodes in a /signature node. Required
properties are:
algo
- Algorithm name (e.g. "sha1,rsa2048" or "sha256,ecdsa256")
+ Algorithm name (e.g. "sha256,rsa2048" or "sha512,ecdsa256")
Optional properties are:
@@ -219,28 +219,28 @@ As an example, consider this FIT::
kernel-1 {
data = <data for kernel1>
signature-1 {
- algo = "sha1,rsa2048";
+ algo = "sha256,rsa2048";
value = <...kernel signature 1...>
};
};
kernel-2 {
data = <data for kernel2>
signature-1 {
- algo = "sha1,rsa2048";
+ algo = "sha256,rsa2048";
value = <...kernel signature 2...>
};
};
fdt-1 {
data = <data for fdt1>;
signature-1 {
- algo = "sha1,rsa2048";
+ algo = "sha256,rsa2048";
value = <...fdt signature 1...>
};
};
fdt-2 {
data = <data for fdt2>;
signature-1 {
- algo = "sha1,rsa2048";
+ algo = "sha256,rsa2048";
value = <...fdt signature 2...>
};
};
@@ -291,28 +291,28 @@ So the above example is adjusted to look like this::
kernel-1 {
data = <data for kernel1>
hash-1 {
- algo = "sha1";
+ algo = "sha256";
value = <...kernel hash 1...>
};
};
kernel-2 {
data = <data for kernel2>
hash-1 {
- algo = "sha1";
+ algo = "sha256";
value = <...kernel hash 2...>
};
};
fdt-1 {
data = <data for fdt1>;
hash-1 {
- algo = "sha1";
+ algo = "sha256";
value = <...fdt hash 1...>
};
};
fdt-2 {
data = <data for fdt2>;
hash-1 {
- algo = "sha1";
+ algo = "sha256";
value = <...fdt hash 2...>
};
};
@@ -323,7 +323,7 @@ So the above example is adjusted to look like this::
kernel = "kernel-1";
fdt = "fdt-1";
signature-1 {
- algo = "sha1,rsa2048";
+ algo = "sha256,rsa2048";
value = <...conf 1 signature...>;
};
};
@@ -331,7 +331,7 @@ So the above example is adjusted to look like this::
kernel = "kernel-2";
fdt = "fdt-2";
signature-1 {
- algo = "sha1,rsa2048";
+ algo = "sha256,rsa2048";
value = <...conf 1 signature...>;
};
};
diff --git a/doc/usage/fit/update3.rst b/doc/usage/fit/update3.rst
index 4ff3950..2423580 100644
--- a/doc/usage/fit/update3.rst
+++ b/doc/usage/fit/update3.rst
@@ -19,7 +19,7 @@ Automatic software update: multiple files
type = "firmware";
load = <FF700000>;
hash-1 {
- algo = "sha1";
+ algo = "sha256";
};
};
update-2 {
@@ -29,7 +29,7 @@ Automatic software update: multiple files
type = "firmware";
load = <FF8E0000>;
hash-1 {
- algo = "sha1";
+ algo = "sha256";
};
};
@@ -40,7 +40,7 @@ Automatic software update: multiple files
type = "firmware";
load = <FFAC0000>;
hash-1 {
- algo = "sha1";
+ algo = "sha256";
};
};
};
diff --git a/doc/usage/fit/update_uboot.rst b/doc/usage/fit/update_uboot.rst
index a9288ee..811d008 100644
--- a/doc/usage/fit/update_uboot.rst
+++ b/doc/usage/fit/update_uboot.rst
@@ -21,7 +21,7 @@ Make sure the flashing addresses ('load' prop) is correct for your board!
type = "firmware";
load = <0xFFFC0000>;
hash-1 {
- algo = "sha1";
+ algo = "sha256";
};
};
};
diff --git a/doc/usage/fit/x86-fit-boot.rst b/doc/usage/fit/x86-fit-boot.rst
index 93b73bb..9e3e322 100644
--- a/doc/usage/fit/x86-fit-boot.rst
+++ b/doc/usage/fit/x86-fit-boot.rst
@@ -207,16 +207,16 @@ You can take a look at the resulting fit file if you like::
OS: Linux
Load Address: 0x01000000
Entry Point: 0x00000000
- Hash algo: sha1
- Hash value: 446b5163ebfe0fb6ee20cbb7a8501b263cd92392
+ Hash algo: sha256
+ Hash value: 4bbf49981ade163ed089f8525236fedfe44508e9b02a21a48294a96a1518107b
Image 1 (setup)
Description: Linux setup.bin
Created: Tue Oct 7 10:57:24 2014
Type: x86 setup.bin
Compression: uncompressed
Data Size: 12912 Bytes = 12.61 kB = 0.01 MB
- Hash algo: sha1
- Hash value: a1f2099cf47ff9816236cd534c77af86e713faad
+ Hash algo: sha256
+ Hash value: 6aa50c2e0392cb119cdf0971dce8339f100608ed3757c8200b0e39e889e432d2
Default Configuration: 'config-1'
Configuration 0 (config-1)
Description: Boot Linux kernel
diff --git a/include/efi_loader.h b/include/efi_loader.h
index 664dae2..34e7fbb 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -90,6 +90,8 @@ efi_status_t efi_add_runtime_mmio(void *mmio_ptr, u64 len);
* back to u-boot world
*/
void efi_restore_gd(void);
+/* Call this to unset the current device name */
+void efi_clear_bootdev(void);
/* Call this to set the current device name */
void efi_set_bootdev(const char *dev, const char *devnr, const char *path,
void *buffer, size_t buffer_size);
@@ -114,6 +116,7 @@ static inline efi_status_t efi_add_runtime_mmio(void *mmio_ptr, u64 len)
/* No loader configured, stub out EFI_ENTRY */
static inline void efi_restore_gd(void) { }
+static inline void efi_clear_bootdev(void) { }
static inline void efi_set_bootdev(const char *dev, const char *devnr,
const char *path, void *buffer,
size_t buffer_size) { }
@@ -527,14 +530,21 @@ efi_status_t efi_bootmgr_get_unused_bootoption(u16 *buf,
efi_status_t efi_bootmgr_update_media_device_boot_option(void);
/* Delete selected boot option */
efi_status_t efi_bootmgr_delete_boot_option(u16 boot_index);
+/* Invoke EFI boot manager */
+efi_status_t efi_bootmgr_run(void *fdt);
/* search the boot option index in BootOrder */
bool efi_search_bootorder(u16 *bootorder, efi_uintn_t num, u32 target, u32 *index);
/* Set up console modes */
void efi_setup_console_size(void);
+/* Set up load options from environment variable */
+efi_status_t efi_env_set_load_options(efi_handle_t handle, const char *env_var,
+ u16 **load_options);
/* Install device tree */
efi_status_t efi_install_fdt(void *fdt);
/* Run loaded UEFI image */
efi_status_t efi_run_image(void *source_buffer, efi_uintn_t source_size);
+/* Run loaded UEFI image with given fdt */
+efi_status_t efi_binary_run(void *image, size_t size, void *fdt);
/* Initialize variable services */
efi_status_t efi_init_variables(void);
/* Notify ExitBootServices() is called */
@@ -879,14 +889,12 @@ efi_status_t __efi_runtime EFIAPI efi_get_time(
efi_status_t __efi_runtime EFIAPI efi_set_time(struct efi_time *time);
-#ifdef CONFIG_CMD_BOOTEFI_SELFTEST
/*
* Entry point for the tests of the EFI API.
* It is called by 'bootefi selftest'
*/
efi_status_t EFIAPI efi_selftest(efi_handle_t image_handle,
struct efi_system_table *systab);
-#endif
efi_status_t EFIAPI efi_get_variable(u16 *variable_name,
const efi_guid_t *vendor, u32 *attributes,
diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c
index 48153bd..56d97f2 100644
--- a/lib/efi_loader/efi_bootmgr.c
+++ b/lib/efi_loader/efi_bootmgr.c
@@ -3,6 +3,8 @@
* EFI boot manager
*
* Copyright (c) 2017 Rob Clark
+ * For the code moved from cmd/bootefi.c
+ * Copyright (c) 2016 Alexander Graf
*/
#define LOG_CATEGORY LOGC_EFI
@@ -20,6 +22,17 @@
#include <efi_variable.h>
#include <asm/unaligned.h>
+/* TODO: temporarily added here; clean up later */
+#include <bootm.h>
+#include <efi_selftest.h>
+#include <env.h>
+#include <mapmem.h>
+#include <asm/global_data.h>
+#include <linux/libfdt.h>
+#include <linux/libfdt_env.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
static const struct efi_boot_services *bs;
static const struct efi_runtime_services *rs;
@@ -1115,3 +1128,520 @@ out:
return EFI_SUCCESS;
return ret;
}
+
+static struct efi_device_path *bootefi_image_path;
+static struct efi_device_path *bootefi_device_path;
+static void *image_addr;
+static size_t image_size;
+
+/**
+ * efi_get_image_parameters() - return image parameters
+ *
+ * @img_addr: address of loaded image in memory
+ * @img_size: size of loaded image
+ */
+void efi_get_image_parameters(void **img_addr, size_t *img_size)
+{
+ *img_addr = image_addr;
+ *img_size = image_size;
+}
+
+/**
+ * efi_clear_bootdev() - clear boot device
+ */
+void efi_clear_bootdev(void)
+{
+ efi_free_pool(bootefi_device_path);
+ efi_free_pool(bootefi_image_path);
+ bootefi_device_path = NULL;
+ bootefi_image_path = NULL;
+ image_addr = NULL;
+ image_size = 0;
+}
+
+/**
+ * efi_set_bootdev() - set boot device
+ *
+ * This function is called when a file is loaded, e.g. via the 'load' command.
+ * We use the path to this file to inform the UEFI binary about the boot device.
+ *
+ * @dev: device, e.g. "MMC"
+ * @devnr: number of the device, e.g. "1:2"
+ * @path: path to file loaded
+ * @buffer: buffer with file loaded
+ * @buffer_size: size of file loaded
+ */
+void efi_set_bootdev(const char *dev, const char *devnr, const char *path,
+ void *buffer, size_t buffer_size)
+{
+ struct efi_device_path *device, *image;
+ efi_status_t ret;
+
+ log_debug("dev=%s, devnr=%s, path=%s, buffer=%p, size=%zx\n", dev,
+ devnr, path, buffer, buffer_size);
+
+ /* Forget overwritten image */
+ if (buffer + buffer_size >= image_addr &&
+ image_addr + image_size >= buffer)
+ efi_clear_bootdev();
+
+ /* Remember only PE-COFF and FIT images */
+ if (efi_check_pe(buffer, buffer_size, NULL) != EFI_SUCCESS) {
+ if (IS_ENABLED(CONFIG_FIT) &&
+ !fit_check_format(buffer, IMAGE_SIZE_INVAL)) {
+ /*
+ * FIT images of type EFI_OS are started via command
+ * bootm. We should not use their boot device with the
+ * bootefi command.
+ */
+ buffer = 0;
+ buffer_size = 0;
+ } else {
+ log_debug("- not remembering image\n");
+ return;
+ }
+ }
+
+ /* efi_set_bootdev() is typically called repeatedly, recover memory */
+ efi_clear_bootdev();
+
+ image_addr = buffer;
+ image_size = buffer_size;
+
+ ret = efi_dp_from_name(dev, devnr, path, &device, &image);
+ if (ret == EFI_SUCCESS) {
+ bootefi_device_path = device;
+ if (image) {
+ /* FIXME: image should not contain device */
+ struct efi_device_path *image_tmp = image;
+
+ efi_dp_split_file_path(image, &device, &image);
+ efi_free_pool(image_tmp);
+ }
+ bootefi_image_path = image;
+ log_debug("- boot device %pD\n", device);
+ if (image)
+ log_debug("- image %pD\n", image);
+ } else {
+ log_debug("- efi_dp_from_name() failed, err=%lx\n", ret);
+ efi_clear_bootdev();
+ }
+}
+
+/**
+ * efi_env_set_load_options() - set load options from environment variable
+ *
+ * @handle: the image handle
+ * @env_var: name of the environment variable
+ * @load_options: pointer to load options (output)
+ * Return: status code
+ */
+efi_status_t efi_env_set_load_options(efi_handle_t handle,
+ const char *env_var,
+ u16 **load_options)
+{
+ const char *env = env_get(env_var);
+ size_t size;
+ u16 *pos;
+ efi_status_t ret;
+
+ *load_options = NULL;
+ if (!env)
+ return EFI_SUCCESS;
+ size = sizeof(u16) * (utf8_utf16_strlen(env) + 1);
+ pos = calloc(size, 1);
+ if (!pos)
+ return EFI_OUT_OF_RESOURCES;
+ *load_options = pos;
+ utf8_utf16_strcpy(&pos, env);
+ ret = efi_set_load_options(handle, size, *load_options);
+ if (ret != EFI_SUCCESS) {
+ free(*load_options);
+ *load_options = NULL;
+ }
+ return ret;
+}
+
+#if !CONFIG_IS_ENABLED(GENERATE_ACPI_TABLE)
+
+/**
+ * copy_fdt() - Copy the device tree to a new location available to EFI
+ *
+ * The FDT is copied to a suitable location within the EFI memory map.
+ * Additional 12 KiB are added to the space in case the device tree needs to be
+ * expanded later with fdt_open_into().
+ *
+ * @fdtp: On entry a pointer to the flattened device tree.
+ * On exit a pointer to the copy of the flattened device tree.
+ * FDT start
+ * Return: status code
+ */
+static efi_status_t copy_fdt(void **fdtp)
+{
+ unsigned long fdt_ram_start = -1L, fdt_pages;
+ efi_status_t ret = 0;
+ void *fdt, *new_fdt;
+ u64 new_fdt_addr;
+ uint fdt_size;
+ int i;
+
+ for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+ u64 ram_start = gd->bd->bi_dram[i].start;
+ u64 ram_size = gd->bd->bi_dram[i].size;
+
+ if (!ram_size)
+ continue;
+
+ if (ram_start < fdt_ram_start)
+ fdt_ram_start = ram_start;
+ }
+
+ /*
+ * Give us at least 12 KiB of breathing room in case the device tree
+ * needs to be expanded later.
+ */
+ fdt = *fdtp;
+ fdt_pages = efi_size_in_pages(fdt_totalsize(fdt) + 0x3000);
+ fdt_size = fdt_pages << EFI_PAGE_SHIFT;
+
+ ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
+ EFI_ACPI_RECLAIM_MEMORY, fdt_pages,
+ &new_fdt_addr);
+ if (ret != EFI_SUCCESS) {
+ log_err("ERROR: Failed to reserve space for FDT\n");
+ goto done;
+ }
+ new_fdt = (void *)(uintptr_t)new_fdt_addr;
+ memcpy(new_fdt, fdt, fdt_totalsize(fdt));
+ fdt_set_totalsize(new_fdt, fdt_size);
+
+ *fdtp = (void *)(uintptr_t)new_fdt_addr;
+done:
+ return ret;
+}
+
+/**
+ * get_config_table() - get configuration table
+ *
+ * @guid: GUID of the configuration table
+ * Return: pointer to configuration table or NULL
+ */
+static void *get_config_table(const efi_guid_t *guid)
+{
+ size_t i;
+
+ for (i = 0; i < systab.nr_tables; i++) {
+ if (!guidcmp(guid, &systab.tables[i].guid))
+ return systab.tables[i].table;
+ }
+ return NULL;
+}
+
+#endif /* !CONFIG_IS_ENABLED(GENERATE_ACPI_TABLE) */
+
+/**
+ * efi_install_fdt() - install device tree
+ *
+ * If fdt is not EFI_FDT_USE_INTERNAL, the device tree located at that memory
+ * address will be installed as configuration table, otherwise the device
+ * tree located at the address indicated by environment variable fdt_addr or as
+ * fallback fdtcontroladdr will be used.
+ *
+ * On architectures using ACPI tables device trees shall not be installed as
+ * configuration table.
+ *
+ * @fdt: address of device tree or EFI_FDT_USE_INTERNAL to use
+ * the hardware device tree as indicated by environment variable
+ * fdt_addr or as fallback the internal device tree as indicated by
+ * the environment variable fdtcontroladdr
+ * Return: status code
+ */
+efi_status_t efi_install_fdt(void *fdt)
+{
+ /*
+ * The EBBR spec requires that we have either an FDT or an ACPI table
+ * but not both.
+ */
+#if CONFIG_IS_ENABLED(GENERATE_ACPI_TABLE)
+ if (fdt) {
+ log_warning("WARNING: Can't have ACPI table and device tree - ignoring DT.\n");
+ return EFI_SUCCESS;
+ }
+#else
+ struct bootm_headers img = { 0 };
+ efi_status_t ret;
+
+ if (fdt == EFI_FDT_USE_INTERNAL) {
+ const char *fdt_opt;
+ uintptr_t fdt_addr;
+
+ /* Look for device tree that is already installed */
+ if (get_config_table(&efi_guid_fdt))
+ return EFI_SUCCESS;
+ /* Check if there is a hardware device tree */
+ fdt_opt = env_get("fdt_addr");
+ /* Use our own device tree as fallback */
+ if (!fdt_opt) {
+ fdt_opt = env_get("fdtcontroladdr");
+ if (!fdt_opt) {
+ log_err("ERROR: need device tree\n");
+ return EFI_NOT_FOUND;
+ }
+ }
+ fdt_addr = hextoul(fdt_opt, NULL);
+ if (!fdt_addr) {
+ log_err("ERROR: invalid $fdt_addr or $fdtcontroladdr\n");
+ return EFI_LOAD_ERROR;
+ }
+ fdt = map_sysmem(fdt_addr, 0);
+ }
+
+ /* Install device tree */
+ if (fdt_check_header(fdt)) {
+ log_err("ERROR: invalid device tree\n");
+ return EFI_LOAD_ERROR;
+ }
+
+ /* Prepare device tree for payload */
+ ret = copy_fdt(&fdt);
+ if (ret) {
+ log_err("ERROR: out of memory\n");
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (image_setup_libfdt(&img, fdt, NULL)) {
+ log_err("ERROR: failed to process device tree\n");
+ return EFI_LOAD_ERROR;
+ }
+
+ /* Create memory reservations as indicated by the device tree */
+ efi_carve_out_dt_rsv(fdt);
+
+ efi_try_purge_kaslr_seed(fdt);
+
+ if (CONFIG_IS_ENABLED(EFI_TCG2_PROTOCOL_MEASURE_DTB)) {
+ ret = efi_tcg2_measure_dtb(fdt);
+ if (ret == EFI_SECURITY_VIOLATION) {
+ log_err("ERROR: failed to measure DTB\n");
+ return ret;
+ }
+ }
+
+ /* Install device tree as UEFI table */
+ ret = efi_install_configuration_table(&efi_guid_fdt, fdt);
+ if (ret != EFI_SUCCESS) {
+ log_err("ERROR: failed to install device tree\n");
+ return ret;
+ }
+#endif /* GENERATE_ACPI_TABLE */
+
+ return EFI_SUCCESS;
+}
+
+/**
+ * do_bootefi_exec() - execute EFI binary
+ *
+ * The image indicated by @handle is started. When it returns the allocated
+ * memory for the @load_options is freed.
+ *
+ * @handle: handle of loaded image
+ * @load_options: load options
+ * Return: status code
+ *
+ * Load the EFI binary into a newly assigned memory unwinding the relocation
+ * information, install the loaded image protocol, and call the binary.
+ */
+static efi_status_t do_bootefi_exec(efi_handle_t handle, void *load_options)
+{
+ efi_status_t ret;
+ efi_uintn_t exit_data_size = 0;
+ u16 *exit_data = NULL;
+ struct efi_event *evt;
+
+ /* On ARM switch from EL3 or secure mode to EL2 or non-secure mode */
+ switch_to_non_secure_mode();
+
+ /*
+ * The UEFI standard requires that the watchdog timer is set to five
+ * minutes when invoking an EFI boot option.
+ *
+ * Unified Extensible Firmware Interface (UEFI), version 2.7 Errata A
+ * 7.5. Miscellaneous Boot Services - EFI_BOOT_SERVICES.SetWatchdogTimer
+ */
+ ret = efi_set_watchdog(300);
+ if (ret != EFI_SUCCESS) {
+ log_err("ERROR: Failed to set watchdog timer\n");
+ goto out;
+ }
+
+ /* Call our payload! */
+ ret = EFI_CALL(efi_start_image(handle, &exit_data_size, &exit_data));
+ if (ret != EFI_SUCCESS) {
+ log_err("## Application failed, r = %lu\n",
+ ret & ~EFI_ERROR_MASK);
+ if (exit_data) {
+ log_err("## %ls\n", exit_data);
+ efi_free_pool(exit_data);
+ }
+ }
+
+ efi_restore_gd();
+
+out:
+ free(load_options);
+
+ if (IS_ENABLED(CONFIG_EFI_LOAD_FILE2_INITRD)) {
+ if (efi_initrd_deregister() != EFI_SUCCESS)
+ log_err("Failed to remove loadfile2 for initrd\n");
+ }
+
+ /* Notify EFI_EVENT_GROUP_RETURN_TO_EFIBOOTMGR event group. */
+ list_for_each_entry(evt, &efi_events, link) {
+ if (evt->group &&
+ !guidcmp(evt->group,
+ &efi_guid_event_group_return_to_efibootmgr)) {
+ efi_signal_event(evt);
+ EFI_CALL(systab.boottime->close_event(evt));
+ break;
+ }
+ }
+
+ /* Control is returned to U-Boot, disable EFI watchdog */
+ efi_set_watchdog(0);
+
+ return ret;
+}
+
+/**
+ * efi_bootmgr_run() - execute EFI boot manager
+ * @fdt: Flat device tree
+ *
+ * Invoke EFI boot manager and execute a binary depending on
+ * boot options. If @fdt is not NULL, it will be passed to
+ * the executed binary.
+ *
+ * Return: status code
+ */
+efi_status_t efi_bootmgr_run(void *fdt)
+{
+ efi_handle_t handle;
+ void *load_options;
+ efi_status_t ret;
+
+ /* Initialize EFI drivers */
+ ret = efi_init_obj_list();
+ if (ret != EFI_SUCCESS) {
+ log_err("Error: Cannot initialize UEFI sub-system, r = %lu\n",
+ ret & ~EFI_ERROR_MASK);
+ return CMD_RET_FAILURE;
+ }
+
+ ret = efi_install_fdt(fdt);
+ if (ret != EFI_SUCCESS)
+ return ret;
+
+ ret = efi_bootmgr_load(&handle, &load_options);
+ if (ret != EFI_SUCCESS) {
+ log_notice("EFI boot manager: Cannot load any image\n");
+ return ret;
+ }
+
+ return do_bootefi_exec(handle, load_options);
+}
+
+/**
+ * efi_run_image() - run loaded UEFI image
+ *
+ * @source_buffer: memory address of the UEFI image
+ * @source_size: size of the UEFI image
+ * Return: status code
+ */
+efi_status_t efi_run_image(void *source_buffer, efi_uintn_t source_size)
+{
+ efi_handle_t mem_handle = NULL, handle;
+ struct efi_device_path *file_path = NULL;
+ struct efi_device_path *msg_path;
+ efi_status_t ret, ret2;
+ u16 *load_options;
+
+ if (!bootefi_device_path || !bootefi_image_path) {
+ log_debug("Not loaded from disk\n");
+ /*
+ * Special case for efi payload not loaded from disk,
+ * such as 'bootefi hello' or for example payload
+ * loaded directly into memory via JTAG, etc:
+ */
+ file_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE,
+ (uintptr_t)source_buffer,
+ source_size);
+ /*
+ * Make sure that device for device_path exist
+ * in load_image(). Otherwise, shell and grub will fail.
+ */
+ ret = efi_install_multiple_protocol_interfaces(&mem_handle,
+ &efi_guid_device_path,
+ file_path, NULL);
+ if (ret != EFI_SUCCESS)
+ goto out;
+ msg_path = file_path;
+ } else {
+ file_path = efi_dp_append(bootefi_device_path,
+ bootefi_image_path);
+ msg_path = bootefi_image_path;
+ log_debug("Loaded from disk\n");
+ }
+
+ log_info("Booting %pD\n", msg_path);
+
+ ret = EFI_CALL(efi_load_image(false, efi_root, file_path, source_buffer,
+ source_size, &handle));
+ if (ret != EFI_SUCCESS) {
+ log_err("Loading image failed\n");
+ goto out;
+ }
+
+ /* Transfer environment variable as load options */
+ ret = efi_env_set_load_options(handle, "bootargs", &load_options);
+ if (ret != EFI_SUCCESS)
+ goto out;
+
+ ret = do_bootefi_exec(handle, load_options);
+
+out:
+ ret2 = efi_uninstall_multiple_protocol_interfaces(mem_handle,
+ &efi_guid_device_path,
+ file_path, NULL);
+ efi_free_pool(file_path);
+ return (ret != EFI_SUCCESS) ? ret : ret2;
+}
+
+/**
+ * efi_binary_run() - run loaded UEFI image
+ *
+ * @image: memory address of the UEFI image
+ * @size: size of the UEFI image
+ * @fdt: device-tree
+ *
+ * Execute an EFI binary image loaded at @image.
+ * @size may be zero if the binary is loaded with U-Boot load command.
+ *
+ * Return: status code
+ */
+efi_status_t efi_binary_run(void *image, size_t size, void *fdt)
+{
+ efi_status_t ret;
+
+ /* Initialize EFI drivers */
+ ret = efi_init_obj_list();
+ if (ret != EFI_SUCCESS) {
+ log_err("Error: Cannot initialize UEFI sub-system, r = %lu\n",
+ ret & ~EFI_ERROR_MASK);
+ return -1;
+ }
+
+ ret = efi_install_fdt(fdt);
+ if (ret != EFI_SUCCESS)
+ return ret;
+
+ return efi_run_image(image, size);
+}
diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c
index 597f624..f3e5a83 100644
--- a/test/boot/bootflow.c
+++ b/test/boot/bootflow.c
@@ -374,7 +374,7 @@ static int bootflow_system(struct unit_test_state *uts)
{
struct udevice *bootstd, *dev;
- if (!IS_ENABLED(CONFIG_CMD_BOOTEFI_BOOTMGR))
+ if (!IS_ENABLED(CONFIG_BOOTEFI_BOOTMGR))
return -EAGAIN;
ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd));
ut_assertok(device_bind(bootstd, DM_DRIVER_GET(bootmeth_efi_mgr),