@@ -6,6 +6,7 @@ use crate::data_types::PhysicalAddress;
66use crate :: mem:: memory_map:: { MemoryMapBackingMemory , MemoryMapKey , MemoryMapMeta , MemoryMapOwned } ;
77use crate :: proto:: device_path:: DevicePath ;
88use crate :: proto:: { Protocol , ProtocolPointer } ;
9+ use crate :: table:: Revision ;
910use crate :: util:: opt_nonnull_to_ptr;
1011use core:: ffi:: c_void;
1112use 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