|
21 | 21 |
|
22 | 22 | pub use uefi::table::boot::{
|
23 | 23 | AllocateType, EventNotifyFn, LoadImageSource, OpenProtocolAttributes, OpenProtocolParams,
|
24 |
| - SearchType, |
| 24 | + SearchType, TimerTrigger, |
25 | 25 | };
|
26 | 26 | pub use uefi_raw::table::boot::{EventType, MemoryType, Tpl};
|
27 | 27 |
|
@@ -233,6 +233,78 @@ pub fn check_event(event: Event) -> Result<bool> {
|
233 | 233 | }
|
234 | 234 | }
|
235 | 235 |
|
| 236 | +/// Sets the trigger for an event of type [`TIMER`]. |
| 237 | +/// |
| 238 | +/// # Errors |
| 239 | +/// |
| 240 | +/// * [`Status::INVALID_PARAMETER`]: `event` is not valid. |
| 241 | +/// |
| 242 | +/// [`TIMER`]: EventType::TIMER |
| 243 | +pub fn set_timer(event: &Event, trigger_time: TimerTrigger) -> Result { |
| 244 | + let bt = boot_services_raw_panicking(); |
| 245 | + let bt = unsafe { bt.as_ref() }; |
| 246 | + |
| 247 | + let (ty, time) = match trigger_time { |
| 248 | + TimerTrigger::Cancel => (0, 0), |
| 249 | + TimerTrigger::Periodic(hundreds_ns) => (1, hundreds_ns), |
| 250 | + TimerTrigger::Relative(hundreds_ns) => (2, hundreds_ns), |
| 251 | + }; |
| 252 | + unsafe { (bt.set_timer)(event.as_ptr(), ty, time) }.to_result() |
| 253 | +} |
| 254 | + |
| 255 | +/// Stops execution until an event is signaled. |
| 256 | +/// |
| 257 | +/// This function must be called at priority level [`Tpl::APPLICATION`]. |
| 258 | +/// |
| 259 | +/// The input [`Event`] slice is repeatedly iterated from first to last until |
| 260 | +/// an event is signaled or an error is detected. The following checks are |
| 261 | +/// performed on each event: |
| 262 | +/// |
| 263 | +/// * If an event is of type [`NOTIFY_SIGNAL`], then a |
| 264 | +/// [`Status::INVALID_PARAMETER`] error is returned with the index of the |
| 265 | +/// event that caused the failure. |
| 266 | +/// * If an event is in the signaled state, the signaled state is cleared |
| 267 | +/// and the index of the event that was signaled is returned. |
| 268 | +/// * If an event is not in the signaled state but does have a notification |
| 269 | +/// function, the notification function is queued at the event's |
| 270 | +/// notification task priority level. If the execution of the event's |
| 271 | +/// notification function causes the event to be signaled, then the |
| 272 | +/// signaled state is cleared and the index of the event that was signaled |
| 273 | +/// is returned. |
| 274 | +/// |
| 275 | +/// To wait for a specified time, a timer event must be included in `events`. |
| 276 | +/// |
| 277 | +/// To check if an event is signaled without waiting, an already signaled |
| 278 | +/// event can be used as the last event in the slice being checked, or the |
| 279 | +/// [`check_event`] interface may be used. |
| 280 | +/// |
| 281 | +/// # Errors |
| 282 | +/// |
| 283 | +/// * [`Status::INVALID_PARAMETER`]: `events` is empty, or one of the events of |
| 284 | +/// of type [`NOTIFY_SIGNAL`]. |
| 285 | +/// * [`Status::UNSUPPORTED`]: the current TPL is not [`Tpl::APPLICATION`]. |
| 286 | +/// |
| 287 | +/// [`NOTIFY_SIGNAL`]: EventType::NOTIFY_SIGNAL |
| 288 | +pub fn wait_for_event(events: &mut [Event]) -> Result<usize, Option<usize>> { |
| 289 | + let bt = boot_services_raw_panicking(); |
| 290 | + let bt = unsafe { bt.as_ref() }; |
| 291 | + |
| 292 | + let number_of_events = events.len(); |
| 293 | + let events: *mut uefi_raw::Event = events.as_mut_ptr().cast(); |
| 294 | + |
| 295 | + let mut index = 0; |
| 296 | + unsafe { (bt.wait_for_event)(number_of_events, events, &mut index) }.to_result_with( |
| 297 | + || index, |
| 298 | + |s| { |
| 299 | + if s == Status::INVALID_PARAMETER { |
| 300 | + Some(index) |
| 301 | + } else { |
| 302 | + None |
| 303 | + } |
| 304 | + }, |
| 305 | + ) |
| 306 | +} |
| 307 | + |
236 | 308 | /// Connect one or more drivers to a controller.
|
237 | 309 | ///
|
238 | 310 | /// Usually one disconnects and then reconnects certain drivers
|
|
0 commit comments