Skip to content

Commit cc27f2f

Browse files
boot: Add freestanding wait_for_event
1 parent d684b13 commit cc27f2f

File tree

1 file changed

+53
-0
lines changed

1 file changed

+53
-0
lines changed

uefi/src/boot.rs

+53
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,59 @@ pub fn set_timer(event: &Event, trigger_time: TimerTrigger) -> Result {
252252
unsafe { (bt.set_timer)(event.as_ptr(), ty, time) }.to_result()
253253
}
254254

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+
255308
/// Connect one or more drivers to a controller.
256309
///
257310
/// Usually one disconnects and then reconnects certain drivers

0 commit comments

Comments
 (0)