fix(menu): don't panic on very large timeouts

The basic menu set a single timer for the whole timeout, and converting
a timeout of more than about 1.8e12 seconds into 100ns timer units
panics. The timeout can come from --menu-timeout or from
LoaderConfigTimeout, which persists, so the panic would repeat on every
boot. Limit a single timer to u32::MAX seconds.
This commit is contained in:
alex authored and Alex Zenla committed 2026-09-26 20:52:15 -07:00
1 parent 98f1a2c8c5
commit 11736ccabb
1 file changed
+7 -1
+7 -1
View File
@@ -19,6 +19,10 @@ pub mod basic;
/// 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;
/// 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.
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,
@@ -49,7 +53,9 @@ pub fn wait_for_key(input: &mut Input, timeout: Duration) -> Result<bool> {
}; };
// Set a timer to trigger after the specified duration. // Set a timer to trigger after the specified duration.
let trigger = TimerTrigger::Relative(timeout); // The timer is limited to what the firmware can represent, as a longer timeout
// can't be converted into a timer trigger.
let trigger = TimerTrigger::Relative(timeout.min(MAX_TIMER_DURATION));
uefi::boot::set_timer(&timer_event, trigger).context("unable to set timeout timer")?; uefi::boot::set_timer(&timer_event, trigger).context("unable to set timeout timer")?;
let events = vec![timer_event, key_event]; let events = vec![timer_event, key_event];