diff --git a/src/table/boot.rs b/src/table/boot.rs index 5d48a3bb0..9342cf7bc 100644 --- a/src/table/boot.rs +++ b/src/table/boot.rs @@ -48,7 +48,11 @@ pub struct BootServices { notify_ctx: *mut c_void, event: *mut Event, ) -> Status, - set_timer: usize, + set_timer: unsafe extern "efiapi" fn( + event: Event, + ty: u32, + trigger_time: u64 + ) -> Status, wait_for_event: unsafe extern "efiapi" fn( number_of_events: usize, events: *mut Event, @@ -346,6 +350,16 @@ impl BootServices { ) } + /// Sets the trigger for `EventType::TIMER` event. + pub fn set_timer(&self, event: Event, trigger_time: TimerTrigger) -> Result { + let (ty, time) = match trigger_time { + TimerTrigger::Cancel => (0, 0), + TimerTrigger::Periodic(hundreds_ns) => (1, hundreds_ns), + TimerTrigger::Relative(hundreds_ns) => (2, hundreds_ns), + }; + unsafe { (self.set_timer)(event, ty, time) }.into() + } + /// Query a handle for a certain protocol. /// /// This function attempts to get the protocol implementation of a handle, @@ -805,3 +819,17 @@ bitflags! { /// Raw event notification function type EventNotifyFn = unsafe extern "efiapi" fn(event: Event, context: *mut c_void); + +/// Timer events manipulation +pub enum TimerTrigger { + /// Cancel event's timer + Cancel, + /// The event is to be signaled periodically. + /// Parameter is the period in 100ns units. + /// Delay of 0 will be signalled on every timer tick. + Periodic(u64), + /// The event is to be signaled once in 100ns units. + /// Parameter is the delay in 100ns units. + /// Delay of 0 will be signalled on next timer tick. + Relative(u64), +} diff --git a/uefi-test-runner/src/boot/misc.rs b/uefi-test-runner/src/boot/misc.rs index be53da85a..6ced9780a 100644 --- a/uefi-test-runner/src/boot/misc.rs +++ b/uefi-test-runner/src/boot/misc.rs @@ -1,7 +1,10 @@ use uefi::prelude::*; -use uefi::table::boot::BootServices; +use uefi::table::boot::{BootServices, EventType, Tpl, TimerTrigger}; pub fn test(bt: &BootServices) { + info!("Testing timer..."); + test_timer(bt); + info!("Testing watchdog..."); test_watchdog(bt); } @@ -10,3 +13,13 @@ fn test_watchdog(bt: &BootServices) { bt.set_watchdog_timer(0, 0x10000, None) .expect_success("Could not set watchdog timer"); } + +fn test_timer(bt: &BootServices) { + let timer_event = unsafe { bt.create_event(EventType::TIMER, Tpl::APPLICATION, None) } + .expect_success("Failed to create TIMER event"); + let mut events = [timer_event]; + bt.set_timer(timer_event, TimerTrigger::Relative(5_0/*00 ns */)) + .expect_success("Failed to set timer"); + bt.wait_for_event(&mut events) + .expect_success("Wait for event failed"); +}