mirror of
https://github.com/edera-dev/sprout.git
synced 2026-11-04 22:02:20 +00:00
fix(menu): show the boot menu when it is forced
--force-menu and LoaderConfigTimeout=menu-force only stopped --boot and LoaderEntryOneShot from skipping the menu. The timeout was left as is, so with a zero timeout the menu booted the default entry without being drawn, and menu-force counted down and booted the default entry, where the Boot Loader Interface says it should wait for the user. Menus now take an optional timeout. menu-force waits for the user, and --force-menu keeps the configured timeout unless it is zero, in which case it waits for the user too.
This commit is contained in:
1 parent
df0bda04c0
commit
e8e3361764
4 files changed
+27
-14
No files matched your search
+12
-2
@@ -291,11 +291,15 @@ fn run() -> Result<()> {
|
|||||||
.menu_timeout
|
.menu_timeout
|
||||||
.unwrap_or(config.options.menu_timeout);
|
.unwrap_or(config.options.menu_timeout);
|
||||||
|
|
||||||
|
// Whether the boot menu should wait for the user, instead of counting down.
|
||||||
|
let mut wait_for_user = false;
|
||||||
|
|
||||||
// Apply bootloader interface timeout settings.
|
// Apply bootloader interface timeout settings.
|
||||||
match bootloader_interface_timeout {
|
match bootloader_interface_timeout {
|
||||||
BootloaderInterfaceTimeout::MenuForce => {
|
BootloaderInterfaceTimeout::MenuForce => {
|
||||||
// Force the boot menu.
|
// Force the boot menu, and wait for the user to choose an entry.
|
||||||
force_boot_menu = true;
|
force_boot_menu = true;
|
||||||
|
wait_for_user = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
BootloaderInterfaceTimeout::MenuHidden | BootloaderInterfaceTimeout::MenuDisabled => {
|
BootloaderInterfaceTimeout::MenuHidden | BootloaderInterfaceTimeout::MenuDisabled => {
|
||||||
@@ -341,7 +345,13 @@ fn run() -> Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Convert the menu timeout to a duration.
|
// Convert the menu timeout to a duration.
|
||||||
let menu_timeout = Duration::from_secs(menu_timeout);
|
// A zero timeout boots without showing the menu, so a forced menu with a zero timeout
|
||||||
|
// waits for the user instead.
|
||||||
|
let menu_timeout = if wait_for_user || (force_boot_menu && menu_timeout == 0) {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(Duration::from_secs(menu_timeout))
|
||||||
|
};
|
||||||
|
|
||||||
// Determine the menu style based on the options or configuration.
|
// Determine the menu style based on the options or configuration.
|
||||||
// We prefer the options over the configuration to allow for overriding.
|
// We prefer the options over the configuration to allow for overriding.
|
||||||
|
|||||||
@@ -26,10 +26,11 @@ const MAX_TIMER_DURATION: Duration = Duration::from_secs(u32::MAX as u64);
|
|||||||
/// A boot menu that can be shown to select an entry to boot.
|
/// A boot menu that can be shown to select an entry to boot.
|
||||||
pub trait BootMenu {
|
pub trait BootMenu {
|
||||||
/// Select an entry from `entries` to boot. If no entry is chosen before `timeout` passes,
|
/// Select an entry from `entries` to boot. If no entry is chosen before `timeout` passes,
|
||||||
/// the default entry is selected.
|
/// the default entry is selected. If `timeout` is zero, the default entry is selected
|
||||||
|
/// without showing the menu. If `timeout` is [None], the menu waits for the user.
|
||||||
fn select<'a>(
|
fn select<'a>(
|
||||||
&self,
|
&self,
|
||||||
timeout: Duration,
|
timeout: Option<Duration>,
|
||||||
entries: &'a [BootableEntry],
|
entries: &'a [BootableEntry],
|
||||||
) -> Result<&'a BootableEntry>;
|
) -> Result<&'a BootableEntry>;
|
||||||
}
|
}
|
||||||
@@ -108,9 +109,10 @@ pub fn read_key(input: &mut Input, timeout: Option<Duration>) -> Result<Option<K
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// 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.
|
||||||
pub fn select<'live>(
|
pub fn select<'live>(
|
||||||
timer: &'live PlatformTimer,
|
timer: &'live PlatformTimer,
|
||||||
timeout: Duration,
|
timeout: Option<Duration>,
|
||||||
style: MenuStyle,
|
style: MenuStyle,
|
||||||
entries: &'live [BootableEntry],
|
entries: &'live [BootableEntry],
|
||||||
) -> Result<&'live BootableEntry> {
|
) -> Result<&'live BootableEntry> {
|
||||||
|
|||||||
@@ -76,16 +76,16 @@ fn default_entry(entries: &[BootableEntry]) -> Result<&BootableEntry> {
|
|||||||
/// Selects an entry from the list of entries using the boot menu.
|
/// Selects an entry from the list of entries using the boot menu.
|
||||||
fn select_with_input<'a>(
|
fn select_with_input<'a>(
|
||||||
input: &mut Input,
|
input: &mut Input,
|
||||||
timeout: Duration,
|
timeout: Option<Duration>,
|
||||||
entries: &'a [BootableEntry],
|
entries: &'a [BootableEntry],
|
||||||
) -> Result<&'a BootableEntry> {
|
) -> Result<&'a BootableEntry> {
|
||||||
// If the timeout is zero, boot the default entry without showing the menu.
|
// If the timeout is zero, boot the default entry without showing the menu.
|
||||||
if timeout.is_zero() {
|
if timeout.is_some_and(|timeout| timeout.is_zero()) {
|
||||||
return default_entry(entries);
|
return default_entry(entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The time to wait for a key, or None once a key stops the countdown.
|
// The time to wait for a key, or None once a key stops the countdown.
|
||||||
let mut countdown = Some(timeout);
|
let mut countdown = timeout;
|
||||||
|
|
||||||
// The entry number typed so far, while more digits could still select another entry.
|
// The entry number typed so far, while more digits could still select another entry.
|
||||||
let mut typed: Option<usize> = None;
|
let mut typed: Option<usize> = None;
|
||||||
@@ -176,7 +176,7 @@ impl BootMenu for BasicMenu {
|
|||||||
/// within the context of the standard input device.
|
/// within the context of the standard input device.
|
||||||
fn select<'a>(
|
fn select<'a>(
|
||||||
&self,
|
&self,
|
||||||
timeout: Duration,
|
timeout: Option<Duration>,
|
||||||
entries: &'a [BootableEntry],
|
entries: &'a [BootableEntry],
|
||||||
) -> Result<&'a BootableEntry> {
|
) -> Result<&'a BootableEntry> {
|
||||||
uefi::system::with_stdin(move |input| select_with_input(input, timeout, entries))
|
uefi::system::with_stdin(move |input| select_with_input(input, timeout, entries))
|
||||||
|
|||||||
@@ -163,11 +163,12 @@ fn render(
|
|||||||
|
|
||||||
/// Run the menu until an entry is chosen, returning the index of that entry.
|
/// Run the menu until an entry is chosen, returning the index of that entry.
|
||||||
/// The `selected` entry is booted if no key is pressed before `timeout` passes.
|
/// The `selected` entry is booted if no key is pressed before `timeout` passes.
|
||||||
|
/// Without a timeout, the menu waits for the user.
|
||||||
fn run(
|
fn run(
|
||||||
input: &mut Input,
|
input: &mut Input,
|
||||||
output: &mut Output,
|
output: &mut Output,
|
||||||
layout: &Layout,
|
layout: &Layout,
|
||||||
timeout: Duration,
|
timeout: Option<Duration>,
|
||||||
entries: &[BootableEntry],
|
entries: &[BootableEntry],
|
||||||
mut selected: usize,
|
mut selected: usize,
|
||||||
) -> Result<usize> {
|
) -> Result<usize> {
|
||||||
@@ -175,7 +176,7 @@ fn run(
|
|||||||
// The first visible entry, which changes when scrolling through a long list.
|
// The first visible entry, which changes when scrolling through a long list.
|
||||||
let mut offset = 0;
|
let mut offset = 0;
|
||||||
// The time left before booting, or None once a key stops the countdown.
|
// The time left before booting, or None once a key stops the countdown.
|
||||||
let mut remaining = Some(timeout);
|
let mut remaining = timeout;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
// Scroll so that the selected entry is visible.
|
// Scroll so that the selected entry is visible.
|
||||||
@@ -230,7 +231,7 @@ fn run(
|
|||||||
fn select_with_console<'a>(
|
fn select_with_console<'a>(
|
||||||
input: &mut Input,
|
input: &mut Input,
|
||||||
output: &mut Output,
|
output: &mut Output,
|
||||||
timeout: Duration,
|
timeout: Option<Duration>,
|
||||||
entries: &'a [BootableEntry],
|
entries: &'a [BootableEntry],
|
||||||
) -> Result<&'a BootableEntry> {
|
) -> Result<&'a BootableEntry> {
|
||||||
let default = entries
|
let default = entries
|
||||||
@@ -239,7 +240,7 @@ fn select_with_console<'a>(
|
|||||||
.context("no default entry available")?;
|
.context("no default entry available")?;
|
||||||
|
|
||||||
// If the timeout is zero, boot the default entry without showing the menu.
|
// If the timeout is zero, boot the default entry without showing the menu.
|
||||||
if timeout.is_zero() {
|
if timeout.is_some_and(|timeout| timeout.is_zero()) {
|
||||||
return Ok(&entries[default]);
|
return Ok(&entries[default]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -269,7 +270,7 @@ impl BootMenu for SimpleMenu {
|
|||||||
/// within the context of the standard input and output devices.
|
/// within the context of the standard input and output devices.
|
||||||
fn select<'a>(
|
fn select<'a>(
|
||||||
&self,
|
&self,
|
||||||
timeout: Duration,
|
timeout: Option<Duration>,
|
||||||
entries: &'a [BootableEntry],
|
entries: &'a [BootableEntry],
|
||||||
) -> Result<&'a BootableEntry> {
|
) -> Result<&'a BootableEntry> {
|
||||||
uefi::system::with_stdin(|input| {
|
uefi::system::with_stdin(|input| {
|
||||||
|
|||||||
Reference in new issue
Block a user