|
5 | 5 | use crate::data_types::PhysicalAddress;
|
6 | 6 | use crate::proto::device_path::DevicePath;
|
7 | 7 | use crate::proto::{Protocol, ProtocolPointer};
|
| 8 | +use crate::util::opt_nonnull_to_ptr; |
8 | 9 | use core::ffi::c_void;
|
9 | 10 | use core::ops::{Deref, DerefMut};
|
10 | 11 | use core::ptr::{self, NonNull};
|
11 |
| -use core::slice; |
12 | 12 | use core::sync::atomic::{AtomicPtr, Ordering};
|
13 |
| -use uefi::{table, Char16, Handle, Result, Status, StatusExt}; |
| 13 | +use core::{mem, slice}; |
| 14 | +use uefi::{table, Char16, Event, Handle, Result, Status, StatusExt}; |
14 | 15 |
|
15 | 16 | #[cfg(doc)]
|
16 | 17 | use {
|
|
19 | 20 | };
|
20 | 21 |
|
21 | 22 | pub use uefi::table::boot::{
|
22 |
| - AllocateType, LoadImageSource, OpenProtocolAttributes, OpenProtocolParams, SearchType, |
| 23 | + AllocateType, EventNotifyFn, LoadImageSource, OpenProtocolAttributes, OpenProtocolParams, |
| 24 | + SearchType, |
23 | 25 | };
|
24 |
| -pub use uefi_raw::table::boot::{MemoryType, Tpl}; |
| 26 | +pub use uefi_raw::table::boot::{EventType, MemoryType, Tpl}; |
25 | 27 |
|
26 | 28 | /// Global image handle. This is only set by [`set_image_handle`], and it is
|
27 | 29 | /// only read by [`image_handle`].
|
@@ -162,6 +164,50 @@ pub unsafe fn free_pool(ptr: NonNull<u8>) -> Result {
|
162 | 164 | unsafe { (bt.free_pool)(ptr.as_ptr()) }.to_result()
|
163 | 165 | }
|
164 | 166 |
|
| 167 | +/// Creates an event. |
| 168 | +/// |
| 169 | +/// This function creates a new event of the specified type and returns it. |
| 170 | +/// |
| 171 | +/// Events are created in a "waiting" state, and may switch to a "signaled" |
| 172 | +/// state. If the event type has flag `NotifySignal` set, this will result in |
| 173 | +/// a callback for the event being immediately enqueued at the `notify_tpl` |
| 174 | +/// priority level. If the event type has flag `NotifyWait`, the notification |
| 175 | +/// will be delivered next time `wait_for_event` or `check_event` is called. |
| 176 | +/// In both cases, a `notify_fn` callback must be specified. |
| 177 | +/// |
| 178 | +/// # Safety |
| 179 | +/// |
| 180 | +/// This function is unsafe because callbacks must handle exit from boot |
| 181 | +/// services correctly. |
| 182 | +/// |
| 183 | +/// # Errors |
| 184 | +/// |
| 185 | +/// * [`Status::INVALID_PARAMETER`]: an invalid combination of parameters was provided. |
| 186 | +/// * [`Status::OUT_OF_RESOURCES`]: the event could not be allocated. |
| 187 | +pub unsafe fn create_event( |
| 188 | + event_ty: EventType, |
| 189 | + notify_tpl: Tpl, |
| 190 | + notify_fn: Option<EventNotifyFn>, |
| 191 | + notify_ctx: Option<NonNull<c_void>>, |
| 192 | +) -> Result<Event> { |
| 193 | + let bt = boot_services_raw_panicking(); |
| 194 | + let bt = unsafe { bt.as_ref() }; |
| 195 | + |
| 196 | + let mut event = ptr::null_mut(); |
| 197 | + |
| 198 | + // Safety: the argument types of the function pointers are defined |
| 199 | + // differently, but are compatible and can be safely transmuted. |
| 200 | + let notify_fn: Option<uefi_raw::table::boot::EventNotifyFn> = mem::transmute(notify_fn); |
| 201 | + |
| 202 | + let notify_ctx = opt_nonnull_to_ptr(notify_ctx); |
| 203 | + |
| 204 | + // Now we're ready to call UEFI |
| 205 | + (bt.create_event)(event_ty, notify_tpl, notify_fn, notify_ctx, &mut event).to_result_with_val( |
| 206 | + // OK to unwrap: event is non-null for Status::SUCCESS. |
| 207 | + || Event::from_ptr(event).unwrap(), |
| 208 | + ) |
| 209 | +} |
| 210 | + |
165 | 211 | /// Connect one or more drivers to a controller.
|
166 | 212 | ///
|
167 | 213 | /// Usually one disconnects and then reconnects certain drivers
|
|
0 commit comments