Skip to content

Commit 09d1645

Browse files
authored
Merge pull request #1313 from nicholasbishop/bishop-create-event-ex
boot: Add freestanding create_event_ex
2 parents 6d2331a + d23da7e commit 09d1645

File tree

2 files changed

+78
-1
lines changed

2 files changed

+78
-1
lines changed

uefi-test-runner/src/boot/misc.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ fn test_check_event_freestanding() {
5757

5858
fn test_timer_freestanding() {
5959
let timer_event =
60-
unsafe { boot::create_event(EventType::TIMER, Tpl::CALLBACK, None, None) }.unwrap();
60+
unsafe { boot::create_event_ex(EventType::TIMER, Tpl::CALLBACK, None, None, None) }
61+
.unwrap();
6162
let mut events = unsafe { [timer_event.unsafe_clone()] };
6263
boot::set_timer(&timer_event, TimerTrigger::Relative(5_0 /*00 ns */)).unwrap();
6364
assert_eq!(boot::wait_for_event(&mut events).unwrap(), 0);

uefi/src/boot.rs

+76
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::data_types::PhysicalAddress;
66
use crate::mem::memory_map::{MemoryMapBackingMemory, MemoryMapKey, MemoryMapMeta, MemoryMapOwned};
77
use crate::proto::device_path::DevicePath;
88
use crate::proto::{Protocol, ProtocolPointer};
9+
use crate::table::Revision;
910
use crate::util::opt_nonnull_to_ptr;
1011
use core::ffi::c_void;
1112
use core::ops::{Deref, DerefMut};
@@ -267,6 +268,81 @@ pub unsafe fn create_event(
267268
)
268269
}
269270

271+
/// Creates an event in an event group.
272+
///
273+
/// The event's notification function, context, and task priority are specified
274+
/// by `notify_fn`, `notify_ctx`, and `notify_tpl`, respectively. The event will
275+
/// be added to the group of events identified by `event_group`.
276+
///
277+
/// If no group is specified by `event_group`, this function behaves as if the
278+
/// same parameters had been passed to `create_event()`.
279+
///
280+
/// Event groups are collections of events identified by a shared GUID where,
281+
/// when one member event is signaled, all other events are signaled and their
282+
/// individual notification actions are taken. All events are guaranteed to be
283+
/// signaled before the first notification action is taken. All notification
284+
/// functions will be executed in the order specified by their `Tpl`.
285+
///
286+
/// An event can only be part of a single event group. An event may be removed
287+
/// from an event group by calling [`close_event`].
288+
///
289+
/// The [`EventType`] of an event uses the same values as `create_event()`, except that
290+
/// `EventType::SIGNAL_EXIT_BOOT_SERVICES` and `EventType::SIGNAL_VIRTUAL_ADDRESS_CHANGE`
291+
/// are not valid.
292+
///
293+
/// For events of type `NOTIFY_SIGNAL` or `NOTIFY_WAIT`, `notify_fn` must be
294+
/// `Some` and `notify_tpl` must be a valid task priority level. For other event
295+
/// types these parameters are ignored.
296+
///
297+
/// More than one event of type `EventType::TIMER` may be part of a single event
298+
/// group. However, there is no mechanism for determining which of the timers
299+
/// was signaled.
300+
///
301+
/// This operation is only supported starting with UEFI 2.0; earlier versions
302+
/// will fail with [`Status::UNSUPPORTED`].
303+
///
304+
/// # Safety
305+
///
306+
/// The caller must ensure they are passing a valid `Guid` as `event_group`, if applicable.
307+
///
308+
/// # Errors
309+
///
310+
/// * [`Status::INVALID_PARAMETER`]: an invalid combination of parameters was provided.
311+
/// * [`Status::OUT_OF_RESOURCES`]: the event could not be allocated.
312+
pub unsafe fn create_event_ex(
313+
event_type: EventType,
314+
notify_tpl: Tpl,
315+
notify_fn: Option<EventNotifyFn>,
316+
notify_ctx: Option<NonNull<c_void>>,
317+
event_group: Option<NonNull<Guid>>,
318+
) -> Result<Event> {
319+
let bt = boot_services_raw_panicking();
320+
let bt = unsafe { bt.as_ref() };
321+
322+
if bt.header.revision < Revision::EFI_2_00 {
323+
return Err(Status::UNSUPPORTED.into());
324+
}
325+
326+
let mut event = ptr::null_mut();
327+
328+
// Safety: the argument types of the function pointers are defined
329+
// differently, but are compatible and can be safely transmuted.
330+
let notify_fn: Option<uefi_raw::table::boot::EventNotifyFn> = mem::transmute(notify_fn);
331+
332+
(bt.create_event_ex)(
333+
event_type,
334+
notify_tpl,
335+
notify_fn,
336+
opt_nonnull_to_ptr(notify_ctx),
337+
opt_nonnull_to_ptr(event_group),
338+
&mut event,
339+
)
340+
.to_result_with_val(
341+
// OK to unwrap: event is non-null for Status::SUCCESS.
342+
|| Event::from_ptr(event).unwrap(),
343+
)
344+
}
345+
270346
/// Checks to see if an event is signaled, without blocking execution to wait for it.
271347
///
272348
/// Returns `Ok(true)` if the event is in the signaled state or `Ok(false)`

0 commit comments

Comments
 (0)