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(-)
@@ -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"
);
@@ -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
------------
@@ -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;
@@ -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();
@@ -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,
@@ -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;
@@ -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,