@@ -6,6 +6,7 @@ use crate::data_types::PhysicalAddress;
6
6
use crate :: mem:: memory_map:: { MemoryMapBackingMemory , MemoryMapKey , MemoryMapMeta , MemoryMapOwned } ;
7
7
use crate :: proto:: device_path:: DevicePath ;
8
8
use crate :: proto:: { Protocol , ProtocolPointer } ;
9
+ use crate :: table:: Revision ;
9
10
use crate :: util:: opt_nonnull_to_ptr;
10
11
use core:: ffi:: c_void;
11
12
use core:: ops:: { Deref , DerefMut } ;
@@ -267,6 +268,81 @@ pub unsafe fn create_event(
267
268
)
268
269
}
269
270
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
+
270
346
/// Checks to see if an event is signaled, without blocking execution to wait for it.
271
347
///
272
348
/// Returns `Ok(true)` if the event is in the signaled state or `Ok(false)`
0 commit comments