Skip to content

Commit 0c533bd

Browse files
Merge pull request #1116 from sky5454/main
[Misc] Add ResetNotification protocol. Add Misc to uefi-test-runner.
2 parents a307922 + fc01d48 commit 0c533bd

File tree

7 files changed

+198
-2
lines changed

7 files changed

+198
-2
lines changed

uefi-raw/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33

44
# uefi-raw - 0.5.2 (2024-04-19)
55

6+
## Added
7+
- Added `ResetNotificationProtocol`.
8+
69
## Added
710
- Added `TimestampProtocol`.
811
- Added `DevicePathToTextProtocol` and `DevicePathFromTextProtocol`.

uefi-raw/src/protocol/misc.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::table::runtime;
12
use crate::{guid, Guid, Status};
23

34
#[derive(Debug)]
@@ -22,3 +23,25 @@ pub struct TimestampProperties {
2223
/// example, a 24-bit counter would have an end value of `0xff_ffff`.
2324
pub end_value: u64,
2425
}
26+
27+
/// Properties of Reset Notification.
28+
#[derive(Debug)]
29+
#[repr(C)]
30+
pub struct ResetNotificationProtocol {
31+
pub register_reset_notify:
32+
unsafe extern "efiapi" fn(this: *mut Self, reset_function: ResetSystemFn) -> Status,
33+
pub unregister_reset_notify:
34+
unsafe extern "efiapi" fn(this: *mut Self, reset_function: ResetSystemFn) -> Status,
35+
}
36+
37+
impl ResetNotificationProtocol {
38+
pub const GUID: Guid = guid!("9da34ae0-eaf9-4bbf-8ec3-fd60226c44be");
39+
}
40+
41+
/// Raw reset notification function, to be called if you register it when a ResetSystem() is executed.
42+
pub type ResetSystemFn = unsafe extern "efiapi" fn(
43+
rt: runtime::ResetType,
44+
status: Status,
45+
data_size: usize,
46+
data: *const u8,
47+
);
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// ANCHOR: all
2+
// ANCHOR: features
3+
#![no_main]
4+
#![no_std]
5+
// ANCHOR_END: features
6+
7+
extern crate alloc;
8+
9+
use log::{info, warn};
10+
11+
// ANCHOR: use
12+
use uefi::prelude::*;
13+
use uefi::proto::misc::Timestamp;
14+
15+
// ANCHOR_END: use
16+
17+
// ANCHOR: entry
18+
#[entry]
19+
fn main(image_handle: Handle, mut system_table: SystemTable<Boot>) -> Status {
20+
// ANCHOR_END: entry
21+
// ANCHOR: services
22+
uefi::helpers::init(&mut system_table).unwrap();
23+
let boot_services = system_table.boot_services();
24+
// ANCHOR_END: services
25+
26+
// ANCHOR: params
27+
test_timestamp(boot_services);
28+
// ANCHOR_END: params
29+
30+
// ANCHOR: stall
31+
boot_services.stall(10_000_000);
32+
// ANCHOR_END: stall
33+
34+
// ANCHOR: return
35+
Status::SUCCESS
36+
}
37+
// ANCHOR_END: return
38+
39+
// ANCHOR: test_timestamp
40+
pub fn test_timestamp(bt: &BootServices) {
41+
// ANCHOR_END: test_timestamp
42+
info!("Running loaded Timestamp Protocol test");
43+
44+
let handle = bt.get_handle_for_protocol::<Timestamp>();
45+
46+
match handle {
47+
Ok(handle) => {
48+
let timestamp_proto = bt
49+
.open_protocol_exclusive::<Timestamp>(handle)
50+
.expect("Founded Timestamp Protocol but open failed");
51+
// ANCHOR: text
52+
let timestamp = timestamp_proto.get_timestamp();
53+
info!("Timestamp Protocol's timestamp: {:?}", timestamp);
54+
55+
let properties = timestamp_proto.get_properties();
56+
info!("Timestamp Protocol's properties: {:?}", properties);
57+
// ANCHOR_END: text
58+
}
59+
Err(err) => {
60+
warn!("Failed to found Timestamp Protocol: {:?}", err);
61+
}
62+
}
63+
}
64+
// ANCHOR_END: all

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

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
use uefi::prelude::*;
2+
use uefi::proto::misc::ResetNotification;
3+
use uefi::table::runtime;
4+
5+
pub fn test(bt: &BootServices) {
6+
test_reset_notification(bt);
7+
}
8+
9+
pub fn test_reset_notification(bt: &BootServices) {
10+
info!("Running loaded ResetNotification protocol test");
11+
12+
let handle = bt
13+
.get_handle_for_protocol::<ResetNotification>()
14+
.expect("Failed to get handles for `ResetNotification` protocol");
15+
16+
let mut reset_notif_proto = bt
17+
.open_protocol_exclusive::<ResetNotification>(handle)
18+
.expect("Founded ResetNotification Protocol but open failed");
19+
20+
// value efi_reset_fn is the type of ResetSystemFn, a function pointer
21+
unsafe extern "efiapi" fn efi_reset_fn(
22+
rt: runtime::ResetType,
23+
status: Status,
24+
data_size: usize,
25+
data: *const u8,
26+
) {
27+
info!("Inside the event callback, hi, efi_reset_fn");
28+
info!("rt: {:?} status: {:?}", rt, status);
29+
info!("size: {:?} data: {:?}", data_size, data);
30+
// do what you want
31+
}
32+
33+
let result = reset_notif_proto.register_reset_notify(efi_reset_fn);
34+
info!(
35+
"ResetNotification Protocol register efi_reset_fn test: {:?}",
36+
result
37+
);
38+
39+
let result = reset_notif_proto.unregister_reset_notify(efi_reset_fn);
40+
info!(
41+
"ResetNotification Protocol unregister efi_reset_fn test: {:?}",
42+
result
43+
);
44+
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use uefi::prelude::*;
2-
32
use uefi::proto::loaded_image::LoadedImage;
43
use uefi::{proto, Identify};
54

@@ -22,6 +21,7 @@ pub fn test(image: Handle, st: &mut SystemTable<Boot>) {
2221
rng::test(bt);
2322
shell_params::test(bt);
2423
string::test(bt);
24+
misc::test(bt);
2525

2626
#[cfg(any(
2727
target_arch = "x86",
@@ -61,6 +61,7 @@ mod device_path;
6161
mod driver;
6262
mod loaded_image;
6363
mod media;
64+
mod misc;
6465
mod network;
6566
mod pi;
6667
mod rng;

uefi/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33

44
# uefi - 0.28.0 (2024-04-19)
55

6+
## Added
7+
- Added `ResetNotification` protocol.
8+
69
## Added
710
- Added `Timestamp` protocol.
811
- Added `UnalignedSlice::as_ptr`.

uefi/src/proto/misc.rs

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
//! Miscellaneous protocols.
22
3+
use uefi_raw::protocol::misc::{
4+
ResetNotificationProtocol, ResetSystemFn, TimestampProperties, TimestampProtocol,
5+
};
6+
37
use crate::proto::unsafe_protocol;
48
use crate::{Result, StatusExt};
5-
use uefi_raw::protocol::misc::{TimestampProperties, TimestampProtocol};
69

710
/// Protocol for retrieving a high-resolution timestamp counter.
11+
/// **Note:**
12+
/// If your UEFI firmware not support timestamp protocol which first added at UEFI spec 2.4 2013.
13+
/// you also could use `RDTSC` in rust, here is a demo [Slint-UI](https://github.com/slint-ui/slint/blob/2c0ba2bc0f151eba8d1fa17839fa2ac58832ca80/examples/uefi-demo/main.rs#L28-L62) who use uefi-rs.
814
#[derive(Debug)]
915
#[repr(transparent)]
1016
#[unsafe_protocol(TimestampProtocol::GUID)]
@@ -23,3 +29,55 @@ impl Timestamp {
2329
unsafe { (self.0.get_properties)(&mut properties) }.to_result_with_val(|| properties)
2430
}
2531
}
32+
33+
/// Protocol to register for a notification when ResetSystem is called.
34+
#[derive(Debug)]
35+
#[repr(transparent)]
36+
#[unsafe_protocol(ResetNotificationProtocol::GUID)]
37+
pub struct ResetNotification(ResetNotificationProtocol);
38+
39+
impl ResetNotification {
40+
/// Register a notification function to be called when ResetSystem() is called.
41+
///
42+
///
43+
/// # Example
44+
///
45+
/// ```rust
46+
/// use log::info;
47+
/// use uefi::Handle;
48+
/// use uefi::prelude::BootServices;
49+
/// use uefi::proto::misc::{ResetNotification};
50+
/// use uefi_raw::Status;
51+
/// use uefi_raw::table::runtime;
52+
///
53+
///
54+
/// // value efi_reset_fn is the type of ResetSystemFn, a function pointer
55+
/// unsafe extern "efiapi" fn efi_reset_fn(
56+
/// rt: runtime::ResetType,
57+
/// status: Status,
58+
/// data_size: usize,
59+
/// data: *const u8,
60+
/// ){
61+
/// info!("Inside the event callback");
62+
/// info!("do what you want");
63+
/// }
64+
///
65+
/// pub fn test(image: Handle, bt: &BootServices) {
66+
///
67+
/// let mut rn = bt
68+
/// .open_protocol_exclusive::<ResetNotification>(image)
69+
/// .expect("Failed to open Timestamp protocol");
70+
///
71+
/// rn.register_reset_notify(efi_reset_fn)
72+
/// .expect("Failed to register a reset notification function!");
73+
/// }
74+
/// ```
75+
pub fn register_reset_notify(&mut self, reset_function: ResetSystemFn) -> Result {
76+
unsafe { (self.0.register_reset_notify)(&mut self.0, reset_function) }.to_result()
77+
}
78+
79+
/// Remove a reset notification function that was previously registered with [`ResetNotification::register_reset_notify`].
80+
pub fn unregister_reset_notify(&mut self, reset_function: ResetSystemFn) -> Result {
81+
unsafe { (self.0.unregister_reset_notify)(&mut self.0, reset_function) }.to_result()
82+
}
83+
}

0 commit comments

Comments
 (0)