[PATCH 00/18] efi: Improve integration of the app with a Shim environment

From: Simon Glass <sjg@chromium.org> This series collects together various small fixes and improvements which make it easier to use the U-Boot EFI app in a bootflow which includes Shim: - 'Reset' back to the caller (e.g. EDK2) - Machine reset using cold and warm reset - Reset and enter the firmware UI - Shim command now supports persistent debug - Bootmenu shows the real media for each bootflow rather than just 'efi' Simon Glass (18): efi: Correct calculate_paths() when an image is used efi: doc: Mention some EFI commands in the app documentation efi: Allow inclusion of EFI-runtime headers efi: Set the log category throughout lib/efi_client/ efi_loader: Drop unnecessary efi_dp_str() efi: Move loaded-image, fs and device-path GUIDs to common boot: Move obtaining the label into a common file boot: Use the new label finder in bootflow_menu_add() boot: Drop an unwanted blank line in distro_efi_boot() efidebug: doc: Indent the media output correctly efidebug: Support sorting with efidebug memmap efi: doc: Add documentation for about efidebug boot efi: Use the console mux by default with the EFI app shim: Add a flag to make the setting persistent sysreset: Support a hot reset efi: app: Support proper reset options sysreset: Add SYSRESET_TO_FIRMWARE_UI with reset -u support sysreset: Add -c flag for explicit cold reset boot/bootflow.c | 27 +++++ boot/bootflow_menu.c | 7 +- boot/bootmeth_efi.c | 1 - cmd/boot.c | 2 + cmd/bootflow.c | 16 +-- cmd/efidebug.c | 58 +++++++++- cmd/shim.c | 21 +++- doc/develop/uefi/u-boot_on_efi.rst | 9 ++ doc/usage/cmd/efidebug.rst | 171 ++++++++++++++++++++++++++-- doc/usage/cmd/reset.rst | 12 +- doc/usage/cmd/shim.rst | 16 ++- drivers/sysreset/sysreset-uclass.c | 18 ++- drivers/sysreset/sysreset_sandbox.c | 2 + include/bootflow.h | 8 ++ include/efi.h | 11 ++ include/efi_loader.h | 6 - include/sysreset.h | 5 + lib/efi/run.c | 2 +- lib/efi_client/Kconfig | 1 + lib/efi_client/app_run.c | 2 + lib/efi_client/efi.c | 2 + lib/efi_client/efi_app.c | 43 ++++++- lib/efi_client/efi_info.c | 2 + lib/efi_client/efi_vars.c | 2 + lib/efi_client/sdram.c | 2 + lib/efi_client/stub.c | 2 + lib/efi_client/stub_arm64.c | 1 + lib/efi_client/stub_x86.c | 2 + lib/efi_client/sync_dt.c | 2 + test/boot/bootflow.c | 4 +- test/dm/sysreset.c | 4 + 31 files changed, 403 insertions(+), 58 deletions(-) -- 2.43.0 base-commit: 1dd869d9bacb5f9bf6d6075159226dc36c8c7cbb branch: apc

