Skip to content

Commit 118fdd2

Browse files
committed
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 118fdd2

File tree

3 files changed

+57
-0
lines changed

3 files changed

+57
-0
lines changed

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

Lines changed: 33 additions & 0 deletions
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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
- `SimpleNetwork::transmit` now passes the correct buffer size argument.
1111
Previously it incorrectly added the header size to the buffer length, which
1212
could cause the firmware to read past the end of the buffer.
13+
- `boot::signal_event()` is implemented.
1314

1415

1516
# uefi - 0.34.1 (2025-02-07)

uefi/src/boot.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,29 @@ 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+
pub fn signal_event(event: &Event) -> Result {
487+
let bt = boot_services_raw_panicking();
488+
let bt = unsafe { bt.as_ref() };
489+
490+
unsafe { (bt.signal_event)(event.as_ptr()) }.to_result()
491+
}
492+
470493
/// Removes `event` from any event group to which it belongs and closes it.
471494
///
472495
/// If `event` was registered with [`register_protocol_notify`], then the

0 commit comments

Comments
 (0)