mirror of
https://github.com/systemd/systemd.git
synced 2024-11-23 10:13:34 +08:00
sd-boot: Add keys to reboot into firmware interface
This is useful if the auto-firmware setting has been disabled. The keys used here are based on what the majority of firmware employ in the wild. This also ensures there's a chance for the user to discover this in case they were too slow during POST or simply used the wrong ones.
This commit is contained in:
parent
784c249f41
commit
e6cab77eca
@ -188,8 +188,9 @@
|
||||
<varlistentry>
|
||||
<term>auto-firmware</term>
|
||||
|
||||
<listitem><para>Takes a boolean argument. Enable (the default) or disable
|
||||
the "Reboot into firmware" entry.</para></listitem>
|
||||
<listitem><para>A boolean controlling the presence of the "Reboot into firmware" entry
|
||||
(enabled by default). If this is disabled, the firmware interface may still be reached
|
||||
by using the <keycap>f</keycap> key.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
|
@ -178,6 +178,15 @@
|
||||
<term><keycap>F1</keycap></term>
|
||||
<listitem><para>Show a help screen</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><keycap>f</keycap></term>
|
||||
<listitem><para>Reboot into firmware interface.</para>
|
||||
|
||||
<para>For compatibility with the keybindings of several firmware implementations this operation
|
||||
may also be reached with <keycap>F2</keycap>, <keycap>F10</keycap>, <keycap>Del</keycap> and
|
||||
<keycap>Esc</keycap>.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
<para>The following keys may be pressed during bootup or in the boot menu to directly boot a specific
|
||||
|
@ -543,6 +543,24 @@ static void print_status(Config *config, CHAR16 *loaded_image_path) {
|
||||
}
|
||||
}
|
||||
|
||||
static EFI_STATUS reboot_into_firmware(void) {
|
||||
UINT64 osind = 0;
|
||||
EFI_STATUS err;
|
||||
|
||||
if (!(get_os_indications_supported() & EFI_OS_INDICATIONS_BOOT_TO_FW_UI))
|
||||
return log_error_status_stall(EFI_UNSUPPORTED, L"Reboot to firmware interface not supported.");
|
||||
|
||||
(void) efivar_get_uint64_le(EFI_GLOBAL_GUID, L"OsIndications", &osind);
|
||||
osind |= EFI_OS_INDICATIONS_BOOT_TO_FW_UI;
|
||||
|
||||
err = efivar_set_uint64_le(EFI_GLOBAL_GUID, L"OsIndications", osind, EFI_VARIABLE_NON_VOLATILE);
|
||||
if (EFI_ERROR(err))
|
||||
return log_error_status_stall(err, L"Error setting OsIndications: %r", err);
|
||||
|
||||
err = RT->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL);
|
||||
return log_error_status_stall(err, L"Error calling ResetSystem: %r", err);
|
||||
}
|
||||
|
||||
static BOOLEAN menu_run(
|
||||
Config *config,
|
||||
ConfigEntry **chosen_entry,
|
||||
@ -566,7 +584,7 @@ static BOOLEAN menu_run(
|
||||
UINT32 timeout_efivar_saved = config->timeout_sec_efivar;
|
||||
UINT32 timeout_remain = config->timeout_sec == TIMEOUT_MENU_FORCE ? 0 : config->timeout_sec;
|
||||
INT16 idx;
|
||||
BOOLEAN exit = FALSE, run = TRUE;
|
||||
BOOLEAN exit = FALSE, run = TRUE, firmware_setup = FALSE;
|
||||
INT64 console_mode_initial = ST->ConOut->Mode->Mode, console_mode_efivar_saved = config->console_mode_efivar;
|
||||
|
||||
graphics_mode(FALSE);
|
||||
@ -738,6 +756,13 @@ static BOOLEAN menu_run(
|
||||
|
||||
idx_highlight_prev = idx_highlight;
|
||||
|
||||
if (firmware_setup) {
|
||||
firmware_setup = FALSE;
|
||||
if (key == KEYPRESS(0, 0, CHAR_CARRIAGE_RETURN))
|
||||
reboot_into_firmware();
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (key) {
|
||||
case KEYPRESS(0, SCAN_UP, 0):
|
||||
case KEYPRESS(0, 0, 'k'):
|
||||
@ -794,7 +819,7 @@ static BOOLEAN menu_run(
|
||||
case KEYPRESS(0, 0, 'h'):
|
||||
case KEYPRESS(0, 0, 'H'):
|
||||
case KEYPRESS(0, 0, '?'):
|
||||
/* This must stay below 80 characters! Q/v/Ctrl+l deliberately not advertised. */
|
||||
/* This must stay below 80 characters! Q/v/Ctrl+l/f deliberately not advertised. */
|
||||
status = StrDuplicate(L"(d)efault (t/T)timeout (e)dit (r/R)resolution (p)rint (h)elp");
|
||||
break;
|
||||
|
||||
@ -888,6 +913,20 @@ static BOOLEAN menu_run(
|
||||
new_mode = TRUE;
|
||||
break;
|
||||
|
||||
case KEYPRESS(0, 0, 'f'):
|
||||
case KEYPRESS(0, 0, 'F'):
|
||||
case KEYPRESS(0, SCAN_F2, 0): /* Most vendors. */
|
||||
case KEYPRESS(0, SCAN_F10, 0): /* HP and Lenovo. */
|
||||
case KEYPRESS(0, SCAN_DELETE, 0): /* Same as F2. */
|
||||
case KEYPRESS(0, SCAN_ESC, 0): /* HP. */
|
||||
if (get_os_indications_supported() & EFI_OS_INDICATIONS_BOOT_TO_FW_UI) {
|
||||
firmware_setup = TRUE;
|
||||
/* Let's make sure the user really wants to do this. */
|
||||
status = PoolPrint(L"Press Enter to reboot into firmware interface.");
|
||||
} else
|
||||
status = PoolPrint(L"Reboot into firmware interface not supported.");
|
||||
break;
|
||||
|
||||
default:
|
||||
/* jump with a hotkey directly to a matching entry */
|
||||
idx = entry_lookup_key(config, idx_highlight+1, KEYCHAR(key));
|
||||
@ -2180,24 +2219,6 @@ out_unload:
|
||||
return err;
|
||||
}
|
||||
|
||||
static EFI_STATUS reboot_into_firmware(void) {
|
||||
UINT64 old, new;
|
||||
EFI_STATUS err;
|
||||
|
||||
new = EFI_OS_INDICATIONS_BOOT_TO_FW_UI;
|
||||
|
||||
err = efivar_get_uint64_le(EFI_GLOBAL_GUID, L"OsIndications", &old);
|
||||
if (!EFI_ERROR(err))
|
||||
new |= old;
|
||||
|
||||
err = efivar_set_uint64_le(EFI_GLOBAL_GUID, L"OsIndications", new, EFI_VARIABLE_NON_VOLATILE);
|
||||
if (EFI_ERROR(err))
|
||||
return err;
|
||||
|
||||
err = RT->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL);
|
||||
return log_error_status_stall(err, L"Error calling ResetSystem: %r", err);
|
||||
}
|
||||
|
||||
static void config_free(Config *config) {
|
||||
assert(config);
|
||||
for (UINTN i = 0; i < config->entry_count; i++)
|
||||
|
Loading…
Reference in New Issue
Block a user