Skip to content

Commit 782392c

Browse files
quic-bjorandenicholasbishop
authored andcommitted
uefi: Implement SignalEvent() boot services function
Missing from the boot services is the SignalEvent() function, which is used to place signals into a signaled state. Implement this to allow applications to signal e.g. event groups. Also implement a test case, checking that the event callback is signaled when the newly introduced function is invoked. Signed-off-by: Bjorn Andersson <[email protected]>
1 parent ed8fd58 commit 782392c

File tree

3 files changed

+61
-0
lines changed

3 files changed

+61
-0
lines changed

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

+33
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ pub fn test() {
1717
info!("Testing events...");
1818
test_check_event();
1919
test_callback_with_ctx();
20+
test_signal_event();
2021
info!("Testing watchdog...");
2122
test_watchdog();
2223
info!("Testing protocol handler services...");
@@ -92,6 +93,38 @@ fn test_callback_with_ctx() {
9293
assert_eq!(data, 456);
9394
}
9495

96+
fn test_signal_event() {
97+
let mut data = 123u32;
98+
99+
extern "efiapi" fn callback(_event: Event, ctx: Option<NonNull<c_void>>) {
100+
info!("Inside the signal event callback");
101+
// Safety: this callback is run within the parent function's
102+
// scope, so the context pointer is still valid.
103+
unsafe {
104+
let ctx = ctx.unwrap().as_ptr().cast::<u32>();
105+
*ctx = 456;
106+
}
107+
}
108+
109+
let ctx: *mut u32 = &mut data;
110+
let ctx = NonNull::new(ctx.cast::<c_void>()).unwrap();
111+
112+
let event = unsafe {
113+
boot::create_event(
114+
EventType::NOTIFY_SIGNAL,
115+
Tpl::CALLBACK,
116+
Some(callback),
117+
Some(ctx),
118+
)
119+
.expect("Failed to create event with context")
120+
};
121+
122+
boot::signal_event(&event).expect("Failed to signal event");
123+
124+
// Check that `data` was updated inside the event callback.
125+
assert_eq!(data, 456);
126+
}
127+
95128
fn test_watchdog() {
96129
// There's no way to check the watchdog timer value, so just test setting it.
97130

uefi/CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# uefi - [Unreleased]
22

3+
## Added
4+
- Added `boot::signal_event`.
5+
36
## Changed
47
- **Breaking:** Removed `BootPolicyError` as `BootPolicy` construction is no
58
longer fallible. `BootPolicy` now tightly integrates the new `Boolean` type

uefi/src/boot.rs

+25
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,31 @@ pub fn check_event(event: Event) -> Result<bool> {
467467
}
468468
}
469469

470+
/// Places the supplied `event` in the signaled state. If `event` is already in
471+
/// the signaled state, the function returns successfully. If `event` is of type
472+
/// [`NOTIFY_SIGNAL`], the event's notification function is scheduled to be
473+
/// invoked at the event's notification task priority level.
474+
///
475+
/// This function may be invoked from any task priority level.
476+
///
477+
/// If `event` is part of an event group, then all of the events in the event
478+
/// group are also signaled and their notification functions are scheduled.
479+
///
480+
/// When signaling an event group, it is possible to create an event in the
481+
/// group, signal it and then close the event to remove it from the group.
482+
///
483+
/// # Errors
484+
///
485+
/// The specification does not list any errors.
486+
///
487+
/// [`NOTIFY_SIGNAL`]: EventType::NOTIFY_SIGNAL
488+
pub fn signal_event(event: &Event) -> Result {
489+
let bt = boot_services_raw_panicking();
490+
let bt = unsafe { bt.as_ref() };
491+
492+
unsafe { (bt.signal_event)(event.as_ptr()) }.to_result()
493+
}
494+
470495
/// Removes `event` from any event group to which it belongs and closes it.
471496
///
472497
/// If `event` was registered with [`register_protocol_notify`], then the

0 commit comments

Comments
 (0)