From 1cf328476bb210cc0c8e64c61ddfea2b5b988845 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Wed, 7 Aug 2024 00:44:57 -0400 Subject: [PATCH] boot: Add freestanding check_event Also add corresponding test to uefi-test-runner. --- uefi-test-runner/src/boot/misc.rs | 13 +++++++++++++ uefi/src/boot.rs | 25 +++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/uefi-test-runner/src/boot/misc.rs b/uefi-test-runner/src/boot/misc.rs index f78a8ea97..5768320e4 100644 --- a/uefi-test-runner/src/boot/misc.rs +++ b/uefi-test-runner/src/boot/misc.rs @@ -17,6 +17,7 @@ pub fn test(st: &SystemTable) { info!("Testing timer..."); test_timer(bt); info!("Testing events..."); + test_check_event_freestanding(); test_event_callback(bt); test_callback_with_ctx(bt); info!("Testing watchdog..."); @@ -35,6 +36,18 @@ fn test_tpl() { let _guard = unsafe { boot::raise_tpl(Tpl::NOTIFY) }; } +fn test_check_event_freestanding() { + extern "efiapi" fn callback(_event: Event, _ctx: Option>) { + info!("Callback triggered by check_event"); + } + + let event = + unsafe { boot::create_event(EventType::NOTIFY_WAIT, Tpl::CALLBACK, Some(callback), None) } + .unwrap(); + let is_signaled = boot::check_event(event).unwrap(); + assert!(!is_signaled); +} + fn test_timer(bt: &BootServices) { let timer_event = unsafe { bt.create_event(EventType::TIMER, Tpl::APPLICATION, None, None) } .expect("Failed to create TIMER event"); diff --git a/uefi/src/boot.rs b/uefi/src/boot.rs index 2de6cf680..dbf4b6c73 100644 --- a/uefi/src/boot.rs +++ b/uefi/src/boot.rs @@ -208,6 +208,31 @@ pub unsafe fn create_event( ) } +/// Checks to see if an event is signaled, without blocking execution to wait for it. +/// +/// Returns `Ok(true)` if the event is in the signaled state or `Ok(false)` +/// if the event is not in the signaled state. +/// +/// # Errors +/// +/// Note: Instead of returning [`Status::NOT_READY`] as listed in the UEFI +/// Specification, this function will return `Ok(false)`. +/// +/// * [`Status::INVALID_PARAMETER`]: `event` is of type [`NOTIFY_SIGNAL`]. +/// +/// [`NOTIFY_SIGNAL`]: EventType::NOTIFY_SIGNAL +pub fn check_event(event: Event) -> Result { + let bt = boot_services_raw_panicking(); + let bt = unsafe { bt.as_ref() }; + + let status = unsafe { (bt.check_event)(event.as_ptr()) }; + match status { + Status::SUCCESS => Ok(true), + Status::NOT_READY => Ok(false), + _ => Err(status.into()), + } +} + /// Connect one or more drivers to a controller. /// /// Usually one disconnects and then reconnects certain drivers