From 04be50fe34f6f919aa647573d43c112363337091 Mon Sep 17 00:00:00 2001 From: sky5454 <12370628+sky5454@users.noreply.github.com> Date: Fri, 5 Apr 2024 16:48:34 +0800 Subject: [PATCH 1/7] [Misc] Add ResetNotification protocol. Add Misc to uefi-test-runner. --- uefi-raw/CHANGELOG.md | 3 ++ uefi-raw/src/protocol/misc.rs | 23 +++++++++ uefi-test-runner/src/proto/misc.rs | 80 ++++++++++++++++++++++++++++++ uefi-test-runner/src/proto/mod.rs | 21 ++++---- uefi/CHANGELOG.md | 3 ++ uefi/src/proto/misc.rs | 64 +++++++++++++++++++++++- 6 files changed, 182 insertions(+), 12 deletions(-) create mode 100644 uefi-test-runner/src/proto/misc.rs diff --git a/uefi-raw/CHANGELOG.md b/uefi-raw/CHANGELOG.md index d8c669f7a..81660784c 100644 --- a/uefi-raw/CHANGELOG.md +++ b/uefi-raw/CHANGELOG.md @@ -1,5 +1,8 @@ # uefi-raw - [Unreleased] +## Added +- Added `ResetNotification`. + ## Added - Added `TimestampProtocol`. diff --git a/uefi-raw/src/protocol/misc.rs b/uefi-raw/src/protocol/misc.rs index a7a3a905a..8ac33c2a7 100644 --- a/uefi-raw/src/protocol/misc.rs +++ b/uefi-raw/src/protocol/misc.rs @@ -1,4 +1,5 @@ use crate::{guid, Guid, Status}; +use crate::table::runtime; #[derive(Debug)] #[repr(C)] @@ -22,3 +23,25 @@ pub struct TimestampProperties { /// example, a 24-bit counter would have an end value of `0xff_ffff`. pub end_value: u64, } + +/// Properties of Reset Notification. +#[derive(Debug)] +#[repr(C)] +pub struct ResetNotificationProtocol { + pub register_reset_notify: unsafe extern "efiapi" fn(this: *const Self, reset_function: Option) -> Status, + pub unregister_reset_notify: unsafe extern "efiapi" fn(this: *const Self, reset_function: Option) -> Status, +} + +impl ResetNotificationProtocol { + pub const GUID: Guid = guid!("9da34ae0-eaf9-4bbf-8ec3-fd60226c44be"); +} + + +/// Raw reset notification function, to be called if you register it when a RestSystem() is executed. +// copy from uefi-raw/src/table/runtime.rs:53 at commit@6093205c3eb27b2e78be4c003c04d46679bff420 +pub type ResetSystemFn = unsafe extern "efiapi" fn( + rt: runtime::ResetType, + status: Status, + data_size: usize, + data: *const u8, +); diff --git a/uefi-test-runner/src/proto/misc.rs b/uefi-test-runner/src/proto/misc.rs new file mode 100644 index 000000000..14abc06d9 --- /dev/null +++ b/uefi-test-runner/src/proto/misc.rs @@ -0,0 +1,80 @@ +use uefi::prelude::*; +use uefi::proto::misc::{ResetNotification, Timestamp}; +use uefi::table::runtime; + +/// +/// you may see those log, it's nothing just for your computer firmware does not support the new UEFI feature. +/// +/// ```sh +/// [ INFO]: uefi-test-runner\src\proto\misc.rs@012: Running loaded Timestamp Protocol test +/// [ WARN]: uefi-test-runner\src\proto\misc.rs@026: Failed to open Timestamp Protocol: Error { status: UNSUPPORTED, data: () } +/// [ INFO]: uefi-test-runner\src\proto\misc.rs@033: Running loaded ResetNotification protocol test +/// [ WARN]: uefi-test-runner\src\proto\misc.rs@068: Failed to open ResetNotification Protocol: Error { status: UNSUPPORTED, data: () } +/// ``` +pub fn test(image: Handle, bt: &BootServices) { + test_timestamp(image, bt); + test_reset_notification(image, bt); +} + +pub fn test_timestamp(image: Handle, bt: &BootServices) { + info!("Running loaded Timestamp Protocol test"); + + let result = bt + .open_protocol_exclusive::(image); + + match result { + Ok(timestamp_proto) => { + let timestamp = timestamp_proto.get_timestamp(); + info!("Timestamp Protocol's timestamp: {:?}", timestamp); + + let properties = timestamp_proto.get_properties(); + info!("Timestamp Protocol's properties: {:?}", properties); + } + Err(err) => { + warn!("Failed to open Timestamp Protocol: {:?}", err); + } + } +} + + +pub fn test_reset_notification(image: Handle, bt: &BootServices) { + info!("Running loaded ResetNotification protocol test"); + + let result = bt + .open_protocol_exclusive::(image); + + match result { + Ok(mut reset_notif_proto) => { + let result = reset_notif_proto.register_reset_notify(None); + info!("ResetNotification Protocol register null test: {:?}", result); + + let result = reset_notif_proto.unregister_reset_notify(None); + info!("ResetNotification Protocol unregister null test: {:?}", result); + + + + // value efi_reset_fn is the type of ResetSystemFn, a function pointer + unsafe extern "efiapi" fn efi_reset_fn( + rt: runtime::ResetType, + status: Status, + data_size: usize, + data: *const u8, + ) { + info!("Inside the event callback, hi, efi_reset_fn"); + info!("rt: {:?} status: {:?}", rt, status); + info!("size: {:?} data: {:?}", data_size, data); + // do what you want + } + + let result = reset_notif_proto.register_reset_notify(Some(efi_reset_fn)); + info!("ResetNotification Protocol register efi_reset_fn test: {:?}", result); + + let result = reset_notif_proto.unregister_reset_notify(Some(efi_reset_fn)); + info!("ResetNotification Protocol unregister efi_reset_fn test: {:?}", result); + } + Err(err) => { + warn!("Failed to open ResetNotification Protocol: {:?}", err); + } + } +} + diff --git a/uefi-test-runner/src/proto/mod.rs b/uefi-test-runner/src/proto/mod.rs index b232e3cf9..413033fbb 100644 --- a/uefi-test-runner/src/proto/mod.rs +++ b/uefi-test-runner/src/proto/mod.rs @@ -1,7 +1,6 @@ +use uefi::{Identify, proto}; use uefi::prelude::*; - use uefi::proto::loaded_image::LoadedImage; -use uefi::{proto, Identify}; pub fn test(image: Handle, st: &mut SystemTable) { info!("Testing various protocols"); @@ -22,12 +21,13 @@ pub fn test(image: Handle, st: &mut SystemTable) { rng::test(bt); shell_params::test(bt); string::test(bt); + misc::test(image, bt); #[cfg(any( - target_arch = "x86", - target_arch = "x86_64", - target_arch = "arm", - target_arch = "aarch64" + target_arch = "x86", + target_arch = "x86_64", + target_arch = "arm", + target_arch = "aarch64" ))] shim::test(bt); tcg::test(bt); @@ -66,11 +66,12 @@ mod pi; mod rng; mod shell_params; #[cfg(any( - target_arch = "x86", - target_arch = "x86_64", - target_arch = "arm", - target_arch = "aarch64" +target_arch = "x86", +target_arch = "x86_64", +target_arch = "arm", +target_arch = "aarch64" ))] mod shim; mod string; mod tcg; +mod misc; diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index e3486f78d..7a5847d9f 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -1,5 +1,8 @@ # uefi - [Unreleased] +## Added +- Added `ResetNotification` protocol. + ## Added - Added `Timestamp` protocol. diff --git a/uefi/src/proto/misc.rs b/uefi/src/proto/misc.rs index 339c8ea6e..fa645081e 100644 --- a/uefi/src/proto/misc.rs +++ b/uefi/src/proto/misc.rs @@ -1,8 +1,9 @@ //! Miscellaneous protocols. -use crate::proto::unsafe_protocol; +use uefi_raw::protocol::misc::{ResetNotificationProtocol, ResetSystemFn, TimestampProperties, TimestampProtocol}; + use crate::{Result, StatusExt}; -use uefi_raw::protocol::misc::{TimestampProperties, TimestampProtocol}; +use crate::proto::unsafe_protocol; /// Protocol for retrieving a high-resolution timestamp counter. #[derive(Debug)] @@ -23,3 +24,62 @@ impl Timestamp { unsafe { (self.0.get_properties)(&mut properties) }.to_result_with_val(|| properties) } } + +/// Protocol to register for a notification when ResetSystem is called. +#[derive(Debug)] +#[repr(transparent)] +#[unsafe_protocol(ResetNotificationProtocol::GUID)] +pub struct ResetNotification(ResetNotificationProtocol); + +impl ResetNotification { + /// Register a notification function to be called when ResetSystem() is called. + /// + /// + /// #example + /// ```rust + /// use log::info; + /// use uefi::Handle; + /// use uefi::prelude::BootServices; + /// use uefi::proto::misc::{ResetNotification}; + /// use uefi_raw::Status; + /// use uefi_raw::table::runtime; + /// + /// // value efi_reset_fn is the type of ResetSystemFn, a function pointer + /// unsafe extern "efiapi" fn efi_reset_fn( + /// rt: runtime::ResetType, + /// status: Status, + /// data_size: usize, + /// data: *const u8, + /// ){ + /// info!("Inside the event callback"); + /// // do what you want + /// } + /// + /// pub fn test(image: Handle, bt: &BootServices) { + /// + /// /* get protocol*/ + /// let mut rn = bt + /// .open_protocol_exclusive::(image) + /// .expect("Failed to open Timestamp protocol"); + /// rn.register_reset_notify(Some(efi_reset_fn)); + /// } + /// ``` + pub fn register_reset_notify(&mut self, reset_function: Option) -> Result { + unsafe { + (self.0.register_reset_notify)(&mut self.0, reset_function) + }.to_result() + } + + /// Removes a reset notification function that has been previously registered with RegisterResetNotify(). + /// Tips: RegisterResetNotify() has named as `register_reset_notify()` in uefi-rs. + pub fn unregister_reset_notify(&mut self, reset_function: Option) -> Result { + unsafe { + (self.0.unregister_reset_notify)(&mut self.0, reset_function) + }.to_result() + } +} + + +// !TODO: make a safe FFI for raw function 'ResetSystemFn' +// copy and edit from uefi-raw/src/table/runtime.rs:84 at commit@6093205c3eb27b2e78be4c003c04d46679bff420 +// pub fn new(&self, rt: ResetType, status: Status, data: Option<&[u8]>) -> Option From d94e1b1b52b020cdca23b6370ceace4f6da6ba1a Mon Sep 17 00:00:00 2001 From: sky5454 <12370628+sky5454@users.noreply.github.com> Date: Fri, 5 Apr 2024 17:29:44 +0800 Subject: [PATCH 2/7] [Fixed] nits and only readonly hook called. --- uefi-raw/CHANGELOG.md | 2 +- uefi-raw/src/protocol/misc.rs | 13 ++++-- uefi-test-runner/src/proto/misc.rs | 72 ++++++++++++++++++------------ uefi-test-runner/src/proto/mod.rs | 22 ++++----- uefi/src/proto/misc.rs | 15 +++---- 5 files changed, 71 insertions(+), 53 deletions(-) diff --git a/uefi-raw/CHANGELOG.md b/uefi-raw/CHANGELOG.md index 81660784c..7935cdb39 100644 --- a/uefi-raw/CHANGELOG.md +++ b/uefi-raw/CHANGELOG.md @@ -1,7 +1,7 @@ # uefi-raw - [Unreleased] ## Added -- Added `ResetNotification`. +- Added `ResetNotificationProtocol`. ## Added - Added `TimestampProtocol`. diff --git a/uefi-raw/src/protocol/misc.rs b/uefi-raw/src/protocol/misc.rs index 8ac33c2a7..329a2572d 100644 --- a/uefi-raw/src/protocol/misc.rs +++ b/uefi-raw/src/protocol/misc.rs @@ -1,5 +1,5 @@ -use crate::{guid, Guid, Status}; use crate::table::runtime; +use crate::{guid, Guid, Status}; #[derive(Debug)] #[repr(C)] @@ -28,15 +28,20 @@ pub struct TimestampProperties { #[derive(Debug)] #[repr(C)] pub struct ResetNotificationProtocol { - pub register_reset_notify: unsafe extern "efiapi" fn(this: *const Self, reset_function: Option) -> Status, - pub unregister_reset_notify: unsafe extern "efiapi" fn(this: *const Self, reset_function: Option) -> Status, + pub register_reset_notify: unsafe extern "efiapi" fn( + this: *const Self, + reset_function: Option, + ) -> Status, + pub unregister_reset_notify: unsafe extern "efiapi" fn( + this: *const Self, + reset_function: Option, + ) -> Status, } impl ResetNotificationProtocol { pub const GUID: Guid = guid!("9da34ae0-eaf9-4bbf-8ec3-fd60226c44be"); } - /// Raw reset notification function, to be called if you register it when a RestSystem() is executed. // copy from uefi-raw/src/table/runtime.rs:53 at commit@6093205c3eb27b2e78be4c003c04d46679bff420 pub type ResetSystemFn = unsafe extern "efiapi" fn( diff --git a/uefi-test-runner/src/proto/misc.rs b/uefi-test-runner/src/proto/misc.rs index 14abc06d9..9f20cd061 100644 --- a/uefi-test-runner/src/proto/misc.rs +++ b/uefi-test-runner/src/proto/misc.rs @@ -3,27 +3,33 @@ use uefi::proto::misc::{ResetNotification, Timestamp}; use uefi::table::runtime; /// -/// you may see those log, it's nothing just for your computer firmware does not support the new UEFI feature. +/// you may see those log, it's nothing just for your computer firmware does not support the new UEFI feature of Timestamp Protocol. /// /// ```sh -/// [ INFO]: uefi-test-runner\src\proto\misc.rs@012: Running loaded Timestamp Protocol test -/// [ WARN]: uefi-test-runner\src\proto\misc.rs@026: Failed to open Timestamp Protocol: Error { status: UNSUPPORTED, data: () } -/// [ INFO]: uefi-test-runner\src\proto\misc.rs@033: Running loaded ResetNotification protocol test -/// [ WARN]: uefi-test-runner\src\proto\misc.rs@068: Failed to open ResetNotification Protocol: Error { status: UNSUPPORTED, data: () } +/// [ INFO]: uefi-test-runner\src\proto\misc.rs@020: Running loaded Timestamp Protocol test +/// [ WARN]: uefi-test-runner\src\proto\misc.rs@037: Failed to found Timestamp Protocol: Error { status: NOT_FOUND, data: () } +/// [ INFO]: uefi-test-runner\src\proto\misc.rs@043: Running loaded ResetNotification protocol test +/// [ INFO]: uefi-test-runner\src\proto\misc.rs@053: ResetNotification Protocol register null test: Err(Error { status: INVALID_PARAMETER, data: () }) +/// [ INFO]: uefi-test-runner\src\proto\misc.rs@059: ResetNotification Protocol unregister null test: Err(Error { status: INVALID_PARAMETER, data: () }) +/// [ INFO]: uefi-test-runner\src\proto\misc.rs@078: ResetNotification Protocol register efi_reset_fn test: Ok(()) +/// [ INFO]: uefi-test-runner\src\proto\misc.rs@084: ResetNotification Protocol unregister efi_reset_fn test: Ok(()) /// ``` -pub fn test(image: Handle, bt: &BootServices) { - test_timestamp(image, bt); - test_reset_notification(image, bt); +pub fn test(bt: &BootServices) { + test_timestamp(bt); + test_reset_notification(bt); } -pub fn test_timestamp(image: Handle, bt: &BootServices) { +pub fn test_timestamp(bt: &BootServices) { info!("Running loaded Timestamp Protocol test"); - let result = bt - .open_protocol_exclusive::(image); + let handle = bt.get_handle_for_protocol::(); + + match handle { + Ok(handle) => { + let timestamp_proto = bt + .open_protocol_exclusive::(handle) + .expect("Founded Timestamp Protocol but open failed"); - match result { - Ok(timestamp_proto) => { let timestamp = timestamp_proto.get_timestamp(); info!("Timestamp Protocol's timestamp: {:?}", timestamp); @@ -31,27 +37,32 @@ pub fn test_timestamp(image: Handle, bt: &BootServices) { info!("Timestamp Protocol's properties: {:?}", properties); } Err(err) => { - warn!("Failed to open Timestamp Protocol: {:?}", err); + warn!("Failed to found Timestamp Protocol: {:?}", err); } } } - -pub fn test_reset_notification(image: Handle, bt: &BootServices) { +pub fn test_reset_notification(bt: &BootServices) { info!("Running loaded ResetNotification protocol test"); - let result = bt - .open_protocol_exclusive::(image); + let handle = bt.get_handle_for_protocol::(); - match result { - Ok(mut reset_notif_proto) => { + match handle { + Ok(handle) => { + let mut reset_notif_proto = bt + .open_protocol_exclusive::(handle) + .expect("Founded ResetNotification Protocol but open failed"); let result = reset_notif_proto.register_reset_notify(None); - info!("ResetNotification Protocol register null test: {:?}", result); + info!( + "ResetNotification Protocol register null test: {:?}", + result + ); let result = reset_notif_proto.unregister_reset_notify(None); - info!("ResetNotification Protocol unregister null test: {:?}", result); - - + info!( + "ResetNotification Protocol unregister null test: {:?}", + result + ); // value efi_reset_fn is the type of ResetSystemFn, a function pointer unsafe extern "efiapi" fn efi_reset_fn( @@ -67,14 +78,19 @@ pub fn test_reset_notification(image: Handle, bt: &BootServices) { } let result = reset_notif_proto.register_reset_notify(Some(efi_reset_fn)); - info!("ResetNotification Protocol register efi_reset_fn test: {:?}", result); + info!( + "ResetNotification Protocol register efi_reset_fn test: {:?}", + result + ); let result = reset_notif_proto.unregister_reset_notify(Some(efi_reset_fn)); - info!("ResetNotification Protocol unregister efi_reset_fn test: {:?}", result); + info!( + "ResetNotification Protocol unregister efi_reset_fn test: {:?}", + result + ); } Err(err) => { - warn!("Failed to open ResetNotification Protocol: {:?}", err); + warn!("Failed to found ResetNotification Protocol: {:?}", err); } } } - diff --git a/uefi-test-runner/src/proto/mod.rs b/uefi-test-runner/src/proto/mod.rs index 413033fbb..261f439e6 100644 --- a/uefi-test-runner/src/proto/mod.rs +++ b/uefi-test-runner/src/proto/mod.rs @@ -1,6 +1,6 @@ -use uefi::{Identify, proto}; use uefi::prelude::*; use uefi::proto::loaded_image::LoadedImage; +use uefi::{proto, Identify}; pub fn test(image: Handle, st: &mut SystemTable) { info!("Testing various protocols"); @@ -21,13 +21,13 @@ pub fn test(image: Handle, st: &mut SystemTable) { rng::test(bt); shell_params::test(bt); string::test(bt); - misc::test(image, bt); + misc::test(bt); #[cfg(any( - target_arch = "x86", - target_arch = "x86_64", - target_arch = "arm", - target_arch = "aarch64" + target_arch = "x86", + target_arch = "x86_64", + target_arch = "arm", + target_arch = "aarch64" ))] shim::test(bt); tcg::test(bt); @@ -61,17 +61,17 @@ mod device_path; mod driver; mod loaded_image; mod media; +mod misc; mod network; mod pi; mod rng; mod shell_params; #[cfg(any( -target_arch = "x86", -target_arch = "x86_64", -target_arch = "arm", -target_arch = "aarch64" + target_arch = "x86", + target_arch = "x86_64", + target_arch = "arm", + target_arch = "aarch64" ))] mod shim; mod string; mod tcg; -mod misc; diff --git a/uefi/src/proto/misc.rs b/uefi/src/proto/misc.rs index fa645081e..9a73b5125 100644 --- a/uefi/src/proto/misc.rs +++ b/uefi/src/proto/misc.rs @@ -1,9 +1,11 @@ //! Miscellaneous protocols. -use uefi_raw::protocol::misc::{ResetNotificationProtocol, ResetSystemFn, TimestampProperties, TimestampProtocol}; +use uefi_raw::protocol::misc::{ + ResetNotificationProtocol, ResetSystemFn, TimestampProperties, TimestampProtocol, +}; -use crate::{Result, StatusExt}; use crate::proto::unsafe_protocol; +use crate::{Result, StatusExt}; /// Protocol for retrieving a high-resolution timestamp counter. #[derive(Debug)] @@ -65,21 +67,16 @@ impl ResetNotification { /// } /// ``` pub fn register_reset_notify(&mut self, reset_function: Option) -> Result { - unsafe { - (self.0.register_reset_notify)(&mut self.0, reset_function) - }.to_result() + unsafe { (self.0.register_reset_notify)(&mut self.0, reset_function) }.to_result() } /// Removes a reset notification function that has been previously registered with RegisterResetNotify(). /// Tips: RegisterResetNotify() has named as `register_reset_notify()` in uefi-rs. pub fn unregister_reset_notify(&mut self, reset_function: Option) -> Result { - unsafe { - (self.0.unregister_reset_notify)(&mut self.0, reset_function) - }.to_result() + unsafe { (self.0.unregister_reset_notify)(&mut self.0, reset_function) }.to_result() } } - // !TODO: make a safe FFI for raw function 'ResetSystemFn' // copy and edit from uefi-raw/src/table/runtime.rs:84 at commit@6093205c3eb27b2e78be4c003c04d46679bff420 // pub fn new(&self, rt: ResetType, status: Status, data: Option<&[u8]>) -> Option From 2c0377809c4a55d72f13d4b27aa2885e30385bc8 Mon Sep 17 00:00:00 2001 From: sky5454 Date: Sat, 13 Apr 2024 20:04:32 +0800 Subject: [PATCH 3/7] [Fixed] move `test_timestamp` from ovmf test to example. fixed other nits. --- uefi-raw/src/protocol/misc.rs | 16 +++---- uefi-test-runner/examples/timestamp.rs | 60 ++++++++++++++++++++++++++ uefi-test-runner/src/proto/misc.rs | 26 +---------- uefi/src/proto/misc.rs | 17 ++++---- 4 files changed, 75 insertions(+), 44 deletions(-) create mode 100644 uefi-test-runner/examples/timestamp.rs diff --git a/uefi-raw/src/protocol/misc.rs b/uefi-raw/src/protocol/misc.rs index 329a2572d..5d0eeb303 100644 --- a/uefi-raw/src/protocol/misc.rs +++ b/uefi-raw/src/protocol/misc.rs @@ -1,5 +1,5 @@ -use crate::table::runtime; use crate::{guid, Guid, Status}; +use crate::table::runtime; #[derive(Debug)] #[repr(C)] @@ -28,14 +28,10 @@ pub struct TimestampProperties { #[derive(Debug)] #[repr(C)] pub struct ResetNotificationProtocol { - pub register_reset_notify: unsafe extern "efiapi" fn( - this: *const Self, - reset_function: Option, - ) -> Status, - pub unregister_reset_notify: unsafe extern "efiapi" fn( - this: *const Self, - reset_function: Option, - ) -> Status, + pub register_reset_notify: + unsafe extern "efiapi" fn(this: *mut Self, reset_function: Option) -> Status, + pub unregister_reset_notify: + unsafe extern "efiapi" fn(this: *mut Self, reset_function: Option) -> Status, } impl ResetNotificationProtocol { @@ -43,7 +39,7 @@ impl ResetNotificationProtocol { } /// Raw reset notification function, to be called if you register it when a RestSystem() is executed. -// copy from uefi-raw/src/table/runtime.rs:53 at commit@6093205c3eb27b2e78be4c003c04d46679bff420 +// similar to uefi-raw/src/table/runtime.rs:53 at commit@6093205c3eb27b2e78be4c003c04d46679bff420 pub type ResetSystemFn = unsafe extern "efiapi" fn( rt: runtime::ResetType, status: Status, diff --git a/uefi-test-runner/examples/timestamp.rs b/uefi-test-runner/examples/timestamp.rs new file mode 100644 index 000000000..7fea84eba --- /dev/null +++ b/uefi-test-runner/examples/timestamp.rs @@ -0,0 +1,60 @@ +// ANCHOR: all +// ANCHOR: features +#![no_main] +#![no_std] +// ANCHOR_END: features + +extern crate alloc; + +use log::{info, warn}; + +// ANCHOR: use +use uefi::prelude::*; +use uefi::proto::misc::Timestamp; + +// ANCHOR_END: use + +// ANCHOR: entry +#[entry] +fn main(image_handle: Handle, mut system_table: SystemTable) -> Status { + // ANCHOR_END: entry + // ANCHOR: services + uefi_services::init(&mut system_table).unwrap(); + let boot_services = system_table.boot_services(); + // ANCHOR_END: services + + // ANCHOR: params + test_timestamp(boot_services); + // ANCHOR_END: params + + // ANCHOR: return + Status::SUCCESS +} +// ANCHOR_END: return + +// ANCHOR: test_timestamp +pub fn test_timestamp(bt: &BootServices) { + // ANCHOR_END: test_timestamp + info!("Running loaded Timestamp Protocol test"); + + let handle = bt.get_handle_for_protocol::(); + + match handle { + Ok(handle) => { + let timestamp_proto = bt + .open_protocol_exclusive::(handle) + .expect("Founded Timestamp Protocol but open failed"); + // ANCHOR: text + let timestamp = timestamp_proto.get_timestamp(); + info!("Timestamp Protocol's timestamp: {:?}", timestamp); + + let properties = timestamp_proto.get_properties(); + info!("Timestamp Protocol's properties: {:?}", properties); + // ANCHOR_END: text + } + Err(err) => { + warn!("Failed to found Timestamp Protocol: {:?}", err); + } + } +} +// ANCHOR_END: all diff --git a/uefi-test-runner/src/proto/misc.rs b/uefi-test-runner/src/proto/misc.rs index 9f20cd061..33f36d363 100644 --- a/uefi-test-runner/src/proto/misc.rs +++ b/uefi-test-runner/src/proto/misc.rs @@ -1,5 +1,5 @@ use uefi::prelude::*; -use uefi::proto::misc::{ResetNotification, Timestamp}; +use uefi::proto::misc::ResetNotification; use uefi::table::runtime; /// @@ -15,33 +15,9 @@ use uefi::table::runtime; /// [ INFO]: uefi-test-runner\src\proto\misc.rs@084: ResetNotification Protocol unregister efi_reset_fn test: Ok(()) /// ``` pub fn test(bt: &BootServices) { - test_timestamp(bt); test_reset_notification(bt); } -pub fn test_timestamp(bt: &BootServices) { - info!("Running loaded Timestamp Protocol test"); - - let handle = bt.get_handle_for_protocol::(); - - match handle { - Ok(handle) => { - let timestamp_proto = bt - .open_protocol_exclusive::(handle) - .expect("Founded Timestamp Protocol but open failed"); - - let timestamp = timestamp_proto.get_timestamp(); - info!("Timestamp Protocol's timestamp: {:?}", timestamp); - - let properties = timestamp_proto.get_properties(); - info!("Timestamp Protocol's properties: {:?}", properties); - } - Err(err) => { - warn!("Failed to found Timestamp Protocol: {:?}", err); - } - } -} - pub fn test_reset_notification(bt: &BootServices) { info!("Running loaded ResetNotification protocol test"); diff --git a/uefi/src/proto/misc.rs b/uefi/src/proto/misc.rs index 9a73b5125..c3048fa94 100644 --- a/uefi/src/proto/misc.rs +++ b/uefi/src/proto/misc.rs @@ -37,7 +37,8 @@ impl ResetNotification { /// Register a notification function to be called when ResetSystem() is called. /// /// - /// #example + /// # Example + /// /// ```rust /// use log::info; /// use uefi::Handle; @@ -46,7 +47,8 @@ impl ResetNotification { /// use uefi_raw::Status; /// use uefi_raw::table::runtime; /// - /// // value efi_reset_fn is the type of ResetSystemFn, a function pointer + /// + /// /* value efi_reset_fn is the type of ResetSystemFn, a function pointer*/ /// unsafe extern "efiapi" fn efi_reset_fn( /// rt: runtime::ResetType, /// status: Status, @@ -54,16 +56,17 @@ impl ResetNotification { /// data: *const u8, /// ){ /// info!("Inside the event callback"); - /// // do what you want + /// info!("do what you want"); /// } /// /// pub fn test(image: Handle, bt: &BootServices) { /// - /// /* get protocol*/ /// let mut rn = bt /// .open_protocol_exclusive::(image) /// .expect("Failed to open Timestamp protocol"); - /// rn.register_reset_notify(Some(efi_reset_fn)); + /// + /// rn.register_reset_notify(Some(efi_reset_fn)) + /// .expect("Failed to register a reset notification function!"); /// } /// ``` pub fn register_reset_notify(&mut self, reset_function: Option) -> Result { @@ -76,7 +79,3 @@ impl ResetNotification { unsafe { (self.0.unregister_reset_notify)(&mut self.0, reset_function) }.to_result() } } - -// !TODO: make a safe FFI for raw function 'ResetSystemFn' -// copy and edit from uefi-raw/src/table/runtime.rs:84 at commit@6093205c3eb27b2e78be4c003c04d46679bff420 -// pub fn new(&self, rt: ResetType, status: Status, data: Option<&[u8]>) -> Option From b8f2129f3a5d8ddb414476473be9fecd6b0ceefa Mon Sep 17 00:00:00 2001 From: sky5454 Date: Sun, 14 Apr 2024 11:49:55 +0800 Subject: [PATCH 4/7] [Fixed] nits and docs. --- uefi-raw/src/protocol/misc.rs | 3 +-- uefi-test-runner/src/proto/misc.rs | 12 --------- uefi/src/proto/misc.rs | 40 ++++++++++++++++-------------- 3 files changed, 22 insertions(+), 33 deletions(-) diff --git a/uefi-raw/src/protocol/misc.rs b/uefi-raw/src/protocol/misc.rs index 5d0eeb303..37b181bc3 100644 --- a/uefi-raw/src/protocol/misc.rs +++ b/uefi-raw/src/protocol/misc.rs @@ -1,5 +1,5 @@ -use crate::{guid, Guid, Status}; use crate::table::runtime; +use crate::{guid, Guid, Status}; #[derive(Debug)] #[repr(C)] @@ -39,7 +39,6 @@ impl ResetNotificationProtocol { } /// Raw reset notification function, to be called if you register it when a RestSystem() is executed. -// similar to uefi-raw/src/table/runtime.rs:53 at commit@6093205c3eb27b2e78be4c003c04d46679bff420 pub type ResetSystemFn = unsafe extern "efiapi" fn( rt: runtime::ResetType, status: Status, diff --git a/uefi-test-runner/src/proto/misc.rs b/uefi-test-runner/src/proto/misc.rs index 33f36d363..6e07ad4e0 100644 --- a/uefi-test-runner/src/proto/misc.rs +++ b/uefi-test-runner/src/proto/misc.rs @@ -2,18 +2,6 @@ use uefi::prelude::*; use uefi::proto::misc::ResetNotification; use uefi::table::runtime; -/// -/// you may see those log, it's nothing just for your computer firmware does not support the new UEFI feature of Timestamp Protocol. -/// -/// ```sh -/// [ INFO]: uefi-test-runner\src\proto\misc.rs@020: Running loaded Timestamp Protocol test -/// [ WARN]: uefi-test-runner\src\proto\misc.rs@037: Failed to found Timestamp Protocol: Error { status: NOT_FOUND, data: () } -/// [ INFO]: uefi-test-runner\src\proto\misc.rs@043: Running loaded ResetNotification protocol test -/// [ INFO]: uefi-test-runner\src\proto\misc.rs@053: ResetNotification Protocol register null test: Err(Error { status: INVALID_PARAMETER, data: () }) -/// [ INFO]: uefi-test-runner\src\proto\misc.rs@059: ResetNotification Protocol unregister null test: Err(Error { status: INVALID_PARAMETER, data: () }) -/// [ INFO]: uefi-test-runner\src\proto\misc.rs@078: ResetNotification Protocol register efi_reset_fn test: Ok(()) -/// [ INFO]: uefi-test-runner\src\proto\misc.rs@084: ResetNotification Protocol unregister efi_reset_fn test: Ok(()) -/// ``` pub fn test(bt: &BootServices) { test_reset_notification(bt); } diff --git a/uefi/src/proto/misc.rs b/uefi/src/proto/misc.rs index c3048fa94..c72556d8e 100644 --- a/uefi/src/proto/misc.rs +++ b/uefi/src/proto/misc.rs @@ -8,6 +8,9 @@ use crate::proto::unsafe_protocol; use crate::{Result, StatusExt}; /// Protocol for retrieving a high-resolution timestamp counter. +/// **Note:** +/// If your UEFI firmware not support timestamp protocol which first added at UEFI spec 2.4 2013. +/// 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. #[derive(Debug)] #[repr(transparent)] #[unsafe_protocol(TimestampProtocol::GUID)] @@ -48,33 +51,32 @@ impl ResetNotification { /// use uefi_raw::table::runtime; /// /// - /// /* value efi_reset_fn is the type of ResetSystemFn, a function pointer*/ - /// unsafe extern "efiapi" fn efi_reset_fn( - /// rt: runtime::ResetType, - /// status: Status, - /// data_size: usize, - /// data: *const u8, - /// ){ - /// info!("Inside the event callback"); - /// info!("do what you want"); - /// } + /// // value efi_reset_fn is the type of ResetSystemFn, a function pointer + /// unsafe extern "efiapi" fn efi_reset_fn( + /// rt: runtime::ResetType, + /// status: Status, + /// data_size: usize, + /// data: *const u8, + /// ){ + /// info!("Inside the event callback"); + /// info!("do what you want"); + /// } /// - /// pub fn test(image: Handle, bt: &BootServices) { + /// pub fn test(image: Handle, bt: &BootServices) { /// - /// let mut rn = bt - /// .open_protocol_exclusive::(image) - /// .expect("Failed to open Timestamp protocol"); + /// let mut rn = bt + /// .open_protocol_exclusive::(image) + /// .expect("Failed to open Timestamp protocol"); /// - /// rn.register_reset_notify(Some(efi_reset_fn)) - /// .expect("Failed to register a reset notification function!"); - /// } + /// rn.register_reset_notify(Some(efi_reset_fn)) + /// .expect("Failed to register a reset notification function!"); + /// } /// ``` pub fn register_reset_notify(&mut self, reset_function: Option) -> Result { unsafe { (self.0.register_reset_notify)(&mut self.0, reset_function) }.to_result() } - /// Removes a reset notification function that has been previously registered with RegisterResetNotify(). - /// Tips: RegisterResetNotify() has named as `register_reset_notify()` in uefi-rs. + /// Remove a reset notification function that was previously registered with [`ResetNotification::register_reset_notify`]. pub fn unregister_reset_notify(&mut self, reset_function: Option) -> Result { unsafe { (self.0.unregister_reset_notify)(&mut self.0, reset_function) }.to_result() } From a0675266c6e8c74ffab9504e208e4ac111bf3e21 Mon Sep 17 00:00:00 2001 From: sky5454 Date: Sun, 14 Apr 2024 12:10:53 +0800 Subject: [PATCH 5/7] [test] test timestamp in vmware UEFI 2.7 and got the result ok. --- uefi-test-runner/examples/timestamp.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/uefi-test-runner/examples/timestamp.rs b/uefi-test-runner/examples/timestamp.rs index 7fea84eba..932afb758 100644 --- a/uefi-test-runner/examples/timestamp.rs +++ b/uefi-test-runner/examples/timestamp.rs @@ -27,6 +27,10 @@ fn main(image_handle: Handle, mut system_table: SystemTable) -> Status { test_timestamp(boot_services); // ANCHOR_END: params + // ANCHOR: stall + boot_services.stall(10_000_000); + // ANCHOR_END: stall + // ANCHOR: return Status::SUCCESS } From aa6d4b250b4e998c11e5bd850e1bb052ad38eb13 Mon Sep 17 00:00:00 2001 From: sky5454 Date: Mon, 15 Apr 2024 00:13:58 +0800 Subject: [PATCH 6/7] [test] expect test. Drop the Option so that the caller is forced to provide a valid input. --- uefi-raw/src/protocol/misc.rs | 6 +-- uefi-test-runner/src/proto/misc.rs | 78 ++++++++++++------------------ uefi/src/proto/misc.rs | 6 +-- 3 files changed, 37 insertions(+), 53 deletions(-) diff --git a/uefi-raw/src/protocol/misc.rs b/uefi-raw/src/protocol/misc.rs index 37b181bc3..0147fce87 100644 --- a/uefi-raw/src/protocol/misc.rs +++ b/uefi-raw/src/protocol/misc.rs @@ -29,16 +29,16 @@ pub struct TimestampProperties { #[repr(C)] pub struct ResetNotificationProtocol { pub register_reset_notify: - unsafe extern "efiapi" fn(this: *mut Self, reset_function: Option) -> Status, + unsafe extern "efiapi" fn(this: *mut Self, reset_function: ResetSystemFn) -> Status, pub unregister_reset_notify: - unsafe extern "efiapi" fn(this: *mut Self, reset_function: Option) -> Status, + unsafe extern "efiapi" fn(this: *mut Self, reset_function: ResetSystemFn) -> Status, } impl ResetNotificationProtocol { pub const GUID: Guid = guid!("9da34ae0-eaf9-4bbf-8ec3-fd60226c44be"); } -/// Raw reset notification function, to be called if you register it when a RestSystem() is executed. +/// Raw reset notification function, to be called if you register it when a ResetSystem() is executed. pub type ResetSystemFn = unsafe extern "efiapi" fn( rt: runtime::ResetType, status: Status, diff --git a/uefi-test-runner/src/proto/misc.rs b/uefi-test-runner/src/proto/misc.rs index 6e07ad4e0..c7b1664f7 100644 --- a/uefi-test-runner/src/proto/misc.rs +++ b/uefi-test-runner/src/proto/misc.rs @@ -9,52 +9,36 @@ pub fn test(bt: &BootServices) { pub fn test_reset_notification(bt: &BootServices) { info!("Running loaded ResetNotification protocol test"); - let handle = bt.get_handle_for_protocol::(); - - match handle { - Ok(handle) => { - let mut reset_notif_proto = bt - .open_protocol_exclusive::(handle) - .expect("Founded ResetNotification Protocol but open failed"); - let result = reset_notif_proto.register_reset_notify(None); - info!( - "ResetNotification Protocol register null test: {:?}", - result - ); - - let result = reset_notif_proto.unregister_reset_notify(None); - info!( - "ResetNotification Protocol unregister null test: {:?}", - result - ); - - // value efi_reset_fn is the type of ResetSystemFn, a function pointer - unsafe extern "efiapi" fn efi_reset_fn( - rt: runtime::ResetType, - status: Status, - data_size: usize, - data: *const u8, - ) { - info!("Inside the event callback, hi, efi_reset_fn"); - info!("rt: {:?} status: {:?}", rt, status); - info!("size: {:?} data: {:?}", data_size, data); - // do what you want - } - - let result = reset_notif_proto.register_reset_notify(Some(efi_reset_fn)); - info!( - "ResetNotification Protocol register efi_reset_fn test: {:?}", - result - ); - - let result = reset_notif_proto.unregister_reset_notify(Some(efi_reset_fn)); - info!( - "ResetNotification Protocol unregister efi_reset_fn test: {:?}", - result - ); - } - Err(err) => { - warn!("Failed to found ResetNotification Protocol: {:?}", err); - } + let handle = bt + .get_handle_for_protocol::() + .expect("Failed to get handles for `ResetNotification` protocol"); + + let mut reset_notif_proto = bt + .open_protocol_exclusive::(handle) + .expect("Founded ResetNotification Protocol but open failed"); + + // value efi_reset_fn is the type of ResetSystemFn, a function pointer + unsafe extern "efiapi" fn efi_reset_fn( + rt: runtime::ResetType, + status: Status, + data_size: usize, + data: *const u8, + ) { + info!("Inside the event callback, hi, efi_reset_fn"); + info!("rt: {:?} status: {:?}", rt, status); + info!("size: {:?} data: {:?}", data_size, data); + // do what you want } + + let result = reset_notif_proto.register_reset_notify(efi_reset_fn); + info!( + "ResetNotification Protocol register efi_reset_fn test: {:?}", + result + ); + + let result = reset_notif_proto.unregister_reset_notify(efi_reset_fn); + info!( + "ResetNotification Protocol unregister efi_reset_fn test: {:?}", + result + ); } diff --git a/uefi/src/proto/misc.rs b/uefi/src/proto/misc.rs index c72556d8e..92666fd08 100644 --- a/uefi/src/proto/misc.rs +++ b/uefi/src/proto/misc.rs @@ -68,16 +68,16 @@ impl ResetNotification { /// .open_protocol_exclusive::(image) /// .expect("Failed to open Timestamp protocol"); /// - /// rn.register_reset_notify(Some(efi_reset_fn)) + /// rn.register_reset_notify(efi_reset_fn) /// .expect("Failed to register a reset notification function!"); /// } /// ``` - pub fn register_reset_notify(&mut self, reset_function: Option) -> Result { + pub fn register_reset_notify(&mut self, reset_function: ResetSystemFn) -> Result { unsafe { (self.0.register_reset_notify)(&mut self.0, reset_function) }.to_result() } /// Remove a reset notification function that was previously registered with [`ResetNotification::register_reset_notify`]. - pub fn unregister_reset_notify(&mut self, reset_function: Option) -> Result { + pub fn unregister_reset_notify(&mut self, reset_function: ResetSystemFn) -> Result { unsafe { (self.0.unregister_reset_notify)(&mut self.0, reset_function) }.to_result() } } From fc01d48d2f98cd3a82eafb824ab7f1f63e0abf8b Mon Sep 17 00:00:00 2001 From: sky5454 Date: Mon, 15 Apr 2024 19:43:00 +0800 Subject: [PATCH 7/7] [test] example timestamp `uefi_services` change to `uefi::helpers` --- uefi-test-runner/examples/timestamp.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uefi-test-runner/examples/timestamp.rs b/uefi-test-runner/examples/timestamp.rs index 932afb758..deccc7e98 100644 --- a/uefi-test-runner/examples/timestamp.rs +++ b/uefi-test-runner/examples/timestamp.rs @@ -19,7 +19,7 @@ use uefi::proto::misc::Timestamp; fn main(image_handle: Handle, mut system_table: SystemTable) -> Status { // ANCHOR_END: entry // ANCHOR: services - uefi_services::init(&mut system_table).unwrap(); + uefi::helpers::init(&mut system_table).unwrap(); let boot_services = system_table.boot_services(); // ANCHOR_END: services