Skip to content

Commit 04be50f

Browse files
committed
[Misc] Add ResetNotification protocol. Add Misc to uefi-test-runner.
1 parent 6093205 commit 04be50f

File tree

6 files changed

+182
-12
lines changed

6 files changed

+182
-12
lines changed

uefi-raw/CHANGELOG.md

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

3+
## Added
4+
- Added `ResetNotification`.
5+
36
## Added
47
- Added `TimestampProtocol`.
58

uefi-raw/src/protocol/misc.rs

+23
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::{guid, Guid, Status};
2+
use crate::table::runtime;
23

34
#[derive(Debug)]
45
#[repr(C)]
@@ -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: unsafe extern "efiapi" fn(this: *const Self, reset_function: Option<ResetSystemFn>) -> Status,
32+
pub unregister_reset_notify: unsafe extern "efiapi" fn(this: *const Self, reset_function: Option<ResetSystemFn>) -> Status,
33+
}
34+
35+
impl ResetNotificationProtocol {
36+
pub const GUID: Guid = guid!("9da34ae0-eaf9-4bbf-8ec3-fd60226c44be");
37+
}
38+
39+
40+
/// Raw reset notification function, to be called if you register it when a RestSystem() is executed.
41+
// copy from uefi-raw/src/table/runtime.rs:53 at commit@6093205c3eb27b2e78be4c003c04d46679bff420
42+
pub type ResetSystemFn = unsafe extern "efiapi" fn(
43+
rt: runtime::ResetType,
44+
status: Status,
45+
data_size: usize,
46+
data: *const u8,
47+
);

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

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
use uefi::prelude::*;
2+
use uefi::proto::misc::{ResetNotification, Timestamp};
3+
use uefi::table::runtime;
4+
5+
///
6+
/// you may see those log, it's nothing just for your computer firmware does not support the new UEFI feature.
7+
///
8+
/// ```sh
9+
/// [ INFO]: uefi-test-runner\src\proto\misc.rs@012: Running loaded Timestamp Protocol test
10+
/// [ WARN]: uefi-test-runner\src\proto\misc.rs@026: Failed to open Timestamp Protocol: Error { status: UNSUPPORTED, data: () }
11+
/// [ INFO]: uefi-test-runner\src\proto\misc.rs@033: Running loaded ResetNotification protocol test
12+
/// [ WARN]: uefi-test-runner\src\proto\misc.rs@068: Failed to open ResetNotification Protocol: Error { status: UNSUPPORTED, data: () }
13+
/// ```
14+
pub fn test(image: Handle, bt: &BootServices) {
15+
test_timestamp(image, bt);
16+
test_reset_notification(image, bt);
17+
}
18+
19+
pub fn test_timestamp(image: Handle, bt: &BootServices) {
20+
info!("Running loaded Timestamp Protocol test");
21+
22+
let result = bt
23+
.open_protocol_exclusive::<Timestamp>(image);
24+
25+
match result {
26+
Ok(timestamp_proto) => {
27+
let timestamp = timestamp_proto.get_timestamp();
28+
info!("Timestamp Protocol's timestamp: {:?}", timestamp);
29+
30+
let properties = timestamp_proto.get_properties();
31+
info!("Timestamp Protocol's properties: {:?}", properties);
32+
}
33+
Err(err) => {
34+
warn!("Failed to open Timestamp Protocol: {:?}", err);
35+
}
36+
}
37+
}
38+
39+
40+
pub fn test_reset_notification(image: Handle, bt: &BootServices) {
41+
info!("Running loaded ResetNotification protocol test");
42+
43+
let result = bt
44+
.open_protocol_exclusive::<ResetNotification>(image);
45+
46+
match result {
47+
Ok(mut reset_notif_proto) => {
48+
let result = reset_notif_proto.register_reset_notify(None);
49+
info!("ResetNotification Protocol register null test: {:?}", result);
50+
51+
let result = reset_notif_proto.unregister_reset_notify(None);
52+
info!("ResetNotification Protocol unregister null test: {:?}", result);
53+
54+
55+
56+
// value efi_reset_fn is the type of ResetSystemFn, a function pointer
57+
unsafe extern "efiapi" fn efi_reset_fn(
58+
rt: runtime::ResetType,
59+
status: Status,
60+
data_size: usize,
61+
data: *const u8,
62+
) {
63+
info!("Inside the event callback, hi, efi_reset_fn");
64+
info!("rt: {:?} status: {:?}", rt, status);
65+
info!("size: {:?} data: {:?}", data_size, data);
66+
// do what you want
67+
}
68+
69+
let result = reset_notif_proto.register_reset_notify(Some(efi_reset_fn));
70+
info!("ResetNotification Protocol register efi_reset_fn test: {:?}", result);
71+
72+
let result = reset_notif_proto.unregister_reset_notify(Some(efi_reset_fn));
73+
info!("ResetNotification Protocol unregister efi_reset_fn test: {:?}", result);
74+
}
75+
Err(err) => {
76+
warn!("Failed to open ResetNotification Protocol: {:?}", err);
77+
}
78+
}
79+
}
80+

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

