sysreset: Add SYSRESET_TO_FIRMWARE_UI with reset -u support
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>
This commit is contained in:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user