Skip to content

Commit 42dd1f0

Browse files
authored
Merge pull request #1324 from rust-osdev/bishop-reg-proto-notify
boot: Add freestanding register_protocol_notify
2 parents fd6a001 + 2758846 commit 42dd1f0

File tree

2 files changed

+45
-2
lines changed

2 files changed

+45
-2
lines changed

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

+15
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ pub fn test(st: &SystemTable<Boot>) {
2525
test_watchdog(bt);
2626
info!("Testing protocol handler services...");
2727
test_register_protocol_notify(bt);
28+
test_register_protocol_notify_freestanding();
2829
test_protocol_interface_management();
2930
test_install_protocol_interface(bt);
3031
test_reinstall_protocol_interface(bt);
@@ -156,6 +157,20 @@ fn test_register_protocol_notify(bt: &BootServices) {
156157
.expect("Failed to register protocol notify fn");
157158
}
158159

160+
fn test_register_protocol_notify_freestanding() {
161+
unsafe extern "efiapi" fn callback(_event: Event, _context: Option<NonNull<c_void>>) {
162+
info!("in callback for test_register_protocol_notify_freestanding")
163+
}
164+
165+
let protocol = &TestProtocol::GUID;
166+
let event = unsafe {
167+
boot::create_event(EventType::NOTIFY_SIGNAL, Tpl::NOTIFY, Some(callback), None).unwrap()
168+
};
169+
170+
boot::register_protocol_notify(protocol, &event)
171+
.expect("Failed to register protocol notify fn");
172+
}
173+
159174
fn test_protocol_interface_management() {
160175
let mut interface = TestProtocol { data: 123 };
161176
let interface_ptr: *mut _ = &mut interface;

uefi/src/boot.rs

+30-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use crate::proto::device_path::LoadedImageDevicePath;
2929

3030
pub use uefi::table::boot::{
3131
AllocateType, EventNotifyFn, LoadImageSource, OpenProtocolAttributes, OpenProtocolParams,
32-
SearchType, TimerTrigger,
32+
ProtocolSearchKey, SearchType, TimerTrigger,
3333
};
3434
pub use uefi_raw::table::boot::{EventType, MemoryAttribute, MemoryDescriptor, MemoryType, Tpl};
3535

@@ -375,7 +375,7 @@ pub fn check_event(event: Event) -> Result<bool> {
375375

376376
/// Removes `event` from any event group to which it belongs and closes it.
377377
///
378-
/// If `event` was registered with `register_protocol_notify`, then the
378+
/// If `event` was registered with [`register_protocol_notify`], then the
379379
/// corresponding registration will be removed. Calling this function within the
380380
/// corresponding notify function is allowed.
381381
///
@@ -616,6 +616,34 @@ pub unsafe fn uninstall_protocol_interface(
616616
(bt.uninstall_protocol_interface)(handle.as_ptr(), protocol, interface).to_result()
617617
}
618618

619+
/// Registers `event` to be signaled whenever a protocol interface is registered for
620+
/// `protocol` by [`install_protocol_interface`] or [`reinstall_protocol_interface`].
621+
///
622+
/// If successful, a [`SearchType::ByRegisterNotify`] is returned. This can be
623+
/// used with [`locate_handle`] or [`locate_handle_buffer`] to identify the
624+
/// newly (re)installed handles that support `protocol`.
625+
///
626+
/// Events can be unregistered from protocol interface notification by calling [`close_event`].
627+
///
628+
/// # Errors
629+
///
630+
/// * [`Status::OUT_OF_RESOURCES`]: the event could not be allocated.
631+
pub fn register_protocol_notify(
632+
protocol: &'static Guid,
633+
event: &Event,
634+
) -> Result<SearchType<'static>> {
635+
let bt = boot_services_raw_panicking();
636+
let bt = unsafe { bt.as_ref() };
637+
638+
let mut key = ptr::null();
639+
unsafe { (bt.register_protocol_notify)(protocol, event.as_ptr(), &mut key) }.to_result_with_val(
640+
|| {
641+
// OK to unwrap: key is non-null for Status::SUCCESS.
642+
SearchType::ByRegisterNotify(ProtocolSearchKey(NonNull::new(key.cast_mut()).unwrap()))
643+
},
644+
)
645+
}
646+
619647
/// Get the list of protocol interface [`Guids`][Guid] that are installed
620648
/// on a [`Handle`].
621649
///

0 commit comments

Comments
 (0)