From: Simon Glass <sjg@chromium.org> The device path is updated if an image is used, so move the setting of *device_pathp lower, to take account of this. Signed-off-by: Simon Glass <sjg@chromium.org> Fixes: 73ad2d99093 ("efi: Move efi_bootflow_run() to a common file") --- lib/efi/run.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/efi/run.c b/lib/efi/run.c index 4f47743476d..1903d6f0b9a 100644 --- a/lib/efi/run.c +++ b/lib/efi/run.c @@ -46,7 +46,6 @@ efi_status_t calculate_paths(const char *dev, const char *devnr, if (ret != EFI_SUCCESS) return ret; - *device_pathp = device; if (image) { /* FIXME: image should not contain device */ struct efi_device_path *image_tmp = image; @@ -54,6 +53,7 @@ efi_status_t calculate_paths(const char *dev, const char *devnr, efi_dp_split_file_path(image, &device, &image); efi_free_pool(image_tmp); } + *device_pathp = device; *image_pathp = image; log_debug("- boot device %pD\n", device); if (image) -- 2.43.0

From: Simon Glass <sjg@chromium.org> It is not obvious what commands can be used in the app. Add some links. Signed-off-by: Simon Glass <sjg@chromium.org> --- doc/develop/uefi/u-boot_on_efi.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/doc/develop/uefi/u-boot_on_efi.rst b/doc/develop/uefi/u-boot_on_efi.rst index 845d04d7826..451a6e71fc3 100644 --- a/doc/develop/uefi/u-boot_on_efi.rst +++ b/doc/develop/uefi/u-boot_on_efi.rst @@ -431,6 +431,15 @@ board/efi/efi-x86_payload common/cmd_efi.c the 'efi' command +Available commands +------------------ + +See :doc:`/usage/cmd/efidebug` and :doc:`/usage/cmd/efi` for useful commands +available in the EFI app. When Shim_ is in the bootflow, the +:doc:`/usage/cmd/shim` may be useful. + +.. _`Shim`: https://github.com/rhboot/shim + -- Ben Stoltz, Simon Glass Google, Inc -- 2.43.0

From: Simon Glass <sjg@chromium.org> Some headers use the __efi_runtime macro in their declarations. With the app we do not have a separate runtime sections, so define this to be empty. This allows the headers to be included from the app. Signed-off-by: Simon Glass <sjg@chromium.org> --- include/efi.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/efi.h b/include/efi.h index 6c2c1f815dd..6caa51c38a7 100644 --- a/include/efi.h +++ b/include/efi.h @@ -58,6 +58,11 @@ struct udevice; #define EFI32_LOADER_SIGNATURE "EL32" #define EFI64_LOADER_SIGNATURE "EL64" +#ifdef CONFIG_EFI_APP +/* add an empty value for this so that efi_variables.h can be included */ +#define __efi_runtime +#endif + /** * struct efi_device_path - device path protocol * -- 2.43.0

From: Simon Glass <sjg@chromium.org> All files in this directory relate to EFI, so set the log category consistently. Signed-off-by: Simon Glass <sjg@chromium.org> --- lib/efi_client/app_run.c | 2 ++ lib/efi_client/efi.c | 2 ++ lib/efi_client/efi_info.c | 2 ++ lib/efi_client/efi_vars.c | 2 ++ lib/efi_client/sdram.c | 2 ++ lib/efi_client/stub.c | 2 ++ lib/efi_client/stub_arm64.c | 1 + lib/efi_client/stub_x86.c | 2 ++ lib/efi_client/sync_dt.c | 2 ++ 9 files changed, 17 insertions(+) diff --git a/lib/efi_client/app_run.c b/lib/efi_client/app_run.c index 9fc753ceed8..de2c6b8bdd2 100644 --- a/lib/efi_client/app_run.c +++ b/lib/efi_client/app_run.c @@ -6,6 +6,8 @@ * Copyright 2024 Canonical Ltd */ +#define LOG_CATEGORY LOGC_EFI + #include <bootm.h> #include <dm.h> #include <efi.h> diff --git a/lib/efi_client/efi.c b/lib/efi_client/efi.c index 12a646a36b7..083ad1f423c 100644 --- a/lib/efi_client/efi.c +++ b/lib/efi_client/efi.c @@ -10,6 +10,8 @@ * Common EFI functions */ +#define LOG_CATEGORY LOGC_EFI + #include <debug_uart.h> #include <errno.h> #include <malloc.h> diff --git a/lib/efi_client/efi_info.c b/lib/efi_client/efi_info.c index a0d7d3b5d7d..5ff98e8829e 100644 --- a/lib/efi_client/efi_info.c +++ b/lib/efi_client/efi_info.c @@ -5,6 +5,8 @@ * Access to the EFI information table */ +#define LOG_CATEGORY LOGC_EFI + #include <efi.h> #include <efi_loader.h> #include <efi_stub.h> diff --git a/lib/efi_client/efi_vars.c b/lib/efi_client/efi_vars.c index 4fc48b90d6c..9764a9802a4 100644 --- a/lib/efi_client/efi_vars.c +++ b/lib/efi_client/efi_vars.c @@ -4,6 +4,8 @@ * */ +#define LOG_CATEGORY LOGC_EFI + #define __efi_runtime #include <errno.h> diff --git a/lib/efi_client/sdram.c b/lib/efi_client/sdram.c index bd59dfade0f..357ca095f86 100644 --- a/lib/efi_client/sdram.c +++ b/lib/efi_client/sdram.c @@ -3,6 +3,8 @@ * Copyright (c) 2015 Google, Inc */ +#define LOG_CATEGORY LOGC_EFI + #include <efi.h> #include <init.h> #include <asm/global_data.h> diff --git a/lib/efi_client/stub.c b/lib/efi_client/stub.c index 01d62c3e5c9..3e3ea91f915 100644 --- a/lib/efi_client/stub.c +++ b/lib/efi_client/stub.c @@ -8,6 +8,8 @@ * Provides helper functions for use with the stub */ +#define LOG_CATEGORY LOGC_EFI + #include <debug_uart.h> #include <efi.h> #include <efi_api.h> diff --git a/lib/efi_client/stub_arm64.c b/lib/efi_client/stub_arm64.c index 0e579a17a75..3184be64cd0 100644 --- a/lib/efi_client/stub_arm64.c +++ b/lib/efi_client/stub_arm64.c @@ -9,6 +9,7 @@ * Call ExitBootServices() and launch U-Boot from an EFI environment. */ +#define LOG_CATEGORY LOGC_EFI #include <debug_uart.h> #include <efi.h> #include <efi_api.h> diff --git a/lib/efi_client/stub_x86.c b/lib/efi_client/stub_x86.c index fac55fa8f32..b223c36c798 100644 --- a/lib/efi_client/stub_x86.c +++ b/lib/efi_client/stub_x86.c @@ -9,6 +9,8 @@ * EFI application. It can be built either in 32-bit or 64-bit mode. */ +#define LOG_CATEGORY LOGC_EFI + #include <debug_uart.h> #include <efi.h> #include <efi_api.h> diff --git a/lib/efi_client/sync_dt.c b/lib/efi_client/sync_dt.c index f191a31125f..44627451dae 100644 --- a/lib/efi_client/sync_dt.c +++ b/lib/efi_client/sync_dt.c @@ -5,6 +5,8 @@ * Copyright 2025 Simon Glass <sjg@chromium.org> */ +#define LOG_CATEGORY LOGC_EFI + #include <efi.h> #include <efi_api.h> #include <fdt_support.h> -- 2.43.0

From: Simon Glass <sjg@chromium.org> This declaration already exists in efi.h so drop it from this header. Signed-off-by: Simon Glass <sjg@chromium.org> --- include/efi_loader.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/efi_loader.h b/include/efi_loader.h index 52314c33533..57bf508adb9 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -302,8 +302,6 @@ extern const struct efi_hii_config_access_protocol efi_hii_config_access; extern const struct efi_hii_database_protocol efi_hii_database; extern const struct efi_hii_string_protocol efi_hii_string; -uint16_t *efi_dp_str(struct efi_device_path *dp); - /* GUID for the auto generated boot menu entry */ extern const efi_guid_t efi_guid_bootmenu_auto_generated; -- 2.43.0

From: Simon Glass <sjg@chromium.org> Allow these to be used from the app, when EFI_LOADER is disabled. Signed-off-by: Simon Glass <sjg@chromium.org> --- include/efi.h | 6 ++++++ include/efi_loader.h | 4 ---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/include/efi.h b/include/efi.h index 6caa51c38a7..e9ca4840352 100644 --- a/include/efi.h +++ b/include/efi.h @@ -171,6 +171,12 @@ extern const efi_guid_t efi_guid_image_security_database; /* Access to Shim variables */ extern const efi_guid_t efi_shim_lock; +extern const efi_guid_t efi_guid_loaded_image; +extern const efi_guid_t efi_guid_loaded_image_device_path; +extern const efi_guid_t efi_guid_device_path; + +extern const efi_guid_t efi_simple_file_system_protocol_guid; + /* Generic EFI table header */ struct efi_table_hdr { u64 signature; diff --git a/include/efi_loader.h b/include/efi_loader.h index 57bf508adb9..2caaaf56e3e 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -316,7 +316,6 @@ extern const efi_guid_t efi_block_io_guid; /* GUID of the EFI_SIMPLE_NETWORK_PROTOCOL */ extern const efi_guid_t efi_net_guid; extern const efi_guid_t efi_guid_console_control; -extern const efi_guid_t efi_guid_device_path; /* GUID of the EFI system partition */ extern const efi_guid_t efi_system_partition_guid; /* event group ExitBootServices() invoked */ @@ -331,10 +330,7 @@ extern const efi_guid_t efi_guid_event_group_ready_to_boot; extern const efi_guid_t efi_guid_event_group_reset_system; /* event group return to efibootmgr */ extern const efi_guid_t efi_guid_event_group_return_to_efibootmgr; -extern const efi_guid_t efi_guid_loaded_image; -extern const efi_guid_t efi_guid_loaded_image_device_path; extern const efi_guid_t efi_guid_device_path_to_text_protocol; -extern const efi_guid_t efi_simple_file_system_protocol_guid; extern const efi_guid_t efi_file_info_guid; /* GUID for file system information */ extern const efi_guid_t efi_file_system_info_guid; -- 2.43.0

From: Simon Glass <sjg@chromium.org> The 'bootflow list' command supports looking at the EFI device-path when available. Move this piece into a common function so it can be used elsewhere. This updates the output from 'bootflow list'. Signed-off-by: Simon Glass <sjg@chromium.org> --- boot/bootflow.c | 27 +++++++++++++++++++++++++++ cmd/bootflow.c | 16 +--------------- include/bootflow.h | 8 ++++++++ test/boot/bootflow.c | 4 ++-- 4 files changed, 38 insertions(+), 17 deletions(-) diff --git a/boot/bootflow.c b/boot/bootflow.c index c088300ea96..c8391641001 100644 --- a/boot/bootflow.c +++ b/boot/bootflow.c @@ -11,6 +11,7 @@ #include <bootmeth.h> #include <bootstd.h> #include <dm.h> +#include <efi_device_path.h> #include <env_internal.h> #include <malloc.h> #include <serial.h> @@ -1024,3 +1025,29 @@ int bootflow_get_seq(const struct bootflow *bflow) return alist_calc_index(&std->bootflows, bflow); } + +const char *bootflow_guess_label(const struct bootflow *bflow) +{ + const char *name = NULL; + + if (IS_ENABLED(CONFIG_EFI_APP)) { + struct efi_device_path *dp; + enum uclass_id id; + int ret; + + ret = efi_dp_from_bootflow(bflow, &dp, NULL); + if (!ret) + name = efi_dp_guess_uclass(dp, &id); + } else if (bflow->dev) { + struct udevice *media = dev_get_parent(bflow->dev); + + if (device_get_uclass_id(media) == UCLASS_MASS_STORAGE) + name = "usb"; + else + name = dev_get_uclass_name(media); + } + if (!name) + name = "(none)"; + + return name; +} diff --git a/cmd/bootflow.c b/cmd/bootflow.c index 20fc04bdda3..43335fecb34 100644 --- a/cmd/bootflow.c +++ b/cmd/bootflow.c @@ -70,21 +70,7 @@ static void report_bootflow_err(struct bootflow *bflow, int err) */ static void show_bootflow(int index, struct bootflow *bflow, bool errors) { - const char *name = NULL; - - if (IS_ENABLED(CONFIG_EFI_APP)) { - struct efi_device_path *dp; - enum uclass_id id; - int ret; - - ret = efi_dp_from_bootflow(bflow, &dp, NULL); - if (!ret) - name = efi_dp_guess_uclass(dp, &id); - } else if (bflow->dev) { - name = dev_get_uclass_name(dev_get_parent(bflow->dev)); - } - if (!name) - name = "(none)"; + const char *name = bootflow_guess_label(bflow); printf("%3x %-11s %-6s %-9.9s %4x %-25.25s %s\n", index, bflow->method ? bflow->method->name : "(none)", diff --git a/include/bootflow.h b/include/bootflow.h index ec5baff7e01..422fd32a3ca 100644 --- a/include/bootflow.h +++ b/include/bootflow.h @@ -725,4 +725,12 @@ int bootflow_menu_start(struct bootstd_priv *std, bool text_mode, */ int bootflow_menu_poll(struct expo *exp, int *seqp); +/** + * bootflow_guess_label() - Produce a plausible label for a bootflow + * + * This uses the uclass name or EFI device-path to come up with a useful label + * for display to the user. Ideally it will say "mmc", "usb", nvme", etc. + */ +const char *bootflow_guess_label(const struct bootflow *bflow); + #endif diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c index 620af312700..14e3326a08f 100644 --- a/test/boot/bootflow.c +++ b/test/boot/bootflow.c @@ -1349,9 +1349,9 @@ static int bootflow_efi(struct unit_test_state *uts) ut_assert_nextlinen("---"); ut_assert_nextlinen(" 0 extlinux"); ut_assert_nextlinen( - " 1 efi ready usb_mass_ 1 hub1.p2.usb_mass_storage. /EFI/BOOT/BOOTSBOX.EFI"); + " 1 efi ready usb 1 hub1.p2.usb_mass_storage. /EFI/BOOT/BOOTSBOX.EFI"); ut_assert_nextlinen( - " 2 extlinux ready usb_mass_ 1 hub1.p4.usb_mass_storage. /extlinux/extlinux.conf"); + " 2 extlinux ready usb 1 hub1.p4.usb_mass_storage. /extlinux/extlinux.conf"); ut_assert_nextlinen("---"); ut_assert_skip_to_line("(3 bootflows, 3 valid)"); ut_assert_console_end(); -- 2.43.0

From: Simon Glass <sjg@chromium.org> Make use of bootflow_guess_label() to get the label for a menu, since it provides more information for the EFI app. Signed-off-by: Simon Glass <sjg@chromium.org> --- boot/bootflow_menu.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/boot/bootflow_menu.c b/boot/bootflow_menu.c index 2f08fa54081..5e0e365d12b 100644 --- a/boot/bootflow_menu.c +++ b/boot/bootflow_menu.c @@ -124,7 +124,6 @@ int bootflow_menu_add(struct expo *exp, struct bootflow *bflow, int seq, { struct menu_priv *priv = exp->priv; char str[2], *label, *key; - struct udevice *media; struct scene *scn; const char *name; uint preview_id; @@ -144,11 +143,7 @@ int bootflow_menu_add(struct expo *exp, struct bootflow *bflow, int seq, if (!key) return log_msg_ret("key", -ENOMEM); - media = dev_get_parent(bflow->dev); - if (device_get_uclass_id(media) == UCLASS_MASS_STORAGE) - name = "usb"; - else - name = media->name; + name = bootflow_guess_label(bflow); label = strdup(name); if (!label) { -- 2.43.0

From: Simon Glass <sjg@chromium.org> This crept in a while back, so let's drop it. Signed-off-by: Simon Glass <sjg@chromium.org> Fixes: 184fc0379dd ("bootflow: bootmeth_efi: Handle fdt not available.") --- boot/bootmeth_efi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/boot/bootmeth_efi.c b/boot/bootmeth_efi.c index 6903734c546..09c4d2c0647 100644 --- a/boot/bootmeth_efi.c +++ b/boot/bootmeth_efi.c @@ -317,7 +317,6 @@ static int distro_efi_boot(struct udevice *dev, struct bootflow *bflow) */ if (bflow->flags & ~BOOTFLOWF_USE_BUILTIN_FDT) fdt = bflow->fdt_addr; - } if (efi_bootflow_run(bflow)) -- 2.43.0

From: Simon Glass <sjg@chromium.org> The lines after the 'edidebug media' command are only intended three spaces, but it should be four. Fix it. Signed-off-by: Simon Glass <sjg@chromium.org> Fixes: 9390344c350 ("efi: Add a uclass column to efidebug media command") --- doc/usage/cmd/efidebug.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/usage/cmd/efidebug.rst b/doc/usage/cmd/efidebug.rst index 29167dfa394..5dd68a689a6 100644 --- a/doc/usage/cmd/efidebug.rst +++ b/doc/usage/cmd/efidebug.rst @@ -49,11 +49,11 @@ Example This shows checking the EFI media devices:: - => efidebug media - Device Media type Device Path - ------------------- --------------- ----------- - efi_media_1 ahci PciRoot(0x0)/Pci(0x3,0x0)/Sata(0x0,0xFFFF,0x0) - efi_media_2 pci PciRoot(0x0)/Pci(0x5,0x0) + => efidebug media + Device Media type Device Path + ------------------- --------------- ----------- + efi_media_1 ahci PciRoot(0x0)/Pci(0x3,0x0)/Sata(0x0,0xFFFF,0x0) + efi_media_2 pci PciRoot(0x0)/Pci(0x5,0x0) This shows checking the log, then using 'efidebug tables' to fully set up the -- 2.43.0

From: Simon Glass <sjg@chromium.org> Provide a -s option to sort the memory map in order of address. Add documentation while we are here. Also fix an errant extra line before do_efi_show_media() Co-developed-by: Claude <noreply@anthropic.com> Signed-off-by: Simon Glass <sjg@chromium.org> --- cmd/efidebug.c | 51 +++++++++++++++++++-- doc/usage/cmd/efidebug.rst | 92 +++++++++++++++++++++++++++++++++++++- 2 files changed, 139 insertions(+), 4 deletions(-) diff --git a/cmd/efidebug.c b/cmd/efidebug.c index f88da42c2c4..627045a295e 100644 --- a/cmd/efidebug.c +++ b/cmd/efidebug.c @@ -25,6 +25,7 @@ #include <net.h> #include <part.h> #include <search.h> +#include <sort.h> #include <linux/ctype.h> #include <linux/err.h> @@ -655,6 +656,26 @@ static void print_memory_attributes(u64 attributes) #define EFI_PHYS_ADDR_WIDTH (int)(sizeof(efi_physical_addr_t) * 2) +/** + * efi_memmap_sort_by_addr() - compare two memory descriptors by address + * + * @a: first memory descriptor + * @b: second memory descriptor + * Return: -1 if a < b, 0 if a == b, 1 if a > b + */ +static int efi_memmap_sort_by_addr(const void *a, const void *b) +{ + const struct efi_mem_desc *desc_a = a; + const struct efi_mem_desc *desc_b = b; + + if (desc_a->physical_start < desc_b->physical_start) + return -1; + else if (desc_a->physical_start > desc_b->physical_start) + return 1; + + return 0; +} + /** * do_efi_show_memmap() - show UEFI memory map * @@ -676,6 +697,25 @@ static int do_efi_show_memmap(struct cmd_tbl *cmdtp, int flag, int desc_size, i; efi_status_t eret; int ret; + bool sort_by_addr = false; + int num_entries; + + argc--; + argv++; + while (argc > 0 && *argv[0] == '-') { + if (!strcmp(argv[0], "-s")) { + sort_by_addr = true; + } else { + printf("Unknown option: %s\n", argv[0]); + return CMD_RET_USAGE; + } + argc--; + } + + if (argc > 0) { + printf("Too many arguments\n"); + return CMD_RET_USAGE; + } if (IS_ENABLED(CONFIG_EFI_APP)) { uint key, version; @@ -692,6 +732,12 @@ static int do_efi_show_memmap(struct cmd_tbl *cmdtp, int flag, desc_size = sizeof(*map); } + /* Sort entries by address if requested */ + if (sort_by_addr) { + num_entries = map_size / desc_size; + qsort(memmap, num_entries, desc_size, efi_memmap_sort_by_addr); + } + printf("Type Start%.*s End%.*s Attributes\n", EFI_PHYS_ADDR_WIDTH - 5, spc, EFI_PHYS_ADDR_WIDTH - 3, spc); printf("================ %.*s %.*s ==========\n", @@ -1594,7 +1640,6 @@ static int do_efi_test(struct cmd_tbl *cmdtp, int flag, return cp->cmd(cmdtp, flag, argc, argv); } - /** * do_efi_show_media() - show EFI media devices * @@ -1807,8 +1852,8 @@ U_BOOT_LONGHELP(efidebug, " - show UEFI log\n" "efidebug media\n" " - show EFI media devices\n" - "efidebug memmap\n" - " - show UEFI memory map\n" + "efidebug memmap [-s]\n" + " - show UEFI memory map (use -s to sort by address)\n" "efidebug tables\n" " - show UEFI configuration tables\n" #ifdef CONFIG_EFI_BOOTMGR diff --git a/doc/usage/cmd/efidebug.rst b/doc/usage/cmd/efidebug.rst index 5dd68a689a6..8c8a4895197 100644 --- a/doc/usage/cmd/efidebug.rst +++ b/doc/usage/cmd/efidebug.rst @@ -15,6 +15,7 @@ Synopsis efidebug log efidebug media + efidebug memmap [-s] Description ----------- @@ -22,7 +23,7 @@ Description The *efidebug* command provides access to debugging features for the EFI-loader subsystem. -Only two of the subcommands are documented at present. +Only three of the subcommands are documented at present. efidebug log ~~~~~~~~~~~~ @@ -43,6 +44,15 @@ driver subsystem would likely handle the device (e.g., "ahci" for SATA drives, device, which can be useful for debugging boot issues or understanding the system topology. +efidebug memmap +~~~~~~~~~~~~~~~ + +This shows the UEFI memory map, which displays all memory regions and their +types as known to the EFI loader subsystem. This includes information about +memory allocation, reserved regions, and available memory. + +The command supports an optional '-s' flag to sort the memory map entries by +address, making it easier to visualize the memory layout in ascending order. Example ------- @@ -55,6 +65,86 @@ This shows checking the EFI media devices:: efi_media_1 ahci PciRoot(0x0)/Pci(0x3,0x0)/Sata(0x0,0xFFFF,0x0) efi_media_2 pci PciRoot(0x0)/Pci(0x5,0x0) +This shows checking the UEFI memory map, first unsorted and then sorted by +address:: + + => efidebug mem + Type Start End Attributes + ================ ================ ================ ========== + CONVENTIONAL 0000000040000000-0000000044000000 WB + BOOT DATA 0000000044000000-0000000044020000 WB + CONVENTIONAL 0000000044020000-00000000475ee000 WB + BOOT DATA 00000000475ee000-0000000047610000 WB + BOOT CODE 0000000047610000-0000000047647000 WB + BOOT DATA 0000000047647000-0000000047ef2000 WB + BOOT CODE 0000000047ef2000-0000000047ef6000 WB + BOOT DATA 0000000047ef6000-0000000047ff7000 WB + BOOT CODE 0000000047ff7000-0000000047ffa000 WB + BOOT DATA 0000000047ffa000-0000000048000000 WB + CONVENTIONAL 0000000048000000-00000000e0000000 WB + LOADER DATA 00000000e0000000-0000000100000000 WB + CONVENTIONAL 0000000100000000-000000013c278000 WB + LOADER DATA 000000013c278000-000000013c27c000 WB + LOADER CODE 000000013c27c000-000000013c3e0000 WB + ACPI RECLAIM MEM 000000013c3e0000-000000013c3f0000 WB + RUNTIME CODE 000000013c3f0000-000000013c470000 WB|RT + RUNTIME DATA 000000013c470000-000000013c630000 WB|RT + RUNTIME CODE 000000013c630000-000000013c730000 WB|RT + CONVENTIONAL 000000013c730000-000000013dc2a000 WB + BOOT DATA 000000013dc2a000-000000013e9f1000 WB + CONVENTIONAL 000000013e9f1000-000000013e9fe000 WB + BOOT DATA 000000013e9fe000-000000013ea1c000 WB + CONVENTIONAL 000000013ea1c000-000000013ea1e000 WB + BOOT DATA 000000013ea1e000-000000013ea47000 WB + CONVENTIONAL 000000013ea47000-000000013ea48000 WB + BOOT DATA 000000013ea48000-000000013f624000 WB + CONVENTIONAL 000000013f624000-000000013f731000 WB + BOOT CODE 000000013f731000-000000013fc00000 WB + RUNTIME CODE 000000013fc00000-000000013fd90000 WB|RT + RUNTIME DATA 000000013fd90000-000000013ffe0000 WB|RT + CONVENTIONAL 000000013ffe0000-000000013ffff000 WB + BOOT DATA 000000013ffff000-0000000140000000 WB + IO 0000000004000000-0000000008000000 UC|RT + IO 0000000009010000-0000000009011000 UC|RT + => efidebug mem -s + Type Start End Attributes + ================ ================ ================ ========== + IO 0000000004000000-0000000008000000 UC|RT + IO 0000000009010000-0000000009011000 UC|RT + CONVENTIONAL 0000000040000000-0000000044000000 WB + BOOT DATA 0000000044000000-0000000044020000 WB + CONVENTIONAL 0000000044020000-00000000475ee000 WB + BOOT DATA 00000000475ee000-0000000047610000 WB + BOOT CODE 0000000047610000-0000000047647000 WB + BOOT DATA 0000000047647000-0000000047ef2000 WB + BOOT CODE 0000000047ef2000-0000000047ef6000 WB + BOOT DATA 0000000047ef6000-0000000047ff7000 WB + BOOT CODE 0000000047ff7000-0000000047ffa000 WB + BOOT DATA 0000000047ffa000-0000000048000000 WB + CONVENTIONAL 0000000048000000-00000000e0000000 WB + LOADER DATA 00000000e0000000-0000000100000000 WB + CONVENTIONAL 0000000100000000-000000013c278000 WB + LOADER DATA 000000013c278000-000000013c27c000 WB + LOADER CODE 000000013c27c000-000000013c3e0000 WB + ACPI RECLAIM MEM 000000013c3e0000-000000013c3f0000 WB + RUNTIME CODE 000000013c3f0000-000000013c470000 WB|RT + RUNTIME DATA 000000013c470000-000000013c630000 WB|RT + RUNTIME CODE 000000013c630000-000000013c730000 WB|RT + CONVENTIONAL 000000013c730000-000000013dc2a000 WB + BOOT DATA 000000013dc2a000-000000013e9f1000 WB + CONVENTIONAL 000000013e9f1000-000000013e9fe000 WB + BOOT DATA 000000013e9fe000-000000013ea1c000 WB + CONVENTIONAL 000000013ea1c000-000000013ea1e000 WB + BOOT DATA 000000013ea1e000-000000013ea47000 WB + CONVENTIONAL 000000013ea47000-000000013ea48000 WB + BOOT DATA 000000013ea48000-000000013f624000 WB + CONVENTIONAL 000000013f624000-000000013f731000 WB + BOOT CODE 000000013f731000-000000013fc00000 WB + RUNTIME CODE 000000013fc00000-000000013fd90000 WB|RT + RUNTIME DATA 000000013fd90000-000000013ffe0000 WB|RT + CONVENTIONAL 000000013ffe0000-000000013ffff000 WB + BOOT DATA 000000013ffff000-0000000140000000 WB + => This shows checking the log, then using 'efidebug tables' to fully set up the EFI-loader subsystem, then checking the log again:: -- 2.43.0

From: Simon Glass <sjg@chromium.org> So far this subcommand is undocumented. Provide some notes. Also show a better error when 'efidebug boot rm' fails. Co-developed-by: Claude <noreply@anthropic.com> Signed-off-by: Simon Glass <sjg@chromium.org> --- cmd/efidebug.c | 7 ++-- doc/usage/cmd/efidebug.rst | 73 +++++++++++++++++++++++++++++++++++--- 2 files changed, 74 insertions(+), 6 deletions(-) diff --git a/cmd/efidebug.c b/cmd/efidebug.c index 627045a295e..baa2c73b149 100644 --- a/cmd/efidebug.c +++ b/cmd/efidebug.c @@ -1167,9 +1167,12 @@ static int do_efi_boot_rm(struct cmd_tbl *cmdtp, int flag, guid = efi_global_variable_guid; for (i = 1; i < argc; i++, argv++) { - id = (int)hextoul(argv[1], &endp); - if (*endp != '\0' || id > 0xffff) + id = (int)hextoul(argv[i], &endp); + if (*endp || id > 0xffff) { + printf("Invalid ID '%s', use '0001' for example\n", + argv[i]); return CMD_RET_FAILURE; + } efi_create_indexed_name(var_name16, sizeof(var_name16), "Boot", id); diff --git a/doc/usage/cmd/efidebug.rst b/doc/usage/cmd/efidebug.rst index 8c8a4895197..deab986887a 100644 --- a/doc/usage/cmd/efidebug.rst +++ b/doc/usage/cmd/efidebug.rst @@ -13,6 +13,11 @@ Synopsis :: + efidebug boot add -b <bootid> <label> <interface> <devnum>[:<part>] <file> + efidebug boot rm <bootid> [<bootid> ...] + efidebug boot dump + efidebug boot next <bootid> + efidebug boot order [<bootid> ...] efidebug log efidebug media efidebug memmap [-s] @@ -20,10 +25,44 @@ Synopsis Description ----------- -The *efidebug* command provides access to debugging features for the EFI-loader -subsystem. +The *efidebug* command provides access some EFI features, including boot +management, memory mapping, and system information. -Only three of the subcommands are documented at present. +efidebug boot +~~~~~~~~~~~~~ + +The boot subcommands manage UEFI boot options (BootXXXX variables) and boot +order. + +**efidebug boot add** + Create or modify a UEFI boot option. The basic syntax is: + ``efidebug boot add -b <bootid> <label> <interface> <devnum>[:<part>] <file>`` + + Where: + + - ``<bootid>`` is a hexadecimal boot option ID (e.g., 0001, 000A) + - ``<label>`` is a descriptive name for the boot option + - ``<interface>`` is the storage interface (e.g., mmc, usb, virtio) + - ``<devnum>[:<part>]`` specifies device and optionally partition number + - ``<file>`` is the path to the EFI executable + + Additional options include ``-i`` for initrd, ``-s`` for optional data, + and ``-d`` for device tree files. + +**efidebug boot rm** + Remove one or more UEFI boot options by their boot IDs. + +**efidebug boot dump** + List all defined UEFI boot options with their details including boot ID, + label, and file path. + +**efidebug boot next** + Set the BootNext variable to specify which boot option should be used for + the next boot only. + +**efidebug boot order** + Show the current boot order when called without arguments, or sets a new + boot order when given a list of boot IDs. efidebug log ~~~~~~~~~~~~ @@ -57,12 +96,38 @@ address, making it easier to visualize the memory layout in ascending order. Example ------- +This shows managing UEFI boot options:: + + => efidebug boot add -b 1 "Ubuntu" mmc 0:2 /EFI/ubuntu/grubx64.efi + => efidebug boot add -b 2 "Windows" mmc 0:1 /EFI/Microsoft/Boot/bootmgfw.efi + => efidebug boot dump + Boot0001: + attributes: A-- (0x00000001) + label: Ubuntu + file_path: /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/SD(0)/ + HD(2,GPT,dfae5a37-e8d5-4a2e-aab6-6b6e8c8cb8a3,0x100800, + 0x5dc1800)/\EFI\ubuntu\grubx64.efi + data: + Boot0002: + attributes: A-- (0x00000001) + label: Windows + file_path: /VenHw(e61d73b9-a384-4acc-aeab-82e828f3628b)/SD(0)/ + HD(1,GPT,c8a9e8e7-2d2a-4b8e-9b4f-7b7b3b7b7b7b,0x800, + 0x100000)/\EFI\Microsoft\Boot\bootmgfw.efi + data: + => efidebug boot order 1 2 + => efidebug boot order + BootOrder: 0001 0002 + => efidebug boot next 2 + => efidebug boot rm 1 + This shows checking the EFI media devices:: => efidebug media Device Media type Device Path ------------------- --------------- ----------- - efi_media_1 ahci PciRoot(0x0)/Pci(0x3,0x0)/Sata(0x0,0xFFFF,0x0) + efi_media_1 ahci PciRoot(0x0)/Pci(0x3,0x0)/ + Sata(0x0,0xFFFF,0x0) efi_media_2 pci PciRoot(0x0)/Pci(0x5,0x0) This shows checking the UEFI memory map, first unsorted and then sorted by -- 2.43.0

From: Simon Glass <sjg@chromium.org> It is handy to have the pager in the app, since some output can be quite long. Enable the console mux since the pager feature depends on it. Signed-off-by: Simon Glass <sjg@chromium.org> --- lib/efi_client/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/efi_client/Kconfig b/lib/efi_client/Kconfig index 5726e91e814..9361a548c9d 100644 --- a/lib/efi_client/Kconfig +++ b/lib/efi_client/Kconfig @@ -22,6 +22,7 @@ config EFI_APP depends on X86 || ARM select CHARSET select EVENT + imply CONSOLE_MUX imply CONSOLE_PAGER help Build U-Boot as an application which can be started from EFI. This -- 2.43.0

From: Simon Glass <sjg@chromium.org> Provide a -n flag to 'shim debug' so that the setting persists across reboots. Co-developed-by: Claude <noreply@anthropic.com> Signed-off-by: Simon Glass <sjg@chromium.org> --- cmd/shim.c | 21 +++++++++++++++------ doc/usage/cmd/shim.rst | 16 ++++++++++++---- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/cmd/shim.c b/cmd/shim.c index 903f1823f19..3a24b66ccf4 100644 --- a/cmd/shim.c +++ b/cmd/shim.c @@ -22,11 +22,12 @@ static int do_shim_debug(struct cmd_tbl *cmdtp, int flag, int argc, struct abuf buf; const char *sub; u32 value; + u32 attr; int ret; sub = cmd_arg1(argc, argv); - if (!sub) { - ret = efi_read_var(SHIM_VERBOSE_VAR_NAME, &efi_shim_lock, NULL, + if (argc == 1) { + ret = efi_read_var(SHIM_VERBOSE_VAR_NAME, &efi_shim_lock, &attr, &buf, NULL); if (ret == -ENOENT) { value = 0; @@ -41,10 +42,18 @@ static int do_shim_debug(struct cmd_tbl *cmdtp, int flag, int argc, } printf("%d\n", value); } else { - value = hextoul(sub, NULL) ? 1 : 0; + int arg = 1; + + attr = EFI_VARIABLE_BOOTSERVICE_ACCESS; + if (!strcmp("-n", argv[arg])) { + attr |= EFI_VARIABLE_NON_VOLATILE; + arg++; + } + if (arg == argc) + return CMD_RET_USAGE; + value = hextoul(argv[arg], NULL) ? 1 : 0; eret = efi_set_variable_int(SHIM_VERBOSE_VAR_NAME, - &efi_shim_lock, - EFI_VARIABLE_BOOTSERVICE_ACCESS, + &efi_shim_lock, attr, sizeof(value), &value, false); if (eret) { printf("Failed to write variable (err=%lx)\n", eret); @@ -59,7 +68,7 @@ fail: } U_BOOT_LONGHELP(shim, - "debug [<0/1>] - Enable / disable debug verbose mode"); + "debug [[-n] <0/1>] - Enable / disable debug verbose mode"); U_BOOT_CMD_WITH_SUBCMDS(shim, "Shim utilities", shim_help_text, U_BOOT_SUBCMD_MKENT(debug, 3, 1, do_shim_debug)); diff --git a/doc/usage/cmd/shim.rst b/doc/usage/cmd/shim.rst index 285dd200558..71974f46bb7 100644 --- a/doc/usage/cmd/shim.rst +++ b/doc/usage/cmd/shim.rst @@ -8,7 +8,7 @@ Synopsis :: - shim debug [<0/1>] + shim debug [[-n] <0/1>] Description ----------- @@ -36,6 +36,7 @@ Controls the Shim verbose debugging mode. shim debug # Display current debug state (0 or 1) shim debug 0 # Disable verbose debugging shim debug 1 # Enable verbose debugging + shim debug -n 1 # Enable verbose debugging (non-volatile) The command reads from or writes to the ``SHIM_VERBOSE`` EFI variable in the Shim Lock GUID namespace. When verbose mode is enabled (value = 1), Shim will @@ -44,6 +45,7 @@ output additional debugging information during the boot process. When disabled **Parameters:** +* ``-n`` - Makes the variable non-volatile (persistent across reboots) * ``<0/1>`` - Optional parameter to set debug mode: * ``0`` - Disable verbose debugging @@ -69,6 +71,10 @@ Disable verbose debugging:: => shim debug 0 +Enable verbose debugging with persistence across reboots:: + + => shim debug -n 1 + Configuration ~~~~~~~~~~~~~ @@ -86,12 +92,14 @@ The command uses the EFI variable services to read and write the * **Variable Name:** ``SHIM_VERBOSE`` (Unicode string) * **GUID:** EFI Shim Lock GUID (``605dab50-e046-4300-abb6-3dd810dd8b23``) -* **Attributes:** ``EFI_VARIABLE_BOOTSERVICE_ACCESS`` +* **Attributes:** ``EFI_VARIABLE_BOOTSERVICE_ACCESS`` (default) or + ``EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE`` (with ``-n`` flag) * **Data Type:** 32-bit unsigned integer (4 bytes) * **Values:** 0 (disabled) or 1 (enabled) -The variable is stored in the EFI variable store and persists across reboots -until explicitly changed or the variable store is cleared. +By default, the variable is volatile and will be reset on reboot. When the +``-n`` flag is used, the variable becomes non-volatile and persists across +reboots until explicitly changed or the variable store is cleared. See Also ~~~~~~~~ -- 2.43.0

From: Simon Glass <sjg@chromium.org> In some cases we may wish to return back to the program which started U-Boot. Add the concept of a 'hot' reset, to support this. Signed-off-by: Simon Glass <sjg@chromium.org> --- cmd/boot.c | 1 + doc/usage/cmd/reset.rst | 3 +++ drivers/sysreset/sysreset-uclass.c | 15 +++++++++++++-- drivers/sysreset/sysreset_sandbox.c | 1 + include/sysreset.h | 3 +++ test/dm/sysreset.c | 2 ++ 6 files changed, 23 insertions(+), 2 deletions(-) diff --git a/cmd/boot.c b/cmd/boot.c index 23496cafdf5..832ad08c319 100644 --- a/cmd/boot.c +++ b/cmd/boot.c @@ -60,6 +60,7 @@ U_BOOT_CMD( reset, 2, 0, do_reset, "Perform RESET of the CPU", "- cold boot without level specifier\n" + "reset -h - hotreset if implemented\n" "reset -w - warm reset if implemented" ); diff --git a/doc/usage/cmd/reset.rst b/doc/usage/cmd/reset.rst index 126db21cdb8..3a43db204e5 100644 --- a/doc/usage/cmd/reset.rst +++ b/doc/usage/cmd/reset.rst @@ -22,6 +22,9 @@ DDR and peripherals, on some boards also resets external PMIC. -w Do warm WARM, reset CPU but keep peripheral/DDR/PMIC active. +-h + Do a hot reset, if supported, which returns back to the program which + started U-Boot. Return value ------------ diff --git a/drivers/sysreset/sysreset-uclass.c b/drivers/sysreset/sysreset-uclass.c index 536ac727142..db81c9b5779 100644 --- a/drivers/sysreset/sysreset-uclass.c +++ b/drivers/sysreset/sysreset-uclass.c @@ -125,8 +125,19 @@ int do_reset(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) if (argc > 2) return CMD_RET_USAGE; - if (argc == 2 && argv[1][0] == '-' && argv[1][1] == 'w') { - reset_type = SYSRESET_WARM; + if (argc == 2 && argv[1][0] == '-') { + int type = argv[1][1]; + + switch (type) { + case 'h': + reset_type = SYSRESET_HOT; + break; + case 'w': + reset_type = SYSRESET_WARM; + break; + default: + return CMD_RET_USAGE; + } } printf("resetting ...\n"); diff --git a/drivers/sysreset/sysreset_sandbox.c b/drivers/sysreset/sysreset_sandbox.c index 93179f90bbb..522050eb4bf 100644 --- a/drivers/sysreset/sysreset_sandbox.c +++ b/drivers/sysreset/sysreset_sandbox.c @@ -65,6 +65,7 @@ static int sandbox_sysreset_request(struct udevice *dev, enum sysreset_t type) return -EACCES; sandbox_exit(); case SYSRESET_POWER: + case SYSRESET_HOT: if (!state->sysreset_allowed[type]) return -EACCES; sandbox_exit(); diff --git a/include/sysreset.h b/include/sysreset.h index ff20abdeed3..f231d4e8bc4 100644 --- a/include/sysreset.h +++ b/include/sysreset.h @@ -21,6 +21,9 @@ enum sysreset_t { SYSRESET_POWER, /** @SYSRESET_POWER_OFF: turn off power */ SYSRESET_POWER_OFF, + /** @SYSRESET_HOT: exit out of U-Boot (e.g. from EFI app) */ + SYSRESET_HOT, + /** @SYSRESET_COUNT: number of available reset types */ SYSRESET_COUNT, }; diff --git a/test/dm/sysreset.c b/test/dm/sysreset.c index 8431aaa0a9e..a30d035b9a6 100644 --- a/test/dm/sysreset.c +++ b/test/dm/sysreset.c @@ -76,10 +76,12 @@ static int dm_test_sysreset_walk(struct unit_test_state *uts) state->sysreset_allowed[SYSRESET_COLD] = false; state->sysreset_allowed[SYSRESET_POWER] = false; state->sysreset_allowed[SYSRESET_POWER_OFF] = false; + state->sysreset_allowed[SYSRESET_HOT] = false; ut_asserteq(-EACCES, sysreset_walk(SYSRESET_WARM)); ut_asserteq(-EACCES, sysreset_walk(SYSRESET_COLD)); ut_asserteq(-EACCES, sysreset_walk(SYSRESET_POWER)); ut_asserteq(-EACCES, sysreset_walk(SYSRESET_POWER_OFF)); + ut_asserteq(-EACCES, sysreset_walk(SYSRESET_HOT)); /* * Enable cold system reset - this should make cold system reset work, -- 2.43.0

From: Simon Glass <sjg@chromium.org> At present reset just exits the U-Boot app and returns to the caller. Add support for proper warm and cold resets, with 'hot' reset preserving the current behaviour. Signed-off-by: Simon Glass <sjg@chromium.org> --- lib/efi_client/efi_app.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/efi_client/efi_app.c b/lib/efi_client/efi_app.c index 6b8b53fbb41..88e04f1084b 100644 --- a/lib/efi_client/efi_app.c +++ b/lib/efi_client/efi_app.c @@ -250,7 +250,17 @@ static void efi_exit(void) static int efi_sysreset_request(struct udevice *dev, enum sysreset_t type) { - efi_exit(); + struct efi_priv *priv = efi_get_priv(); + + switch (type) { + case SYSRESET_WARM: + priv->run->reset_system(EFI_RESET_WARM, EFI_SUCCESS, 0, NULL); + break; + case SYSRESET_HOT: + default: + efi_exit(); + break; + } return -EINPROGRESS; } -- 2.43.0

From: Simon Glass <sjg@chromium.org> Add new SYSRESET_TO_FIRMWARE_UI reset type to allow resetting directly to firmware UI. This is implemented via the reset command's new -u flag. For the EFI app, this sets the EFI_OS_INDICATIONS_BOOT_TO_FW_UI bit in the OsIndications variable before performing a warm reset, causing the firmware to boot to its setup interface. Co-developed-by: Claude <noreply@anthropic.com> Signed-off-by: Simon Glass <sjg@chromium.org> --- cmd/boot.c | 1 + doc/usage/cmd/reset.rst | 9 ++++++++- drivers/sysreset/sysreset-uclass.c | 3 +++ drivers/sysreset/sysreset_sandbox.c | 1 + include/sysreset.h | 2 ++ lib/efi_client/efi_app.c | 27 +++++++++++++++++++++++++++ test/dm/sysreset.c | 2 ++ 7 files changed, 44 insertions(+), 1 deletion(-) diff --git a/cmd/boot.c b/cmd/boot.c index 832ad08c319..01b4bd76826 100644 --- a/cmd/boot.c +++ b/cmd/boot.c @@ -61,6 +61,7 @@ U_BOOT_CMD( "Perform RESET of the CPU", "- cold boot without level specifier\n" "reset -h - hotreset if implemented\n" + "reset -u - reset to firmware UI if implemented\n" "reset -w - warm reset if implemented" ); diff --git a/doc/usage/cmd/reset.rst b/doc/usage/cmd/reset.rst index 3a43db204e5..190f3281d78 100644 --- a/doc/usage/cmd/reset.rst +++ b/doc/usage/cmd/reset.rst @@ -11,7 +11,7 @@ Synopsis :: - reset [-w] + reset [-w] [-u] Description ----------- @@ -26,6 +26,13 @@ DDR and peripherals, on some boards also resets external PMIC. Do a hot reset, if supported, which returns back to the program which started U-Boot. +-u + Reset to firmware UI (EFI app only). Sets the + EFI_OS_INDICATIONS_BOOT_TO_FW_UI bit in the OsIndications variable and + performs a warm reset, causing the firmware to boot directly to its + setup/configuration interface. + + Return value ------------ diff --git a/drivers/sysreset/sysreset-uclass.c b/drivers/sysreset/sysreset-uclass.c index db81c9b5779..5c9b7c6a4f2 100644 --- a/drivers/sysreset/sysreset-uclass.c +++ b/drivers/sysreset/sysreset-uclass.c @@ -132,6 +132,9 @@ int do_reset(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) case 'h': reset_type = SYSRESET_HOT; break; + case 'u': + reset_type = SYSRESET_TO_FIRMWARE_UI; + break; case 'w': reset_type = SYSRESET_WARM; break; diff --git a/drivers/sysreset/sysreset_sandbox.c b/drivers/sysreset/sysreset_sandbox.c index 522050eb4bf..d126fad0372 100644 --- a/drivers/sysreset/sysreset_sandbox.c +++ b/drivers/sysreset/sysreset_sandbox.c @@ -66,6 +66,7 @@ static int sandbox_sysreset_request(struct udevice *dev, enum sysreset_t type) sandbox_exit(); case SYSRESET_POWER: case SYSRESET_HOT: + case SYSRESET_TO_FIRMWARE_UI: if (!state->sysreset_allowed[type]) return -EACCES; sandbox_exit(); diff --git a/include/sysreset.h b/include/sysreset.h index f231d4e8bc4..16a16952026 100644 --- a/include/sysreset.h +++ b/include/sysreset.h @@ -23,6 +23,8 @@ enum sysreset_t { SYSRESET_POWER_OFF, /** @SYSRESET_HOT: exit out of U-Boot (e.g. from EFI app) */ SYSRESET_HOT, + /** @SYSRESET_TO_FIRMWARE_UI: reset to firmware UI */ + SYSRESET_TO_FIRMWARE_UI, /** @SYSRESET_COUNT: number of available reset types */ SYSRESET_COUNT, diff --git a/lib/efi_client/efi_app.c b/lib/efi_client/efi_app.c index 88e04f1084b..1afccc8c8c7 100644 --- a/lib/efi_client/efi_app.c +++ b/lib/efi_client/efi_app.c @@ -16,6 +16,7 @@ #include <efi.h> #include <efi_api.h> #include <efi_stub.h> +#include <efi_variable.h> #include <errno.h> #include <fdt_simplefb.h> #include <image.h> @@ -253,6 +254,32 @@ static int efi_sysreset_request(struct udevice *dev, enum sysreset_t type) struct efi_priv *priv = efi_get_priv(); switch (type) { + case SYSRESET_TO_FIRMWARE_UI: { + efi_status_t ret; + u64 osind; + + /* Read current OsIndications value */ + osind = 0; + ret = efi_get_variable_int(u"OsIndications", + &efi_global_variable_guid, + NULL, NULL, &osind, NULL); + if (ret && ret != EFI_NOT_FOUND) + log_warning("Failed to read OsIndications: %lx\n", ret); + + /* Set the boot-to-firmware-UI bit */ + osind |= EFI_OS_INDICATIONS_BOOT_TO_FW_UI; + ret = efi_set_variable_int(u"OsIndications", + &efi_global_variable_guid, + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, + sizeof(osind), &osind, false); + if (ret) { + log_err("Failed to set OsIndications: %lx\n", ret); + return -EIO; + } + fallthrough; + } case SYSRESET_WARM: priv->run->reset_system(EFI_RESET_WARM, EFI_SUCCESS, 0, NULL); break; diff --git a/test/dm/sysreset.c b/test/dm/sysreset.c index a30d035b9a6..0afd19ff52f 100644 --- a/test/dm/sysreset.c +++ b/test/dm/sysreset.c @@ -77,11 +77,13 @@ static int dm_test_sysreset_walk(struct unit_test_state *uts) state->sysreset_allowed[SYSRESET_POWER] = false; state->sysreset_allowed[SYSRESET_POWER_OFF] = false; state->sysreset_allowed[SYSRESET_HOT] = false; + state->sysreset_allowed[SYSRESET_TO_FIRMWARE_UI] = false; ut_asserteq(-EACCES, sysreset_walk(SYSRESET_WARM)); ut_asserteq(-EACCES, sysreset_walk(SYSRESET_COLD)); ut_asserteq(-EACCES, sysreset_walk(SYSRESET_POWER)); ut_asserteq(-EACCES, sysreset_walk(SYSRESET_POWER_OFF)); ut_asserteq(-EACCES, sysreset_walk(SYSRESET_HOT)); + ut_asserteq(-EACCES, sysreset_walk(SYSRESET_TO_FIRMWARE_UI)); /* * Enable cold system reset - this should make cold system reset work, -- 2.43.0

From: Simon Glass <sjg@chromium.org> Add support for reset -c flag to explicitly request cold reset. This provides symmetry with -w (warm) and -u (firmware UI) flags. For EFI apps, this performs EFI_RESET_COLD which does a full system reboot without going to firmware setup interface. Signed-off-by: Simon Glass <sjg@chromium.org> --- doc/usage/cmd/reset.rst | 2 +- lib/efi_client/efi_app.c | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/usage/cmd/reset.rst b/doc/usage/cmd/reset.rst index 190f3281d78..d3923c3e8a9 100644 --- a/doc/usage/cmd/reset.rst +++ b/doc/usage/cmd/reset.rst @@ -11,7 +11,7 @@ Synopsis :: - reset [-w] [-u] + reset [-c] [-w] [-u] Description ----------- diff --git a/lib/efi_client/efi_app.c b/lib/efi_client/efi_app.c index 1afccc8c8c7..25fc2e9cade 100644 --- a/lib/efi_client/efi_app.c +++ b/lib/efi_client/efi_app.c @@ -254,6 +254,10 @@ static int efi_sysreset_request(struct udevice *dev, enum sysreset_t type) struct efi_priv *priv = efi_get_priv(); switch (type) { + case SYSRESET_COLD: + /* Perform a cold reset */ + priv->run->reset_system(EFI_RESET_COLD, EFI_SUCCESS, 0, NULL); + break; case SYSRESET_TO_FIRMWARE_UI: { efi_status_t ret; u64 osind; -- 2.43.0
participants (1)
-
Simon Glass