Skip to content

Commit e76ad8a

Browse files
Merge pull request #1280 from nicholasbishop/bishop-free-event
boot: Add freestanding version of `create_event`
2 parents f853371 + 14b7281 commit e76ad8a

File tree

3 files changed

+54
-8
lines changed

3 files changed

+54
-8
lines changed

uefi-test-runner/src/proto/media.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use alloc::string::ToString;
22
use core::cell::RefCell;
33
use core::ptr::NonNull;
4+
use uefi::boot;
45
use uefi::data_types::Align;
56
use uefi::prelude::*;
67
use uefi::proto::media::block::BlockIO;
@@ -305,8 +306,7 @@ fn test_raw_disk_io2(handle: Handle, bt: &BootServices) {
305306

306307
unsafe {
307308
// Create the completion event
308-
let mut event = bt
309-
.create_event(EventType::empty(), Tpl::NOTIFY, None, None)
309+
let mut event = boot::create_event(EventType::empty(), Tpl::NOTIFY, None, None)
310310
.expect("Failed to create disk I/O completion event");
311311

312312
// Initialise the task context

uefi/src/boot.rs

+50-4
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@
55
use crate::data_types::PhysicalAddress;
66
use crate::proto::device_path::DevicePath;
77
use crate::proto::{Protocol, ProtocolPointer};
8+
use crate::util::opt_nonnull_to_ptr;
89
use core::ffi::c_void;
910
use core::ops::{Deref, DerefMut};
1011
use core::ptr::{self, NonNull};
11-
use core::slice;
1212
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};
1415

1516
#[cfg(doc)]
1617
use {
@@ -19,9 +20,10 @@ use {
1920
};
2021

2122
pub use uefi::table::boot::{
22-
AllocateType, LoadImageSource, OpenProtocolAttributes, OpenProtocolParams, SearchType,
23+
AllocateType, EventNotifyFn, LoadImageSource, OpenProtocolAttributes, OpenProtocolParams,
24+
SearchType,
2325
};
24-
pub use uefi_raw::table::boot::{MemoryType, Tpl};
26+
pub use uefi_raw::table::boot::{EventType, MemoryType, Tpl};
2527

2628
/// Global image handle. This is only set by [`set_image_handle`], and it is
2729
/// only read by [`image_handle`].
@@ -162,6 +164,50 @@ pub unsafe fn free_pool(ptr: NonNull<u8>) -> Result {
162164
unsafe { (bt.free_pool)(ptr.as_ptr()) }.to_result()
163165
}
164166

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

uefi/src/table/boot.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1616,8 +1616,8 @@ impl<'guid> SearchType<'guid> {
16161616
}
16171617
}
16181618

1619-
/// Raw event notification function
1620-
type EventNotifyFn = unsafe extern "efiapi" fn(event: Event, context: Option<NonNull<c_void>>);
1619+
/// Event notification callback type.
1620+
pub type EventNotifyFn = unsafe extern "efiapi" fn(event: Event, context: Option<NonNull<c_void>>);
16211621

16221622
/// Timer events manipulation.
16231623
#[derive(Debug)]

0 commit comments

Comments
 (0)