diff options
-rw-r--r-- | arch/Kconfig | 3 | ||||
-rw-r--r-- | arch/sandbox/cpu/start.c | 10 | ||||
-rw-r--r-- | arch/sandbox/dts/test.dts | 2 | ||||
-rw-r--r-- | arch/sandbox/include/asm/state.h | 1 | ||||
-rw-r--r-- | boot/bootmeth_efi.c | 29 | ||||
-rw-r--r-- | cmd/efidebug.c | 25 | ||||
-rw-r--r-- | doc/board/emulation/qemu-riscv.rst | 5 | ||||
-rw-r--r-- | doc/conf.py | 8 | ||||
-rw-r--r-- | doc/develop/devicetree/control.rst | 2 | ||||
-rw-r--r-- | include/efi.h | 34 | ||||
-rw-r--r-- | include/efi_default_filename.h | 56 | ||||
-rw-r--r-- | include/efi_loader.h | 2 | ||||
-rw-r--r-- | lib/efi_loader/Kconfig | 10 | ||||
-rw-r--r-- | lib/efi_loader/Makefile | 1 | ||||
-rw-r--r-- | lib/efi_loader/efi_bootbin.c | 1 | ||||
-rw-r--r-- | lib/efi_loader/efi_bootmgr.c | 10 | ||||
-rw-r--r-- | lib/efi_loader/efi_device_path.c | 7 | ||||
-rw-r--r-- | lib/efi_loader/efi_helper.c | 71 | ||||
-rw-r--r-- | lib/efi_loader/testapp.c | 56 | ||||
-rw-r--r-- | lib/lmb.c | 2 | ||||
-rw-r--r-- | test/boot/bootdev.c | 18 | ||||
-rw-r--r-- | test/boot/bootflow.c | 76 | ||||
-rw-r--r-- | test/py/tests/bootstd/flash1.img.xz | bin | 0 -> 4924 bytes | |||
-rw-r--r-- | test/py/tests/test_ut.py | 53 | ||||
-rw-r--r-- | tools/mkeficapsule.c | 4 |
25 files changed, 372 insertions, 114 deletions
diff --git a/arch/Kconfig b/arch/Kconfig index 8f1f4667012..c39efb4d0a2 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -212,7 +212,8 @@ config SANDBOX imply VIRTIO_MMIO imply VIRTIO_PCI imply VIRTIO_SANDBOX - imply VIRTIO_BLK + # Re-enable this when fully implemented + # imply VIRTIO_BLK imply VIRTIO_NET imply DM_SOUND imply PCI_SANDBOX_EP diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c index 81752edc9f8..2940768cd1c 100644 --- a/arch/sandbox/cpu/start.c +++ b/arch/sandbox/cpu/start.c @@ -449,6 +449,16 @@ static void setup_ram_buf(struct sandbox_state *state) gd->ram_size = state->ram_size; } +static int sandbox_cmdline_cb_native(struct sandbox_state *state, + const char *arg) +{ + state->native = true; + + return 0; +} +SANDBOX_CMDLINE_OPT_SHORT(native, 'N', 0, + "Use native mode (host-based EFI boot filename)"); + void state_show(struct sandbox_state *state) { char **p; diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 3017b33d67b..dee280184b1 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -1515,7 +1515,7 @@ flash-stick@1 { reg = <1>; compatible = "sandbox,usb-flash"; - sandbox,filepath = "testflash1.bin"; + sandbox,filepath = "flash1.img"; }; flash-stick@2 { diff --git a/arch/sandbox/include/asm/state.h b/arch/sandbox/include/asm/state.h index e7dc01759e8..dc21a623106 100644 --- a/arch/sandbox/include/asm/state.h +++ b/arch/sandbox/include/asm/state.h @@ -101,6 +101,7 @@ struct sandbox_state { bool disable_eth; /* Disable Ethernet devices */ bool disable_sf_bootdevs; /* Don't bind SPI flash bootdevs */ bool upl; /* Enable Universal Payload (UPL) */ + bool native; /* Adjust to reflect host arch */ /* Pointer to information for each SPI bus/cs */ struct sandbox_spi_info spi[CONFIG_SANDBOX_SPI_MAX_BUS] diff --git a/boot/bootmeth_efi.c b/boot/bootmeth_efi.c index 2ad6d3b4ace..f836aa655f5 100644 --- a/boot/bootmeth_efi.c +++ b/boot/bootmeth_efi.c @@ -13,7 +13,7 @@ #include <bootmeth.h> #include <command.h> #include <dm.h> -#include <efi_default_filename.h> +#include <efi.h> #include <efi_loader.h> #include <fs.h> #include <malloc.h> @@ -25,32 +25,11 @@ #define EFI_DIRNAME "/EFI/BOOT/" -static int get_efi_pxe_arch(void) -{ - /* http://www.iana.org/assignments/dhcpv6-parameters/dhcpv6-parameters.xml */ - if (IS_ENABLED(CONFIG_ARM64)) - return 0xb; - else if (IS_ENABLED(CONFIG_ARM)) - return 0xa; - else if (IS_ENABLED(CONFIG_X86_64)) - return 0x6; - else if (IS_ENABLED(CONFIG_X86)) - return 0x7; - else if (IS_ENABLED(CONFIG_ARCH_RV32I)) - return 0x19; - else if (IS_ENABLED(CONFIG_ARCH_RV64I)) - return 0x1b; - else if (IS_ENABLED(CONFIG_SANDBOX)) - return 0; /* not used */ - - return -EINVAL; -} - static int get_efi_pxe_vci(char *str, int max_len) { int ret; - ret = get_efi_pxe_arch(); + ret = efi_get_pxe_arch(); if (ret < 0) return ret; @@ -168,7 +147,7 @@ static int distro_efi_try_bootflow_files(struct udevice *dev, } strcpy(fname, EFI_DIRNAME); - strcat(fname, BOOTEFI_NAME); + strcat(fname, efi_get_basename()); if (bflow->blk) desc = dev_get_uclass_plat(bflow->blk); @@ -239,7 +218,7 @@ static int distro_efi_read_bootflow_net(struct bootflow *bflow) ret = get_efi_pxe_vci(str, sizeof(str)); if (ret) return log_msg_ret("vci", ret); - ret = get_efi_pxe_arch(); + ret = efi_get_pxe_arch(); if (ret < 0) return log_msg_ret("arc", ret); arch = ret; diff --git a/cmd/efidebug.c b/cmd/efidebug.c index e040fe75fa1..02f1e080e88 100644 --- a/cmd/efidebug.c +++ b/cmd/efidebug.c @@ -511,6 +511,27 @@ static int do_efi_show_images(struct cmd_tbl *cmdtp, int flag, return CMD_RET_SUCCESS; } +/** + * do_efi_show_defaults() - show UEFI default filename and PXE architecture + * + * @cmdtp: Command table + * @flag: Command flag + * @argc: Number of arguments + * @argv: Argument array + * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure + * + * Implement efidebug "defaults" sub-command. + * Shows the default EFI filename and PXE architecture + */ +static int do_efi_show_defaults(struct cmd_tbl *cmdtp, int flag, + int argc, char *const argv[]) +{ + printf("Default boot path: EFI\\BOOT\\%s\n", efi_get_basename()); + printf("PXE arch: 0x%02x\n", efi_get_pxe_arch()); + + return CMD_RET_SUCCESS; +} + static const char * const efi_mem_type_string[] = { [EFI_RESERVED_MEMORY_TYPE] = "RESERVED", [EFI_LOADER_CODE] = "LOADER CODE", @@ -1561,6 +1582,8 @@ static struct cmd_tbl cmd_efidebug_sub[] = { "", ""), U_BOOT_CMD_MKENT(dh, CONFIG_SYS_MAXARGS, 1, do_efi_show_handles, "", ""), + U_BOOT_CMD_MKENT(defaults, CONFIG_SYS_MAXARGS, 1, do_efi_show_defaults, + "", ""), U_BOOT_CMD_MKENT(images, CONFIG_SYS_MAXARGS, 1, do_efi_show_images, "", ""), U_BOOT_CMD_MKENT(memmap, CONFIG_SYS_MAXARGS, 1, do_efi_show_memmap, @@ -1653,6 +1676,8 @@ U_BOOT_LONGHELP(efidebug, " - show UEFI drivers\n" "efidebug dh\n" " - show UEFI handles\n" + "efidebug defaults\n" + " - show default EFI filename and PXE architecture\n" "efidebug images\n" " - show loaded images\n" "efidebug memmap\n" diff --git a/doc/board/emulation/qemu-riscv.rst b/doc/board/emulation/qemu-riscv.rst index 8a5eb1eda56..8388e13d96d 100644 --- a/doc/board/emulation/qemu-riscv.rst +++ b/doc/board/emulation/qemu-riscv.rst @@ -171,3 +171,8 @@ The following settings provide a debug UART for the virt machine:: CONFIG_DEBUG_UART_NS16550=y CONFIG_DEBUG_UART_BASE=0x10000000 CONFIG_DEBUG_UART_CLOCK=3686400 + +To provide a debug UART in main U-Boot the SBI DBCN extension can be used +instead:: + + CONFIG_DEBUG_SBI_CONSOLE=y diff --git a/doc/conf.py b/doc/conf.py index ced3a6723fc..c50daf874a5 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -560,13 +560,9 @@ epub_exclude_files = ['search.html'] # Grouping the document tree into PDF files. List of tuples # (source start file, target name, title, author, options). # -# See the Sphinx chapter of https://ralsina.me/static/manual.pdf -# -# FIXME: Do not add the index file here; the result will be too big. Adding -# multiple PDF files here actually tries to get the cross-referencing right -# *between* PDF files. +# See https://rst2pdf.org/static/manual.html#sphinx pdf_documents = [ - ('uboot-documentation', u'U-Boot', u'U-Boot', u'J. Random Bozo'), + ('index', u'U-Boot', u'Das U-Boot', u'The U-Boot development community'), ] # kernel-doc extension configuration for running Sphinx directly (e.g. by Read diff --git a/doc/develop/devicetree/control.rst b/doc/develop/devicetree/control.rst index 211f7e4909c..0233945f8b6 100644 --- a/doc/develop/devicetree/control.rst +++ b/doc/develop/devicetree/control.rst @@ -89,7 +89,7 @@ Failing that, you could write one from scratch yourself! Resyncing with devicetree-rebasing ---------------------------------- -The `devicetree-rebasing repository`_ maintains a fork cum mirror copy of +The `devicetree-rebasing repository`_ maintains a mirror copy of devicetree files along with the bindings synced at every Linux kernel major release or intermediate release candidates. The U-Boot maintainers regularly sync the `dts/upstream/` subtree from the devicetree-rebasing repo whenever diff --git a/include/efi.h b/include/efi.h index 84640cf7b25..c559fda3004 100644 --- a/include/efi.h +++ b/include/efi.h @@ -669,4 +669,38 @@ int efi_get_mmap(struct efi_mem_desc **descp, int *sizep, uint *keyp, */ void efi_show_tables(struct efi_system_table *systab); +/** + * efi_get_basename() - Get the default filename to use when loading + * + * E.g. this function returns BOOTAA64.EFI for an aarch target + * + * Return: Default EFI filename + */ +const char *efi_get_basename(void); + +#ifdef CONFIG_SANDBOX +#include <asm/state.h> +#endif + +static inline bool efi_use_host_arch(void) +{ +#ifdef CONFIG_SANDBOX + struct sandbox_state *state = state_get_current(); + + return state->native; +#else + return false; +#endif +} + +/** + * efi_get_pxe_arch() - Get the architecture value for PXE + * + * See: + * http://www.iana.org/assignments/dhcpv6-parameters/dhcpv6-parameters.xml + * + * Return: Architecture value + */ +int efi_get_pxe_arch(void); + #endif /* _LINUX_EFI_H */ diff --git a/include/efi_default_filename.h b/include/efi_default_filename.h deleted file mode 100644 index 77932984b55..00000000000 --- a/include/efi_default_filename.h +++ /dev/null @@ -1,56 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * When a boot option does not provide a file path the EFI file to be - * booted is \EFI\BOOT\$(BOOTEFI_NAME).EFI. The architecture specific - * file name is defined in this include. - * - * Copyright (c) 2022, Heinrich Schuchardt <xypron.glpk@gmx.de> - * Copyright (c) 2022, Linaro Limited - */ - -#ifndef _EFI_DEFAULT_FILENAME_H -#define _EFI_DEFAULT_FILENAME_H - -#include <host_arch.h> - -#undef BOOTEFI_NAME - -#ifdef CONFIG_SANDBOX - -#if HOST_ARCH == HOST_ARCH_X86_64 -#define BOOTEFI_NAME "BOOTX64.EFI" -#elif HOST_ARCH == HOST_ARCH_X86 -#define BOOTEFI_NAME "BOOTIA32.EFI" -#elif HOST_ARCH == HOST_ARCH_AARCH64 -#define BOOTEFI_NAME "BOOTAA64.EFI" -#elif HOST_ARCH == HOST_ARCH_ARM -#define BOOTEFI_NAME "BOOTARM.EFI" -#elif HOST_ARCH == HOST_ARCH_RISCV32 -#define BOOTEFI_NAME "BOOTRISCV32.EFI" -#elif HOST_ARCH == HOST_ARCH_RISCV64 -#define BOOTEFI_NAME "BOOTRISCV64.EFI" -#else -#error Unsupported UEFI architecture -#endif - -#else - -#if defined(CONFIG_ARM64) -#define BOOTEFI_NAME "BOOTAA64.EFI" -#elif defined(CONFIG_ARM) -#define BOOTEFI_NAME "BOOTARM.EFI" -#elif defined(CONFIG_X86_64) -#define BOOTEFI_NAME "BOOTX64.EFI" -#elif defined(CONFIG_X86) -#define BOOTEFI_NAME "BOOTIA32.EFI" -#elif defined(CONFIG_ARCH_RV32I) -#define BOOTEFI_NAME "BOOTRISCV32.EFI" -#elif defined(CONFIG_ARCH_RV64I) -#define BOOTEFI_NAME "BOOTRISCV64.EFI" -#else -#error Unsupported UEFI architecture -#endif - -#endif - -#endif diff --git a/include/efi_loader.h b/include/efi_loader.h index 291eca5c077..39809eac1bc 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -858,7 +858,7 @@ struct efi_device_path *efi_dp_from_file(const struct efi_device_path *dp, struct efi_device_path *efi_dp_from_eth(void); struct efi_device_path *efi_dp_from_mem(uint32_t mem_type, uint64_t start_address, - uint64_t end_address); + size_t size); /* Determine the last device path node that is not the end node. */ const struct efi_device_path *efi_dp_last_node( const struct efi_device_path *dp); diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index 066f0ca0da7..58d49789f12 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -567,6 +567,16 @@ config BOOTEFI_HELLO_COMPILE No additional space will be required in the resulting U-Boot binary when this option is enabled. +config BOOTEFI_TESTAPP_COMPILE + bool "Compile an EFI test app for testing" + default y + help + This compiles an app designed for testing. It is packed into an image + by the test.py testing frame in the setup_efi_image() function. + + No additional space will be required in the resulting U-Boot binary + when this option is enabled. + endif source "lib/efi/Kconfig" diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index 00d18966f9e..87131ab911d 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -20,6 +20,7 @@ apps-$(CONFIG_EFI_LOAD_FILE2_INITRD) += initrddump ifeq ($(CONFIG_GENERATE_ACPI_TABLE),) apps-y += dtbdump endif +apps-$(CONFIG_BOOTEFI_TESTAPP_COMPILE) += testapp obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o obj-$(CONFIG_EFI_BOOTMGR) += efi_bootmgr.o diff --git a/lib/efi_loader/efi_bootbin.c b/lib/efi_loader/efi_bootbin.c index bf38392fac3..a87006b3c0e 100644 --- a/lib/efi_loader/efi_bootbin.c +++ b/lib/efi_loader/efi_bootbin.c @@ -137,7 +137,6 @@ efi_status_t efi_run_image(void *source_buffer, efi_uintn_t source_size) */ file_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE, (uintptr_t)source_buffer, - (uintptr_t)source_buffer + source_size); /* * Make sure that device for device_path exist diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c index f9b5988a06e..8c51a6ef2ed 100644 --- a/lib/efi_loader/efi_bootmgr.c +++ b/lib/efi_loader/efi_bootmgr.c @@ -11,10 +11,10 @@ #include <blkmap.h> #include <charset.h> #include <dm.h> +#include <efi.h> #include <log.h> #include <malloc.h> #include <net.h> -#include <efi_default_filename.h> #include <efi_loader.h> #include <efi_variable.h> #include <asm/unaligned.h> @@ -82,8 +82,12 @@ struct efi_device_path *expand_media_path(struct efi_device_path *device_path) &efi_simple_file_system_protocol_guid, &rem); if (handle) { if (rem->type == DEVICE_PATH_TYPE_END) { - full_path = efi_dp_from_file(device_path, - "/EFI/BOOT/" BOOTEFI_NAME); + char fname[30]; + + snprintf(fname, sizeof(fname), "/EFI/BOOT/%s", + efi_get_basename()); + full_path = efi_dp_from_file(device_path, fname); + } else { full_path = efi_dp_dup(device_path); } diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index d7444588aa0..ee387e1dfd4 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -977,7 +977,7 @@ struct efi_device_path __maybe_unused *efi_dp_from_eth(void) /* Construct a device-path for memory-mapped image */ struct efi_device_path *efi_dp_from_mem(uint32_t memory_type, uint64_t start_address, - uint64_t end_address) + size_t size) { struct efi_device_path_memory *mdp; void *buf, *start; @@ -992,7 +992,7 @@ struct efi_device_path *efi_dp_from_mem(uint32_t memory_type, mdp->dp.length = sizeof(*mdp); mdp->memory_type = memory_type; mdp->start_address = start_address; - mdp->end_address = end_address; + mdp->end_address = start_address + size; buf = &mdp[1]; *((struct efi_device_path *)buf) = END; @@ -1073,8 +1073,7 @@ efi_status_t efi_dp_from_name(const char *dev, const char *devnr, efi_get_image_parameters(&image_addr, &image_size); dp = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE, - (uintptr_t)image_addr, - (uintptr_t)image_addr + image_size); + (uintptr_t)image_addr, image_size); } else if (IS_ENABLED(CONFIG_NETDEVICES) && !strcmp(dev, "Net")) { dp = efi_dp_from_eth(); } else if (!strcmp(dev, "Uart")) { diff --git a/lib/efi_loader/efi_helper.c b/lib/efi_loader/efi_helper.c index 00167bd2a10..bf96f61d3d0 100644 --- a/lib/efi_loader/efi_helper.c +++ b/lib/efi_loader/efi_helper.c @@ -12,18 +12,89 @@ #include <mapmem.h> #include <dm.h> #include <fs.h> +#include <efi.h> #include <efi_api.h> #include <efi_load_initrd.h> #include <efi_loader.h> #include <efi_variable.h> +#include <host_arch.h> #include <linux/libfdt.h> #include <linux/list.h> +#undef BOOTEFI_NAME + +#if HOST_ARCH == HOST_ARCH_X86_64 +#define HOST_BOOTEFI_NAME "BOOTX64.EFI" +#define HOST_PXE_ARCH 0x6 +#elif HOST_ARCH == HOST_ARCH_X86 +#define HOST_BOOTEFI_NAME "BOOTIA32.EFI" +#define HOST_PXE_ARCH 0x7 +#elif HOST_ARCH == HOST_ARCH_AARCH64 +#define HOST_BOOTEFI_NAME "BOOTAA64.EFI" +#define HOST_PXE_ARCH 0xb +#elif HOST_ARCH == HOST_ARCH_ARM +#define HOST_BOOTEFI_NAME "BOOTARM.EFI" +#define HOST_PXE_ARCH 0xa +#elif HOST_ARCH == HOST_ARCH_RISCV32 +#define HOST_BOOTEFI_NAME "BOOTRISCV32.EFI" +#define HOST_PXE_ARCH 0x19 +#elif HOST_ARCH == HOST_ARCH_RISCV64 +#define HOST_BOOTEFI_NAME "BOOTRISCV64.EFI" +#define HOST_PXE_ARCH 0x1b +#else +#error Unsupported Host architecture +#endif + +#if defined(CONFIG_SANDBOX) +#define BOOTEFI_NAME "BOOTSBOX.EFI" +#elif defined(CONFIG_ARM64) +#define BOOTEFI_NAME "BOOTAA64.EFI" +#elif defined(CONFIG_ARM) +#define BOOTEFI_NAME "BOOTARM.EFI" +#elif defined(CONFIG_X86_64) +#define BOOTEFI_NAME "BOOTX64.EFI" +#elif defined(CONFIG_X86) +#define BOOTEFI_NAME "BOOTIA32.EFI" +#elif defined(CONFIG_ARCH_RV32I) +#define BOOTEFI_NAME "BOOTRISCV32.EFI" +#elif defined(CONFIG_ARCH_RV64I) +#define BOOTEFI_NAME "BOOTRISCV64.EFI" +#else +#error Unsupported UEFI architecture +#endif + #if defined(CONFIG_CMD_EFIDEBUG) || defined(CONFIG_EFI_LOAD_FILE2_INITRD) /* GUID used by Linux to identify the LoadFile2 protocol with the initrd */ const efi_guid_t efi_lf2_initrd_guid = EFI_INITRD_MEDIA_GUID; #endif +const char *efi_get_basename(void) +{ + return efi_use_host_arch() ? HOST_BOOTEFI_NAME : BOOTEFI_NAME; +} + +int efi_get_pxe_arch(void) +{ + if (efi_use_host_arch()) + return HOST_PXE_ARCH; + + /* http://www.iana.org/assignments/dhcpv6-parameters/dhcpv6-parameters.xml */ + if (IS_ENABLED(CONFIG_ARM64)) + return 0xb; + else if (IS_ENABLED(CONFIG_ARM)) + return 0xa; + else if (IS_ENABLED(CONFIG_X86_64)) + return 0x6; + else if (IS_ENABLED(CONFIG_X86)) + return 0x7; + else if (IS_ENABLED(CONFIG_ARCH_RV32I)) + return 0x19; + else if (IS_ENABLED(CONFIG_ARCH_RV64I)) + return 0x1b; + + return -EINVAL; +} + /** * efi_create_current_boot_var() - Return Boot#### name were #### is replaced by * the value of BootCurrent diff --git a/lib/efi_loader/testapp.c b/lib/efi_loader/testapp.c new file mode 100644 index 00000000000..804ca7e4679 --- /dev/null +++ b/lib/efi_loader/testapp.c @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * EFI test application + * + * Copyright 2024 Google LLC + * Written by Simon Glass <sjg@chromium.org> + * + * This test program is used to test the invocation of an EFI application. + * It writes a few messages to the console and then exits boot services + */ + +#include <efi_api.h> + +static const efi_guid_t loaded_image_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID; + +static struct efi_system_table *systable; +static struct efi_boot_services *boottime; +static struct efi_simple_text_output_protocol *con_out; + +/** + * efi_main() - entry point of the EFI application. + * + * @handle: handle of the loaded image + * @systab: system table + * Return: status code + */ +efi_status_t EFIAPI efi_main(efi_handle_t handle, + struct efi_system_table *systab) +{ + struct efi_loaded_image *loaded_image; + efi_status_t ret; + + systable = systab; + boottime = systable->boottime; + con_out = systable->con_out; + + /* Get the loaded image protocol */ + ret = boottime->open_protocol(handle, &loaded_image_guid, + (void **)&loaded_image, NULL, NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (ret != EFI_SUCCESS) { + con_out->output_string + (con_out, u"Cannot open loaded image protocol\r\n"); + goto out; + } + + /* UEFI requires CR LF */ + con_out->output_string(con_out, u"U-Boot test app for EFI_LOADER\r\n"); + +out: + con_out->output_string(con_out, u"Exiting test app\n"); + ret = boottime->exit(handle, ret, 0, NULL); + + /* We should never arrive here */ + return ret; +} diff --git a/lib/lmb.c b/lib/lmb.c index 2ed0da21b45..8b306e4de8e 100644 --- a/lib/lmb.c +++ b/lib/lmb.c @@ -220,8 +220,6 @@ static void lmb_reserve_uboot_region(void) */ debug("## Current stack ends at 0x%08lx ", (ulong)rsv_start); - /* adjust sp by 16K to be safe */ - rsv_start -= SZ_16K; for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) { if (!gd->bd->bi_dram[bank].size || rsv_start < gd->bd->bi_dram[bank].start) diff --git a/test/boot/bootdev.c b/test/boot/bootdev.c index 369c611d924..8c44afd9297 100644 --- a/test/boot/bootdev.c +++ b/test/boot/bootdev.c @@ -221,6 +221,10 @@ static int bootdev_test_order(struct unit_test_state *uts) /* Use the environment variable to override it */ ut_assertok(env_set("boot_targets", "mmc1 mmc2 usb")); ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow)); + + /* get the usb device which has a backing file (flash1.img) */ + ut_asserteq(0, bootflow_scan_next(&iter, &bflow)); + ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow)); ut_asserteq(5, iter.num_devs); ut_asserteq_str("mmc1.bootdev", iter.dev_used[0]->name); @@ -260,7 +264,11 @@ static int bootdev_test_order(struct unit_test_state *uts) ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow)); ut_asserteq(2, iter.num_devs); - /* Now scan past mmc1 and make sure that the 3 USB devices show up */ + /* + * Now scan past mmc1 and make sure that the 3 USB devices show up. The + * first one has a backing file so returns success + */ + ut_asserteq(0, bootflow_scan_next(&iter, &bflow)); ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow)); ut_asserteq(6, iter.num_devs); ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name); @@ -322,6 +330,10 @@ static int bootdev_test_prio(struct unit_test_state *uts) /* 3 MMC and 3 USB bootdevs: MMC should come before USB */ ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow)); + + /* get the usb device which has a backing file (flash1.img) */ + ut_asserteq(0, bootflow_scan_next(&iter, &bflow)); + ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow)); ut_asserteq(6, iter.num_devs); ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name); @@ -339,6 +351,10 @@ static int bootdev_test_prio(struct unit_test_state *uts) bootflow_iter_uninit(&iter); ut_assertok(bootflow_scan_first(NULL, NULL, &iter, BOOTFLOWIF_HUNT, &bflow)); + + /* get the usb device which has a backing file (flash1.img) */ + ut_asserteq(0, bootflow_scan_next(&iter, &bflow)); + ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow)); ut_asserteq(7, iter.num_devs); ut_asserteq_str("usb_mass_storage.lun0.bootdev", diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c index 2f859c40adb..9397328609d 100644 --- a/test/boot/bootflow.c +++ b/test/boot/bootflow.c @@ -12,7 +12,8 @@ #include <bootstd.h> #include <cli.h> #include <dm.h> -#include <efi_default_filename.h> +#include <efi.h> +#include <efi_loader.h> #include <expo.h> #ifdef CONFIG_SANDBOX #include <asm/test.h> @@ -31,6 +32,9 @@ extern U_BOOT_DRIVER(bootmeth_android); extern U_BOOT_DRIVER(bootmeth_cros); extern U_BOOT_DRIVER(bootmeth_2script); +/* Use this as the vendor for EFI to tell the app to exit boot services */ +static u16 __efi_runtime_data test_vendor[] = u"U-Boot testing"; + static int inject_response(struct unit_test_state *uts) { /* @@ -184,8 +188,9 @@ static int bootflow_cmd_scan_e(struct unit_test_state *uts) ut_assert_nextline(" 3 efi media mmc 0 mmc1.bootdev.whole "); ut_assert_nextline(" ** No partition found, err=-2: No such file or directory"); ut_assert_nextline(" 4 extlinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf"); - ut_assert_nextline(" 5 efi fs mmc 1 mmc1.bootdev.part_1 /EFI/BOOT/" - BOOTEFI_NAME); + ut_assert_nextline( + " 5 efi fs mmc 1 mmc1.bootdev.part_1 /EFI/BOOT/%s", + efi_get_basename()); ut_assert_skip_to_line("Scanning bootdev 'mmc0.bootdev':"); ut_assert_skip_to_line( @@ -533,7 +538,7 @@ static int prep_mmc_bootdev(struct unit_test_state *uts, const char *mmc_dev, order[2] = mmc_dev; - /* Enable the mmc4 node since we need a second bootflow */ + /* Enable the requested mmc node since we need a second bootflow */ root = oftree_root(oftree_default()); node = ofnode_find_subnode(root, mmc_dev); ut_assert(ofnode_valid(node)); @@ -1216,3 +1221,66 @@ static int bootflow_android(struct unit_test_state *uts) return 0; } BOOTSTD_TEST(bootflow_android, UTF_CONSOLE); + +/* Test EFI bootmeth */ +static int bootflow_efi(struct unit_test_state *uts) +{ + static const char *order[] = {"mmc1", "usb", NULL}; + struct bootstd_priv *std; + struct udevice *bootstd; + const char **old_order; + + ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd)); + std = dev_get_priv(bootstd); + old_order = std->bootdev_order; + std->bootdev_order = order; + + /* disable ethernet since the hunter will run dhcp */ + test_set_eth_enable(false); + + /* make USB scan without delays */ + test_set_skip_delays(true); + + bootstd_reset_usb(); + + ut_assertok(run_command("bootflow scan", 0)); + ut_assert_skip_to_line( + "Bus usb@1: scanning bus usb@1 for devices... 5 USB Device(s) found"); + + ut_assertok(run_command("bootflow list", 0)); + + ut_assert_nextlinen("Showing all"); + ut_assert_nextlinen("Seq"); + ut_assert_nextlinen("---"); + ut_assert_nextlinen(" 0 extlinux"); + ut_assert_nextlinen( + " 1 efi ready usb_mass_ 1 usb_mass_storage.lun0.boo /EFI/BOOT/BOOTSBOX.EFI"); + ut_assert_nextlinen("---"); + ut_assert_skip_to_line("(2 bootflows, 2 valid)"); + ut_assert_console_end(); + + ut_assertok(run_command("bootflow select 1", 0)); + ut_assert_console_end(); + + systab.fw_vendor = test_vendor; + + ut_asserteq(1, run_command("bootflow boot", 0)); + ut_assert_nextline( + "** Booting bootflow 'usb_mass_storage.lun0.bootdev.part_1' with efi"); + if (IS_ENABLED(CONFIG_LOGF_FUNC)) + ut_assert_skip_to_line(" efi_run_image() Booting /\\EFI\\BOOT\\BOOTSBOX.EFI"); + else + ut_assert_skip_to_line("Booting /\\EFI\\BOOT\\BOOTSBOX.EFI"); + + /* TODO: Why the \r ? */ + ut_assert_nextline("U-Boot test app for EFI_LOADER\r"); + ut_assert_nextline("Exiting test app"); + ut_assert_nextline("Boot failed (err=-14)"); + + ut_assert_console_end(); + + ut_assertok(bootstd_test_drop_bootdev_order(uts)); + + return 0; +} +BOOTSTD_TEST(bootflow_efi, UTF_CONSOLE); diff --git a/test/py/tests/bootstd/flash1.img.xz b/test/py/tests/bootstd/flash1.img.xz Binary files differnew file mode 100644 index 00000000000..29b78c62a9b --- /dev/null +++ b/test/py/tests/bootstd/flash1.img.xz diff --git a/test/py/tests/test_ut.py b/test/py/tests/test_ut.py index 9166c8f6b6e..6d44191976b 100644 --- a/test/py/tests/test_ut.py +++ b/test/py/tests/test_ut.py @@ -28,21 +28,22 @@ def mkdir_cond(dirname): if not os.path.exists(dirname): os.mkdir(dirname) -def setup_image(cons, mmc_dev, part_type, second_part=False): +def setup_image(cons, devnum, part_type, second_part=False, basename='mmc'): """Create a 20MB disk image with a single partition Args: cons (ConsoleBase): Console to use - mmc_dev (int): MMC device number to use, e.g. 1 + devnum (int): Device number to use, e.g. 1 part_type (int): Partition type, e.g. 0xc for FAT32 second_part (bool): True to contain a small second partition + basename (str): Base name to use in the filename, e.g. 'mmc' Returns: tuple: str: Filename of MMC image str: Directory name of 'mnt' directory """ - fname = os.path.join(cons.config.source_dir, f'mmc{mmc_dev}.img') + fname = os.path.join(cons.config.source_dir, f'{basename}{devnum}.img') mnt = os.path.join(cons.config.persistent_data_dir, 'mnt') mkdir_cond(mnt) @@ -78,16 +79,17 @@ def mount_image(cons, fname, mnt, fstype): u_boot_utils.run_and_log(cons, f'sudo chown {getpass.getuser()} {mnt}') return loop -def copy_prepared_image(cons, mmc_dev, fname): +def copy_prepared_image(cons, devnum, fname, basename='mmc'): """Use a prepared image since we cannot create one Args: cons (ConsoleBase): Console touse - mmc_dev (int): MMC device number + devnum (int): device number fname (str): Filename of MMC image + basename (str): Base name to use in the filename, e.g. 'mmc' """ infname = os.path.join(cons.config.source_dir, - f'test/py/tests/bootstd/mmc{mmc_dev}.img.xz') + f'test/py/tests/bootstd/{basename}{devnum}.img.xz') u_boot_utils.run_and_log(cons, ['sh', '-c', f'xz -dc {infname} >{fname}']) def setup_bootmenu_image(cons): @@ -547,6 +549,44 @@ def test_ut_dm_init(u_boot_console): with open(fn, 'wb') as fh: fh.write(data) + +def setup_efi_image(cons): + """Create a 20MB disk image with an EFI app on it""" + devnum = 1 + basename = 'flash' + fname, mnt = setup_image(cons, devnum, 0xc, second_part=True, + basename=basename) + + loop = None + mounted = False + complete = False + try: + loop = mount_image(cons, fname, mnt, 'ext4') + mounted = True + efi_dir = os.path.join(mnt, 'EFI') + mkdir_cond(efi_dir) + bootdir = os.path.join(efi_dir, 'BOOT') + mkdir_cond(bootdir) + efi_src = os.path.join(cons.config.build_dir, + f'lib/efi_loader/testapp.efi') + efi_dst = os.path.join(bootdir, 'BOOTSBOX.EFI') + with open(efi_src, 'rb') as inf: + with open(efi_dst, 'wb') as outf: + outf.write(inf.read()) + complete = True + except ValueError as exc: + print(f'Falled to create image, failing back to prepared copy: {exc}') + + finally: + if mounted: + u_boot_utils.run_and_log(cons, 'sudo umount --lazy %s' % mnt) + if loop: + u_boot_utils.run_and_log(cons, 'sudo losetup -d %s' % loop) + + if not complete: + copy_prepared_image(cons, devnum, fname, basename) + + @pytest.mark.buildconfigspec('cmd_bootflow') @pytest.mark.buildconfigspec('sandbox') def test_ut_dm_init_bootstd(u_boot_console): @@ -557,6 +597,7 @@ def test_ut_dm_init_bootstd(u_boot_console): setup_cedit_file(u_boot_console) setup_cros_image(u_boot_console) setup_android_image(u_boot_console) + setup_efi_image(u_boot_console) # Restart so that the new mmc1.img is picked up u_boot_console.restart_uboot() diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c index 49f5b7849e4..fb6c57f77c1 100644 --- a/tools/mkeficapsule.c +++ b/tools/mkeficapsule.c @@ -866,12 +866,12 @@ static struct fdt_header *load_dtb(const char *path) dtb = malloc(dtb_size); if (!dtb) { - fprintf(stderr, "Can't allocated %ld\n", dtb_size); + fprintf(stderr, "Can't allocated %zd\n", dtb_size); return NULL; } if (fread(dtb, dtb_size, 1, f) != 1) { - fprintf(stderr, "Can't read %ld bytes from %s\n", + fprintf(stderr, "Can't read %zd bytes from %s\n", dtb_size, path); free(dtb); return NULL; |