From cc7717871b4885c636bff4a81d5af54691a840c5 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 11 Aug 2024 11:10:31 -0400 Subject: [PATCH 1/2] boot: Add freestanding set_watchdog_timer --- uefi/src/boot.rs | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/uefi/src/boot.rs b/uefi/src/boot.rs index e86edcb87..23daed99b 100644 --- a/uefi/src/boot.rs +++ b/uefi/src/boot.rs @@ -804,6 +804,53 @@ pub unsafe fn install_configuration_table( (bt.install_configuration_table)(guid_entry, table_ptr).to_result() } +/// Sets the watchdog timer. +/// +/// UEFI will start a 5-minute countdown after an UEFI image is loaded. The +/// image must either successfully load an OS and exit boot services in that +/// time, or disable the watchdog. +/// +/// Otherwise, the firmware will log the event using the provided numeric +/// code and data, then reset the system. +/// +/// This function allows you to change the watchdog timer's timeout to a +/// certain amount of seconds or to disable the watchdog entirely. It also +/// allows you to change what will be logged when the timer expires. +/// +/// The watchdog codes from 0 to 0xffff (65535) are reserved for internal +/// firmware use. Higher values can be used freely by applications. +/// +/// If provided, the watchdog data must be a null-terminated string optionally +/// followed by other binary data. +/// +/// # Errors +/// +/// * [`Status::INVALID_PARAMETER`]: `watchdog_code` is invalid. +/// * [`Status::UNSUPPORTED`]: the system does not have a watchdog timer. +/// * [`Status::DEVICE_ERROR`]: the watchdog timer could not be set due to a +/// hardware error. +pub fn set_watchdog_timer( + timeout_in_seconds: usize, + watchdog_code: u64, + data: Option<&mut [u16]>, +) -> Result { + let bt = boot_services_raw_panicking(); + let bt = unsafe { bt.as_ref() }; + + let (data_len, data) = data + .map(|d| { + assert!( + d.contains(&0), + "Watchdog data must start with a null-terminated string" + ); + (d.len(), d.as_mut_ptr()) + }) + .unwrap_or((0, ptr::null_mut())); + + unsafe { (bt.set_watchdog_timer)(timeout_in_seconds, watchdog_code, data_len, data) } + .to_result() +} + /// Stalls execution for the given number of microseconds. pub fn stall(microseconds: usize) { let bt = boot_services_raw_panicking(); From a11f98a240835f93fb7e58d138a1fed45a06e9c6 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 11 Aug 2024 11:16:39 -0400 Subject: [PATCH 2/2] test-runner: Test boot::set_watchdog_timer --- uefi-test-runner/src/boot/misc.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/uefi-test-runner/src/boot/misc.rs b/uefi-test-runner/src/boot/misc.rs index 39bc86571..e6464e035 100644 --- a/uefi-test-runner/src/boot/misc.rs +++ b/uefi-test-runner/src/boot/misc.rs @@ -119,9 +119,14 @@ fn test_callback_with_ctx(bt: &BootServices) { } fn test_watchdog(bt: &BootServices) { - // Disable the UEFI watchdog timer + // There's no way to check the watchdog timer value, so just test setting it. + + // Disable the UEFI watchdog timer. bt.set_watchdog_timer(0, 0x10000, None) .expect("Could not set watchdog timer"); + + // Set the timer with the freestanding function. + boot::set_watchdog_timer(240, 0x10000, None).expect("Could not set watchdog timer"); } /// Dummy protocol for tests