+11-10
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1+
use uefi::{Identify, proto};
12
use uefi::prelude::*;
2-
33
use uefi::proto::loaded_image::LoadedImage;
4-
use uefi::{proto, Identify};
54

65
pub fn test(image: Handle, st: &mut SystemTable<Boot>) {
76
info!("Testing various protocols");
@@ -22,12 +21,13 @@ 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(image, bt);
2525

2626
#[cfg(any(
27-
target_arch = "x86",
28-
target_arch = "x86_64",
29-
target_arch = "arm",
30-
target_arch = "aarch64"
27+
target_arch = "x86",
28+
target_arch = "x86_64",
29+
target_arch = "arm",
30+
target_arch = "aarch64"
3131
))]
3232
shim::test(bt);
3333
tcg::test(bt);
@@ -66,11 +66,12 @@ mod pi;
6666
mod rng;
6767
mod shell_params;
6868
#[cfg(any(
69-
target_arch = "x86",
70-
target_arch = "x86_64",
71-
target_arch = "arm",
72-
target_arch = "aarch64"
69+
target_arch = "x86",
70+
target_arch = "x86_64",
71+
target_arch = "arm",
72+
target_arch = "aarch64"
7373
))]
7474
mod shim;
7575
mod string;
7676
mod tcg;
77+
mod misc;

uefi/CHANGELOG.md

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

3+
## Added
4+
- Added `ResetNotification` protocol.
5+
36
## Added
47
- Added `Timestamp` protocol.
58

uefi/src/proto/misc.rs

+62-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
//! Miscellaneous protocols.
22
3-
use crate::proto::unsafe_protocol;
3+
use uefi_raw::protocol::misc::{ResetNotificationProtocol, ResetSystemFn, TimestampProperties, TimestampProtocol};
4+
45
use crate::{Result, StatusExt};
5-
use uefi_raw::protocol::misc::{TimestampProperties, TimestampProtocol};
6+
use crate::proto::unsafe_protocol;
67

78
/// Protocol for retrieving a high-resolution timestamp counter.
89
#[derive(Debug)]
@@ -23,3 +24,62 @@ impl Timestamp {
2324
unsafe { (self.0.get_properties)(&mut properties) }.to_result_with_val(|| properties)
2425
}
2526
}
27+
28+
/// Protocol to register for a notification when ResetSystem is called.
29+
#[derive(Debug)]
30+
#[repr(transparent)]
31+
#[unsafe_protocol(ResetNotificationProtocol::GUID)]
32+
pub struct ResetNotification(ResetNotificationProtocol);
33+
34+
impl ResetNotification {
35+
/// Register a notification function to be called when ResetSystem() is called.
36+
///
37+
///
38+
/// #example
39+
/// ```rust
40+
/// use log::info;
41+
/// use uefi::Handle;
42+
/// use uefi::prelude::BootServices;
43+
/// use uefi::proto::misc::{ResetNotification};
44+
/// use uefi_raw::Status;
45+
/// use uefi_raw::table::runtime;
46+
///
47+
/// // value efi_reset_fn is the type of ResetSystemFn, a function pointer
48+
/// unsafe extern "efiapi" fn efi_reset_fn(
49+
/// rt: runtime::ResetType,
50+
/// status: Status,
51+
/// data_size: usize,
52+
/// data: *const u8,
53+
/// ){
54+
/// info!("Inside the event callback");
55+
/// // do what you want
56+
/// }
57+
///
58+
/// pub fn test(image: Handle, bt: &BootServices) {
59+
///
60+
/// /* get protocol*/
61+
/// let mut rn = bt
62+
/// .open_protocol_exclusive::<ResetNotification>(image)
63+
/// .expect("Failed to open Timestamp protocol");
64+
/// rn.register_reset_notify(Some(efi_reset_fn));
65+
/// }
66+
/// ```
67+
pub fn register_reset_notify(&mut self, reset_function: Option<ResetSystemFn>) -> Result {
68+
unsafe {
69+
(self.0.register_reset_notify)(&mut self.0, reset_function)
70+
}.to_result()
71+
}
72+
73+
/// Removes a reset notification function that has been previously registered with RegisterResetNotify().
74+
/// Tips: RegisterResetNotify() has named as `register_reset_notify()` in uefi-rs.
75+
pub fn unregister_reset_notify(&mut self, reset_function: Option<ResetSystemFn>) -> Result {
76+
unsafe {
77+
(self.0.unregister_reset_notify)(&mut self.0, reset_function)
78+
}.to_result()
79+
}
80+
}
81+
82+
83+
// !TODO: make a safe FFI for raw function 'ResetSystemFn'
84+
// copy and edit from uefi-raw/src/table/runtime.rs:84 at commit@6093205c3eb27b2e78be4c003c04d46679bff420
85+
// pub fn new(&self, rt: ResetType, status: Status, data: Option<&[u8]>) -> Option<ResetSystemFn>

0 commit comments

Comments
 (0)