mirror of
https://github.com/edera-dev/sprout.git
synced 2026-11-04 17:52:20 +00:00
fix(menu): let a key press show a hidden menu
A menu with a zero timeout or menu-hidden now waits 100 ms for a key press before booting the default entry, which is how the boot loader interface lets a user interrupt a hidden menu. menu-disabled still skips the wait.
This commit is contained in:
1 parent
590eeead5e
commit
8bb5f1132d
2 files changed
+31
-3
No files matched your search
+11
-2
@@ -410,6 +410,9 @@ fn run() -> Result<()> {
|
|||||||
// Whether the boot menu should wait for the user, instead of counting down.
|
// Whether the boot menu should wait for the user, instead of counting down.
|
||||||
let mut wait_for_user = false;
|
let mut wait_for_user = false;
|
||||||
|
|
||||||
|
// Whether the menu is disabled, so that a key press can't bring it up.
|
||||||
|
let mut menu_disabled = false;
|
||||||
|
|
||||||
// Apply the chosen timeout.
|
// Apply the chosen timeout.
|
||||||
match timeout {
|
match timeout {
|
||||||
BootloaderInterfaceTimeout::MenuForce => {
|
BootloaderInterfaceTimeout::MenuForce => {
|
||||||
@@ -424,11 +427,17 @@ fn run() -> Result<()> {
|
|||||||
menu_timeout = timeout;
|
menu_timeout = timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
BootloaderInterfaceTimeout::MenuHidden | BootloaderInterfaceTimeout::MenuDisabled => {
|
BootloaderInterfaceTimeout::MenuHidden => {
|
||||||
// Hide the boot menu by setting the timeout to zero.
|
// Hide the boot menu by setting the timeout to zero.
|
||||||
menu_timeout = 0;
|
menu_timeout = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BootloaderInterfaceTimeout::MenuDisabled => {
|
||||||
|
// Hide the boot menu, and don't let a key press show it.
|
||||||
|
menu_timeout = 0;
|
||||||
|
menu_disabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
BootloaderInterfaceTimeout::Timeout(timeout) => {
|
BootloaderInterfaceTimeout::Timeout(timeout) => {
|
||||||
// Configure the timeout to the specified value.
|
// Configure the timeout to the specified value.
|
||||||
menu_timeout = timeout;
|
menu_timeout = timeout;
|
||||||
@@ -593,7 +602,7 @@ fn run() -> Result<()> {
|
|||||||
let entry = match forced_entry {
|
let entry = match forced_entry {
|
||||||
Some(entry) => entry,
|
Some(entry) => entry,
|
||||||
// Delegate to the menu to select an entry to boot.
|
// Delegate to the menu to select an entry to boot.
|
||||||
None => menu::select(&timer, menu_timeout, menu_style, &entries)
|
None => menu::select(&timer, menu_timeout, menu_disabled, menu_style, &entries)
|
||||||
.context("unable to select entry via boot menu")?,
|
.context("unable to select entry via boot menu")?,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+20
-1
@@ -31,6 +31,9 @@ mod logo;
|
|||||||
/// simple: A full-screen menu that selects entries with the arrow keys.
|
/// simple: A full-screen menu that selects entries with the arrow keys.
|
||||||
pub mod simple;
|
pub mod simple;
|
||||||
|
|
||||||
|
/// How long a hidden menu waits for a key press before the default entry is booted.
|
||||||
|
const HIDDEN_MENU_KEY_WAIT: Duration = Duration::from_millis(100);
|
||||||
|
|
||||||
/// The longest duration a single timer is set for. This is well within the range of
|
/// The longest duration a single timer is set for. This is well within the range of
|
||||||
/// the 100ns units that timers are set in, and still over a century long.
|
/// the 100ns units that timers are set in, and still over a century long.
|
||||||
const MAX_TIMER_DURATION: Duration = Duration::from_secs(u32::MAX as u64);
|
const MAX_TIMER_DURATION: Duration = Duration::from_secs(u32::MAX as u64);
|
||||||
@@ -167,13 +170,29 @@ pub fn wait_for_events(events: &[Event], timeout: Option<Duration>) -> Result<Op
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Shows a boot menu of the specified `style` to select a bootable entry to boot.
|
/// Shows a boot menu of the specified `style` to select a bootable entry to boot.
|
||||||
/// See [BootMenu::select] for how `timeout` is handled.
|
/// See [BootMenu::select] for how `timeout` is handled. A zero `timeout` hides the menu, but
|
||||||
|
/// the menu is still shown if a key is pressed right away, unless `menu_disabled` is set.
|
||||||
pub fn select<'live>(
|
pub fn select<'live>(
|
||||||
timer: &'live PlatformTimer,
|
timer: &'live PlatformTimer,
|
||||||
timeout: Option<Duration>,
|
timeout: Option<Duration>,
|
||||||
|
menu_disabled: bool,
|
||||||
style: MenuStyle,
|
style: MenuStyle,
|
||||||
entries: &'live [BootableEntry],
|
entries: &'live [BootableEntry],
|
||||||
) -> Result<&'live BootableEntry> {
|
) -> Result<&'live BootableEntry> {
|
||||||
|
// A hidden menu gives the user a moment to ask for the menu with a key press.
|
||||||
|
let timeout = if timeout.is_some_and(|timeout| timeout.is_zero()) && !menu_disabled {
|
||||||
|
match uefi::system::with_stdin(|input| read_key(input, Some(HIDDEN_MENU_KEY_WAIT))) {
|
||||||
|
Ok(Some(_)) => None,
|
||||||
|
Ok(None) => timeout,
|
||||||
|
Err(error) => {
|
||||||
|
warn!("unable to check for a key press: {:#}", error);
|
||||||
|
timeout
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
timeout
|
||||||
|
};
|
||||||
|
|
||||||
// Notify the bootloader interface that we are about to display the menu.
|
// Notify the bootloader interface that we are about to display the menu.
|
||||||
// This is only informational, so it should not prevent booting.
|
// This is only informational, so it should not prevent booting.
|
||||||
if let Err(error) = BootloaderInterface::mark_menu(timer) {
|
if let Err(error) = BootloaderInterface::mark_menu(timer) {
|
||||||
|
|||||||
Reference in new issue
Block a user