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 01/91] [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 02/91] [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 03/91] [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 04/91] [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 05/91] [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 06/91] [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 07/91] [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 From e0b9d05c7b9c5fc13abf9bf7fb636386e1ce854c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 20 Apr 2024 09:42:29 +0000 Subject: [PATCH 08/91] build(deps): bump rustls from 0.22.2 to 0.22.4 Bumps [rustls](https://github.com/rustls/rustls) from 0.22.2 to 0.22.4. - [Release notes](https://github.com/rustls/rustls/releases) - [Changelog](https://github.com/rustls/rustls/blob/main/CHANGELOG.md) - [Commits](https://github.com/rustls/rustls/compare/v/0.22.2...v/0.22.4) --- updated-dependencies: - dependency-name: rustls dependency-type: indirect ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 398511bf9..57fb4250d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -573,9 +573,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.22.2" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e87c9956bd9807afa1f77e0f7594af32566e830e088a5576d27c5b6f30f49d41" +checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" dependencies = [ "log", "ring", From 4cea282995e770fe6d0d4bbd3b550a18d69bd261 Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Fri, 19 Apr 2024 16:56:52 +0200 Subject: [PATCH 09/91] treewide: nuke uefi-services --- .github/workflows/release.yml | 2 +- CHANGELOG.md | 1 - Cargo.lock | 7 - Cargo.toml | 2 - PUBLISHING.md | 1 - book/src/reference.md | 1 - uefi-services/CHANGELOG.md | 105 ---------- uefi-services/Cargo.toml | 23 --- uefi-services/LICENSE | 373 ---------------------------------- uefi-services/README.md | 3 +- uefi-services/build.rs | 3 - uefi-services/src/lib.rs | 20 -- xtask/src/cargo.rs | 22 +- xtask/src/main.rs | 31 ++- 14 files changed, 22 insertions(+), 572 deletions(-) delete mode 100644 uefi-services/CHANGELOG.md delete mode 100644 uefi-services/Cargo.toml delete mode 100644 uefi-services/LICENSE delete mode 100644 uefi-services/build.rs delete mode 100644 uefi-services/src/lib.rs diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a4858c5d8..44b538998 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -16,6 +16,6 @@ jobs: - uses: actions/checkout@v4 - run: | cargo install auto-release - auto-release --condition body -p uefi-raw -p uefi-macros -p uefi -p uefi-services + auto-release --condition body -p uefi-raw -p uefi-macros -p uefi env: CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 97f0921a7..d996c1222 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,4 +3,3 @@ * [`uefi` changelog](uefi/CHANGELOG.md) * [`uefi-macros` changelog](uefi-macros/CHANGELOG.md) * [`uefi-raw` changelog](uefi-raw/CHANGELOG.md) -* [`uefi-services` changelog](uefi-services/CHANGELOG.md) diff --git a/Cargo.lock b/Cargo.lock index 57fb4250d..991affa26 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -883,13 +883,6 @@ dependencies = [ "uguid", ] -[[package]] -name = "uefi-services" -version = "0.25.0" -dependencies = [ - "uefi", -] - [[package]] name = "uefi-test-runner" version = "0.2.0" diff --git a/Cargo.toml b/Cargo.toml index 7a8639d9b..89e9533f5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,6 @@ members = [ "uefi", "uefi-macros", "uefi-raw", - "uefi-services", "uefi-test-runner", "xtask", ] @@ -29,7 +28,6 @@ uguid = "2.1.0" uefi = { path = "uefi" } uefi-macros = { path = "uefi-macros" } uefi-raw = { path = "uefi-raw" } -uefi-services = { path = "uefi-services" } # Enable optimization for xtask itself, not for its dependencies. This speeds up # OVMF prebuilt decompression without much increase in compilation time. diff --git a/PUBLISHING.md b/PUBLISHING.md index e855031a2..1e3e9759d 100644 --- a/PUBLISHING.md +++ b/PUBLISHING.md @@ -11,7 +11,6 @@ repository to [crates.io](https://crates.io/). release is performed. - We want git tags like `uefi-raw-v0.4.0` or `uefi-v0.25.0` for every release. - We want our crate dependencies published in the right order (if necessary): - - `uefi-services` depends on `uefi` - `uefi` depends on `uefi-macros` and `uefi-raw` ## How: Ways to Publish diff --git a/book/src/reference.md b/book/src/reference.md index 5c525a2d6..00db5891b 100644 --- a/book/src/reference.md +++ b/book/src/reference.md @@ -4,5 +4,4 @@ * [`uefi` crate reference](https://docs.rs/uefi) * [`uefi-macros` crate reference](https://docs.rs/uefi-macros) * [`uefi-raw` crate reference](https://docs.rs/uefi-raw) -* [`uefi-services` crate reference](https://docs.rs/uefi-services) * [UEFI Specifications](https://uefi.org/specifications) diff --git a/uefi-services/CHANGELOG.md b/uefi-services/CHANGELOG.md deleted file mode 100644 index eeebcac7a..000000000 --- a/uefi-services/CHANGELOG.md +++ /dev/null @@ -1,105 +0,0 @@ -# uefi-services - [Unreleased] - - -# uefi-services - 0.25.0 (2023-11-12) - -## Changed -- `uefi-services` is deprecated and should be removed. All functionality was -moved to `uefi::helpers::init()` - - -# uefi-services - 0.24.0 (2023-03-17) - -## Changed -- Updated to latest version of `uefi`. - - -# uefi-services - 0.23.0 (2023-11-12) - -## Changed -- `uefi_services::system_table` now returns `SystemTable` directly, rather - than wrapped in a `NonNull` pointer. - - -# uefi-services - 0.22.0 (2023-10-11) - -## Changed -- Updated to latest version of `uefi`. - - -# uefi-services - 0.21.0 (2023-06-20) - -## Changed -- Updated to latest version of `uefi`. - - -# uefi-services - 0.20.0 (2023-06-04) - -## Changed -- Updated to latest version of `uefi`. - - -# uefi-services - 0.19.0 (2023-06-01) - -## Changed -- Internal updates for changes in `uefi`. - - -# uefi-services - 0.18.0 (2023-05-15) - -## Changed -- Internal updates for changes in `uefi`. - - -# uefi-services - 0.17.0 (2023-03-19) - -## Changed -- Drop use of unstable `alloc_error_handler` feature. As of Rust 1.68 we can use - [`default_alloc_error_handler`](https://github.com/rust-lang/rust/pull/102318) - instead. - - -# uefi-services - 0.16.0 (2023-01-16) - -## Changed -- Bumped `uefi` dependency to latest version. - - -# uefi-services - 0.15.0 (2022-11-15) - -## Changed -- Changed the panic handler log message to use `println!` instead of - `error!`. This removes an extraneous file name and line number from - the log message. -- Added a `logger` feature which reflects the same feature in `uefi`. - This allows using both crates while disabling `logger` in `uefi`, - which was previously impossible. - - -# uefi-services - 0.14.0 (2022-09-09) - -## Added -- Added `print!` and `println!` macros. - -## Changed -- The `no_panic_handler` feature has been replaced with an additive - `panic_handler` feature. The new feature is enabled by default. - - -# uefi-services - 0.13.1 (2022-08-26) - -## Changed -- Relaxed the version requirements for the `log` dependency to allow - earlier patch versions. - - -# uefi-services - 0.13.0 (2022-05-16) - -## Changed -- Bumped `uefi` dependency to latest version. - - -# uefi-services - 0.12.1 (2022-03-15) - -## Changed -- Updated to the 2021 edition. diff --git a/uefi-services/Cargo.toml b/uefi-services/Cargo.toml deleted file mode 100644 index 41797dd46..000000000 --- a/uefi-services/Cargo.toml +++ /dev/null @@ -1,23 +0,0 @@ -[package] -name = "uefi-services" -version = "0.25.0" -readme = "README.md" -description = "Deprecated. Please migrate to `uefi::helpers`." - -authors.workspace = true -categories.workspace = true -edition.workspace = true -keywords.workspace = true -license.workspace = true -repository.workspace = true -rust-version.workspace = true - -[dependencies] -uefi = { version = "0.28.0", features = ["global_allocator"] } - -[features] -default = ["panic_handler", "logger"] -# Enable QEMU-specific functionality -qemu = ["uefi/qemu"] -panic_handler = [ "uefi/panic_handler" ] -logger = ["uefi/logger"] diff --git a/uefi-services/LICENSE b/uefi-services/LICENSE deleted file mode 100644 index a612ad981..000000000 --- a/uefi-services/LICENSE +++ /dev/null @@ -1,373 +0,0 @@ -Mozilla Public License Version 2.0 -================================== - -1. Definitions --------------- - -1.1. "Contributor" - means each individual or legal entity that creates, contributes to - the creation of, or owns Covered Software. - -1.2. "Contributor Version" - means the combination of the Contributions of others (if any) used - by a Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - means Source Code Form to which the initial Contributor has attached - the notice in Exhibit A, the Executable Form of such Source Code - Form, and Modifications of such Source Code Form, in each case - including portions thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - (a) that the initial Contributor has attached the notice described - in Exhibit B to the Covered Software; or - - (b) that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the - terms of a Secondary License. - -1.6. "Executable Form" - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - means a work that combines Covered Software with other material, in - a separate file or files, that is not Covered Software. - -1.8. "License" - means this document. - -1.9. "Licensable" - means having the right to grant, to the maximum extent possible, - whether at the time of the initial grant or subsequently, any and - all of the rights conveyed by this License. - -1.10. "Modifications" - means any of the following: - - (a) any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered - Software; or - - (b) any new file in Source Code Form that contains any Covered - Software. - -1.11. "Patent Claims" of a Contributor - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the - License, by the making, using, selling, offering for sale, having - made, import, or transfer of either its Contributions or its - Contributor Version. - -1.12. "Secondary License" - means either the GNU General Public License, Version 2.0, the GNU - Lesser General Public License, Version 2.1, the GNU Affero General - Public License, Version 3.0, or any later versions of those - licenses. - -1.13. "Source Code Form" - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that - controls, is controlled by, or is under common control with You. For - purposes of this definition, "control" means (a) the power, direct - or indirect, to cause the direction or management of such entity, - whether by contract or otherwise, or (b) ownership of more than - fifty percent (50%) of the outstanding shares or beneficial - ownership of such entity. - -2. License Grants and Conditions --------------------------------- - -2.1. Grants - -Each Contributor hereby grants You a world-wide, royalty-free, -non-exclusive license: - -(a) under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - -(b) under Patent Claims of such Contributor to make, use, sell, offer - for sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - -The licenses granted in Section 2.1 with respect to any Contribution -become effective for each Contribution on the date the Contributor first -distributes such Contribution. - -2.3. Limitations on Grant Scope - -The licenses granted in this Section 2 are the only rights granted under -this License. No additional rights or licenses will be implied from the -distribution or licensing of Covered Software under this License. -Notwithstanding Section 2.1(b) above, no patent license is granted by a -Contributor: - -(a) for any code that a Contributor has removed from Covered Software; - or - -(b) for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - -(c) under Patent Claims infringed by Covered Software in the absence of - its Contributions. - -This License does not grant any rights in the trademarks, service marks, -or logos of any Contributor (except as may be necessary to comply with -the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - -No Contributor makes additional grants as a result of Your choice to -distribute the Covered Software under a subsequent version of this -License (see Section 10.2) or under the terms of a Secondary License (if -permitted under the terms of Section 3.3). - -2.5. Representation - -Each Contributor represents that the Contributor believes its -Contributions are its original creation(s) or it has sufficient rights -to grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - -This License is not intended to limit any rights You have under -applicable copyright doctrines of fair use, fair dealing, or other -equivalents. - -2.7. Conditions - -Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted -in Section 2.1. - -3. Responsibilities -------------------- - -3.1. Distribution of Source Form - -All distribution of Covered Software in Source Code Form, including any -Modifications that You create or to which You contribute, must be under -the terms of this License. You must inform recipients that the Source -Code Form of the Covered Software is governed by the terms of this -License, and how they can obtain a copy of this License. You may not -attempt to alter or restrict the recipients' rights in the Source Code -Form. - -3.2. Distribution of Executable Form - -If You distribute Covered Software in Executable Form then: - -(a) such Covered Software must also be made available in Source Code - Form, as described in Section 3.1, and You must inform recipients of - the Executable Form how they can obtain a copy of such Source Code - Form by reasonable means in a timely manner, at a charge no more - than the cost of distribution to the recipient; and - -(b) You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter - the recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - -You may create and distribute a Larger Work under terms of Your choice, -provided that You also comply with the requirements of this License for -the Covered Software. If the Larger Work is a combination of Covered -Software with a work governed by one or more Secondary Licenses, and the -Covered Software is not Incompatible With Secondary Licenses, this -License permits You to additionally distribute such Covered Software -under the terms of such Secondary License(s), so that the recipient of -the Larger Work may, at their option, further distribute the Covered -Software under the terms of either this License or such Secondary -License(s). - -3.4. Notices - -You may not remove or alter the substance of any license notices -(including copyright notices, patent notices, disclaimers of warranty, -or limitations of liability) contained within the Source Code Form of -the Covered Software, except that You may alter any license notices to -the extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - -You may choose to offer, and to charge a fee for, warranty, support, -indemnity or liability obligations to one or more recipients of Covered -Software. However, You may do so only on Your own behalf, and not on -behalf of any Contributor. You must make it absolutely clear that any -such warranty, support, indemnity, or liability obligation is offered by -You alone, and You hereby agree to indemnify every Contributor for any -liability incurred by such Contributor as a result of warranty, support, -indemnity or liability terms You offer. You may include additional -disclaimers of warranty and limitations of liability specific to any -jurisdiction. - -4. Inability to Comply Due to Statute or Regulation ---------------------------------------------------- - -If it is impossible for You to comply with any of the terms of this -License with respect to some or all of the Covered Software due to -statute, judicial order, or regulation then You must: (a) comply with -the terms of this License to the maximum extent possible; and (b) -describe the limitations and the code they affect. Such description must -be placed in a text file included with all distributions of the Covered -Software under this License. Except to the extent prohibited by statute -or regulation, such description must be sufficiently detailed for a -recipient of ordinary skill to be able to understand it. - -5. Termination --------------- - -5.1. The rights granted under this License will terminate automatically -if You fail to comply with any of its terms. However, if You become -compliant, then the rights granted under this License from a particular -Contributor are reinstated (a) provisionally, unless and until such -Contributor explicitly and finally terminates Your grants, and (b) on an -ongoing basis, if such Contributor fails to notify You of the -non-compliance by some reasonable means prior to 60 days after You have -come back into compliance. Moreover, Your grants from a particular -Contributor are reinstated on an ongoing basis if such Contributor -notifies You of the non-compliance by some reasonable means, this is the -first time You have received notice of non-compliance with this License -from such Contributor, and You become compliant prior to 30 days after -Your receipt of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent -infringement claim (excluding declaratory judgment actions, -counter-claims, and cross-claims) alleging that a Contributor Version -directly or indirectly infringes any patent, then the rights granted to -You by any and all Contributors for the Covered Software under Section -2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all -end user license agreements (excluding distributors and resellers) which -have been validly granted by You or Your distributors under this License -prior to termination shall survive termination. - -************************************************************************ -* * -* 6. Disclaimer of Warranty * -* ------------------------- * -* * -* Covered Software is provided under this License on an "as is" * -* basis, without warranty of any kind, either expressed, implied, or * -* statutory, including, without limitation, warranties that the * -* Covered Software is free of defects, merchantable, fit for a * -* particular purpose or non-infringing. The entire risk as to the * -* quality and performance of the Covered Software is with You. * -* Should any Covered Software prove defective in any respect, You * -* (not any Contributor) assume the cost of any necessary servicing, * -* repair, or correction. This disclaimer of warranty constitutes an * -* essential part of this License. No use of any Covered Software is * -* authorized under this License except under this disclaimer. * -* * -************************************************************************ - -************************************************************************ -* * -* 7. Limitation of Liability * -* -------------------------- * -* * -* Under no circumstances and under no legal theory, whether tort * -* (including negligence), contract, or otherwise, shall any * -* Contributor, or anyone who distributes Covered Software as * -* permitted above, be liable to You for any direct, indirect, * -* special, incidental, or consequential damages of any character * -* including, without limitation, damages for lost profits, loss of * -* goodwill, work stoppage, computer failure or malfunction, or any * -* and all other commercial damages or losses, even if such party * -* shall have been informed of the possibility of such damages. This * -* limitation of liability shall not apply to liability for death or * -* personal injury resulting from such party's negligence to the * -* extent applicable law prohibits such limitation. Some * -* jurisdictions do not allow the exclusion or limitation of * -* incidental or consequential damages, so this exclusion and * -* limitation may not apply to You. * -* * -************************************************************************ - -8. Litigation -------------- - -Any litigation relating to this License may be brought only in the -courts of a jurisdiction where the defendant maintains its principal -place of business and such litigation shall be governed by laws of that -jurisdiction, without reference to its conflict-of-law provisions. -Nothing in this Section shall prevent a party's ability to bring -cross-claims or counter-claims. - -9. Miscellaneous ----------------- - -This License represents the complete agreement concerning the subject -matter hereof. If any provision of this License is held to be -unenforceable, such provision shall be reformed only to the extent -necessary to make it enforceable. Any law or regulation which provides -that the language of a contract shall be construed against the drafter -shall not be used to construe this License against a Contributor. - -10. Versions of the License ---------------------------- - -10.1. New Versions - -Mozilla Foundation is the license steward. Except as provided in Section -10.3, no one other than the license steward has the right to modify or -publish new versions of this License. Each version will be given a -distinguishing version number. - -10.2. Effect of New Versions - -You may distribute the Covered Software under the terms of the version -of the License under which You originally received the Covered Software, -or under the terms of any subsequent version published by the license -steward. - -10.3. Modified Versions - -If you create software not governed by this License, and you want to -create a new license for such software, you may create and use a -modified version of this License if you rename the license and remove -any references to the name of the license steward (except to note that -such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary -Licenses - -If You choose to distribute Source Code Form that is Incompatible With -Secondary Licenses under the terms of this version of the License, the -notice described in Exhibit B of this License must be attached. - -Exhibit A - Source Code Form License Notice -------------------------------------------- - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular -file, then You may include the notice in a location (such as a LICENSE -file in a relevant directory) where a recipient would be likely to look -for such a notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice ---------------------------------------------------------- - - This Source Code Form is "Incompatible With Secondary Licenses", as - defined by the Mozilla Public License, v. 2.0. diff --git a/uefi-services/README.md b/uefi-services/README.md index 642763126..ddb053248 100644 --- a/uefi-services/README.md +++ b/uefi-services/README.md @@ -1,3 +1,4 @@ # uefi-services -WARNING: `uefi-services` is deprecated. Functionality was moved to `uefi::helpers::init`. +WARNING: `uefi-services` is deprecated. Functionality was moved to +`uefi::helpers::init` in `uefi` ´v0.28.0`. diff --git a/uefi-services/build.rs b/uefi-services/build.rs deleted file mode 100644 index 96cea2f34..000000000 --- a/uefi-services/build.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("cargo:warning=`uefi-services` is deprecated. Functionality was moved to `uefi::helpers::init`."); -} diff --git a/uefi-services/src/lib.rs b/uefi-services/src/lib.rs deleted file mode 100644 index 3b73e4c16..000000000 --- a/uefi-services/src/lib.rs +++ /dev/null @@ -1,20 +0,0 @@ -//! WARNING: `uefi-services` is deprecated. Functionality was moved to `uefi::helpers::init`. -#![no_std] - -use uefi::prelude::*; -use uefi::Event; -use uefi::Result; - -pub use uefi::{print, println}; - -/// Deprecated. Use [`uefi::helpers::init`] instead. -#[deprecated = "WARNING: `uefi-services` is deprecated. Functionality was moved to `uefi::helpers::init`."] -pub fn init(st: &mut SystemTable) -> Result> { - uefi::helpers::init(st).map(|_| None) -} - -/// Deprecated. Use [`uefi::helpers::system_table`] instead. -#[deprecated = "WARNING: `uefi-services` is deprecated. Functionality was moved to `uefi::helpers::system_table`."] -pub fn system_table() -> SystemTable { - uefi::helpers::system_table() -} diff --git a/xtask/src/cargo.rs b/xtask/src/cargo.rs index 0ac87cd41..78c9e94fb 100644 --- a/xtask/src/cargo.rs +++ b/xtask/src/cargo.rs @@ -10,7 +10,6 @@ pub enum Package { UefiApp, UefiMacros, UefiRaw, - UefiServices, UefiTestRunner, Xtask, } @@ -23,7 +22,6 @@ impl Package { Self::UefiApp => "uefi_app", Self::UefiMacros => "uefi-macros", Self::UefiRaw => "uefi-raw", - Self::UefiServices => "uefi-services", Self::UefiTestRunner => "uefi-test-runner", Self::Xtask => "xtask", } @@ -31,12 +29,7 @@ impl Package { /// All published packages, in the order that publishing should occur. pub fn published() -> Vec { - vec![ - Self::UefiRaw, - Self::UefiMacros, - Self::Uefi, - Self::UefiServices, - ] + vec![Self::UefiRaw, Self::UefiMacros, Self::Uefi] } /// All the packages except for xtask. @@ -46,7 +39,6 @@ impl Package { Self::UefiApp, Self::UefiMacros, Self::UefiRaw, - Self::UefiServices, Self::UefiTestRunner, ] } @@ -60,11 +52,8 @@ pub enum Feature { Logger, PanicOnLoggerErrors, Unstable, - - // `uefi-services` features. PanicHandler, Qemu, - ServicesLogger, // `uefi-test-runner` features. DebugSupport, @@ -83,10 +72,8 @@ impl Feature { Self::Logger => "logger", Self::PanicOnLoggerErrors => "panic-on-logger-errors", Self::Unstable => "unstable", - - Self::PanicHandler => "uefi-services/panic_handler", - Self::Qemu => "uefi-services/qemu", - Self::ServicesLogger => "uefi-services/logger", + Self::PanicHandler => "panic_handler", + Self::Qemu => "qemu", Self::DebugSupport => "uefi-test-runner/debug_support", Self::MultiProcessor => "uefi-test-runner/multi_processor", @@ -106,8 +93,9 @@ impl Feature { Self::Logger, Self::PanicOnLoggerErrors, Self::Unstable, + Self::PanicHandler, + Self::Qemu, ], - Package::UefiServices => vec![Self::PanicHandler, Self::Qemu, Self::ServicesLogger], Package::UefiTestRunner => { vec![ Self::DebugSupport, diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 8cba0feeb..b9133d81e 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -21,23 +21,22 @@ use opt::{Action, BuildOpt, ClippyOpt, DocOpt, Opt, QemuOpt, TpmVersion}; use std::process::Command; use util::run_cmd; +/// Builds various feature permutations that are valid for the `uefi` crate. fn build_feature_permutations(opt: &BuildOpt) -> Result<()> { - for package in [Package::Uefi, Package::UefiServices] { - let all_package_features = Feature::package_features(package); - for features in all_package_features.iter().powerset() { - let features = features.iter().map(|f| **f).collect(); + let all_package_features = Feature::package_features(Package::Uefi); + for features in all_package_features.iter().powerset() { + let features = features.iter().map(|f| **f).collect(); - let cargo = Cargo { - action: CargoAction::Build, - features, - packages: vec![package], - release: opt.build_mode.release, - target: Some(*opt.target), - warnings_as_errors: true, - target_types: TargetTypes::BinsExamplesLib, - }; - run_cmd(cargo.command()?)?; - } + let cargo = Cargo { + action: CargoAction::Build, + features, + packages: vec![Package::Uefi], + release: opt.build_mode.release, + target: Some(*opt.target), + warnings_as_errors: true, + target_types: TargetTypes::BinsExamplesLib, + }; + run_cmd(cargo.command()?)?; } Ok(()) @@ -195,8 +194,6 @@ fn run_host_tests(test_opt: &TestOpt) -> Result<()> { // features is set to no as it is not possible as as soon a #[global_allocator] is // registered, the Rust runtime executing the tests uses it as well. features: Feature::more_code(*test_opt.unstable, false), - // Don't test uefi-services (or the packages that depend on it) - // as it has lang items that conflict with `std`. packages, release: false, // Use the host target so that tests can run without a VM. From bcac03d6f454d85e097b1901e6bb54a5e6d61c34 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sat, 20 Apr 2024 12:53:00 -0400 Subject: [PATCH 10/91] uefi: Drop the panic-on-logger-errors feature This was originally added because of occasional panics when logging quickly on VirtualBox. (Unclear whether this bug is still present, and also as far as I know we haven't observed this behavior on any other UEFI implementations.) The decision was made to panic by default on logger errors, but offer an escape mechanism. However, making this a compile-time choice is not ideal, since most UEFI programs are intended to run on arbitrary UEFI implementations. We could make it a runtime option instead, but since loggers are usually just informational (i.e. not critical functionality for the application), silently ignoring errors seems like a better choice for most uses. In the rare case where an application does consider logging critical, they can turn off the `logger` helper and implement their own logger. For prior discussion, see: * https://github.com/rust-osdev/uefi-rs/issues/121 * https://github.com/rust-osdev/uefi-rs/issues/123 --- uefi/CHANGELOG.md | 4 ++++ uefi/Cargo.toml | 5 ----- uefi/src/helpers/logger.rs | 23 +++++------------------ xtask/src/cargo.rs | 3 --- 4 files changed, 9 insertions(+), 26 deletions(-) diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index dea4a1775..88cbed758 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -1,5 +1,9 @@ # uefi - [Unreleased] +## Removed +- Removed the `panic-on-logger-errors` feature of the `uefi` crate. Logger + errors are now silently ignored. + # uefi - 0.28.0 (2024-04-19) diff --git a/uefi/Cargo.toml b/uefi/Cargo.toml index d1ba545ba..ce50ed6a2 100644 --- a/uefi/Cargo.toml +++ b/uefi/Cargo.toml @@ -13,7 +13,6 @@ repository.workspace = true rust-version.workspace = true [features] -default = ["panic-on-logger-errors"] alloc = [] # Generic gate to code that uses unstable features of Rust. You usually need a nightly toolchain. @@ -23,10 +22,6 @@ unstable = [] logger = [] global_allocator = [] panic_handler = [] -# Ignore text output errors in logger as a workaround for firmware issues that -# were observed on the VirtualBox UEFI implementation (see uefi-rs#121). -# In those cases, this feature can be excluded by removing the default features. -panic-on-logger-errors = [] qemu = ["dep:qemu-exit", "panic_handler"] # panic_handler: logical, not technical dependency [dependencies] diff --git a/uefi/src/helpers/logger.rs b/uefi/src/helpers/logger.rs index 3fc386bb1..31e65c3a3 100644 --- a/uefi/src/helpers/logger.rs +++ b/uefi/src/helpers/logger.rs @@ -107,30 +107,17 @@ impl log::Log for Logger { if !output.is_null() { let writer = unsafe { &mut *output }; - let result = DecoratedLog::write( + + // Ignore all errors. Since we're in the logger implementation we + // can't log the error. We also don't want to panic, since logging + // is generally not critical functionality. + let _ = DecoratedLog::write( writer, record.level(), record.args(), record.file().unwrap_or(""), record.line().unwrap_or(0), ); - - // Some UEFI implementations, such as the one used by VirtualBox, - // may intermittently drop out some text from SimpleTextOutput and - // report an EFI_DEVICE_ERROR. This will be reported here as an - // `fmt::Error`, and given how the `log` crate is designed, our main - // choices when that happens are to ignore the error or panic. - // - // Ignoring errors is bad, especially when they represent loss of - // precious early-boot system diagnosis data, so we panic by - // default. But if you experience this problem and want your UEFI - // application to keep running when it happens, you can disable the - // `panic-on-logger-errors` cargo feature. If you do so, logging errors - // will be ignored by `uefi-rs` instead. - // - if cfg!(feature = "panic-on-logger-errors") { - result.unwrap() - } } } diff --git a/xtask/src/cargo.rs b/xtask/src/cargo.rs index 78c9e94fb..8376e514e 100644 --- a/xtask/src/cargo.rs +++ b/xtask/src/cargo.rs @@ -50,7 +50,6 @@ pub enum Feature { Alloc, GlobalAllocator, Logger, - PanicOnLoggerErrors, Unstable, PanicHandler, Qemu, @@ -70,7 +69,6 @@ impl Feature { Self::Alloc => "alloc", Self::GlobalAllocator => "global_allocator", Self::Logger => "logger", - Self::PanicOnLoggerErrors => "panic-on-logger-errors", Self::Unstable => "unstable", Self::PanicHandler => "panic_handler", Self::Qemu => "qemu", @@ -91,7 +89,6 @@ impl Feature { Self::Alloc, Self::GlobalAllocator, Self::Logger, - Self::PanicOnLoggerErrors, Self::Unstable, Self::PanicHandler, Self::Qemu, From b0e8dd20fb7701a80612f0ad025d1fc2e29b5a92 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sat, 20 Apr 2024 13:44:33 -0400 Subject: [PATCH 11/91] uefi: Clean up macro imports All of the macros from uefi_macros are imported into the uefi crate. Consistently use those imports everywhere, rather than reimporting from `uefi_macros`. --- uefi/src/data_types/strs.rs | 2 +- uefi/src/fs/dir_entry_iter.rs | 3 +-- uefi/src/fs/mod.rs | 2 +- uefi/src/fs/path/mod.rs | 4 ++-- uefi/src/fs/path/path.rs | 2 +- uefi/src/fs/path/pathbuf.rs | 2 +- uefi/src/fs/path/validation.rs | 3 +-- uefi/src/lib.rs | 2 +- uefi/src/prelude.rs | 5 +---- uefi/src/proto/network/snp.rs | 2 +- uefi/src/table/boot.rs | 4 ++-- 11 files changed, 13 insertions(+), 18 deletions(-) diff --git a/uefi/src/data_types/strs.rs b/uefi/src/data_types/strs.rs index e3819dac1..20c23db3c 100644 --- a/uefi/src/data_types/strs.rs +++ b/uefi/src/data_types/strs.rs @@ -620,8 +620,8 @@ where #[cfg(test)] mod tests { use super::*; + use crate::{cstr16, cstr8}; use alloc::string::String; - use uefi_macros::{cstr16, cstr8}; // Tests if our CStr8 type can be constructed from a valid core::ffi::CStr #[test] diff --git a/uefi/src/fs/dir_entry_iter.rs b/uefi/src/fs/dir_entry_iter.rs index 09ba03a52..334825e2e 100644 --- a/uefi/src/fs/dir_entry_iter.rs +++ b/uefi/src/fs/dir_entry_iter.rs @@ -1,9 +1,8 @@ //! Module for directory iteration. See [`UefiDirectoryIter`]. use super::*; -use crate::{CStr16, Result}; +use crate::{cstr16, CStr16, Result}; use alloc::boxed::Box; -use uefi_macros::cstr16; /// Common skip dirs in UEFI/FAT-style file systems. pub const COMMON_SKIP_DIRS: &[&CStr16] = &[cstr16!("."), cstr16!("..")]; diff --git a/uefi/src/fs/mod.rs b/uefi/src/fs/mod.rs index d32ee483c..b66acbfcc 100644 --- a/uefi/src/fs/mod.rs +++ b/uefi/src/fs/mod.rs @@ -47,7 +47,7 @@ //! There is no automatic synchronization of the file system for concurrent //! accesses. This is in the responsibility of the user. //! -//! [`cstr16!`]: uefi_macros::cstr16 +//! [`cstr16!`]: crate::cstr16 mod dir_entry_iter; mod file_system; diff --git a/uefi/src/fs/path/mod.rs b/uefi/src/fs/path/mod.rs index ce943d35a..3e1edb9a8 100644 --- a/uefi/src/fs/path/mod.rs +++ b/uefi/src/fs/path/mod.rs @@ -21,7 +21,7 @@ pub use path::{Components, Path}; pub use pathbuf::PathBuf; use crate::data_types::chars::NUL_16; -use crate::{CStr16, Char16}; +use crate::{cstr16, CStr16, Char16}; pub(super) use validation::validate_path; pub use validation::PathError; @@ -29,7 +29,7 @@ pub use validation::PathError; pub const SEPARATOR: Char16 = unsafe { Char16::from_u16_unchecked('\\' as u16) }; /// Stringified version of [`SEPARATOR`]. -pub const SEPARATOR_STR: &CStr16 = uefi_macros::cstr16!("\\"); +pub const SEPARATOR_STR: &CStr16 = cstr16!("\\"); /// Deny list of characters for path components. UEFI supports FAT-like file /// systems. According to , diff --git a/uefi/src/fs/path/path.rs b/uefi/src/fs/path/path.rs index 122ea4965..efa5019d5 100644 --- a/uefi/src/fs/path/path.rs +++ b/uefi/src/fs/path/path.rs @@ -198,8 +198,8 @@ mod convenience_impls { #[cfg(test)] mod tests { use super::*; + use crate::cstr16; use alloc::vec::Vec; - use uefi_macros::cstr16; #[test] fn from_cstr16() { diff --git a/uefi/src/fs/path/pathbuf.rs b/uefi/src/fs/path/pathbuf.rs index 222121f9b..de81441da 100644 --- a/uefi/src/fs/path/pathbuf.rs +++ b/uefi/src/fs/path/pathbuf.rs @@ -120,8 +120,8 @@ mod convenience_impls { #[cfg(test)] mod tests { use super::*; + use crate::cstr16; use alloc::string::ToString; - use uefi_macros::cstr16; #[test] fn from_cstr16() { diff --git a/uefi/src/fs/path/validation.rs b/uefi/src/fs/path/validation.rs index b1b5cb531..144073003 100644 --- a/uefi/src/fs/path/validation.rs +++ b/uefi/src/fs/path/validation.rs @@ -67,8 +67,7 @@ pub fn validate_path>(path: P) -> Result<(), PathError> { mod tests { use super::*; use crate::fs::PathBuf; - use crate::CString16; - use uefi_macros::cstr16; + use crate::{cstr16, CString16}; #[test] fn test_validate_path() { diff --git a/uefi/src/lib.rs b/uefi/src/lib.rs index d715bfb55..cca1188fd 100644 --- a/uefi/src/lib.rs +++ b/uefi/src/lib.rs @@ -139,7 +139,7 @@ mod util; // Crates that create procedural macros can't unit test the macros they export. // Therefore, we do some tests here. mod macro_tests { - use uefi_macros::{cstr16, cstr8}; + use crate::{cstr16, cstr8}; #[test] fn cstr8_macro_literal() { diff --git a/uefi/src/prelude.rs b/uefi/src/prelude.rs index 644acbe40..f32f9903c 100644 --- a/uefi/src/prelude.rs +++ b/uefi/src/prelude.rs @@ -2,12 +2,9 @@ //! //! This includes the system table types, `Status` codes, etc. -pub use crate::{Handle, ResultExt, Status, StatusExt}; +pub use crate::{cstr16, cstr8, entry, Handle, ResultExt, Status, StatusExt}; // Import the basic table types. pub use crate::table::boot::BootServices; pub use crate::table::runtime::RuntimeServices; pub use crate::table::{Boot, SystemTable}; - -// Import the macro for creating the custom entry point, as well as the cstr macros. -pub use uefi_macros::{cstr16, cstr8, entry}; diff --git a/uefi/src/proto/network/snp.rs b/uefi/src/proto/network/snp.rs index d8a5f4bb6..ee9c2a999 100644 --- a/uefi/src/proto/network/snp.rs +++ b/uefi/src/proto/network/snp.rs @@ -9,12 +9,12 @@ use super::{IpAddress, MacAddress}; use crate::data_types::Event; +use crate::proto::unsafe_protocol; use crate::{Result, Status, StatusExt}; use bitflags::bitflags; use core::ffi::c_void; use core::ptr; use core::ptr::NonNull; -use uefi_macros::unsafe_protocol; /// The Simple Network Protocol #[derive(Debug)] diff --git a/uefi/src/table/boot.rs b/uefi/src/table/boot.rs index 6dbfb0bd1..8cc34e1fd 100644 --- a/uefi/src/table/boot.rs +++ b/uefi/src/table/boot.rs @@ -95,9 +95,9 @@ impl BootServices { /// Update the global image [`Handle`]. /// /// This is called automatically in the `main` entry point as part - /// of [`uefi_macros::entry`]. It should not be called at any other + /// of [`uefi::entry`]. It should not be called at any other /// point in time, unless the executable does not use - /// [`uefi_macros::entry`], in which case it should be called once + /// [`uefi::entry`], in which case it should be called once /// before calling other `BootServices` functions. /// /// # Safety From 063af74d8c2f85d55fd43b82762ba85446ab3dbb Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sat, 20 Apr 2024 15:55:32 -0400 Subject: [PATCH 12/91] uefi: Clean up imports of uefi Consistently import items in the `uefi` crate with `crate::` instead of `uefi::`. --- uefi/src/helpers/mod.rs | 4 ++-- uefi/src/helpers/panic_handler.rs | 4 ++-- uefi/src/proto/media/file/mod.rs | 4 +++- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/uefi/src/helpers/mod.rs b/uefi/src/helpers/mod.rs index 0a757b615..f8aa20761 100644 --- a/uefi/src/helpers/mod.rs +++ b/uefi/src/helpers/mod.rs @@ -92,7 +92,7 @@ pub fn init(st: &mut SystemTable) -> Result<()> { #[cfg(feature = "global_allocator")] unsafe { - uefi::allocator::init(st); + crate::allocator::init(st); } Ok(()) @@ -111,5 +111,5 @@ pub(crate) fn exit() { logger::disable(); #[cfg(feature = "global_allocator")] - uefi::allocator::exit_boot_services(); + crate::allocator::exit_boot_services(); } diff --git a/uefi/src/helpers/panic_handler.rs b/uefi/src/helpers/panic_handler.rs index b70b33273..c5f672a1a 100644 --- a/uefi/src/helpers/panic_handler.rs +++ b/uefi/src/helpers/panic_handler.rs @@ -29,9 +29,9 @@ fn panic_handler(info: &core::panic::PanicInfo) -> ! { } else { // If the system table is available, use UEFI's standard shutdown mechanism if let Some(st) = system_table_opt() { - use uefi::table::runtime::ResetType; + use crate::table::runtime::ResetType; st.runtime_services() - .reset(ResetType::SHUTDOWN, uefi::Status::ABORTED, None); + .reset(ResetType::SHUTDOWN, crate::Status::ABORTED, None); } // If we don't have any shutdown mechanism handy, the best we can do is loop diff --git a/uefi/src/proto/media/file/mod.rs b/uefi/src/proto/media/file/mod.rs index 2628e0443..c9b137617 100644 --- a/uefi/src/proto/media/file/mod.rs +++ b/uefi/src/proto/media/file/mod.rs @@ -15,10 +15,12 @@ use core::ffi::c_void; use core::fmt::Debug; use core::{mem, ptr}; use uefi_raw::protocol::file_system::FileProtocolV1; + #[cfg(all(feature = "unstable", feature = "alloc"))] use {alloc::alloc::Global, core::alloc::Allocator}; + #[cfg(feature = "alloc")] -use {alloc::boxed::Box, uefi::mem::make_boxed}; +use {crate::mem::make_boxed, alloc::boxed::Box}; pub use self::dir::Directory; pub use self::info::{ From 826e55907e45b72655f3e20a612d82e3fc94bc8c Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sat, 20 Apr 2024 16:00:14 -0400 Subject: [PATCH 13/91] uefi: Clean up unnecessary uses of `self::` --- uefi/src/data_types/mod.rs | 8 ++++---- uefi/src/lib.rs | 6 +++--- uefi/src/proto/console/text/mod.rs | 4 ++-- uefi/src/proto/debug/mod.rs | 4 ++-- uefi/src/proto/media/file/mod.rs | 6 +++--- uefi/src/result/mod.rs | 4 ++-- uefi/src/table/mod.rs | 4 ++-- 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/uefi/src/data_types/mod.rs b/uefi/src/data_types/mod.rs index 1238a583d..d4be9e772 100644 --- a/uefi/src/data_types/mod.rs +++ b/uefi/src/data_types/mod.rs @@ -138,23 +138,23 @@ pub trait Align { } mod guid; -pub use self::guid::{Guid, Identify}; +pub use guid::{Guid, Identify}; pub mod chars; -pub use self::chars::{Char16, Char8}; +pub use chars::{Char16, Char8}; #[macro_use] mod opaque; mod strs; -pub use self::strs::{ +pub use strs::{ CStr16, CStr8, EqStrUntilNul, FromSliceWithNulError, FromStrWithBufError, UnalignedCStr16Error, }; #[cfg(feature = "alloc")] mod owned_strs; #[cfg(feature = "alloc")] -pub use self::owned_strs::{CString16, FromStrError}; +pub use owned_strs::{CString16, FromStrError}; mod unaligned_slice; pub use unaligned_slice::UnalignedSlice; diff --git a/uefi/src/lib.rs b/uefi/src/lib.rs index cca1188fd..0179af23b 100644 --- a/uefi/src/lib.rs +++ b/uefi/src/lib.rs @@ -106,13 +106,13 @@ extern crate uefi_raw; #[macro_use] pub mod data_types; #[cfg(feature = "alloc")] -pub use self::data_types::CString16; -pub use self::data_types::{CStr16, CStr8, Char16, Char8, Event, Guid, Handle, Identify}; +pub use data_types::CString16; +pub use data_types::{CStr16, CStr8, Char16, Char8, Event, Guid, Handle, Identify}; pub use uefi_macros::{cstr16, cstr8, entry}; pub use uguid::guid; mod result; -pub use self::result::{Error, Result, ResultExt, Status, StatusExt}; +pub use result::{Error, Result, ResultExt, Status, StatusExt}; pub mod table; diff --git a/uefi/src/proto/console/text/mod.rs b/uefi/src/proto/console/text/mod.rs index ebcd3fcec..089575fce 100644 --- a/uefi/src/proto/console/text/mod.rs +++ b/uefi/src/proto/console/text/mod.rs @@ -1,7 +1,7 @@ //! Text I/O. mod input; -pub use self::input::{Input, Key, ScanCode}; +pub use input::{Input, Key, ScanCode}; mod output; -pub use self::output::{Color, Output, OutputMode}; +pub use output::{Color, Output, OutputMode}; diff --git a/uefi/src/proto/debug/mod.rs b/uefi/src/proto/debug/mod.rs index f626cb866..f2321889a 100644 --- a/uefi/src/proto/debug/mod.rs +++ b/uefi/src/proto/debug/mod.rs @@ -15,8 +15,8 @@ use crate::proto::unsafe_protocol; use crate::{Result, Status, StatusExt}; // re-export for ease of use -pub use self::context::SystemContext; -pub use self::exception::ExceptionType; +pub use context::SystemContext; +pub use exception::ExceptionType; mod context; mod exception; diff --git a/uefi/src/proto/media/file/mod.rs b/uefi/src/proto/media/file/mod.rs index c9b137617..bbb6d365d 100644 --- a/uefi/src/proto/media/file/mod.rs +++ b/uefi/src/proto/media/file/mod.rs @@ -22,12 +22,12 @@ use {alloc::alloc::Global, core::alloc::Allocator}; #[cfg(feature = "alloc")] use {crate::mem::make_boxed, alloc::boxed::Box}; -pub use self::dir::Directory; -pub use self::info::{ +pub use dir::Directory; +pub use info::{ FileInfo, FileInfoCreationError, FileProtocolInfo, FileSystemInfo, FileSystemVolumeLabel, FromUefi, }; -pub use self::regular::RegularFile; +pub use regular::RegularFile; pub use uefi_raw::protocol::file_system::FileAttribute; /// Common interface to `FileHandle`, `RegularFile`, and `Directory`. diff --git a/uefi/src/result/mod.rs b/uefi/src/result/mod.rs index 5afc9b7df..4826c2f0c 100644 --- a/uefi/src/result/mod.rs +++ b/uefi/src/result/mod.rs @@ -4,11 +4,11 @@ use core::fmt::Debug; /// The error type that we use, essentially a status code + optional additional data mod error; -pub use self::error::Error; +pub use error::Error; /// Definition of UEFI's standard status codes mod status; -pub use self::status::{Status, StatusExt}; +pub use status::{Status, StatusExt}; /// Return type of most UEFI functions. Both success and error payloads are optional. /// diff --git a/uefi/src/table/mod.rs b/uefi/src/table/mod.rs index 8c57aba3b..4917946a4 100644 --- a/uefi/src/table/mod.rs +++ b/uefi/src/table/mod.rs @@ -8,10 +8,10 @@ pub trait Table { } mod header; -pub use self::header::Header; +pub use header::Header; mod system; -pub use self::system::{Boot, Runtime, SystemTable}; +pub use system::{Boot, Runtime, SystemTable}; pub mod boot; pub mod runtime; From a5a3ec1c1d61a7cae63195ea65d5ba07928c3986 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sat, 20 Apr 2024 13:56:37 -0400 Subject: [PATCH 14/91] uefi: Add new cstr16 implementation Instead of importing the `cstr16` proc macro from `uefi_macros`, add a new declarative macro. This makes use of the new `ucs2::ucs2_cstr` declarative macro, so bump the minimum version of `ucs2` to 0.3.3. --- uefi/Cargo.toml | 2 +- uefi/src/lib.rs | 17 ++++++++--------- uefi/src/macros.rs | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 10 deletions(-) create mode 100644 uefi/src/macros.rs diff --git a/uefi/Cargo.toml b/uefi/Cargo.toml index ce50ed6a2..fdb2e64fb 100644 --- a/uefi/Cargo.toml +++ b/uefi/Cargo.toml @@ -30,7 +30,7 @@ log.workspace = true ptr_meta.workspace = true uguid.workspace = true cfg-if = "1.0.0" -ucs2 = "0.3.2" +ucs2 = "0.3.3" uefi-macros = "0.13.0" uefi-raw = "0.5.2" qemu-exit = { version = "3.0.2", optional = true } diff --git a/uefi/src/lib.rs b/uefi/src/lib.rs index 0179af23b..651e1b3d7 100644 --- a/uefi/src/lib.rs +++ b/uefi/src/lib.rs @@ -100,6 +100,11 @@ extern crate alloc; // see https://github.com/rust-lang/rust/issues/54647 extern crate self as uefi; +/// Re-export ucs2_cstr so that it can be used in the implementation of the +/// cstr16 macro. It is hidden since it's not intended to be used directly. +#[doc(hidden)] +pub use ucs2::ucs2_cstr; + #[macro_use] extern crate uefi_raw; @@ -108,7 +113,7 @@ pub mod data_types; #[cfg(feature = "alloc")] pub use data_types::CString16; pub use data_types::{CStr16, CStr8, Char16, Char8, Event, Guid, Handle, Identify}; -pub use uefi_macros::{cstr16, cstr8, entry}; +pub use uefi_macros::{cstr8, entry}; pub use uguid::guid; mod result; @@ -133,13 +138,14 @@ pub(crate) mod polyfill; pub mod helpers; +mod macros; mod util; #[cfg(test)] // Crates that create procedural macros can't unit test the macros they export. // Therefore, we do some tests here. mod macro_tests { - use crate::{cstr16, cstr8}; + use crate::cstr8; #[test] fn cstr8_macro_literal() { @@ -147,11 +153,4 @@ mod macro_tests { let _empty2 = cstr8!(""); let _regular = cstr8!("foobar"); } - - #[test] - fn cstr16_macro_literal() { - let _empty1 = cstr16!(); - let _empty2 = cstr16!(""); - let _regular = cstr16!("foobar"); - } } diff --git a/uefi/src/macros.rs b/uefi/src/macros.rs new file mode 100644 index 000000000..4e9897157 --- /dev/null +++ b/uefi/src/macros.rs @@ -0,0 +1,36 @@ +/// Encode a string literal as a [`&CStr16`]. +/// +/// The encoding is done at compile time, so the result can be used in a +/// `const` item. +/// +/// An empty string containing just a null character can be created with either +/// `cstr16!()` or `cstr16!("")`. +/// +/// # Example +/// +/// ``` +/// use uefi::{CStr16, cstr16}; +/// +/// const S: &CStr16 = cstr16!("abc"); +/// assert_eq!(S.to_u16_slice_with_nul(), [97, 98, 99, 0]); +/// +/// const EMPTY: &CStr16 = cstr16!(); +/// assert_eq!(EMPTY.to_u16_slice_with_nul(), [0]); +/// assert_eq!(cstr16!(""), EMPTY); +/// ``` +/// +/// [`&CStr16`]: crate::CStr16 +#[macro_export] +macro_rules! cstr16 { + () => {{ + const S: &[u16] = &[0]; + // SAFETY: `S` is a trivially correct UCS-2 C string. + unsafe { $crate::CStr16::from_u16_with_nul_unchecked(S) } + }}; + ($s:literal) => {{ + const S: &[u16] = &$crate::ucs2_cstr!($s); + // SAFETY: the ucs2_cstr macro always produces a valid UCS-2 string with + // a trailing null character. + unsafe { $crate::CStr16::from_u16_with_nul_unchecked(S) } + }}; +} From ff7cc7aa3e14a3446909f87ea85143a1d87bf09b Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sat, 20 Apr 2024 14:01:22 -0400 Subject: [PATCH 15/91] uefi-macros: Drop the cstr16 macro This is replaced by a new `cstr16` declarative macro in the `uefi` crate. --- uefi-macros/CHANGELOG.md | 4 ++++ uefi-macros/src/lib.rs | 44 ---------------------------------------- 2 files changed, 4 insertions(+), 44 deletions(-) diff --git a/uefi-macros/CHANGELOG.md b/uefi-macros/CHANGELOG.md index a86e687e4..9ddd357fa 100644 --- a/uefi-macros/CHANGELOG.md +++ b/uefi-macros/CHANGELOG.md @@ -1,5 +1,9 @@ # uefi-macros - [Unreleased] +## Removed +- Removed the `cstr16` macro. Use the `cstr16` declarative macro exported by the + `uefi` crate instead. + # uefi-macros - 0.13.0 (2023-11-12) ## Changed diff --git a/uefi-macros/src/lib.rs b/uefi-macros/src/lib.rs index 971bf2c9f..635494304 100644 --- a/uefi-macros/src/lib.rs +++ b/uefi-macros/src/lib.rs @@ -288,47 +288,3 @@ pub fn cstr8(input: proc_macro::TokenStream) -> proc_macro::TokenStream { .into(), } } - -/// Builds a `CStr16` literal at compile time from a string literal. -/// -/// This will throw a compile error if an invalid character is in the passed string. -/// -/// # Example -/// ```rust -/// # use uefi_macros::cstr16; -/// // Empty string -/// assert_eq!(cstr16!().to_u16_slice_with_nul(), [0]); -/// assert_eq!(cstr16!("").to_u16_slice_with_nul(), [0]); -/// // Non-empty string -/// assert_eq!(cstr16!("test €").to_u16_slice_with_nul(), [116, 101, 115, 116, 32, 8364, 0]); -/// ``` -#[proc_macro] -pub fn cstr16(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - // Accept empty input. - if input.is_empty() { - return quote!(unsafe { ::uefi::CStr16::from_u16_with_nul_unchecked(&[0]) }).into(); - } - let input: LitStr = parse_macro_input!(input); - let input = input.value(); - // Accept "" input. - if input.is_empty() { - return quote!(unsafe { ::uefi::CStr16::from_u16_with_nul_unchecked(&[0]) }).into(); - } - - // Accept any non-empty string input. - match input - .chars() - .map(|c| u16::try_from(c as u32)) - .collect::, _>>() - { - Ok(c) => { - quote!(unsafe { ::uefi::CStr16::from_u16_with_nul_unchecked(&[ #(#c),* , 0 ]) }).into() - } - Err(_) => syn::Error::new_spanned( - input, - "There are UTF-8 characters that can't be transformed to UCS-2 character", - ) - .into_compile_error() - .into(), - } -} From ed65e8e490fa49c3b7d0213f38b3bffae664c0a9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 00:14:49 +0000 Subject: [PATCH 16/91] chore(deps): update crate-ci/typos action to v1.20.9 --- .github/workflows/qa.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index 0ddea1962..26d8e2b7b 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -7,4 +7,4 @@ jobs: steps: - uses: actions/checkout@v4 # Executes "typos ." - - uses: crate-ci/typos@v1.20.8 + - uses: crate-ci/typos@v1.20.9 From 6d26b586eb00fa8e9a2fe235b51135fed4574d67 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 00:24:10 +0000 Subject: [PATCH 17/91] fix(deps): update rust crate proc-macro2 to v1.0.81 --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 991affa26..ac6101663 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -458,9 +458,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "proc-macro2" -version = "1.0.80" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56dea16b0a29e94408b9aa5e2940a4eedbd128a1ba20e8f7ae60fd3d465af0e" +checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" dependencies = [ "unicode-ident", ] From 8820b573469b9a14a816c1aebef08763058aea9e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 02:26:29 +0000 Subject: [PATCH 18/91] fix(deps): update rust crate serde_json to v1.0.116 --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ac6101663..3635e5442 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -648,9 +648,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.115" +version = "1.0.116" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" +checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" dependencies = [ "itoa", "ryu", From 396b8f82a7e00eb3b2d58711831effbd9ca5b40c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 02:26:36 +0000 Subject: [PATCH 19/91] fix(deps): update rust crate syn to v2.0.60 --- Cargo.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ac6101663..2b971bba7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -145,7 +145,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -643,7 +643,7 @@ checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -702,9 +702,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.58" +version = "2.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" +checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" dependencies = [ "proc-macro2", "quote", @@ -766,7 +766,7 @@ checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -869,7 +869,7 @@ version = "0.13.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", "trybuild", "uefi", ] @@ -1202,7 +1202,7 @@ dependencies = [ "regex", "serde_json", "sha2", - "syn 2.0.58", + "syn 2.0.60", "tar", "tempfile", "ureq", From 1d5c2266a5cab93204777bbd2af0d77ee9e0029e Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sat, 20 Apr 2024 15:02:00 -0400 Subject: [PATCH 20/91] uefi: Add new cstr8 implementation Implement cstr8 as a proc macro, similar to cstr16. --- uefi/src/data_types/mod.rs | 4 ++ uefi/src/data_types/strs.rs | 87 +++++++++++++++++++++++++++++++++++++ uefi/src/lib.rs | 16 +------ uefi/src/macros.rs | 44 +++++++++++++++++++ 4 files changed, 136 insertions(+), 15 deletions(-) diff --git a/uefi/src/data_types/mod.rs b/uefi/src/data_types/mod.rs index d4be9e772..74239c025 100644 --- a/uefi/src/data_types/mod.rs +++ b/uefi/src/data_types/mod.rs @@ -151,6 +151,10 @@ pub use strs::{ CStr16, CStr8, EqStrUntilNul, FromSliceWithNulError, FromStrWithBufError, UnalignedCStr16Error, }; +/// These functions are used in the implementation of the [`cstr8`] macro. +#[doc(hidden)] +pub use strs::{str_num_latin1_chars, str_to_latin1}; + #[cfg(feature = "alloc")] mod owned_strs; #[cfg(feature = "alloc")] diff --git a/uefi/src/data_types/strs.rs b/uefi/src/data_types/strs.rs index 20c23db3c..2855e8802 100644 --- a/uefi/src/data_types/strs.rs +++ b/uefi/src/data_types/strs.rs @@ -221,6 +221,93 @@ impl<'a> TryFrom<&'a CStr> for &'a CStr8 { } } +/// Get a Latin-1 character from a UTF-8 byte slice at the given offset. +/// +/// Returns a pair containing the Latin-1 character and the number of bytes in +/// the UTF-8 encoding of that character. +/// +/// Panics if the string cannot be encoded in Latin-1. +/// +/// # Safety +/// +/// The input `bytes` must be valid UTF-8. +const unsafe fn latin1_from_utf8_at_offset(bytes: &[u8], offset: usize) -> (u8, usize) { + if bytes[offset] & 0b1000_0000 == 0b0000_0000 { + (bytes[offset], 1) + } else if bytes[offset] & 0b1110_0000 == 0b1100_0000 { + let a = (bytes[offset] & 0b0001_1111) as u16; + let b = (bytes[offset + 1] & 0b0011_1111) as u16; + let ch = a << 6 | b; + if ch > 0xff { + panic!("input string cannot be encoded as Latin-1"); + } + (ch as u8, 2) + } else { + // Latin-1 code points only go up to 0xff, so if the input contains any + // UTF-8 characters larger than two bytes it cannot be converted to + // Latin-1. + panic!("input string cannot be encoded as Latin-1"); + } +} + +/// Count the number of Latin-1 characters in a string. +/// +/// Panics if the string cannot be encoded in Latin-1. +/// +/// This is public but hidden; it is used in the `cstr8` macro. +#[must_use] +pub const fn str_num_latin1_chars(s: &str) -> usize { + let bytes = s.as_bytes(); + let len = bytes.len(); + + let mut offset = 0; + let mut num_latin1_chars = 0; + + while offset < len { + // SAFETY: `bytes` is valid UTF-8. + let (_, num_utf8_bytes) = unsafe { latin1_from_utf8_at_offset(bytes, offset) }; + offset += num_utf8_bytes; + num_latin1_chars += 1; + } + + num_latin1_chars +} + +/// Convert a `str` into a null-terminated Latin-1 character array. +/// +/// Panics if the string cannot be encoded in Latin-1. +/// +/// This is public but hidden; it is used in the `cstr8` macro. +#[must_use] +pub const fn str_to_latin1(s: &str) -> [u8; N] { + let bytes = s.as_bytes(); + let len = bytes.len(); + + let mut output = [0; N]; + + let mut output_offset = 0; + let mut input_offset = 0; + while input_offset < len { + // SAFETY: `bytes` is valid UTF-8. + let (ch, num_utf8_bytes) = unsafe { latin1_from_utf8_at_offset(bytes, input_offset) }; + if ch == 0 { + panic!("interior null character"); + } else { + output[output_offset] = ch; + output_offset += 1; + input_offset += num_utf8_bytes; + } + } + + // The output array must be one bigger than the converted string, + // to leave room for the trailing null character. + if output_offset + 1 != N { + panic!("incorrect array length"); + } + + output +} + /// An UCS-2 null-terminated string slice. /// /// This type is largely inspired by [`core::ffi::CStr`] with the exception that all characters are diff --git a/uefi/src/lib.rs b/uefi/src/lib.rs index 651e1b3d7..9a425aac6 100644 --- a/uefi/src/lib.rs +++ b/uefi/src/lib.rs @@ -113,7 +113,7 @@ pub mod data_types; #[cfg(feature = "alloc")] pub use data_types::CString16; pub use data_types::{CStr16, CStr8, Char16, Char8, Event, Guid, Handle, Identify}; -pub use uefi_macros::{cstr8, entry}; +pub use uefi_macros::entry; pub use uguid::guid; mod result; @@ -140,17 +140,3 @@ pub mod helpers; mod macros; mod util; - -#[cfg(test)] -// Crates that create procedural macros can't unit test the macros they export. -// Therefore, we do some tests here. -mod macro_tests { - use crate::cstr8; - - #[test] - fn cstr8_macro_literal() { - let _empty1 = cstr8!(); - let _empty2 = cstr8!(""); - let _regular = cstr8!("foobar"); - } -} diff --git a/uefi/src/macros.rs b/uefi/src/macros.rs index 4e9897157..5bb2f7b79 100644 --- a/uefi/src/macros.rs +++ b/uefi/src/macros.rs @@ -1,3 +1,47 @@ +/// Encode a string literal as a [`&CStr8`]. +/// +/// The encoding is done at compile time, so the result can be used in a +/// `const` item. +/// +/// An empty string containing just a null character can be created with either +/// `cstr8!()` or `cstr8!("")`. +/// +/// # Example +/// +/// ``` +/// use uefi::{CStr8, cstr8}; +/// +/// const S: &CStr8 = cstr8!("abÿ"); +/// assert_eq!(S.as_bytes(), [97, 98, 255, 0]); +/// +/// const EMPTY: &CStr8 = cstr8!(); +/// assert_eq!(EMPTY.as_bytes(), [0]); +/// assert_eq!(cstr8!(""), EMPTY); +/// ``` +/// +/// [`&CStr8`]: crate::CStr8 +#[macro_export] +macro_rules! cstr8 { + () => {{ + const S: &[u8] = &[0]; + // SAFETY: `S` is a trivially correct Latin-1 C string. + unsafe { $crate::CStr8::from_bytes_with_nul_unchecked(S) } + }}; + ($s:literal) => {{ + // Use `const` values here to force errors to happen at compile + // time. + + // Add one for the null char. + const NUM_CHARS: usize = $crate::data_types::str_num_latin1_chars($s) + 1; + + const VAL: [u8; NUM_CHARS] = $crate::data_types::str_to_latin1($s); + + // SAFETY: the `str_to_latin1` function always produces a valid Latin-1 + // string with a trailing null character. + unsafe { $crate::CStr8::from_bytes_with_nul_unchecked(&VAL) } + }}; +} + /// Encode a string literal as a [`&CStr16`]. /// /// The encoding is done at compile time, so the result can be used in a From 7b1fa84564795a9d0ea04a73f07d80abfa1834a2 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sat, 20 Apr 2024 15:49:22 -0400 Subject: [PATCH 21/91] uefi-macros: Drop the cstr8 macro This is replaced by a new `cstr8` declarative macro in the `uefi` crate. --- uefi-macros/CHANGELOG.md | 4 ++-- uefi-macros/src/lib.rs | 43 +--------------------------------------- 2 files changed, 3 insertions(+), 44 deletions(-) diff --git a/uefi-macros/CHANGELOG.md b/uefi-macros/CHANGELOG.md index 9ddd357fa..b56ff7fce 100644 --- a/uefi-macros/CHANGELOG.md +++ b/uefi-macros/CHANGELOG.md @@ -1,8 +1,8 @@ # uefi-macros - [Unreleased] ## Removed -- Removed the `cstr16` macro. Use the `cstr16` declarative macro exported by the - `uefi` crate instead. +- Removed the `cstr8` and `cstr16` macros. Use the declarative macros of the + same names exported by the `uefi` crate as a replacement. # uefi-macros - 0.13.0 (2023-11-12) diff --git a/uefi-macros/src/lib.rs b/uefi-macros/src/lib.rs index 635494304..9f5b67da8 100644 --- a/uefi-macros/src/lib.rs +++ b/uefi-macros/src/lib.rs @@ -9,7 +9,7 @@ use quote::{quote, quote_spanned, TokenStreamExt}; use syn::spanned::Spanned; use syn::{ parse_macro_input, parse_quote, Error, Expr, ExprLit, ExprPath, FnArg, Ident, ItemFn, - ItemStruct, Lit, LitStr, Pat, Visibility, + ItemStruct, Lit, Pat, Visibility, }; macro_rules! err { @@ -247,44 +247,3 @@ pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream { }; result.into() } - -/// Builds a `CStr8` literal at compile time from a string literal. -/// -/// This will throw a compile error if an invalid character is in the passed string. -/// -/// # Example -/// ``` -/// # use uefi_macros::cstr8; -/// // Empty string -/// assert_eq!(cstr8!().to_u16_slice_with_nul(), [0]); -/// assert_eq!(cstr8!("").to_u16_slice_with_nul(), [0]); -/// // Non-empty string -/// assert_eq!(cstr8!("test").as_bytes(), [116, 101, 115, 116, 0]); -/// ``` -#[proc_macro] -pub fn cstr8(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - // Accept empty input. - if input.is_empty() { - return quote!(unsafe { ::uefi::CStr16::from_u16_with_nul_unchecked(&[0]) }).into(); - } - let input: LitStr = parse_macro_input!(input); - let input = input.value(); - // Accept "" input. - if input.is_empty() { - return quote!(unsafe { ::uefi::CStr16::from_u16_with_nul_unchecked(&[0]) }).into(); - } - - // Accept any non-empty string input. - match input - .chars() - .map(u8::try_from) - .collect::, _>>() - { - Ok(c) => { - quote!(unsafe { ::uefi::CStr8::from_bytes_with_nul_unchecked(&[ #(#c),* , 0 ]) }).into() - } - Err(_) => syn::Error::new_spanned(input, "invalid character in string") - .into_compile_error() - .into(), - } -} From ed039fd32f92e5924e627f323abc9bb3951db2bb Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Mon, 22 Apr 2024 11:41:50 -0400 Subject: [PATCH 22/91] ci: Remove xtask from MSRV build We don't care about the MSRV for xtask, since it's just a dev tool. Also, some of xtask's dependencies (like clap) update MSRV somewhat frequently, so in order to update to the latest version of those deps it's better to not restrict xtask's MSRV. --- .github/workflows/rust.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 5436a4086..5fc22ba11 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -114,7 +114,10 @@ jobs: run: cp .github/workflows/msrv_toolchain.toml rust-toolchain.toml - uses: Swatinem/rust-cache@v2 - name: Build - run: cargo xtask build + # Build uefi-test-runner since its dependency tree includes all the + # library packages. Note that xtask isn't used or built here; since it's + # just a dev tool we don't care about the MSRV for that package. + run: cargo build --target x86_64-unknown-uefi -p uefi-test-runner # This job requires the nightly channel, but keep it as a separate job from # `nightly_channel` because it takes a while to run. build_feature_permutations: From 3c22b948415bd78ada0064e8a7986afa482b18c4 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Mon, 22 Apr 2024 11:43:24 -0400 Subject: [PATCH 23/91] Update clap dep --- Cargo.lock | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5a95e50bd..ae0bff778 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -118,9 +118,9 @@ checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" [[package]] name = "clap" -version = "4.4.18" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" dependencies = [ "clap_builder", "clap_derive", @@ -128,9 +128,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.18" +version = "4.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" dependencies = [ "anstyle", "clap_lex", @@ -138,11 +138,11 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.4.7" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" dependencies = [ - "heck", + "heck 0.5.0", "proc-macro2", "quote", "syn 2.0.60", @@ -150,9 +150,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" [[package]] name = "cpufeatures" @@ -331,6 +331,12 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "idna" version = "0.3.0" @@ -1191,7 +1197,7 @@ dependencies = [ "clap", "fatfs", "fs-err", - "heck", + "heck 0.4.1", "itertools", "lzma-rs", "mbrman", From 4fb78341e587835cd49b27fa91224f7cbde46e9c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 16:05:52 +0000 Subject: [PATCH 24/91] chore(deps): lock file maintenance --- Cargo.lock | 251 ++++++++++++++++++++--------------------------------- 1 file changed, 95 insertions(+), 156 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ae0bff778..43c608599 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10,18 +10,18 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] [[package]] name = "anstyle" -version = "1.0.4" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" +checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" [[package]] name = "anyhow" @@ -31,9 +31,9 @@ checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" [[package]] name = "autocfg" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" [[package]] name = "base64" @@ -97,12 +97,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cc" -version = "1.0.83" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] +checksum = "d32a725bc159af97c3e629873bb9f88fb8cf8a4867175f76dc987815ea07c83b" [[package]] name = "cfg-if" @@ -165,9 +162,9 @@ dependencies = [ [[package]] name = "crc" -version = "3.0.1" +version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86ec7a15cbe22e59248fc7eadb1907dab5ba09372595da4d73dd805ed4417dfe" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" dependencies = [ "crc-catalog", ] @@ -180,9 +177,9 @@ checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" dependencies = [ "cfg-if", ] @@ -209,9 +206,9 @@ dependencies = [ [[package]] name = "either" -version = "1.9.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" [[package]] name = "equivalent" @@ -226,14 +223,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] name = "fastrand" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" [[package]] name = "fatfs" @@ -255,7 +252,7 @@ dependencies = [ "cfg-if", "libc", "redox_syscall", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] @@ -304,9 +301,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.12" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" dependencies = [ "cfg-if", "libc", @@ -339,9 +336,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "idna" -version = "0.3.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -349,9 +346,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.5" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", "hashbrown", @@ -368,9 +365,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "libc" @@ -415,15 +412,15 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.1" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", ] @@ -453,7 +450,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae99c7fa6dd38c7cafe1ec085e804f8f555a2f8659b0dbe03f1f9963a9b51092" dependencies = [ "log", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] @@ -535,9 +532,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", @@ -546,35 +543,36 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "ring" -version = "0.17.7" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", + "cfg-if", "getrandom", "libc", "spin", "untrusted", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] name = "rustix" -version = "0.38.31" +version = "0.38.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" +checksum = "e3cc72858054fcff6d7dea32df2aeaee6a7c24227366d7ea429aada2f26b16ad" dependencies = [ "bitflags 2.5.0", "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] @@ -593,15 +591,15 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.2.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a716eb65e3158e90e17cd93d855216e27bde02745ab842f2cab4a39dba1bacf" +checksum = "ecd36cc4259e3e4514335c4a138c6b43171a8d61d8f5c9348f9fc7529416f247" [[package]] name = "rustls-webpki" -version = "0.102.2" +version = "0.102.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faaa0a62740bedb9b2ef5afa303da42764c012f743917351dc9a237ea1663610" +checksum = "f3bce581c0dd41bce533ce695a1437fa16a7ab5ac3ccfa99fe1a620a7885eabf" dependencies = [ "ring", "rustls-pki-types", @@ -610,9 +608,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "same-file" @@ -625,9 +623,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.196" +version = "1.0.198" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" +checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc" dependencies = [ "serde_derive", ] @@ -643,9 +641,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.196" +version = "1.0.198" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" +checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9" dependencies = [ "proc-macro2", "quote", @@ -743,7 +741,7 @@ dependencies = [ "cfg-if", "fastrand", "rustix", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] @@ -757,18 +755,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.56" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" +checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.56" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" +checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" dependencies = [ "proc-macro2", "quote", @@ -792,9 +790,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "toml" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af06656561d28735e9c1cd63dfd57132c8155426aa6af24f36a00a351f88c48e" +checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3" dependencies = [ "serde", "serde_spanned", @@ -813,9 +811,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.7" +version = "0.22.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18769cd1cec395d70860ceb4d932812a0b4d06b1a4bb336745a4d21b9496e992" +checksum = "d3328d4f68a705b2a4498da1d580585d39a6510f98318a2cec3018a7ec61ddef" dependencies = [ "indexmap", "serde", @@ -925,9 +923,9 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] @@ -957,9 +955,9 @@ dependencies = [ [[package]] name = "url" -version = "2.3.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", "idna", @@ -1028,143 +1026,84 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", + "windows-targets", ] [[package]] name = "windows-targets" -version = "0.48.5" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] -[[package]] -name = "windows-targets" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" -dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" [[package]] name = "windows_i686_gnu" -version = "0.48.5" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" [[package]] -name = "windows_i686_gnu" -version = "0.52.0" +name = "windows_i686_gnullvm" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" [[package]] name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.5" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" [[package]] name = "windows_x86_64_msvc" -version = "0.48.5" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "winnow" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8" +checksum = "f0c976aaaa0e1f90dbb21e9587cdaf1d9679a1cde8875c0d6bd83ab96a208352" dependencies = [ "memchr", ] From 3d18d303094cfabc7f2e51536a65f3cad33eb180 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 29 Apr 2024 02:07:49 +0000 Subject: [PATCH 25/91] chore(deps): update crate-ci/typos action to v1.20.10 --- .github/workflows/qa.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index 26d8e2b7b..c41d1cbc1 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -7,4 +7,4 @@ jobs: steps: - uses: actions/checkout@v4 # Executes "typos ." - - uses: crate-ci/typos@v1.20.9 + - uses: crate-ci/typos@v1.20.10 From 466383847ed8b0f363102137cded3447a5dfd0af Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 29 Apr 2024 02:18:25 +0000 Subject: [PATCH 26/91] fix(deps): update rust crate ureq to v2.9.7 --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 43c608599..e4f99a03b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -37,9 +37,9 @@ checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" [[package]] name = "base64" -version = "0.21.7" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51" [[package]] name = "bincode" @@ -938,9 +938,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "ureq" -version = "2.9.6" +version = "2.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11f214ce18d8b2cbe84ed3aa6486ed3f5b285cf8d8fbdbce9f3f767a724adc35" +checksum = "d11a831e3c0b56e438a28308e7c810799e3c118417f342d30ecec080105395cd" dependencies = [ "base64", "flate2", From 128fd0a5b71414f0862c3dfdc19fc389971bb400 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 5 May 2024 22:04:41 -0400 Subject: [PATCH 27/91] Fix risc target_arch cfg Nightly now checks if target_arch is correct, which revealed a spot where we used `riscv`, which isn't valid. Switched to test both riscv32 and riscv64. --- uefi/src/proto/debug/exception.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uefi/src/proto/debug/exception.rs b/uefi/src/proto/debug/exception.rs index ae3852711..4298a54b6 100644 --- a/uefi/src/proto/debug/exception.rs +++ b/uefi/src/proto/debug/exception.rs @@ -140,7 +140,7 @@ impl ExceptionType { pub const MAX_AARCH64_EXCEPTION: ExceptionType = ExceptionType::EXCEPT_AARCH64_SERROR; } -#[cfg(target_arch = "riscv")] +#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] impl ExceptionType { /// Instruction misaligned pub const EXCEPT_RISCV_INST_MISALIGNED: ExceptionType = ExceptionType(0); From 93d60bb07902017fe4d0b717fd4c7e9a9cddc170 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 6 May 2024 06:14:25 +0000 Subject: [PATCH 28/91] chore(deps): update crate-ci/typos action to v1.21.0 --- .github/workflows/qa.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index c41d1cbc1..2776cfe4a 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -7,4 +7,4 @@ jobs: steps: - uses: actions/checkout@v4 # Executes "typos ." - - uses: crate-ci/typos@v1.20.10 + - uses: crate-ci/typos@v1.21.0 From bf468f907384d9187e27669fdf752cdf86ad221a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 6 May 2024 06:24:41 +0000 Subject: [PATCH 29/91] chore(deps): update rust crate trybuild to v1.0.93 --- Cargo.lock | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e4f99a03b..734547d20 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -824,12 +824,11 @@ dependencies = [ [[package]] name = "trybuild" -version = "1.0.91" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ad7eb6319ebadebca3dacf1f85a93bc54b73dd81b9036795f73de7ddfe27d5a" +checksum = "2a0e5d82932dfbf36df38de5df0cfe846d13430b3ae3fdc48b2e91ed692c8df7" dependencies = [ "glob", - "once_cell", "serde", "serde_derive", "serde_json", From 47106899a42da7d07a0c6e4f48e66ee44403bb66 Mon Sep 17 00:00:00 2001 From: andre-braga Date: Fri, 10 May 2024 21:34:08 +0000 Subject: [PATCH 30/91] Match MaximumCapsuleSize to UEFI spec Per section 8.5.3.4 of the latest UEFI spec [1], `QueryCapsuleCapabilities` uses a uint64 for MaximumCapsuleSize, not a usize. [1]:https://uefi.org/sites/default/files/resources/UEFI_Spec_2_10_Aug29.pdf --- uefi-raw/CHANGELOG.md | 2 ++ uefi-raw/src/table/runtime.rs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/uefi-raw/CHANGELOG.md b/uefi-raw/CHANGELOG.md index c9014782c..15a8d793f 100644 --- a/uefi-raw/CHANGELOG.md +++ b/uefi-raw/CHANGELOG.md @@ -1,5 +1,7 @@ # uefi-raw - [Unreleased] +## Changed +- `maximum_capsule_size` of `query_capsule_capabilities` now takes a *mut u64 instead of a *mut usize. # uefi-raw - 0.5.2 (2024-04-19) diff --git a/uefi-raw/src/table/runtime.rs b/uefi-raw/src/table/runtime.rs index e6474e71d..088118272 100644 --- a/uefi-raw/src/table/runtime.rs +++ b/uefi-raw/src/table/runtime.rs @@ -66,7 +66,7 @@ pub struct RuntimeServices { pub query_capsule_capabilities: unsafe extern "efiapi" fn( capsule_header_array: *const *const CapsuleHeader, capsule_count: usize, - maximum_capsule_size: *mut usize, + maximum_capsule_size: *mut u64, reset_type: *mut ResetType, ) -> Status, From b43b0b07862bc312932b3a0313820483e1b3c167 Mon Sep 17 00:00:00 2001 From: andre-braga Date: Fri, 10 May 2024 22:15:11 +0000 Subject: [PATCH 31/91] Add RuntimeServices::update_capsule This allows passing capsules[1] to firmware. Firmware updates cannot be explicitly tested as it is not supported by OVMF. [1]:https://uefi.org/specs/UEFI/2.9_A/08_Services_Runtime_Services.html#update-capsule --- uefi/CHANGELOG.md | 3 +++ uefi/src/table/runtime.rs | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index 88cbed758..8e7e3930e 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -1,5 +1,8 @@ # uefi - [Unreleased] +## Added +- Added `RuntimeServices::update_capsule`. + ## Removed - Removed the `panic-on-logger-errors` feature of the `uefi` crate. Logger errors are now silently ignored. diff --git a/uefi/src/table/runtime.rs b/uefi/src/table/runtime.rs index 3947869e4..1b127d88d 100644 --- a/uefi/src/table/runtime.rs +++ b/uefi/src/table/runtime.rs @@ -7,10 +7,12 @@ use core::fmt::{self, Debug, Display, Formatter}; use core::mem::MaybeUninit; use core::ptr; +pub use uefi_raw::capsule::{CapsuleBlockDescriptor, CapsuleHeader}; pub use uefi_raw::table::runtime::{ ResetType, TimeCapabilities, VariableAttributes, VariableVendor, }; pub use uefi_raw::time::Daylight; +pub use uefi_raw::PhysicalAddress; #[cfg(feature = "alloc")] use { @@ -290,6 +292,22 @@ impl RuntimeServices { ) -> Status { (self.0.set_virtual_address_map)(map_size, desc_size, desc_version, virtual_map) } + + /// Passes capsules to the firmware. Capsules are most commonly used to update system firmware. + pub fn update_capsule( + &self, + capsule_header_array: &[&CapsuleHeader], + capsule_block_descriptors: &[CapsuleBlockDescriptor], + ) -> Result { + unsafe { + (self.0.update_capsule)( + capsule_header_array.as_ptr().cast(), + capsule_header_array.len(), + capsule_block_descriptors.as_ptr() as PhysicalAddress, + ) + .to_result() + } + } } impl super::Table for RuntimeServices { From a301205ce8323de8878dec996d939cafdfc4a1f3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 13 May 2024 00:35:24 +0000 Subject: [PATCH 32/91] chore(deps): lock file maintenance --- Cargo.lock | 130 ++++++++++++++++++++++------------------------------- 1 file changed, 54 insertions(+), 76 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 734547d20..fbd8b46d3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,27 +19,27 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" [[package]] name = "anyhow" -version = "1.0.82" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" +checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3" [[package]] name = "autocfg" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "base64" -version = "0.22.0" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bincode" @@ -97,9 +97,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cc" -version = "1.0.95" +version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d32a725bc159af97c3e629873bb9f88fb8cf8a4867175f76dc987815ea07c83b" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" [[package]] name = "cfg-if" @@ -142,7 +142,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.63", ] [[package]] @@ -218,9 +218,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", "windows-sys", @@ -228,9 +228,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" [[package]] name = "fatfs" @@ -257,9 +257,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.28" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" dependencies = [ "crc32fast", "miniz_oxide", @@ -301,9 +301,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -318,9 +318,9 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "heck" @@ -371,9 +371,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "libc" -version = "0.2.153" +version = "0.2.154" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" [[package]] name = "linux-raw-sys" @@ -461,9 +461,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "proc-macro2" -version = "1.0.81" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" dependencies = [ "unicode-ident", ] @@ -564,9 +564,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.33" +version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3cc72858054fcff6d7dea32df2aeaee6a7c24227366d7ea429aada2f26b16ad" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ "bitflags 2.5.0", "errno", @@ -591,9 +591,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.4.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecd36cc4259e3e4514335c4a138c6b43171a8d61d8f5c9348f9fc7529416f247" +checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" [[package]] name = "rustls-webpki" @@ -608,9 +608,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "same-file" @@ -623,9 +623,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.198" +version = "1.0.201" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc" +checksum = "780f1cebed1629e4753a1a38a3c72d30b97ec044f0aef68cb26650a3c5cf363c" dependencies = [ "serde_derive", ] @@ -641,20 +641,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.198" +version = "1.0.201" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9" +checksum = "c5e405930b9796f1c00bee880d03fc7e0bb4b9a11afc776885ffe84320da2865" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.63", ] [[package]] name = "serde_json" -version = "1.0.116" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" dependencies = [ "itoa", "ryu", @@ -706,9 +706,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.60" +version = "2.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" dependencies = [ "proc-macro2", "quote", @@ -755,22 +755,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.59" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" +checksum = "579e9083ca58dd9dcf91a9923bb9054071b9ebbd800b342194c9feb0ee89fc18" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.59" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" +checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.63", ] [[package]] @@ -824,9 +824,9 @@ dependencies = [ [[package]] name = "trybuild" -version = "1.0.93" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0e5d82932dfbf36df38de5df0cfe846d13430b3ae3fdc48b2e91ed692c8df7" +checksum = "4ddb747392ea12569d501a5bbca08852e4c8cd88b92566074b2243b8846f09e6" dependencies = [ "glob", "serde", @@ -872,7 +872,7 @@ version = "0.13.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.63", "trybuild", "uefi", ] @@ -994,37 +994,15 @@ dependencies = [ "rustls-pki-types", ] -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - [[package]] name = "winapi-util" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" dependencies = [ - "winapi", + "windows-sys", ] -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - [[package]] name = "windows-sys" version = "0.52.0" @@ -1100,9 +1078,9 @@ checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "winnow" -version = "0.6.6" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0c976aaaa0e1f90dbb21e9587cdaf1d9679a1cde8875c0d6bd83ab96a208352" +checksum = "c3c52e9c97a68071b23e836c9380edae937f17b9c4667bd021973efc689f618d" dependencies = [ "memchr", ] @@ -1146,7 +1124,7 @@ dependencies = [ "regex", "serde_json", "sha2", - "syn 2.0.60", + "syn 2.0.63", "tar", "tempfile", "ureq", From bdbc80fbc482a2abe74799752ae0a4155a4732c6 Mon Sep 17 00:00:00 2001 From: andre-braga Date: Fri, 10 May 2024 23:24:11 +0000 Subject: [PATCH 33/91] Add RuntimeServices::query_capsule_capabilities This adds the ability to query whether an update capsule is supported by update_capsule or not. --- uefi-raw/CHANGELOG.md | 1 + uefi-raw/src/table/runtime.rs | 1 + uefi/CHANGELOG.md | 1 + uefi/src/table/runtime.rs | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 35 insertions(+) diff --git a/uefi-raw/CHANGELOG.md b/uefi-raw/CHANGELOG.md index 15a8d793f..58a8664c3 100644 --- a/uefi-raw/CHANGELOG.md +++ b/uefi-raw/CHANGELOG.md @@ -2,6 +2,7 @@ ## Changed - `maximum_capsule_size` of `query_capsule_capabilities` now takes a *mut u64 instead of a *mut usize. +- `ResetType` now derives the `Default` trait. # uefi-raw - 0.5.2 (2024-04-19) diff --git a/uefi-raw/src/table/runtime.rs b/uefi-raw/src/table/runtime.rs index 088118272..69daa0f23 100644 --- a/uefi-raw/src/table/runtime.rs +++ b/uefi-raw/src/table/runtime.rs @@ -80,6 +80,7 @@ pub struct RuntimeServices { } newtype_enum! { + #[derive(Default)] /// The type of system reset. pub enum ResetType: u32 => { /// System-wide reset. diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index 8e7e3930e..671cf33c7 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -2,6 +2,7 @@ ## Added - Added `RuntimeServices::update_capsule`. +- Added `RuntimeServices::query_capsule_capabilities`. ## Removed - Removed the `panic-on-logger-errors` feature of the `uefi` crate. Logger diff --git a/uefi/src/table/runtime.rs b/uefi/src/table/runtime.rs index 1b127d88d..72cff98a7 100644 --- a/uefi/src/table/runtime.rs +++ b/uefi/src/table/runtime.rs @@ -308,6 +308,25 @@ impl RuntimeServices { .to_result() } } + + /// Tests whether a capsule or capsules can be updated via [`RuntimeServices::update_capsule`]. + /// + /// See [`CapsuleInfo`] for details of the information returned. + pub fn query_capsule_capabilities( + &self, + capsule_header_array: &[&CapsuleHeader], + ) -> Result { + let mut info = CapsuleInfo::default(); + unsafe { + (self.0.query_capsule_capabilities)( + capsule_header_array.as_ptr().cast(), + capsule_header_array.len(), + &mut info.maximum_capsule_size, + &mut info.reset_type, + ) + .to_result_with_val(|| info) + } + } } impl super::Table for RuntimeServices { @@ -551,3 +570,16 @@ pub struct VariableStorageInfo { /// Maximum size of an individual variable of the specified type. pub maximum_variable_size: u64, } + +/// Information about UEFI variable storage space returned by +/// [`RuntimeServices::query_capsule_capabilities`]. +#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] +pub struct CapsuleInfo { + /// The maximum size in bytes that [`RuntimeServices::update_capsule`] + /// can support as input. Note that the size of an update capsule is composed of + /// all [`CapsuleHeader`]s and [CapsuleBlockDescriptor]s. + pub maximum_capsule_size: u64, + + /// The type of reset required for the capsule update. + pub reset_type: ResetType, +} From 37eb5f5fdc3d1c3650efa9410f49aca751d46729 Mon Sep 17 00:00:00 2001 From: Liz Date: Tue, 14 May 2024 06:40:54 -0700 Subject: [PATCH 34/91] Note about feature flags for uefi book --- book/src/tutorial/app.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/book/src/tutorial/app.md b/book/src/tutorial/app.md index 272ccd078..d2be726a8 100644 --- a/book/src/tutorial/app.md +++ b/book/src/tutorial/app.md @@ -16,7 +16,15 @@ cd my-uefi-app Add a few dependencies: ```sh -cargo add log uefi +cargo add log +cargo add uefi --features logger,panic_handler +``` + +to your `Cargo.toml`. The resulting `Cargo.toml` should look like that: +```toml +[dependencies] +log = "0.4.21" +uefi = { version = "0.28.0", features = [ "panic_handler", "logger" ] } ``` Replace the contents of `src/main.rs` with this: From 1f3ec744aa5414953fb6195e10982a17610853a8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 17 May 2024 18:46:50 +0000 Subject: [PATCH 35/91] chore(deps): lock file maintenance --- Cargo.lock | 78 +++++++++++++++++++++++++++--------------------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fbd8b46d3..d3bfaacf7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -25,9 +25,9 @@ checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" [[package]] name = "anyhow" -version = "1.0.83" +version = "1.0.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3" +checksum = "18b8795de6d09abb2b178fa5a9e3bb10da935750f33449a132b328b9391b2c6a" [[package]] name = "autocfg" @@ -142,7 +142,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.64", ] [[package]] @@ -206,9 +206,9 @@ dependencies = [ [[package]] name = "either" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" +checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" [[package]] name = "equivalent" @@ -301,9 +301,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.15" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" dependencies = [ "cfg-if", "libc", @@ -371,15 +371,15 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "libc" -version = "0.2.154" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "linux-raw-sys" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "log" @@ -418,9 +418,9 @@ checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" dependencies = [ "adler", ] @@ -597,9 +597,9 @@ checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" [[package]] name = "rustls-webpki" -version = "0.102.3" +version = "0.102.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3bce581c0dd41bce533ce695a1437fa16a7ab5ac3ccfa99fe1a620a7885eabf" +checksum = "ff448f7e92e913c4b7d4c6d8e4540a1724b319b4152b8aef6d4cf8339712b33e" dependencies = [ "ring", "rustls-pki-types", @@ -623,9 +623,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.201" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "780f1cebed1629e4753a1a38a3c72d30b97ec044f0aef68cb26650a3c5cf363c" +checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395" dependencies = [ "serde_derive", ] @@ -641,13 +641,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.201" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e405930b9796f1c00bee880d03fc7e0bb4b9a11afc776885ffe84320da2865" +checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.64", ] [[package]] @@ -663,9 +663,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" dependencies = [ "serde", ] @@ -706,9 +706,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.63" +version = "2.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" +checksum = "7ad3dee41f36859875573074334c200d1add8e4a87bb37113ebd31d926b7b11f" dependencies = [ "proc-macro2", "quote", @@ -755,22 +755,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.60" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "579e9083ca58dd9dcf91a9923bb9054071b9ebbd800b342194c9feb0ee89fc18" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.60" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.64", ] [[package]] @@ -790,9 +790,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "toml" -version = "0.8.12" +version = "0.8.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3" +checksum = "a4e43f8cc456c9704c851ae29c67e17ef65d2c30017c17a9765b89c382dc8bba" dependencies = [ "serde", "serde_spanned", @@ -802,18 +802,18 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.22.12" +version = "0.22.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3328d4f68a705b2a4498da1d580585d39a6510f98318a2cec3018a7ec61ddef" +checksum = "c127785850e8c20836d49732ae6abfa47616e60bf9d9f57c43c250361a9db96c" dependencies = [ "indexmap", "serde", @@ -824,9 +824,9 @@ dependencies = [ [[package]] name = "trybuild" -version = "1.0.95" +version = "1.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ddb747392ea12569d501a5bbca08852e4c8cd88b92566074b2243b8846f09e6" +checksum = "33a5f13f11071020bb12de7a16b925d2d58636175c20c11dc5f96cb64bb6c9b3" dependencies = [ "glob", "serde", @@ -872,7 +872,7 @@ version = "0.13.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.64", "trybuild", "uefi", ] @@ -1124,7 +1124,7 @@ dependencies = [ "regex", "serde_json", "sha2", - "syn 2.0.63", + "syn 2.0.64", "tar", "tempfile", "ureq", From ab86fc0ad8d5e222c143dd8037f2a393eaa737d8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 18 May 2024 12:27:51 +0000 Subject: [PATCH 36/91] fix(deps): update rust crate anyhow to v1.0.86 --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d3bfaacf7..5252d10b6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -25,9 +25,9 @@ checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" [[package]] name = "anyhow" -version = "1.0.84" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18b8795de6d09abb2b178fa5a9e3bb10da935750f33449a132b328b9391b2c6a" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "autocfg" From 7d30baaecaa2575254dd15d12ba379fc7cf6adcc Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Wed, 22 May 2024 19:01:19 +0200 Subject: [PATCH 37/91] uefi-raw: decouple MSRV from workspace Usually, the MSRV of this will be much more releaxed. --- uefi-raw/Cargo.toml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/uefi-raw/Cargo.toml b/uefi-raw/Cargo.toml index 682b9c342..ef18e36a3 100644 --- a/uefi-raw/Cargo.toml +++ b/uefi-raw/Cargo.toml @@ -10,7 +10,9 @@ edition.workspace = true keywords.workspace = true license.workspace = true repository.workspace = true -rust-version.workspace = true +# uefi-raw is much less likely to need the latest bleeding-edge features. +# Hence, it is okay to not use the workspace MSRV. +rust-version = "1.70" [dependencies] bitflags.workspace = true From f5022cbc84fb7a9e63497ee4b9bcc7e27f43f5aa Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Wed, 22 May 2024 19:01:44 +0200 Subject: [PATCH 38/91] uefi-raw: better description --- uefi-raw/Cargo.toml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/uefi-raw/Cargo.toml b/uefi-raw/Cargo.toml index ef18e36a3..f5e5e4d5a 100644 --- a/uefi-raw/Cargo.toml +++ b/uefi-raw/Cargo.toml @@ -2,7 +2,11 @@ name = "uefi-raw" version = "0.5.2" readme = "README.md" -description = "Raw UEFI types" +description = """ +Raw UEFI types and bindings for protocols, boot, and runtime services. This can +serve as base for an UEFI firmware implementation or a high-level wrapper to +access UEFI functionality from an UEFI image. +""" authors.workspace = true categories.workspace = true From 54ea8b60c5475b2c6879c40f12027466bbb12dfd Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Wed, 22 May 2024 19:22:55 +0200 Subject: [PATCH 39/91] mem: clarify confusion around MemoryDescriptor I was wondering why `desc_size` is always 48 even size_of of the properly typed struct reported 40. This is by design to force users to use `desc_size`. --- uefi-raw/src/table/boot.rs | 20 +++++++++++++++++++- uefi/src/table/boot.rs | 28 ++++++++++++++++++++++++---- 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/uefi-raw/src/table/boot.rs b/uefi-raw/src/table/boot.rs index 5e325d189..f0d3bbf02 100644 --- a/uefi-raw/src/table/boot.rs +++ b/uefi-raw/src/table/boot.rs @@ -326,12 +326,30 @@ bitflags! { } } -/// A structure describing a region of memory. +/// A structure describing a region of memory. This type corresponds to [version] +/// of this struct in the UEFI spec and is always bound to a corresponding +/// UEFI memory map. +/// +/// # UEFI pitfalls +/// As of May 2024: +/// The memory descriptor struct might be extended in the future by a new UEFI +/// spec revision, which will be reflected in another `version` of that +/// descriptor. The version is reported when using `get_memory_map` of +/// [`BootServices`]. +/// +/// Also note that you **must never** work with `size_of::` +/// but always with `desc_size`, which is reported when using `get_memory_map` +/// as well [[0]]. For example, although the actual size is of version 1 +/// descriptors is `40`, the reported `desc_size` is `48`. +/// +/// [version]: MemoryDescriptor::VERSION +/// [0]: https://github.com/tianocore/edk2/blob/7142e648416ff5d3eac6c6d607874805f5de0ca8/MdeModulePkg/Core/PiSmmCore/Page.c#L1059 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(C)] pub struct MemoryDescriptor { /// Type of memory occupying this range. pub ty: MemoryType, + // Implicit 32-bit padding. /// Starting physical address. pub phys_start: PhysicalAddress, /// Starting virtual address. diff --git a/uefi/src/table/boot.rs b/uefi/src/table/boot.rs index 8cc34e1fd..6d9b74289 100644 --- a/uefi/src/table/boot.rs +++ b/uefi/src/table/boot.rs @@ -1617,21 +1617,35 @@ pub struct MemoryMapSize { /// An accessory to the memory map that can be either iterated or /// indexed like an array. /// -/// A [`MemoryMap`] is always associated with the -/// unique [`MemoryMapKey`] contained in the struct. +/// A [`MemoryMap`] is always associated with the unique [`MemoryMapKey`] +/// contained in the struct. /// /// To iterate over the entries, call [`MemoryMap::entries`]. To get a sorted /// map, you manually have to call [`MemoryMap::sort`] first. +/// +/// ## UEFI pitfalls +/// **Please note that when working with memory maps, the `entry_size` is +/// usually larger than `size_of:: { key: MemoryMapKey, buf: &'buf mut [u8], + /// Usually bound to the size of a [`MemoryDescriptor`] but can indicate if + /// this field is ever extended by a new UEFI standard. entry_size: usize, len: usize, } impl<'buf> MemoryMap<'buf> { /// Creates a [`MemoryMap`] from the given buffer and entry size. + /// The entry size is usually bound to the size of a [`MemoryDescriptor`] + /// but can indicate if this field is ever extended by a new UEFI standard. /// /// This allows parsing a memory map provided by a kernel after boot /// services have already exited. @@ -1722,8 +1736,14 @@ impl<'buf> MemoryMap<'buf> { elem.phys_start } - /// Returns an iterator over the contained memory map. To get a sorted map, - /// call [`MemoryMap::sort`] first. + /// Returns an [`MemoryMapIter`] emitting [`MemoryDescriptor`]s. + /// + /// To get a sorted map, call [`MemoryMap::sort`] first. + /// + /// # UEFI pitfalls + /// Currently, only the descriptor version specified in + /// [`MemoryDescriptor`] is supported. This is going to change if the UEFI + /// spec ever introduces a new memory descriptor version. #[must_use] pub fn entries(&self) -> MemoryMapIter { MemoryMapIter { From 1607f5d9ccb9954ba487d3758b1fac1259b0f312 Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Wed, 22 May 2024 18:53:43 +0200 Subject: [PATCH 40/91] uefi/helpers: logger logs to debugcon device This modifies the logger so that it also prints to the debugcon device in QEMU respectively the debug-console device in cloud-hypervisor [0]. By default, this device is at I/O port 0xe9. This only works on x86. The major benefit is that one can get log output from the logger set up by uefi::helpers::init even after boot services has been exited. Now the memory map can be logged, for example. When the integration test runs, the output txt file is put into the root directory of the project. Also everyone else developing UEFI apps using uefi-rs and running them in QEMU or cloud-hypervisor (on x86) benefits. [0]: https://phip1611.de/blog/how-to-use-qemus-debugcon-feature/ --- .gitignore | 3 ++ uefi-test-runner/src/main.rs | 17 +++++++++-- uefi/CHANGELOG.md | 7 +++-- uefi/Cargo.toml | 10 ++++++- uefi/src/helpers/logger.rs | 55 ++++++++++++++++++++++++++++++------ uefi/src/helpers/mod.rs | 8 ++++-- xtask/src/qemu.rs | 4 +++ 7 files changed, 89 insertions(+), 15 deletions(-) diff --git a/.gitignore b/.gitignore index 1d263f4af..39bd96a03 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,6 @@ # Files generated by mdBook. /book/book/ + +# Integration test output by QEMU. +integration-test-debugcon.log diff --git a/uefi-test-runner/src/main.rs b/uefi-test-runner/src/main.rs index b3a3e7ad4..39baced14 100644 --- a/uefi-test-runner/src/main.rs +++ b/uefi-test-runner/src/main.rs @@ -196,10 +196,23 @@ fn shutdown(mut st: SystemTable) -> ! { // type of regression this prevents. info!("LOGGING_STILL_WORKING_RIGHT_BEFORE_EBS"); - info!("Testing complete, shutting down..."); + info!("Testing complete, exiting boot services..."); // Exit boot services as a proof that it works :) - let (st, _iter) = st.exit_boot_services(MemoryType::LOADER_DATA); + let (st, mmap) = st.exit_boot_services(MemoryType::LOADER_DATA); + + info!("Memory Map:"); + for desc in mmap.entries() { + info!( + "start=0x{:016x} size=0x{:016x} type={:?}, attr={:?}", + desc.phys_start, + desc.page_count * 4096, + desc.ty, + desc.att + ); + } + + info!("Shutting down..."); #[cfg(target_arch = "x86_64")] { diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index 671cf33c7..866baf204 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -3,6 +3,11 @@ ## Added - Added `RuntimeServices::update_capsule`. - Added `RuntimeServices::query_capsule_capabilities`. +- The logger from `uefi::helpers` now also logs to the [debugcon](https://phip1611.de/blog/how-to-use-qemus-debugcon-feature/) + device (QEMU) respectively the debug-console (cloud-hypervisor). This only + works on x86. It is activated by default (only on x86) and can be deactivated + by removing the `log-debugcon` cargo feature. The major benefit is that one + can get log messages even after one exited the boot services. ## Removed - Removed the `panic-on-logger-errors` feature of the `uefi` crate. Logger @@ -13,8 +18,6 @@ ## Added - Added `ResetNotification` protocol. - -## Added - Added `Timestamp` protocol. - Added `UnalignedSlice::as_ptr`. - Added common derives for `Event` and `Handle`. diff --git a/uefi/Cargo.toml b/uefi/Cargo.toml index fdb2e64fb..22c45c4bc 100644 --- a/uefi/Cargo.toml +++ b/uefi/Cargo.toml @@ -13,6 +13,7 @@ repository.workspace = true rust-version.workspace = true [features] +default = [ "log-debugcon" ] alloc = [] # Generic gate to code that uses unstable features of Rust. You usually need a nightly toolchain. @@ -22,7 +23,14 @@ unstable = [] logger = [] global_allocator = [] panic_handler = [] -qemu = ["dep:qemu-exit", "panic_handler"] # panic_handler: logical, not technical dependency +# Some convenience when running inside QEMU. +# - dependency log-debugcon: logical, not technical +# - dependency panic_handler: logical, not technical +qemu = ["dep:qemu-exit", "panic_handler", "log-debugcon"] +# Whether the internal logger from the helpers module should also log to +# the debugcon device (QEMU) and debug-console (cloud-hypervisor). Only works +# on x86. +log-debugcon = [] [dependencies] bitflags.workspace = true diff --git a/uefi/src/helpers/logger.rs b/uefi/src/helpers/logger.rs index 31e65c3a3..b8d8cfa41 100644 --- a/uefi/src/helpers/logger.rs +++ b/uefi/src/helpers/logger.rs @@ -12,9 +12,8 @@ //! The last part also means that some Unicode characters might not be //! supported by the UEFI console. Don't expect emoji output support. -use crate::proto::console::text::Output; - use crate::prelude::{Boot, SystemTable}; +use crate::proto::console::text::Output; use core::fmt::{self, Write}; use core::ptr; use core::sync::atomic::{AtomicPtr, Ordering}; @@ -43,6 +42,31 @@ pub fn disable() { LOGGER.disable(); } +/// Writer to the QEMU debugcon device and the debug-console of +/// cloud-hypervisor. +/// +/// More info: +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[derive(Copy, Clone, Debug)] +struct DebugconWriter; + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +impl DebugconWriter { + const IO_PORT: u16 = 0xe9; +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +impl core::fmt::Write for DebugconWriter { + fn write_str(&mut self, s: &str) -> fmt::Result { + for &byte in s.as_bytes() { + unsafe { + core::arch::asm!("outb %al, %dx", in("al") byte, in("dx") DebugconWriter::IO_PORT, options(att_syntax)) + }; + } + Ok(()) + } +} + /// Logging implementation which writes to a UEFI output stream. /// /// If this logger is used as a global logger, you must disable it using the @@ -99,15 +123,13 @@ impl Logger { impl log::Log for Logger { fn enabled(&self, _metadata: &log::Metadata) -> bool { - !self.output().is_null() + // We decide in `log` already if something is printed. We do not + // need micro optimizations here. + true } fn log(&self, record: &log::Record) { - let output = self.output(); - - if !output.is_null() { - let writer = unsafe { &mut *output }; - + if let Some(writer) = unsafe { self.output().as_mut() } { // Ignore all errors. Since we're in the logger implementation we // can't log the error. We also don't want to panic, since logging // is generally not critical functionality. @@ -119,6 +141,23 @@ impl log::Log for Logger { record.line().unwrap_or(0), ); } + + #[cfg(all( + any(target_arch = "x86", target_arch = "x86_64"), + feature = "log-debugcon" + ))] + { + // Ignore all errors. Since we're in the logger implementation we + // can't log the error. We also don't want to panic, since logging + // is generally not critical functionality. + let _ = DecoratedLog::write( + &mut DebugconWriter, + record.level(), + record.args(), + record.file().unwrap_or(""), + record.line().unwrap_or(0), + ); + } } fn flush(&self) { diff --git a/uefi/src/helpers/mod.rs b/uefi/src/helpers/mod.rs index f8aa20761..a10d61e12 100644 --- a/uefi/src/helpers/mod.rs +++ b/uefi/src/helpers/mod.rs @@ -4,7 +4,10 @@ //! //! For now, this includes: //! - using [`uefi::allocator::Allocator`] as global allocator (feature `global_allocator`) -//! - an implementation of [`log::Log`] (feature `logger`) +//! - an implementation of [`log::Log`] (feature `logger`) which logs to +//! the stdout text protocol of UEFI (as long as boot services were not +//! excited) and to the [debugcon device](https://phip1611.de/blog/how-to-use-qemus-debugcon-feature/) +//! (only on x86) (feature `log-debugcon`). //! - [`print!`][print_macro] and [`println!`][println_macro] macros defaulting //! to the uefi boot service stdout stream //! - default panic handler (feature `panic_handler`) @@ -73,7 +76,8 @@ pub fn system_table() -> SystemTable { /// memory allocation capabilities. /// /// **PLEASE NOTE** that these helpers are meant for the pre exit boot service -/// epoch. +/// epoch. Limited functionality might work after exiting them, such as logging +/// to the debugcon device. pub fn init(st: &mut SystemTable) -> Result<()> { if system_table_opt().is_some() { // Avoid double initialization. diff --git a/xtask/src/qemu.rs b/xtask/src/qemu.rs index 94386862e..d0ac4cd60 100644 --- a/xtask/src/qemu.rs +++ b/xtask/src/qemu.rs @@ -484,6 +484,10 @@ pub fn run_qemu(arch: UefiArch, opt: &QemuOpt) -> Result<()> { cmd.args(["-device", "virtio-rng-pci"]); + if arch == UefiArch::IA32 || arch == UefiArch::X86_64 { + cmd.args(["-debugcon", "file:./integration-test-debugcon.log"]); + } + // Set the boot menu timeout to zero. On aarch64 in particular this speeds // up the boot a lot. Note that we have to enable the menu here even though // we are skipping right past it, otherwise `splash-time` is ignored in From 6cff6c5aad5309c93914944e3af46f799ff17bb2 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Thu, 2 May 2024 15:09:53 -0400 Subject: [PATCH 41/91] uefi: Sort the code in table/mod.rs --- uefi/src/table/mod.rs | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/uefi/src/table/mod.rs b/uefi/src/table/mod.rs index 4917946a4..c0afc07ba 100644 --- a/uefi/src/table/mod.rs +++ b/uefi/src/table/mod.rs @@ -1,21 +1,19 @@ //! Standard UEFI tables. +pub mod boot; +pub mod cfg; +pub mod runtime; + +mod header; +mod system; + +pub use header::Header; +pub use system::{Boot, Runtime, SystemTable}; +pub use uefi_raw::table::Revision; + /// Common trait implemented by all standard UEFI tables. pub trait Table { /// A unique number assigned by the UEFI specification /// to the standard tables. const SIGNATURE: u64; } - -mod header; -pub use header::Header; - -mod system; -pub use system::{Boot, Runtime, SystemTable}; - -pub mod boot; -pub mod runtime; - -pub mod cfg; - -pub use uefi_raw::table::Revision; From a42ddc5bf25ac4f41b851f821116d1c8ab655ff2 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Thu, 2 May 2024 15:24:51 -0400 Subject: [PATCH 42/91] uefi: Add global system table pointer and API This is a minimal solution to providing a global system table so that users of the API don't have to pass around references to `SystemTable` / `BootServices` / `RuntimeServices` everywhere. --- uefi/CHANGELOG.md | 3 ++ uefi/src/table/mod.rs | 65 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index 866baf204..19633769d 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -8,6 +8,9 @@ works on x86. It is activated by default (only on x86) and can be deactivated by removing the `log-debugcon` cargo feature. The major benefit is that one can get log messages even after one exited the boot services. +- Added `table::{set_system_table, system_table_boot, system_table_runtime}`. + This provides an initial API for global tables that do not require passing + around a reference. ## Removed - Removed the `panic-on-logger-errors` feature of the `uefi` crate. Logger diff --git a/uefi/src/table/mod.rs b/uefi/src/table/mod.rs index c0afc07ba..7282d8148 100644 --- a/uefi/src/table/mod.rs +++ b/uefi/src/table/mod.rs @@ -11,6 +11,71 @@ pub use header::Header; pub use system::{Boot, Runtime, SystemTable}; pub use uefi_raw::table::Revision; +use core::ptr; +use core::sync::atomic::{AtomicPtr, Ordering}; + +/// Global system table pointer. This is only modified by [`set_system_table`]. +static SYSTEM_TABLE: AtomicPtr = + AtomicPtr::new(ptr::null_mut()); + +/// Update the global system table pointer. +/// +/// This is called automatically in the `main` entry point as part of +/// [`uefi::entry`]. It should not be called at any other point in time, unless +/// the executable does not use [`uefi::entry`], in which case it should be +/// called once before calling any other API in this crate. +/// +/// # Safety +/// +/// This function should only be called as described above, and the +/// `ptr` must be a valid [`SystemTable`]. +pub unsafe fn set_system_table(ptr: *const uefi_raw::table::system::SystemTable) { + SYSTEM_TABLE.store(ptr.cast_mut(), Ordering::Release); +} + +/// Get the system table while boot services are active. +/// +/// # Panics +/// +/// Panics if the system table has not been set with `set_system_table`, or if +/// boot services are not available (e.g. if [`exit_boot_services`] has been +/// called). +/// +/// [`exit_boot_services`]: SystemTable::exit_boot_services +pub fn system_table_boot() -> SystemTable { + let st = SYSTEM_TABLE.load(Ordering::Acquire); + assert!(!st.is_null()); + + // SAFETY: the system table is valid per the requirements of `set_system_table`. + unsafe { + if (*st).boot_services.is_null() { + panic!("boot services are not active"); + } + + SystemTable::::from_ptr(st.cast()).unwrap() + } +} + +/// Get the system table while runtime services are active. +/// +/// # Panics +/// +/// Panics if the system table has not been set with `set_system_table`, or if +/// runtime services are not available. +pub fn system_table_runtime() -> SystemTable { + let st = SYSTEM_TABLE.load(Ordering::Acquire); + assert!(!st.is_null()); + + // SAFETY: the system table is valid per the requirements of `set_system_table`. + unsafe { + if (*st).runtime_services.is_null() { + panic!("runtime services are not active"); + } + + SystemTable::::from_ptr(st.cast()).unwrap() + } +} + /// Common trait implemented by all standard UEFI tables. pub trait Table { /// A unique number assigned by the UEFI specification From ec956eb6f5cf2a4ea7a47025f965a2f1bb8e6197 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Thu, 2 May 2024 15:36:48 -0400 Subject: [PATCH 43/91] uefi-macros: Call set_image_handle from the entry macro --- uefi-macros/CHANGELOG.md | 3 +++ uefi-macros/src/lib.rs | 1 + 2 files changed, 4 insertions(+) diff --git a/uefi-macros/CHANGELOG.md b/uefi-macros/CHANGELOG.md index b56ff7fce..a2e56ccd4 100644 --- a/uefi-macros/CHANGELOG.md +++ b/uefi-macros/CHANGELOG.md @@ -1,5 +1,8 @@ # uefi-macros - [Unreleased] +## Changed +- The `entry` macro now sets the global system table pointer with `uefi::set_system_table`. + ## Removed - Removed the `cstr8` and `cstr16` macros. Use the declarative macros of the same names exported by the `uefi` crate as a replacement. diff --git a/uefi-macros/src/lib.rs b/uefi-macros/src/lib.rs index 9f5b67da8..09a67716e 100644 --- a/uefi-macros/src/lib.rs +++ b/uefi-macros/src/lib.rs @@ -204,6 +204,7 @@ pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream { parse_quote! { unsafe { #system_table_ident.boot_services().set_image_handle(#image_handle_ident); + ::uefi::table::set_system_table(#system_table_ident.as_ptr().cast()); } }, ); From c04e423cedfa0321e4110b75adb6ad368a63b996 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Thu, 2 May 2024 16:04:25 -0400 Subject: [PATCH 44/91] uefi: Make exit_boot_services unsafe This method was already unsafe in practice, since it's very hard to statically ensure that no references to boot-services data exist. Change the signature to acknowledge that reality, and update the docstring with details. --- uefi-test-runner/src/main.rs | 2 +- uefi/CHANGELOG.md | 4 ++++ uefi/src/table/system.rs | 29 ++++++++++++++++++++++++++--- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/uefi-test-runner/src/main.rs b/uefi-test-runner/src/main.rs index 39baced14..61d763c74 100644 --- a/uefi-test-runner/src/main.rs +++ b/uefi-test-runner/src/main.rs @@ -199,7 +199,7 @@ fn shutdown(mut st: SystemTable) -> ! { info!("Testing complete, exiting boot services..."); // Exit boot services as a proof that it works :) - let (st, mmap) = st.exit_boot_services(MemoryType::LOADER_DATA); + let (st, mmap) = unsafe { st.exit_boot_services(MemoryType::LOADER_DATA) }; info!("Memory Map:"); for desc in mmap.entries() { diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index 19633769d..d7c79efdc 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -12,6 +12,10 @@ This provides an initial API for global tables that do not require passing around a reference. +## Changed +- `SystemTable::exit_boot_services` is now `unsafe`. See that method's + documentation for details of obligations for callers. + ## Removed - Removed the `panic-on-logger-errors` feature of the `uefi` crate. Logger errors are now silently ignored. diff --git a/uefi/src/table/system.rs b/uefi/src/table/system.rs index d9cdec170..ab7cb3305 100644 --- a/uefi/src/table/system.rs +++ b/uefi/src/table/system.rs @@ -208,8 +208,27 @@ impl SystemTable { /// /// Note that once the boot services are exited, associated loggers and /// allocators can't use the boot services anymore. For the corresponding - /// abstractions provided by this crate, invoking this function will - /// automatically disable them. + /// abstractions provided by this crate (see the [`helpers`] module), + /// invoking this function will automatically disable them. If the + /// `global_allocator` feature is enabled, attempting to use the allocator + /// after exiting boot services will panic. + /// + /// # Safety + /// + /// The caller is responsible for ensuring that no references to + /// boot-services data remain. A non-exhaustive list of resources to check: + /// + /// * All protocols will be invalid after exiting boot services. This + /// includes the [`Output`] protocols attached to stdout/stderr. The + /// caller must ensure that no protocol references remain. + /// * The pool allocator is not usable after exiting boot services. Types + /// such as [`PoolString`] which call [`BootServices::free_pool`] on drop + /// must be cleaned up before calling `exit_boot_services`, or leaked to + /// avoid drop ever being called. + /// * All data in the memory map marked as + /// [`MemoryType::BOOT_SERVICES_CODE`] and + /// [`MemoryType::BOOT_SERVICES_DATA`] will become free memory, the caller + /// must ensure that no references to such memory exist. /// /// # Errors /// @@ -220,8 +239,12 @@ impl SystemTable { /// All errors are treated as unrecoverable because the system is /// now in an undefined state. Rather than returning control to the /// caller, the system will be reset. + /// + /// [`helpers`]: crate::helpers + /// [`Output`]: crate::proto::console::text::Output + /// [`PoolString`]: crate::proto::device_path::text::PoolString #[must_use] - pub fn exit_boot_services( + pub unsafe fn exit_boot_services( self, memory_type: MemoryType, ) -> (SystemTable, MemoryMap<'static>) { From 2f4aece6c2f29da16c82cfc2040085a1aba07dd8 Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Sat, 25 May 2024 15:59:31 +0200 Subject: [PATCH 45/91] uefi: BootServices::allocate_pool now returns NonZero instead of *mut u8 This is safe as each null pointer (=failed allocation) is already returned as non-successful status code by UEFI. --- uefi-test-runner/src/boot/misc.rs | 6 ++++-- uefi/CHANGELOG.md | 2 ++ uefi/src/allocator.rs | 3 ++- uefi/src/table/boot.rs | 8 ++++++-- uefi/src/table/system.rs | 2 +- 5 files changed, 15 insertions(+), 6 deletions(-) diff --git a/uefi-test-runner/src/boot/misc.rs b/uefi-test-runner/src/boot/misc.rs index 0399ff2ba..8b7422be4 100644 --- a/uefi-test-runner/src/boot/misc.rs +++ b/uefi-test-runner/src/boot/misc.rs @@ -121,7 +121,8 @@ fn test_install_protocol_interface(bt: &BootServices) { mem::size_of::(), ) .unwrap() - .cast(); + .cast() + .as_ptr(); unsafe { alloc.write(TestProtocol { data: 123 }) }; let _ = unsafe { @@ -187,7 +188,8 @@ fn test_install_configuration_table(st: &SystemTable) { let config = st .boot_services() .allocate_pool(MemoryType::ACPI_RECLAIM, 1) - .expect("Failed to allocate config table"); + .expect("Failed to allocate config table") + .as_ptr(); unsafe { config.write(42) }; let count = st.config_table().len(); diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index d7c79efdc..0f01003eb 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -15,6 +15,8 @@ ## Changed - `SystemTable::exit_boot_services` is now `unsafe`. See that method's documentation for details of obligations for callers. +- `BootServices::allocate_pool` now returns `NonZero` instead of + `*mut u8`. ## Removed - Removed the `panic-on-logger-errors` feature of the `uefi` crate. Logger diff --git a/uefi/src/allocator.rs b/uefi/src/allocator.rs index 3be75c164..d1ef3dc93 100644 --- a/uefi/src/allocator.rs +++ b/uefi/src/allocator.rs @@ -86,7 +86,7 @@ unsafe impl GlobalAlloc for Allocator { // within the allocation. let full_alloc_ptr = if let Ok(ptr) = boot_services.allocate_pool(memory_type, size + align) { - ptr + ptr.as_ptr() } else { return ptr::null_mut(); }; @@ -116,6 +116,7 @@ unsafe impl GlobalAlloc for Allocator { // use `allocate_pool` directly. boot_services .allocate_pool(memory_type, size) + .map(|ptr| ptr.as_ptr()) .unwrap_or(ptr::null_mut()) } } diff --git a/uefi/src/table/boot.rs b/uefi/src/table/boot.rs index 6d9b74289..1a5e44876 100644 --- a/uefi/src/table/boot.rs +++ b/uefi/src/table/boot.rs @@ -271,9 +271,13 @@ impl BootServices { /// /// * [`uefi::Status::OUT_OF_RESOURCES`] /// * [`uefi::Status::INVALID_PARAMETER`] - pub fn allocate_pool(&self, mem_ty: MemoryType, size: usize) -> Result<*mut u8> { + pub fn allocate_pool(&self, mem_ty: MemoryType, size: usize) -> Result> { let mut buffer = ptr::null_mut(); - unsafe { (self.0.allocate_pool)(mem_ty, size, &mut buffer) }.to_result_with_val(|| buffer) + let ptr = unsafe { (self.0.allocate_pool)(mem_ty, size, &mut buffer) } + .to_result_with_val(|| buffer)?; + + Ok(NonNull::new(ptr) + .expect("UEFI should return error if an allocation failed but never a null pointer")) } /// Frees memory allocated from a pool. diff --git a/uefi/src/table/system.rs b/uefi/src/table/system.rs index ab7cb3305..87ed22a55 100644 --- a/uefi/src/table/system.rs +++ b/uefi/src/table/system.rs @@ -265,7 +265,7 @@ impl SystemTable { // Allocate a byte slice to hold the memory map. If the // allocation fails treat it as an unrecoverable error. let buf: *mut u8 = match boot_services.allocate_pool(memory_type, buf_size) { - Ok(buf) => buf, + Ok(buf) => buf.as_ptr(), Err(err) => reset(err.status()), }; From 9e19084c4f555d82d854b1a016c30d9e5dbcac46 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 27 May 2024 17:15:14 +0000 Subject: [PATCH 46/91] fix(deps): update rust crate itertools to 0.13.0 --- Cargo.lock | 4 ++-- xtask/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5252d10b6..b575cb986 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -356,9 +356,9 @@ dependencies = [ [[package]] name = "itertools" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" dependencies = [ "either", ] diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index 19d8a426c..f087bcb95 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -11,7 +11,7 @@ clap = { version = "4.4.0", default-features = false, features = ["derive", "hel fatfs = { version = "0.3.6", default-features = false, features = ["alloc", "std"] } fs-err = "2.6.0" heck = "0.4.0" -itertools = "0.12.0" +itertools = "0.13.0" lzma-rs = "0.3.0" mbrman = "0.5.1" nix = { version = "0.28.0", default-features = false, features = ["fs"] } From 1ad883db4b1e1dad00435b07fad5c73cdc124065 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 27 May 2024 17:15:18 +0000 Subject: [PATCH 47/91] fix(deps): update rust crate nix to 0.29.0 --- Cargo.lock | 12 ++++++------ xtask/Cargo.toml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5252d10b6..fb9f34953 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -109,9 +109,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cfg_aliases" -version = "0.1.1" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "clap" @@ -371,9 +371,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "libc" -version = "0.2.153" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "linux-raw-sys" @@ -427,9 +427,9 @@ dependencies = [ [[package]] name = "nix" -version = "0.28.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ "bitflags 2.5.0", "cfg-if", diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index 19d8a426c..de382d765 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -14,7 +14,7 @@ heck = "0.4.0" itertools = "0.12.0" lzma-rs = "0.3.0" mbrman = "0.5.1" -nix = { version = "0.28.0", default-features = false, features = ["fs"] } +nix = { version = "0.29.0", default-features = false, features = ["fs"] } os_info = { version = "3.6.0", default-features = false } proc-macro2 = { version = "1.0.46", features = ["span-locations"] } quote = "1.0.21" From 0b5762af4061df1ea863dac176e9c5da12181029 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 27 May 2024 17:15:22 +0000 Subject: [PATCH 48/91] chore(deps): update cachix/install-nix-action action to v27 --- .github/workflows/developer_productivity.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/developer_productivity.yml b/.github/workflows/developer_productivity.yml index f0435a617..944727247 100644 --- a/.github/workflows/developer_productivity.yml +++ b/.github/workflows/developer_productivity.yml @@ -33,7 +33,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v4 - uses: Swatinem/rust-cache@v2 - - uses: cachix/install-nix-action@v26 + - uses: cachix/install-nix-action@v27 with: # This channel is only required to invoke "nix-shell". # Everything inside that nix-shell will use a pinned version of nixpkgs. From b52d3b5c1f1e3ae5204d19260e152e4bcdbefe5e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 27 May 2024 17:15:33 +0000 Subject: [PATCH 49/91] chore(deps): lock file maintenance --- Cargo.lock | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5252d10b6..a68fdcdee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -97,9 +97,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cc" -version = "1.0.97" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" +checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" [[package]] name = "cfg-if" @@ -142,7 +142,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.66", ] [[package]] @@ -177,9 +177,9 @@ checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" [[package]] name = "crc32fast" -version = "1.4.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] @@ -301,9 +301,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -371,9 +371,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "libc" -version = "0.2.153" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "linux-raw-sys" @@ -461,9 +461,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "proc-macro2" -version = "1.0.82" +version = "1.0.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" +checksum = "ec96c6a92621310b51366f1e28d05ef11489516e93be030060e5fc12024a49d6" dependencies = [ "unicode-ident", ] @@ -623,9 +623,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.202" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" dependencies = [ "serde_derive", ] @@ -641,13 +641,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.202" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.66", ] [[package]] @@ -706,9 +706,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.64" +version = "2.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ad3dee41f36859875573074334c200d1add8e4a87bb37113ebd31d926b7b11f" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" dependencies = [ "proc-macro2", "quote", @@ -770,7 +770,7 @@ checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.66", ] [[package]] @@ -872,7 +872,7 @@ version = "0.13.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.66", "trybuild", "uefi", ] @@ -1124,7 +1124,7 @@ dependencies = [ "regex", "serde_json", "sha2", - "syn 2.0.64", + "syn 2.0.66", "tar", "tempfile", "ureq", @@ -1133,6 +1133,6 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" From 2056a0ad14de01fd0194528868447dc691695a8f Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Mon, 27 May 2024 21:12:40 -0400 Subject: [PATCH 50/91] Fix uefi-macros trybuild test A difference in behavior between CI and local testing was observed for the entry_bad_return_type test. This is due to the way trybuild sets the `--verbose` flag, which is overwritten if RUSTFLAGS is set (as it always is for our CI jobs). Add code in xtask to ensure that `--verbose` still gets set correctly. Also update entry_bad_return_type.stderr to match the expected current output. --- .../tests/ui/fail/entry_bad_return_type.stderr | 4 ++-- xtask/src/cargo.rs | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/uefi-macros/tests/ui/fail/entry_bad_return_type.stderr b/uefi-macros/tests/ui/fail/entry_bad_return_type.stderr index 52e4a7cfb..4c7d1674e 100644 --- a/uefi-macros/tests/ui/fail/entry_bad_return_type.stderr +++ b/uefi-macros/tests/ui/fail/entry_bad_return_type.stderr @@ -4,5 +4,5 @@ error[E0308]: mismatched types 8 | fn main(_handle: Handle, _st: SystemTable) -> bool { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Status`, found `bool` | - = note: expected fn pointer `extern "efiapi" fn(uefi::Handle, uefi::table::SystemTable<_>) -> Status` - found fn pointer `extern "efiapi" fn(uefi::Handle, uefi::table::SystemTable<_>) -> bool` + = note: expected fn pointer `extern "efiapi" fn(uefi::Handle, uefi::table::SystemTable) -> Status` + found fn pointer `extern "efiapi" fn(uefi::Handle, uefi::table::SystemTable) -> bool` diff --git a/xtask/src/cargo.rs b/xtask/src/cargo.rs index 8376e514e..8039d6a91 100644 --- a/xtask/src/cargo.rs +++ b/xtask/src/cargo.rs @@ -271,6 +271,21 @@ impl Cargo { } CargoAction::Test => { action = "test"; + + // Ensure that uefi-macros trybuild tests work regardless of + // whether RUSTFLAGS is set. + // + // The trybuild tests run `rustc` with `--verbose`, which + // affects error output. This flag is set via + // `--config=build.rustflags` [1], but that will be ignored if + // the RUSTFLAGS env var is set. Compensate by appending + // `--verbose` to the var in that case. + // + // [1]: https://github.com/dtolnay/trybuild/blob/b1b7064b7ad11e0ab563e9eb843651d86e4545b7/src/cargo.rs#L44 + if let Ok(mut rustflags) = env::var("RUSTFLAGS") { + rustflags.push_str(" --verbose"); + cmd.env("RUSTFLAGS", rustflags); + } } }; cmd.arg(action); From d56ca871ce814035081da192ff04ad27b0e4affe Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 2 Jun 2024 05:04:29 +0000 Subject: [PATCH 51/91] chore(deps): lock file maintenance --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index aa3f04df4..3de3ab484 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -461,9 +461,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "proc-macro2" -version = "1.0.84" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec96c6a92621310b51366f1e28d05ef11489516e93be030060e5fc12024a49d6" +checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" dependencies = [ "unicode-ident", ] @@ -1078,9 +1078,9 @@ checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "winnow" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3c52e9c97a68071b23e836c9380edae937f17b9c4667bd021973efc689f618d" +checksum = "86c949fede1d13936a99f14fafd3e76fd642b556dd2ce96287fbe2e0151bfac6" dependencies = [ "memchr", ] From 225265b2eb53bc5fb6ad406067f53f2b602db086 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Mon, 10 Jun 2024 11:43:30 -0400 Subject: [PATCH 52/91] uefi: Stop enabling error_in_core feature This feature has been stabilized in latest nightly, so no need to enable it. All the uses of it (`impl core::error::Error for for ...`) are still gated by the `unstable` feature, so there's no change for users on the stable channel. --- uefi/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/uefi/src/lib.rs b/uefi/src/lib.rs index 9a425aac6..eef044920 100644 --- a/uefi/src/lib.rs +++ b/uefi/src/lib.rs @@ -83,7 +83,6 @@ //! [spec]: https://uefi.org/specifications //! [unstable features]: https://doc.rust-lang.org/unstable-book/ -#![cfg_attr(feature = "unstable", feature(error_in_core))] #![cfg_attr(all(feature = "unstable", feature = "alloc"), feature(allocator_api))] #![cfg_attr(docsrs, feature(doc_auto_cfg))] #![no_std] From cc18e07161fff10b84282a01aa2ba4154ffb02ee Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 10 Jun 2024 16:16:40 +0000 Subject: [PATCH 53/91] chore(deps): update crate-ci/typos action to v1.22.3 --- .github/workflows/qa.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index 2776cfe4a..3fd705df7 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -7,4 +7,4 @@ jobs: steps: - uses: actions/checkout@v4 # Executes "typos ." - - uses: crate-ci/typos@v1.21.0 + - uses: crate-ci/typos@v1.22.3 From 2ed0a32e6a904ad8ebc5c4ca3af171368b3ed2b1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 10 Jun 2024 16:18:01 +0000 Subject: [PATCH 54/91] chore(deps): lock file maintenance --- Cargo.lock | 345 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 288 insertions(+), 57 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3de3ab484..cb487ee49 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -97,9 +97,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cc" -version = "1.0.98" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" +checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" [[package]] name = "cfg-if" @@ -115,9 +115,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "clap" -version = "4.5.4" +version = "4.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" +checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f" dependencies = [ "clap_builder", "clap_derive", @@ -125,9 +125,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.2" +version = "4.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" dependencies = [ "anstyle", "clap_lex", @@ -135,9 +135,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.4" +version = "4.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" +checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -147,9 +147,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" [[package]] name = "cpufeatures" @@ -204,6 +204,17 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "displaydoc" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "either" version = "1.12.0" @@ -334,14 +345,134 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f8ac670d7422d7f76b32e17a5db556510825b29ec9154f235977c9caba61036" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "idna" -version = "0.5.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "4716a3a0933a1d01c2f72450e89596eb51dd34ef3c211ccd875acdf1f8fe47ed" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "icu_normalizer", + "icu_properties", + "smallvec", + "utf8_iter", ] [[package]] @@ -381,6 +512,12 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "litemap" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" + [[package]] name = "log" version = "0.4.21" @@ -520,9 +657,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.4" +version = "1.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" dependencies = [ "aho-corasick", "memchr", @@ -532,9 +669,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", @@ -543,9 +680,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "ring" @@ -681,12 +818,24 @@ dependencies = [ "digest", ] +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + [[package]] name = "spin" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "subtle" version = "2.5.0" @@ -715,6 +864,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "tap" version = "1.0.1" @@ -723,9 +883,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tar" -version = "0.4.40" +version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb" +checksum = "cb797dad5fb5b76fcf519e702f4a589483b5ef06567f160c392832c1f5e44909" dependencies = [ "filetime", "libc", @@ -774,25 +934,20 @@ dependencies = [ ] [[package]] -name = "tinyvec" -version = "1.6.0" +name = "tinystr" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" dependencies = [ - "tinyvec_macros", + "displaydoc", + "zerovec", ] -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "toml" -version = "0.8.13" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4e43f8cc456c9704c851ae29c67e17ef65d2c30017c17a9765b89c382dc8bba" +checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335" dependencies = [ "serde", "serde_spanned", @@ -811,9 +966,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.13" +version = "0.22.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c127785850e8c20836d49732ae6abfa47616e60bf9d9f57c43c250361a9db96c" +checksum = "f21c7aaf97f1bd9ca9d4f9e73b0a6c74bd5afef56f2bc931943a6e1c37e04e38" dependencies = [ "indexmap", "serde", @@ -908,27 +1063,12 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab14ea9660d240e7865ce9d54ecdbd1cd9fa5802ae6f4512f093c7907e921533" -[[package]] -name = "unicode-bidi" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" - [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" -[[package]] -name = "unicode-normalization" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" -dependencies = [ - "tinyvec", -] - [[package]] name = "untrusted" version = "0.9.0" @@ -954,15 +1094,27 @@ dependencies = [ [[package]] name = "url" -version = "2.5.0" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "f7c25da092f0a868cdf09e8674cd3b7ef3a7d92a24253e663a2fb85e2496de56" dependencies = [ "form_urlencoded", "idna", "percent-encoding", ] +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "version_check" version = "0.9.4" @@ -987,9 +1139,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "webpki-roots" -version = "0.26.1" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3de34ae270483955a94f4b21bdaaeb83d508bb84a01435f393818edb0012009" +checksum = "3c452ad30530b54a4d8e71952716a212b08efd0f3562baa66c29a618b07da7c3" dependencies = [ "rustls-pki-types", ] @@ -1078,13 +1230,25 @@ checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "winnow" -version = "0.6.9" +version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86c949fede1d13936a99f14fafd3e76fd642b556dd2ce96287fbe2e0151bfac6" +checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1" dependencies = [ "memchr", ] +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + [[package]] name = "wyz" version = "0.5.1" @@ -1131,8 +1295,75 @@ dependencies = [ "walkdir", ] +[[package]] +name = "yoke" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", + "synstructure", +] + +[[package]] +name = "zerofrom" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", + "synstructure", +] + [[package]] name = "zeroize" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" + +[[package]] +name = "zerovec" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb2cc8827d6c0994478a15c53f374f46fbd41bea663d809b14744bc42e6b109c" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97cf56601ee5052b4417d90c8755c6683473c926039908196cf35d99f893ebe7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] From 487d6011eaa10ec6b66fe45508b42fe9b4278dd1 Mon Sep 17 00:00:00 2001 From: andre-braga Date: Mon, 10 Jun 2024 21:29:59 +0000 Subject: [PATCH 55/91] reorganize deps cargo fmt added these, missed from some other pr --- uefi-test-runner/src/main.rs | 3 +-- uefi/src/helpers/mod.rs | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/uefi-test-runner/src/main.rs b/uefi-test-runner/src/main.rs index 61d763c74..42d029ece 100644 --- a/uefi-test-runner/src/main.rs +++ b/uefi-test-runner/src/main.rs @@ -13,8 +13,7 @@ use uefi::proto::console::serial::Serial; use uefi::proto::device_path::build::{self, DevicePathBuilder}; use uefi::proto::device_path::messaging::Vendor; use uefi::table::boot::MemoryType; -use uefi::Result; -use uefi::{print, println}; +use uefi::{print, println, Result}; mod boot; mod fs; diff --git a/uefi/src/helpers/mod.rs b/uefi/src/helpers/mod.rs index a10d61e12..958d64c57 100644 --- a/uefi/src/helpers/mod.rs +++ b/uefi/src/helpers/mod.rs @@ -19,8 +19,7 @@ //! [println_macro]: uefi::println! use crate::prelude::{Boot, SystemTable}; -use crate::Result; -use crate::StatusExt; +use crate::{Result, StatusExt}; use core::ffi::c_void; use core::ptr; use core::sync::atomic::{AtomicPtr, Ordering}; From 2ee302ab16a66005441b2f024cd886734311d3b4 Mon Sep 17 00:00:00 2001 From: andre-braga Date: Tue, 11 Jun 2024 15:05:47 +0000 Subject: [PATCH 56/91] uefi: Add TryFrom u8 slice to DevicePathHeader Allows for making a `DevicePathHeader` from a byte splice, used primarily to verify whether the byte splice can also contain `DevicePathHeader.length` bytes. --- uefi/CHANGELOG.md | 2 ++ uefi/src/proto/device_path/mod.rs | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index 0f01003eb..70b95be05 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -11,6 +11,8 @@ - Added `table::{set_system_table, system_table_boot, system_table_runtime}`. This provides an initial API for global tables that do not require passing around a reference. +- Added `TryFrom<&[u8]>` for `DevicePathHeader`. +- Added `ByteConversionError`. ## Changed - `SystemTable::exit_boot_services` is now `unsafe`. See that method's diff --git a/uefi/src/proto/device_path/mod.rs b/uefi/src/proto/device_path/mod.rs index 658d84c9d..6696bcce8 100644 --- a/uefi/src/proto/device_path/mod.rs +++ b/uefi/src/proto/device_path/mod.rs @@ -119,6 +119,19 @@ pub struct DevicePathHeader { pub length: u16, } +impl<'a> TryFrom<&[u8]> for &'a DevicePathHeader { + type Error = ByteConversionError; + + fn try_from(bytes: &[u8]) -> Result { + if mem::size_of::() <= bytes.len() { + unsafe { + return Ok(&*bytes.as_ptr().cast::()); + } + } + Err(ByteConversionError::InvalidLength) + } +} + /// A single node within a [`DevicePath`]. /// /// Each node starts with a [`DevicePathHeader`]. The rest of the data @@ -729,6 +742,14 @@ impl DeviceSubType { pub const END_ENTIRE: DeviceSubType = DeviceSubType(0xff); } +/// Error returned when attempting to convert from a `&[u8]` to a +/// [`DevicePath`] type. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum ByteConversionError { + /// The length of the given slice is not valid for its [`DevicePath`] type. + InvalidLength, +} + /// Error returned when converting from a [`DevicePathNode`] to a more /// specific node type. #[derive(Clone, Copy, Debug, Eq, PartialEq)] From 924d1da8eb9992837d0488dea44b42aea3a6451f Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sat, 8 Jun 2024 20:35:21 -0400 Subject: [PATCH 57/91] test-runner: Consistently use global image handle Rather than passing the image handle around in function args, just use the global image handle. --- uefi-test-runner/src/main.rs | 2 +- uefi-test-runner/src/proto/console/gop.rs | 4 ++-- uefi-test-runner/src/proto/console/mod.rs | 4 ++-- uefi-test-runner/src/proto/device_path.rs | 8 ++++---- uefi-test-runner/src/proto/loaded_image.rs | 4 ++-- uefi-test-runner/src/proto/mod.rs | 14 +++++++------- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/uefi-test-runner/src/main.rs b/uefi-test-runner/src/main.rs index 42d029ece..c61411e27 100644 --- a/uefi-test-runner/src/main.rs +++ b/uefi-test-runner/src/main.rs @@ -55,7 +55,7 @@ fn efi_main(image: Handle, mut st: SystemTable) -> Status { boot::test(&st); // Test all the supported protocols. - proto::test(image, &mut st); + proto::test(&mut st); // TODO: runtime services work before boot services are exited, but we'd // probably want to test them after exit_boot_services. However, diff --git a/uefi-test-runner/src/proto/console/gop.rs b/uefi-test-runner/src/proto/console/gop.rs index 8ce714351..94bcbda40 100644 --- a/uefi-test-runner/src/proto/console/gop.rs +++ b/uefi-test-runner/src/proto/console/gop.rs @@ -3,7 +3,7 @@ use uefi::prelude::*; use uefi::proto::console::gop::{BltOp, BltPixel, FrameBuffer, GraphicsOutput, PixelFormat}; use uefi::table::boot::{OpenProtocolAttributes, OpenProtocolParams}; -pub unsafe fn test(image: Handle, bt: &BootServices) { +pub unsafe fn test(bt: &BootServices) { info!("Running graphics output protocol test"); let handle = bt .get_handle_for_protocol::() @@ -12,7 +12,7 @@ pub unsafe fn test(image: Handle, bt: &BootServices) { .open_protocol::( OpenProtocolParams { handle, - agent: image, + agent: bt.image_handle(), controller: None, }, // For this test, don't open in exclusive mode. That diff --git a/uefi-test-runner/src/proto/console/mod.rs b/uefi-test-runner/src/proto/console/mod.rs index f11b2ef01..8dd7392ec 100644 --- a/uefi-test-runner/src/proto/console/mod.rs +++ b/uefi-test-runner/src/proto/console/mod.rs @@ -1,6 +1,6 @@ use uefi::prelude::*; -pub fn test(image: Handle, st: &mut SystemTable) { +pub fn test(st: &mut SystemTable) { info!("Testing console protocols"); stdout::test(st.stdout()); @@ -8,7 +8,7 @@ pub fn test(image: Handle, st: &mut SystemTable) { let bt = st.boot_services(); unsafe { serial::test(bt); - gop::test(image, bt); + gop::test(bt); } pointer::test(bt); } diff --git a/uefi-test-runner/src/proto/device_path.rs b/uefi-test-runner/src/proto/device_path.rs index fb99d5792..942837241 100644 --- a/uefi-test-runner/src/proto/device_path.rs +++ b/uefi-test-runner/src/proto/device_path.rs @@ -5,13 +5,13 @@ use uefi::proto::device_path::text::*; use uefi::proto::device_path::{DevicePath, LoadedImageDevicePath}; use uefi::proto::loaded_image::LoadedImage; -pub fn test(image: Handle, bt: &BootServices) { +pub fn test(bt: &BootServices) { info!("Running device path protocol test"); // test 1/2: test low-level API by directly opening all protocols { let loaded_image = bt - .open_protocol_exclusive::(image) + .open_protocol_exclusive::(bt.image_handle()) .expect("Failed to open LoadedImage protocol"); let device_path = bt @@ -55,7 +55,7 @@ pub fn test(image: Handle, bt: &BootServices) { // Get the `LoadedImageDevicePath`. Verify it start with the same nodes as // `device_path`. let loaded_image_device_path = bt - .open_protocol_exclusive::(image) + .open_protocol_exclusive::(bt.image_handle()) .expect("Failed to open LoadedImageDevicePath protocol"); for (n1, n2) in device_path @@ -69,7 +69,7 @@ pub fn test(image: Handle, bt: &BootServices) { // test 2/2: test high-level to-string api { let loaded_image_device_path = bt - .open_protocol_exclusive::(image) + .open_protocol_exclusive::(bt.image_handle()) .expect("Failed to open LoadedImageDevicePath protocol"); let device_path: &DevicePath = &loaded_image_device_path; diff --git a/uefi-test-runner/src/proto/loaded_image.rs b/uefi-test-runner/src/proto/loaded_image.rs index 93e499b06..648db3ac5 100644 --- a/uefi-test-runner/src/proto/loaded_image.rs +++ b/uefi-test-runner/src/proto/loaded_image.rs @@ -1,11 +1,11 @@ use uefi::prelude::*; use uefi::proto::loaded_image::LoadedImage; -pub fn test(image: Handle, bt: &BootServices) { +pub fn test(bt: &BootServices) { info!("Running loaded image protocol test"); let loaded_image = bt - .open_protocol_exclusive::(image) + .open_protocol_exclusive::(bt.image_handle()) .expect("Failed to open LoadedImage protocol"); let load_options = loaded_image.load_options_as_bytes(); diff --git a/uefi-test-runner/src/proto/mod.rs b/uefi-test-runner/src/proto/mod.rs index 261f439e6..d40a11453 100644 --- a/uefi-test-runner/src/proto/mod.rs +++ b/uefi-test-runner/src/proto/mod.rs @@ -2,19 +2,19 @@ use uefi::prelude::*; use uefi::proto::loaded_image::LoadedImage; use uefi::{proto, Identify}; -pub fn test(image: Handle, st: &mut SystemTable) { +pub fn test(st: &mut SystemTable) { info!("Testing various protocols"); - console::test(image, st); + console::test(st); let bt = st.boot_services(); find_protocol(bt); - test_protocols_per_handle(image, bt); + test_protocols_per_handle(bt); debug::test(bt); - device_path::test(image, bt); + device_path::test(bt); driver::test(bt); - loaded_image::test(image, bt); + loaded_image::test(bt); media::test(bt); network::test(bt); pi::test(bt); @@ -44,9 +44,9 @@ fn find_protocol(bt: &BootServices) { ); } -fn test_protocols_per_handle(image: Handle, bt: &BootServices) { +fn test_protocols_per_handle(bt: &BootServices) { let pph = bt - .protocols_per_handle(image) + .protocols_per_handle(bt.image_handle()) .expect("Failed to get protocols for image handle"); info!("Image handle has {} protocols", pph.len()); From c649727402f669f0b3b5bb6f1ec800df364ea34c Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sat, 8 Jun 2024 12:47:22 -0400 Subject: [PATCH 58/91] uefi: Remove panics from system_table_boot/system_table_runtime These functions now return an `Option`. --- uefi/src/table/mod.rs | 37 ++++++++++++++----------------------- 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/uefi/src/table/mod.rs b/uefi/src/table/mod.rs index 7282d8148..078c0f79f 100644 --- a/uefi/src/table/mod.rs +++ b/uefi/src/table/mod.rs @@ -34,45 +34,36 @@ pub unsafe fn set_system_table(ptr: *const uefi_raw::table::system::SystemTable) } /// Get the system table while boot services are active. -/// -/// # Panics -/// -/// Panics if the system table has not been set with `set_system_table`, or if -/// boot services are not available (e.g. if [`exit_boot_services`] has been -/// called). -/// -/// [`exit_boot_services`]: SystemTable::exit_boot_services -pub fn system_table_boot() -> SystemTable { +pub fn system_table_boot() -> Option> { let st = SYSTEM_TABLE.load(Ordering::Acquire); - assert!(!st.is_null()); + if st.is_null() { + return None; + } // SAFETY: the system table is valid per the requirements of `set_system_table`. unsafe { if (*st).boot_services.is_null() { - panic!("boot services are not active"); + None + } else { + Some(SystemTable::::from_ptr(st.cast()).unwrap()) } - - SystemTable::::from_ptr(st.cast()).unwrap() } } /// Get the system table while runtime services are active. -/// -/// # Panics -/// -/// Panics if the system table has not been set with `set_system_table`, or if -/// runtime services are not available. -pub fn system_table_runtime() -> SystemTable { +pub fn system_table_runtime() -> Option> { let st = SYSTEM_TABLE.load(Ordering::Acquire); - assert!(!st.is_null()); + if st.is_null() { + return None; + } // SAFETY: the system table is valid per the requirements of `set_system_table`. unsafe { if (*st).runtime_services.is_null() { - panic!("runtime services are not active"); + None + } else { + Some(SystemTable::::from_ptr(st.cast()).unwrap()) } - - SystemTable::::from_ptr(st.cast()).unwrap() } } From 2a63b9e95689563cd302ae0e1cfd05135ad89ae2 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sat, 8 Jun 2024 12:59:47 -0400 Subject: [PATCH 59/91] uefi: Drop duplicate global system table pointer Now that `uefi::table` has a pointer to the system table, drop the pointer from `uefi::helpers`. --- uefi/src/helpers/mod.rs | 44 +++---------------------------- uefi/src/helpers/panic_handler.rs | 6 ++--- uefi/src/helpers/println.rs | 5 ++-- 3 files changed, 9 insertions(+), 46 deletions(-) diff --git a/uefi/src/helpers/mod.rs b/uefi/src/helpers/mod.rs index 958d64c57..910929cdd 100644 --- a/uefi/src/helpers/mod.rs +++ b/uefi/src/helpers/mod.rs @@ -19,13 +19,9 @@ //! [println_macro]: uefi::println! use crate::prelude::{Boot, SystemTable}; -use crate::{Result, StatusExt}; -use core::ffi::c_void; -use core::ptr; -use core::sync::atomic::{AtomicPtr, Ordering}; +use crate::{table, Result}; #[doc(hidden)] pub use println::_print; -use uefi_raw::Status; #[cfg(feature = "global_allocator")] mod global_allocator; @@ -35,25 +31,6 @@ mod logger; mod panic_handler; mod println; -/// Reference to the system table. -/// -/// This table is only fully safe to use until UEFI boot services have been exited. -/// After that, some fields and methods are unsafe to use, see the documentation of -/// UEFI's ExitBootServices entry point for more details. -static SYSTEM_TABLE: AtomicPtr = AtomicPtr::new(core::ptr::null_mut()); - -#[must_use] -fn system_table_opt() -> Option> { - let ptr = SYSTEM_TABLE.load(Ordering::Acquire); - // Safety: the `SYSTEM_TABLE` pointer either be null or a valid system - // table. - // - // Null is the initial value, as well as the value set when exiting boot - // services. Otherwise, the value is set by the call to `init`, which - // requires a valid system table reference as input. - unsafe { SystemTable::from_ptr(ptr) } -} - /// Obtains a pointer to the system table. /// /// This is meant to be used by higher-level libraries, @@ -65,7 +42,7 @@ fn system_table_opt() -> Option> { #[must_use] // TODO do we want to keep this public? pub fn system_table() -> SystemTable { - system_table_opt().expect("The system table handle is not available") + table::system_table_boot().expect("boot services are not active") } /// Initialize all helpers defined in [`uefi::helpers`] whose Cargo features @@ -77,15 +54,8 @@ pub fn system_table() -> SystemTable { /// **PLEASE NOTE** that these helpers are meant for the pre exit boot service /// epoch. Limited functionality might work after exiting them, such as logging /// to the debugcon device. +#[allow(unused_variables)] // `st` is unused if logger and allocator are disabled pub fn init(st: &mut SystemTable) -> Result<()> { - if system_table_opt().is_some() { - // Avoid double initialization. - return Status::SUCCESS.to_result_with_val(|| ()); - } - - // Setup the system table singleton - SYSTEM_TABLE.store(st.as_ptr().cast_mut(), Ordering::Release); - // Setup logging and memory allocation #[cfg(feature = "logger")] @@ -102,14 +72,6 @@ pub fn init(st: &mut SystemTable) -> Result<()> { } pub(crate) fn exit() { - // DEBUG: The UEFI spec does not guarantee that this printout will work, as - // the services used by logging might already have been shut down. - // But it works on current OVMF, and can be used as a handy way to - // check that the callback does get called. - // - // info!("Shutting down the UEFI utility library"); - SYSTEM_TABLE.store(ptr::null_mut(), Ordering::Release); - #[cfg(feature = "logger")] logger::disable(); diff --git a/uefi/src/helpers/panic_handler.rs b/uefi/src/helpers/panic_handler.rs index c5f672a1a..5918395b8 100644 --- a/uefi/src/helpers/panic_handler.rs +++ b/uefi/src/helpers/panic_handler.rs @@ -1,5 +1,5 @@ -use crate::helpers::system_table_opt; use crate::println; +use crate::table::system_table_boot; use cfg_if::cfg_if; #[panic_handler] @@ -7,7 +7,7 @@ fn panic_handler(info: &core::panic::PanicInfo) -> ! { println!("[PANIC]: {}", info); // Give the user some time to read the message - if let Some(st) = system_table_opt() { + if let Some(st) = system_table_boot() { st.boot_services().stall(10_000_000); } else { let mut dummy = 0u64; @@ -28,7 +28,7 @@ fn panic_handler(info: &core::panic::PanicInfo) -> ! { qemu_exit_handle.exit_failure(); } else { // If the system table is available, use UEFI's standard shutdown mechanism - if let Some(st) = system_table_opt() { + if let Some(st) = system_table_boot() { use crate::table::runtime::ResetType; st.runtime_services() .reset(ResetType::SHUTDOWN, crate::Status::ABORTED, None); diff --git a/uefi/src/helpers/println.rs b/uefi/src/helpers/println.rs index 265911da1..2a30eb1d5 100644 --- a/uefi/src/helpers/println.rs +++ b/uefi/src/helpers/println.rs @@ -1,10 +1,11 @@ -use crate::helpers::system_table; +use crate::table::system_table_boot; use core::fmt::Write; /// INTERNAL API! Helper for print macros. #[doc(hidden)] pub fn _print(args: core::fmt::Arguments) { - system_table() + system_table_boot() + .expect("boot services are not active") .stdout() .write_fmt(args) .expect("Failed to write to stdout"); From 1970c81dbed94864c8f9a34bd48bc7b8d9395d98 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sat, 8 Jun 2024 13:05:23 -0400 Subject: [PATCH 60/91] uefi: Deprecate helpers::system_table This functionality is available with `table::system_table_boot` now. --- uefi/CHANGELOG.md | 1 + uefi/src/helpers/mod.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index 70b95be05..bfba9babf 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -19,6 +19,7 @@ documentation for details of obligations for callers. - `BootServices::allocate_pool` now returns `NonZero` instead of `*mut u8`. +- `helpers::system_table` is deprecated, use `table::system_table_boot` instead. ## Removed - Removed the `panic-on-logger-errors` feature of the `uefi` crate. Logger diff --git a/uefi/src/helpers/mod.rs b/uefi/src/helpers/mod.rs index 910929cdd..e7afe9a6e 100644 --- a/uefi/src/helpers/mod.rs +++ b/uefi/src/helpers/mod.rs @@ -40,7 +40,7 @@ mod println; /// /// The returned pointer is only valid until boot services are exited. #[must_use] -// TODO do we want to keep this public? +#[deprecated(note = "use uefi::table::system_table_boot instead")] pub fn system_table() -> SystemTable { table::system_table_boot().expect("boot services are not active") } From 8c61286d67396ede174b14a977175642161a2a01 Mon Sep 17 00:00:00 2001 From: andre-braga Date: Mon, 10 Jun 2024 21:28:00 +0000 Subject: [PATCH 61/91] uefi: Add TryFrom u8 slice to DevicePathNode Adds the capability to convert a byte slice to a DevicePathNode. This will be used to convert a byte slice to a DevicePath in a followup PR, which allows easier interaction with the data returned from UEFI variable services. --- uefi/CHANGELOG.md | 2 +- uefi/src/proto/device_path/mod.rs | 42 +++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index 70b95be05..1c1748b3b 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -11,7 +11,7 @@ - Added `table::{set_system_table, system_table_boot, system_table_runtime}`. This provides an initial API for global tables that do not require passing around a reference. -- Added `TryFrom<&[u8]>` for `DevicePathHeader`. +- Added `TryFrom<&[u8]>` for `DevicePathHeader` and `DevicePathNode`. - Added `ByteConversionError`. ## Changed diff --git a/uefi/src/proto/device_path/mod.rs b/uefi/src/proto/device_path/mod.rs index 6696bcce8..087440bb5 100644 --- a/uefi/src/proto/device_path/mod.rs +++ b/uefi/src/proto/device_path/mod.rs @@ -266,6 +266,19 @@ impl PartialEq for DevicePathNode { } } +impl<'a> TryFrom<&[u8]> for &'a DevicePathNode { + type Error = ByteConversionError; + + fn try_from(bytes: &[u8]) -> Result { + let dp = <&DevicePathHeader>::try_from(bytes)?; + if usize::from(dp.length) <= bytes.len() { + unsafe { Ok(DevicePathNode::from_ffi_ptr(bytes.as_ptr().cast())) } + } else { + Err(ByteConversionError::InvalidLength) + } + } +} + /// A single device path instance that ends with either an [`END_INSTANCE`] /// or [`END_ENTIRE`] node. Use [`DevicePath::instance_iter`] to get the /// path instances in a [`DevicePath`]. @@ -975,4 +988,33 @@ mod tests { let owned_dp_ref = &*owned_dp; assert_eq!(owned_dp_ref, dp) } + + #[test] + fn test_device_path_node_from_bytes() { + let mut raw_data = Vec::new(); + let node = [0xa0, 0xb0]; + let node_data = &[10, 11]; + + // Raw data is less than size of a [`DevicePathNode`]. + raw_data.push(node[0]); + assert!(<&DevicePathNode>::try_from(raw_data.as_slice()).is_err()); + + // Raw data is long enough to hold a [`DevicePathNode`]. + raw_data.push(node[1]); + raw_data.extend( + u16::try_from(mem::size_of::() + node_data.len()) + .unwrap() + .to_le_bytes(), + ); + raw_data.extend(node_data); + let dp = <&DevicePathNode>::try_from(raw_data.as_slice()).unwrap(); + + // Relevant assertions to verify the conversion is fine. + assert_eq!(mem::size_of_val(dp), 6); + check_node(dp, 0xa0, 0xb0, &[10, 11]); + + // [`DevicePathNode`] data length exceeds the raw_data slice. + raw_data[2] += 1; + assert!(<&DevicePathNode>::try_from(raw_data.as_slice()).is_err()); + } } From faf56c7238a3d04d42cd73ea70819fdd99ebef6d Mon Sep 17 00:00:00 2001 From: andre-braga Date: Tue, 11 Jun 2024 20:24:56 +0000 Subject: [PATCH 62/91] uefi: make DevicePathHeader::try_from idiomatic --- uefi/src/proto/device_path/mod.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/uefi/src/proto/device_path/mod.rs b/uefi/src/proto/device_path/mod.rs index 087440bb5..0328fc3db 100644 --- a/uefi/src/proto/device_path/mod.rs +++ b/uefi/src/proto/device_path/mod.rs @@ -124,11 +124,10 @@ impl<'a> TryFrom<&[u8]> for &'a DevicePathHeader { fn try_from(bytes: &[u8]) -> Result { if mem::size_of::() <= bytes.len() { - unsafe { - return Ok(&*bytes.as_ptr().cast::()); - } + unsafe { Ok(&*bytes.as_ptr().cast::()) } + } else { + Err(ByteConversionError::InvalidLength) } - Err(ByteConversionError::InvalidLength) } } From 798797e1e58cac1326a283bb042ada19dc283fd3 Mon Sep 17 00:00:00 2001 From: andre-braga Date: Tue, 11 Jun 2024 20:17:36 +0000 Subject: [PATCH 63/91] uefi: Add TryFrom u8 slice to DevicePath Adds the capability to convert a byte slice to a DevicePath. This allows for users to easily get a DevicePath from the data returned by UEFI variables, etc. --- uefi/CHANGELOG.md | 2 +- uefi/src/proto/device_path/mod.rs | 62 +++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index b33952820..fe4c90515 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -11,7 +11,7 @@ - Added `table::{set_system_table, system_table_boot, system_table_runtime}`. This provides an initial API for global tables that do not require passing around a reference. -- Added `TryFrom<&[u8]>` for `DevicePathHeader` and `DevicePathNode`. +- Added `TryFrom<&[u8]>` for `DevicePathHeader`, `DevicePathNode` and `DevicePath`. - Added `ByteConversionError`. ## Changed diff --git a/uefi/src/proto/device_path/mod.rs b/uefi/src/proto/device_path/mod.rs index 087440bb5..b61268e08 100644 --- a/uefi/src/proto/device_path/mod.rs +++ b/uefi/src/proto/device_path/mod.rs @@ -397,6 +397,35 @@ impl DevicePath { total_size_in_bytes } + /// Calculate the size in bytes of the entire `DevicePath` starting + /// at `bytes`. This adds up each node's length, including the + /// end-entire node. + /// + /// # Errors + /// + /// The [`ByteConversionError::InvalidLength`] error will be returned + /// when the length of the given bytes slice cannot contain the full + /// [`DevicePath`] represented by the slice. + fn size_in_bytes_from_slice(mut bytes: &[u8]) -> Result { + let max_size_in_bytes = bytes.len(); + let mut total_size_in_bytes: usize = 0; + loop { + let node = <&DevicePathNode>::try_from(bytes)?; + let node_size_in_bytes = usize::from(node.length()); + total_size_in_bytes += node_size_in_bytes; + // Length of last processed node extends past the bytes slice. + if total_size_in_bytes > max_size_in_bytes { + return Err(ByteConversionError::InvalidLength); + } + if node.is_end_entire() { + break; + } + bytes = &bytes[node_size_in_bytes..]; + } + + Ok(total_size_in_bytes) + } + /// Create a [`DevicePath`] reference from an opaque pointer. /// /// # Safety @@ -488,6 +517,15 @@ impl PartialEq for DevicePath { } } +impl<'a> TryFrom<&[u8]> for &'a DevicePath { + type Error = ByteConversionError; + + fn try_from(bytes: &[u8]) -> Result { + let len = DevicePath::size_in_bytes_from_slice(bytes)?; + unsafe { Ok(&*ptr_meta::from_raw_parts(bytes.as_ptr().cast(), len)) } + } +} + #[cfg(feature = "alloc")] impl ToOwned for DevicePath { type Owned = Box; @@ -1017,4 +1055,28 @@ mod tests { raw_data[2] += 1; assert!(<&DevicePathNode>::try_from(raw_data.as_slice()).is_err()); } + + #[test] + fn test_device_path_nodes_from_bytes() { + let raw_data = create_raw_device_path(); + let dp = <&DevicePath>::try_from(raw_data.as_slice()).unwrap(); + + // Check that the size is the sum of the nodes' lengths. + assert_eq!(mem::size_of_val(dp), 6 + 8 + 4 + 6 + 8 + 4); + + // Check the list's node iter. + let nodes: Vec<_> = dp.node_iter().collect(); + check_node(nodes[0], 0xa0, 0xb0, &[10, 11]); + check_node(nodes[1], 0xa1, 0xb1, &[20, 21, 22, 23]); + check_node( + nodes[2], + DeviceType::END.0, + DeviceSubType::END_INSTANCE.0, + &[], + ); + check_node(nodes[3], 0xa2, 0xb2, &[30, 31]); + check_node(nodes[4], 0xa3, 0xb3, &[40, 41, 42, 43]); + // The end-entire node is not returned by the iterator. + assert_eq!(nodes.len(), 5); + } } From eaee8b92cec7f3d0c07027692c839c1ab4b305be Mon Sep 17 00:00:00 2001 From: andre-braga Date: Wed, 12 Jun 2024 17:12:45 +0000 Subject: [PATCH 64/91] uefi: re-export CapsuleFlags Users of the UpdateCapsule runtime service will need to interface with CapsuleFlags to determine capsule specific behavior. --- uefi/CHANGELOG.md | 1 + uefi/src/table/runtime.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index fe4c90515..aa8ed737c 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -13,6 +13,7 @@ around a reference. - Added `TryFrom<&[u8]>` for `DevicePathHeader`, `DevicePathNode` and `DevicePath`. - Added `ByteConversionError`. +- Re-exported `CapsuleFlags`. ## Changed - `SystemTable::exit_boot_services` is now `unsafe`. See that method's diff --git a/uefi/src/table/runtime.rs b/uefi/src/table/runtime.rs index 72cff98a7..f4871245f 100644 --- a/uefi/src/table/runtime.rs +++ b/uefi/src/table/runtime.rs @@ -7,7 +7,7 @@ use core::fmt::{self, Debug, Display, Formatter}; use core::mem::MaybeUninit; use core::ptr; -pub use uefi_raw::capsule::{CapsuleBlockDescriptor, CapsuleHeader}; +pub use uefi_raw::capsule::{CapsuleBlockDescriptor, CapsuleFlags, CapsuleHeader}; pub use uefi_raw::table::runtime::{ ResetType, TimeCapabilities, VariableAttributes, VariableVendor, }; From 716f9bc3bd253e697d8ad880a4a0661f0c68fae1 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Fri, 14 Jun 2024 13:08:14 -0400 Subject: [PATCH 65/91] ci: Temporarily turn off warnings-as-errors for nightly CI jobs The dead_code lint on nightly is currently incorrectly flagging a lot of structs as unused. --- .github/workflows/rust.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 5fc22ba11..24c8ff538 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -123,6 +123,11 @@ jobs: build_feature_permutations: name: Build (feature permutations) runs-on: ubuntu-latest + env: + # TODO: temporarily allow warnings to not be errors on nightly due to + # incorrect dead_code lint. + # https://github.com/rust-osdev/uefi-rs/issues/1205 + RUSTFLAGS: "" steps: - name: Checkout sources uses: actions/checkout@v4 @@ -134,6 +139,11 @@ jobs: nightly_channel: name: Build (nightly + unstable feature) runs-on: ubuntu-latest + env: + # TODO: temporarily allow warnings to not be errors on nightly due to + # incorrect dead_code lint. + # https://github.com/rust-osdev/uefi-rs/issues/1205 + RUSTFLAGS: "" steps: - name: Checkout sources uses: actions/checkout@v4 From 1e0e3697688017ca2e43561897db2d7366530818 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 17 Jun 2024 09:24:26 +0000 Subject: [PATCH 66/91] chore(deps): update crate-ci/typos action to v1.22.7 --- .github/workflows/qa.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index 3fd705df7..77ff2b498 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -7,4 +7,4 @@ jobs: steps: - uses: actions/checkout@v4 # Executes "typos ." - - uses: crate-ci/typos@v1.22.3 + - uses: crate-ci/typos@v1.22.7 From 8a5514abc28a363ae7099a9326974de74927aa85 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 17 Jun 2024 09:25:03 +0000 Subject: [PATCH 67/91] chore(deps): lock file maintenance --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cb487ee49..f12fd7749 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -549,9 +549,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.2" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "miniz_oxide" From 5ee9bccd13083c58f6ab746cbfa3406685801d32 Mon Sep 17 00:00:00 2001 From: andre-braga Date: Mon, 17 Jun 2024 17:51:36 +0000 Subject: [PATCH 68/91] uefi: use UNSPECIFIED_TIMEZONE instead of magic number --- uefi/src/table/runtime.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uefi/src/table/runtime.rs b/uefi/src/table/runtime.rs index f4871245f..e61076b65 100644 --- a/uefi/src/table/runtime.rs +++ b/uefi/src/table/runtime.rs @@ -473,7 +473,7 @@ impl Time { /// Query the time offset in minutes from UTC, or None if using local time. #[must_use] pub const fn time_zone(&self) -> Option { - if self.0.time_zone == 2047 { + if self.0.time_zone == Self::UNSPECIFIED_TIMEZONE { None } else { Some(self.0.time_zone) From 871c3f1f993cef8ebd0f16d1de27358e36a2ee7d Mon Sep 17 00:00:00 2001 From: andre-braga Date: Thu, 20 Jun 2024 12:23:54 +0000 Subject: [PATCH 69/91] uefi: Make TimeError more descriptive When returning a TimeError, it'd be helpful to specify to the user which field is invalid so that it can be handled accordingly, or at least communicated. This change does this by adding bool fields to the TimeError struct, representing the validity of each field of a Time struct. --- uefi/CHANGELOG.md | 2 + uefi/src/table/runtime.rs | 100 ++++++++++++++++++++++++++++++++------ 2 files changed, 86 insertions(+), 16 deletions(-) diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index aa8ed737c..1ad46a6fa 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -14,6 +14,8 @@ - Added `TryFrom<&[u8]>` for `DevicePathHeader`, `DevicePathNode` and `DevicePath`. - Added `ByteConversionError`. - Re-exported `CapsuleFlags`. +- One can now specify in `TimeError` what fields of `Time` are outside its valid + range. `Time::is_valid` has been updated accordingly. ## Changed - `SystemTable::exit_boot_services` is now `unsafe`. See that method's diff --git a/uefi/src/table/runtime.rs b/uefi/src/table/runtime.rs index e61076b65..f5945ac4a 100644 --- a/uefi/src/table/runtime.rs +++ b/uefi/src/table/runtime.rs @@ -371,19 +371,61 @@ pub struct TimeParams { pub daylight: Daylight, } -/// Error returned by [`Time`] methods if the input is outside the valid range. -#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)] -pub struct TimeError; +/// Error returned by [`Time`] methods. A bool value of `true` means +/// the specified field is outside of its valid range. +#[allow(missing_docs)] +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +pub struct TimeError { + pub year: bool, + pub month: bool, + pub day: bool, + pub hour: bool, + pub minute: bool, + pub second: bool, + pub nanosecond: bool, + pub timezone: bool, + pub daylight: bool, +} + +#[cfg(feature = "unstable")] +impl core::error::Error for TimeError {} impl Display for TimeError { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "{self:?}") + if self.year { + writeln!(f, "year not within `1900..=9999`")?; + } + if self.month { + writeln!(f, "month not within `1..=12")?; + } + if self.day { + writeln!(f, "day not within `1..=31`")?; + } + if self.hour { + writeln!(f, "hour not within `0..=23`")?; + } + if self.minute { + writeln!(f, "minute not within `0..=59`")?; + } + if self.second { + writeln!(f, "second not within `0..=59`")?; + } + if self.nanosecond { + writeln!(f, "nanosecond not within `0..=999_999_999`")?; + } + if self.timezone { + writeln!( + f, + "time_zone not `Time::UNSPECIFIED_TIMEZONE` nor within `-1440..=1440`" + )?; + } + if self.daylight { + writeln!(f, "unknown bits set for daylight")?; + } + Ok(()) } } -#[cfg(feature = "unstable")] -impl core::error::Error for TimeError {} - impl Time { /// Unspecified Timezone/local time. const UNSPECIFIED_TIMEZONE: i16 = uefi_raw::time::Time::UNSPECIFIED_TIMEZONE; @@ -404,11 +446,8 @@ impl Time { daylight: params.daylight, pad2: 0, }); - if time.is_valid() { - Ok(time) - } else { - Err(TimeError) - } + + time.is_valid().map(|_| time) } /// Create an invalid `Time` with all fields set to zero. This can @@ -422,10 +461,39 @@ impl Time { Self(uefi_raw::time::Time::invalid()) } - /// True if all fields are within valid ranges, false otherwise. - #[must_use] - pub fn is_valid(&self) -> bool { - self.0.is_valid() + /// `Ok()` if all fields are within valid ranges, `Err(TimeError)` otherwise. + pub fn is_valid(&self) -> core::result::Result<(), TimeError> { + let mut err = TimeError::default(); + if !(1900..=9999).contains(&self.year()) { + err.year = true; + } + if !(1..=12).contains(&self.month()) { + err.month = true; + } + if !(1..=31).contains(&self.day()) { + err.day = true; + } + if self.hour() > 23 { + err.hour = true; + } + if self.minute() > 59 { + err.minute = true; + } + if self.second() > 59 { + err.second = true; + } + if self.nanosecond() > 999_999_999 { + err.nanosecond = true; + } + if self.time_zone().is_some() && !((-1440..=1440).contains(&self.time_zone().unwrap())) { + err.timezone = true; + } + // All fields are false, i.e., within their valid range. + if err == TimeError::default() { + Ok(()) + } else { + Err(err) + } } /// Query the year. From cf0e0c423daf77177c088fe865aee724e0caeed8 Mon Sep 17 00:00:00 2001 From: Isaac Elliott Date: Sat, 8 Jun 2024 10:21:46 +1000 Subject: [PATCH 70/91] Fix versions `uefi` 0.28 was released from commit 255359a. The tree for that commit doesn't contain `ResetNotificationProtocol`, even though the changelog says it does. `ResetNotificationProtocol` was added in commit 04be50f, which was merged in commit `0c533bd` - both occurring after 0.28 was released. --- uefi-raw/CHANGELOG.md | 6 +++--- uefi/CHANGELOG.md | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/uefi-raw/CHANGELOG.md b/uefi-raw/CHANGELOG.md index 58a8664c3..08048078c 100644 --- a/uefi-raw/CHANGELOG.md +++ b/uefi-raw/CHANGELOG.md @@ -1,14 +1,14 @@ # uefi-raw - [Unreleased] +## Added +- Added `ResetNotificationProtocol`. + ## Changed - `maximum_capsule_size` of `query_capsule_capabilities` now takes a *mut u64 instead of a *mut usize. - `ResetType` now derives the `Default` trait. # uefi-raw - 0.5.2 (2024-04-19) -## Added -- Added `ResetNotificationProtocol`. - ## Added - Added `TimestampProtocol`. - Added `DevicePathToTextProtocol` and `DevicePathFromTextProtocol`. diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index 1ad46a6fa..4e780f6c4 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -11,6 +11,7 @@ - Added `table::{set_system_table, system_table_boot, system_table_runtime}`. This provides an initial API for global tables that do not require passing around a reference. +- Added `ResetNotification` protocol. - Added `TryFrom<&[u8]>` for `DevicePathHeader`, `DevicePathNode` and `DevicePath`. - Added `ByteConversionError`. - Re-exported `CapsuleFlags`. @@ -32,7 +33,6 @@ # uefi - 0.28.0 (2024-04-19) ## Added -- Added `ResetNotification` protocol. - Added `Timestamp` protocol. - Added `UnalignedSlice::as_ptr`. - Added common derives for `Event` and `Handle`. From 3656b5525b4b40f4a055dc9215d2a7da7ac8102a Mon Sep 17 00:00:00 2001 From: Jeff Li Date: Mon, 17 Jun 2024 11:40:49 +0800 Subject: [PATCH 71/91] uefi-test-runner: speed up ploting of sierpinski triangle by updating changed pixel only Signed-off-by: Jeff Li --- uefi-test-runner/examples/sierpinski.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/uefi-test-runner/examples/sierpinski.rs b/uefi-test-runner/examples/sierpinski.rs index bbd2de48c..ac690eaef 100644 --- a/uefi-test-runner/examples/sierpinski.rs +++ b/uefi-test-runner/examples/sierpinski.rs @@ -55,6 +55,23 @@ impl Buffer { dims: (self.width, self.height), }) } + + /// Update only a pixel to the framebuffer. + fn blit_pixel( + &self, + gop: &mut GraphicsOutput, + coords: (usize, usize), + ) -> Result { + gop.blt(BltOp::BufferToVideo { + buffer: &self.pixels, + src: BltRegion::SubRectangle { + coords, + px_stride: self.width, + }, + dest: coords, + dims: (1, 1), + }) + } } // ANCHOR_END: buffer @@ -90,6 +107,9 @@ fn draw_sierpinski(bt: &BootServices) -> Result { } } + // Draw background. + buffer.blit(&mut gop)?; + let size = Point::new(width as f32, height as f32); // Define the vertices of a big triangle. @@ -119,7 +139,7 @@ fn draw_sierpinski(bt: &BootServices) -> Result { pixel.blue = 0; // Draw the buffer to the screen. - buffer.blit(&mut gop)?; + buffer.blit_pixel(&mut gop, (p.x as usize, p.y as usize))?; } } From 85eb730f3a568c622fad898046b1e30cc8904613 Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Fri, 21 Jun 2024 09:49:04 +0200 Subject: [PATCH 72/91] nix/niv: update nixpkgs to nixos-24.05 --- nix/sources.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/nix/sources.json b/nix/sources.json index 2d2d7cb11..33ce93db6 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -1,14 +1,14 @@ { "nixpkgs": { - "branch": "nixos-23.11", + "branch": "nixos-24.05", "description": "Nix Packages collection", "homepage": null, "owner": "NixOS", "repo": "nixpkgs", - "rev": "e38d7cb66ea4f7a0eb6681920615dfcc30fc2920", - "sha256": "1shml3mf52smfra0x3mpfixddr4krp3n78fc2sv07ghiphn22k43", + "rev": "dd457de7e08c6d06789b1f5b88fc9327f4d96309", + "sha256": "1kpamwmvs5xrmjgl3baxphmm69i0qydvgvk1n1c582ii4bdnzky0", "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/e38d7cb66ea4f7a0eb6681920615dfcc30fc2920.tar.gz", + "url": "https://github.com/NixOS/nixpkgs/archive/dd457de7e08c6d06789b1f5b88fc9327f4d96309.tar.gz", "url_template": "https://github.com///archive/.tar.gz" }, "rust-overlay": { @@ -17,10 +17,10 @@ "homepage": "", "owner": "oxalica", "repo": "rust-overlay", - "rev": "ece8bdb3c3b58def25f204b9a1261dee55d7c9c0", - "sha256": "1avinp5vcaicbjssmfwwfii5v8gab6ygh2hfmg4jli822469p5si", + "rev": "c9a793a5278f711a59fe77b9bf54b215667022c6", + "sha256": "0q6k94320ivsjb5jjldywy68q6jb0qbd6lsji86ig8a54l649jcf", "type": "tarball", - "url": "https://github.com/oxalica/rust-overlay/archive/ece8bdb3c3b58def25f204b9a1261dee55d7c9c0.tar.gz", + "url": "https://github.com/oxalica/rust-overlay/archive/c9a793a5278f711a59fe77b9bf54b215667022c6.tar.gz", "url_template": "https://github.com///archive/.tar.gz" } } From 793af58ea47e1398bcdf2e6fd4c3725a92630065 Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Thu, 23 May 2024 11:18:40 +0200 Subject: [PATCH 73/91] doc: fix typos --- uefi-services/README.md | 2 +- uefi/src/table/boot.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/uefi-services/README.md b/uefi-services/README.md index ddb053248..f240f5870 100644 --- a/uefi-services/README.md +++ b/uefi-services/README.md @@ -1,4 +1,4 @@ # uefi-services WARNING: `uefi-services` is deprecated. Functionality was moved to -`uefi::helpers::init` in `uefi` ´v0.28.0`. +`uefi::helpers::init` in `uefi@v0.28.0`. diff --git a/uefi/src/table/boot.rs b/uefi/src/table/boot.rs index 1a5e44876..436d57d56 100644 --- a/uefi/src/table/boot.rs +++ b/uefi/src/table/boot.rs @@ -216,8 +216,8 @@ impl BootServices { /// /// The buffer must be aligned like a `MemoryDescriptor`. /// - /// The returned key is a unique identifier of the current configuration of memory. - /// Any allocations or such will change the memory map's key. + /// The returned key is a unique identifier of the current configuration of + /// memory. Any allocations or such will change the memory map's key. /// /// If you want to store the resulting memory map without having to keep /// the buffer around, you can use `.copied().collect()` on the iterator. @@ -1628,7 +1628,7 @@ pub struct MemoryMapSize { /// map, you manually have to call [`MemoryMap::sort`] first. /// /// ## UEFI pitfalls -/// **Please note that when working with memory maps, the `entry_size` is +/// **Please note** that when working with memory maps, the `entry_size` is /// usually larger than `size_of:: Date: Sat, 25 May 2024 12:55:13 +0200 Subject: [PATCH 74/91] doc: more clarity in uefi/mem.rs --- uefi/src/mem.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/uefi/src/mem.rs b/uefi/src/mem.rs index bd6d3794a..1d0d66d41 100644 --- a/uefi/src/mem.rs +++ b/uefi/src/mem.rs @@ -23,10 +23,14 @@ use {core::alloc::Allocator, core::ptr::NonNull}; /// success. /// /// # Feature `unstable` / `allocator_api` -/// By default, this function works with Rust's default allocation mechanism. If you activate the -/// `unstable`-feature, it uses the `allocator_api` instead. In that case, the function takes an -/// additional parameter describing the specific [`Allocator`]. You can use [`alloc::alloc::Global`] -/// as default. +/// By default, this function works with the allocator that is set as +/// `#[global_allocator]`. This might be UEFI allocator but depends on your +/// use case and how you set up the environment. +/// +/// If you activate the `unstable`-feature, all allocations uses the provided +/// allocator (via `allocator_api`) instead. In that case, the function takes an +/// additional parameter describing the specific [`Allocator`]. You can use +/// [`alloc::alloc::Global`] which defaults to the `#[global_allocator]`. /// /// [`Allocator`]: https://doc.rust-lang.org/alloc/alloc/trait.Allocator.html /// [`alloc::alloc::Global`]: https://doc.rust-lang.org/alloc/alloc/struct.Global.html From 1b7a9bd7a322cedbe081fc6c9896f4b2e33d4f58 Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Thu, 23 May 2024 11:21:02 +0200 Subject: [PATCH 75/91] treewide: entry_size -> desc_size This helps to prevent confusions. MemoryDescriptors and their reported size are already a pitfall. So at least we should refrain from using non-standard names for them. --- uefi-test-runner/src/boot/memory.rs | 2 +- uefi/src/table/boot.rs | 63 ++++++++++++++++++----------- uefi/src/table/system.rs | 14 +++++-- 3 files changed, 52 insertions(+), 27 deletions(-) diff --git a/uefi-test-runner/src/boot/memory.rs b/uefi-test-runner/src/boot/memory.rs index 078548991..1855d1fc6 100644 --- a/uefi-test-runner/src/boot/memory.rs +++ b/uefi-test-runner/src/boot/memory.rs @@ -67,7 +67,7 @@ fn memory_map(bt: &BootServices) { let sizes = bt.memory_map_size(); // 2 extra descriptors should be enough. - let buf_sz = sizes.map_size + 2 * sizes.entry_size; + let buf_sz = sizes.map_size + 2 * sizes.desc_size; // We will use vectors for convenience. let mut buffer = vec![0_u8; buf_sz]; diff --git a/uefi/src/table/boot.rs b/uefi/src/table/boot.rs index 436d57d56..469ea0f1d 100644 --- a/uefi/src/table/boot.rs +++ b/uefi/src/table/boot.rs @@ -189,7 +189,7 @@ impl BootServices { pub fn memory_map_size(&self) -> MemoryMapSize { let mut map_size = 0; let mut map_key = MemoryMapKey(0); - let mut entry_size = 0; + let mut desc_size = 0; let mut entry_version = 0; let status = unsafe { @@ -197,30 +197,41 @@ impl BootServices { &mut map_size, ptr::null_mut(), &mut map_key.0, - &mut entry_size, + &mut desc_size, &mut entry_version, ) }; assert_eq!(status, Status::BUFFER_TOO_SMALL); + assert_eq!( + map_size % desc_size, + 0, + "Memory map must be a multiple of the reported descriptor size." + ); + MemoryMapSize { - entry_size, + desc_size, map_size, } } - /// Retrieves the current memory map. + /// Stores the current UEFI memory map in the provided buffer. /// - /// The allocated buffer should be big enough to contain the memory map, - /// and a way of estimating how big it should be is by calling `memory_map_size`. + /// The allocated buffer must be at least aligned to a [`MemoryDescriptor`] + /// and should be big enough to store the whole map. To estimating how big + /// the map will be, you can call [`Self::memory_map_size`]. /// - /// The buffer must be aligned like a `MemoryDescriptor`. + /// The memory map contains entries of type [`MemoryDescriptor`]. However, + /// the relevant step size is always the reported `desc_size` but never + /// `size_of::()`. /// /// The returned key is a unique identifier of the current configuration of /// memory. Any allocations or such will change the memory map's key. /// /// If you want to store the resulting memory map without having to keep /// the buffer around, you can use `.copied().collect()` on the iterator. + /// Note that this will change the current memory map again, if the UEFI + /// allocator is used under the hood. /// /// # Errors /// @@ -233,7 +244,7 @@ impl BootServices { MemoryDescriptor::assert_aligned(buffer); let map_buffer = buffer.as_mut_ptr().cast::(); let mut map_key = MemoryMapKey(0); - let mut entry_size = 0; + let mut desc_size = 0; let mut entry_version = 0; assert_eq!( @@ -247,17 +258,17 @@ impl BootServices { &mut map_size, map_buffer, &mut map_key.0, - &mut entry_size, + &mut desc_size, &mut entry_version, ) } .to_result_with_val(move || { - let len = map_size / entry_size; + let len = map_size / desc_size; MemoryMap { key: map_key, buf: buffer, - entry_size, + desc_size, len, } }) @@ -1613,7 +1624,7 @@ pub struct MemoryMapKey(usize); #[derive(Debug)] pub struct MemoryMapSize { /// Size of a single memory descriptor in bytes - pub entry_size: usize, + pub desc_size: usize, /// Size of the entire memory map in bytes pub map_size: usize, } @@ -1642,7 +1653,7 @@ pub struct MemoryMap<'buf> { buf: &'buf mut [u8], /// Usually bound to the size of a [`MemoryDescriptor`] but can indicate if /// this field is ever extended by a new UEFI standard. - entry_size: usize, + desc_size: usize, len: usize, } @@ -1653,13 +1664,19 @@ impl<'buf> MemoryMap<'buf> { /// /// This allows parsing a memory map provided by a kernel after boot /// services have already exited. - pub fn from_raw(buf: &'buf mut [u8], entry_size: usize) -> Self { - assert!(entry_size >= mem::size_of::()); - let len = buf.len() / entry_size; + pub fn from_raw(buf: &'buf mut [u8], desc_size: usize) -> Self { + assert!(!buf.is_empty()); + assert_eq!( + buf.len() % desc_size, + 0, + "The buffer length must be a multiple of the desc_size" + ); + assert!(desc_size >= mem::size_of::()); + let len = buf.len() / desc_size; MemoryMap { key: MemoryMapKey(0), buf, - entry_size, + desc_size, len, } } @@ -1727,15 +1744,15 @@ impl<'buf> MemoryMap<'buf> { unsafe { ptr::swap_nonoverlapping( - base.add(index1 * self.entry_size), - base.add(index2 * self.entry_size), - self.entry_size, + base.add(index1 * self.desc_size), + base.add(index2 * self.desc_size), + self.desc_size, ); } } fn get_element_phys_addr(&self, index: usize) -> PhysicalAddress { - let offset = index.checked_mul(self.entry_size).unwrap(); + let offset = index.checked_mul(self.desc_size).unwrap(); let elem = unsafe { &*self.buf.as_ptr().add(offset).cast::() }; elem.phys_start } @@ -1767,7 +1784,7 @@ impl<'buf> MemoryMap<'buf> { &*self .buf .as_ptr() - .add(self.entry_size * index) + .add(self.desc_size * index) .cast::() }; @@ -1785,7 +1802,7 @@ impl<'buf> MemoryMap<'buf> { &mut *self .buf .as_mut_ptr() - .add(self.entry_size * index) + .add(self.desc_size * index) .cast::() }; diff --git a/uefi/src/table/system.rs b/uefi/src/table/system.rs index 87ed22a55..e27082a2a 100644 --- a/uefi/src/table/system.rs +++ b/uefi/src/table/system.rs @@ -165,7 +165,7 @@ impl SystemTable { let extra_entries = 8; let memory_map_size = self.boot_services().memory_map_size(); - let extra_size = memory_map_size.entry_size.checked_mul(extra_entries)?; + let extra_size = memory_map_size.desc_size.checked_mul(extra_entries)?; memory_map_size.map_size.checked_add(extra_size) } @@ -253,7 +253,12 @@ impl SystemTable { let boot_services = self.boot_services(); // Reboot the device. - let reset = |status| -> ! { self.runtime_services().reset(ResetType::COLD, status, None) }; + let reset = |status| -> ! { + { + log::warn!("Resetting the machine"); + self.runtime_services().reset(ResetType::COLD, status, None) + } + }; // Get the size of the buffer to allocate. If that calculation // overflows treat it as an unrecoverable error. @@ -284,7 +289,10 @@ impl SystemTable { }; return (st, memory_map); } - Err(err) => status = err.status(), + Err(err) => { + log::error!("Error retrieving the memory map for exiting the boot services"); + status = err.status() + } } } From 82178a2d1834f32f4f6ae3696788e86be889e8c3 Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Sun, 26 May 2024 00:05:20 +0200 Subject: [PATCH 76/91] uefi: MemoryMapSize -> MemoryMapMeta This prepares the following changes. --- uefi/src/table/boot.rs | 52 +++++++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/uefi/src/table/boot.rs b/uefi/src/table/boot.rs index 469ea0f1d..cca8a662d 100644 --- a/uefi/src/table/boot.rs +++ b/uefi/src/table/boot.rs @@ -179,18 +179,18 @@ impl BootServices { unsafe { (self.0.free_pages)(addr, count) }.to_result() } - /// Returns struct which contains the size of a single memory descriptor - /// as well as the size of the current memory map. + /// Queries the `get_memory_map` function of UEFI to retrieve the current + /// size of the map. Returns a [`MemoryMapMeta`]. /// - /// Note that the size of the memory map can increase any time an allocation happens, - /// so when creating a buffer to put the memory map into, it's recommended to allocate a few extra - /// elements worth of space above the size of the current memory map. + /// It is recommended to add a few more bytes for a subsequent allocation + /// for the memory map, as the memory map itself also needs heap memory, + /// and other allocations might occur before that call. #[must_use] - pub fn memory_map_size(&self) -> MemoryMapSize { + pub fn memory_map_size(&self) -> MemoryMapMeta { let mut map_size = 0; let mut map_key = MemoryMapKey(0); let mut desc_size = 0; - let mut entry_version = 0; + let mut desc_version = 0; let status = unsafe { (self.0.get_memory_map)( @@ -198,7 +198,7 @@ impl BootServices { ptr::null_mut(), &mut map_key.0, &mut desc_size, - &mut entry_version, + &mut desc_version, ) }; assert_eq!(status, Status::BUFFER_TOO_SMALL); @@ -209,9 +209,11 @@ impl BootServices { "Memory map must be a multiple of the reported descriptor size." ); - MemoryMapSize { + MemoryMapMeta { desc_size, map_size, + map_key, + desc_version, } } @@ -1619,14 +1621,30 @@ impl Align for MemoryDescriptor { #[repr(C)] pub struct MemoryMapKey(usize); -/// A structure containing the size of a memory descriptor and the size of the -/// memory map. -#[derive(Debug)] -pub struct MemoryMapSize { - /// Size of a single memory descriptor in bytes - pub desc_size: usize, - /// Size of the entire memory map in bytes +/// A structure containing the meta attributes associated with a call to +/// `GetMemoryMap` of UEFI. Note that all values refer to the time this was +/// called. All following invocations (hidden, subtle, and asynchronous ones) +/// will likely invalidate this. +#[derive(Copy, Clone, Debug)] +pub struct MemoryMapMeta { + /// The actual size of the map. pub map_size: usize, + /// The reported memory descriptor size. Note that this is the reference + /// and never `size_of::()`! + pub desc_size: usize, + /// A unique memory key bound to a specific memory map version/state. + pub map_key: MemoryMapKey, + /// The version of the descriptor struct. + pub desc_version: u32, +} + +impl MemoryMapMeta { + /// Returns the amount of entries in the map. + #[must_use] + pub fn entry_count(&self) -> usize { + assert_eq!(self.map_size % self.desc_size, 0); + self.map_size / self.desc_size + } } /// An accessory to the memory map that can be either iterated or @@ -1644,8 +1662,6 @@ pub struct MemoryMapSize { /// always use `entry_size` as step-size when interfacing with the memory map on /// a low level. /// -/// -/// /// [0]: https://github.com/tianocore/edk2/blob/7142e648416ff5d3eac6c6d607874805f5de0ca8/MdeModulePkg/Core/PiSmmCore/Page.c#L1059 #[derive(Debug)] pub struct MemoryMap<'buf> { From 98215a287979994e5c4fc89879822adbf48d5377 Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Sat, 25 May 2024 20:24:58 +0200 Subject: [PATCH 77/91] uefi: introduce MemoryMapBackingMemory helper type --- uefi/src/table/boot.rs | 132 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 128 insertions(+), 4 deletions(-) diff --git a/uefi/src/table/boot.rs b/uefi/src/table/boot.rs index cca8a662d..f5bc295b2 100644 --- a/uefi/src/table/boot.rs +++ b/uefi/src/table/boot.rs @@ -1,6 +1,6 @@ //! UEFI services available during boot. -use super::Revision; +use super::{system_table_boot, Revision}; use crate::data_types::{Align, PhysicalAddress}; use crate::proto::device_path::DevicePath; use crate::proto::loaded_image::LoadedImage; @@ -186,7 +186,7 @@ impl BootServices { /// for the memory map, as the memory map itself also needs heap memory, /// and other allocations might occur before that call. #[must_use] - pub fn memory_map_size(&self) -> MemoryMapMeta { + fn memory_map_size(&self) -> MemoryMapMeta { let mut map_size = 0; let mut map_key = MemoryMapKey(0); let mut desc_size = 0; @@ -209,12 +209,16 @@ impl BootServices { "Memory map must be a multiple of the reported descriptor size." ); - MemoryMapMeta { + let mmm = MemoryMapMeta { desc_size, map_size, map_key, desc_version, - } + }; + + mmm.assert_sanity_checks(); + + mmm } /// Stores the current UEFI memory map in the provided buffer. @@ -1621,6 +1625,111 @@ impl Align for MemoryDescriptor { #[repr(C)] pub struct MemoryMapKey(usize); +/// The backing memory for the UEFI memory app on the UEFI heap, allocated using +/// the UEFI boot services allocator. This occupied memory will also be +/// reflected in the memory map itself. +/// +/// Although untyped, it is similar to the `Box` type in terms of heap +/// allocation and deallocation, as well as ownership of the corresponding +/// memory. Apart from that, this type only has the semantics of a buffer. +/// +/// The memory is untyped, which is necessary due to the nature of the UEFI +/// spec. It still ensures a correct alignment to hold [`MemoryDescriptor`]. The +/// size of the buffer is sufficient to hold the memory map at the point in time +/// where this is created. Note that due to (not obvious or asynchronous) +/// allocations/deallocations in your environment, this might be outdated at the +/// time you store the memory map in it. +/// +/// Note that due to the nature of the UEFI memory app, this buffer might +/// hold (a few) bytes more than necessary. The `map_size` reported by +/// `get_memory_map` tells the actual size. +/// +/// When this type is dropped and boot services are not exited yet, the memory +/// is freed. +/// +/// # Usage +/// The type is intended to be used like this: +/// 1. create it using [`MemoryMapBackingMemory::new`] +/// 2. pass it to [`BootServices::get_memory_map`] +/// 3. construct a [`MemoryMap`] from it +#[derive(Debug)] +#[allow(clippy::len_without_is_empty)] // this type is never empty +pub(crate) struct MemoryMapBackingMemory(NonNull<[u8]>); + +impl MemoryMapBackingMemory { + /// Constructs a new [`MemoryMapBackingMemory`]. + /// + /// # Parameters + /// - `memory_type`: The memory type for the memory map allocation. + /// Typically, [`MemoryType::LOADER_DATA`] for regular UEFI applications. + pub(crate) fn new(memory_type: MemoryType) -> Result { + let st = system_table_boot().expect("Should have boot services activated"); + let bs = st.boot_services(); + + let memory_map_meta = bs.memory_map_size(); + let len = Self::safe_allocation_size_hint(memory_map_meta); + let ptr = bs.allocate_pool(memory_type, len)?.as_ptr(); + + // Should be fine as UEFI always has allocations with a guaranteed + // alignment of 8 bytes. + assert_eq!(ptr.align_offset(mem::align_of::()), 0); + + // If this panics, the UEFI implementation is broken. + assert_eq!(memory_map_meta.map_size % memory_map_meta.desc_size, 0); + + unsafe { Ok(Self::from_raw(ptr, len)) } + } + + unsafe fn from_raw(ptr: *mut u8, len: usize) -> Self { + assert_eq!(ptr.align_offset(mem::align_of::()), 0); + + let ptr = NonNull::new(ptr).expect("UEFI should never return a null ptr. An error should have been reflected via an Err earlier."); + let slice = NonNull::slice_from_raw_parts(ptr, len); + + Self(slice) + } + + /// Returns a "safe" best-effort size hint for the memory map size with + /// some additional bytes in buffer compared to the [`MemoryMapMeta`]. + /// This helps + #[must_use] + fn safe_allocation_size_hint(mmm: MemoryMapMeta) -> usize { + // Allocate space for extra entries beyond the current size of the + // memory map. The value of 8 matches the value in the Linux kernel: + // https://github.com/torvalds/linux/blob/e544a07438/drivers/firmware/efi/libstub/efistub.h#L173 + const EXTRA_ENTRIES: usize = 8; + + let extra_size = mmm.desc_size * EXTRA_ENTRIES; + mmm.map_size + extra_size + } + + /// Returns the raw pointer to the beginning of the allocation. + pub fn as_ptr_mut(&mut self) -> *mut u8 { + self.0.as_ptr().cast() + } + + /// Returns a mutable slice to the underlying memory. + #[must_use] + pub fn as_mut_slice(&mut self) -> &mut [u8] { + unsafe { self.0.as_mut() } + } +} + +// Don't drop when we use this in unit tests. +#[cfg(not(test))] +impl Drop for MemoryMapBackingMemory { + fn drop(&mut self) { + if let Some(bs) = system_table_boot() { + let res = unsafe { bs.boot_services().free_pool(self.0.as_ptr().cast()) }; + if let Err(e) = res { + log::error!("Failed to deallocate memory map: {e:?}"); + } + } else { + log::debug!("Boot services are excited. Memory map won't be freed using the UEFI boot services allocator."); + } + } +} + /// A structure containing the meta attributes associated with a call to /// `GetMemoryMap` of UEFI. Note that all values refer to the time this was /// called. All following invocations (hidden, subtle, and asynchronous ones) @@ -1645,6 +1754,21 @@ impl MemoryMapMeta { assert_eq!(self.map_size % self.desc_size, 0); self.map_size / self.desc_size } + + /// Runs some sanity assertions. + pub fn assert_sanity_checks(&self) { + assert!(self.desc_size > 0); + // Although very unlikely, this might fail if the memory descriptor is + // extended by a future UEFI revision by a significant amount, we + // update the struct, but an old UEFI implementation reports a small + // size. + assert!(self.desc_size >= mem::size_of::()); + assert!(self.map_size > 0); + + // Ensure the mmap size is (somehow) sane. + const ONE_GB: usize = 1024 * 1024 * 1024; + assert!(self.map_size <= ONE_GB); + } } /// An accessory to the memory map that can be either iterated or From 098fb7724f1182f89ec51a925caa989b5fcc5bf6 Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Sat, 25 May 2024 23:48:36 +0200 Subject: [PATCH 78/91] uefi: MemoryMap now owns its memory This is an attempt to simplify the overall complex handling of obtaining the UEFI memory map. We have the following pre-requisites and use-cases all to keep in mind when designing the functions and associated helper types: - the memory map itself needs memory; typically on the UEFI heap - acquiring that memory and storing the memory map inside it are two distinct steps - the memory map is not just a slice of [MemoryDescriptor] (desc_size is bigger than size_of) - the required map size can be obtained by a call to a boot service function - the needed memory might change due to hidden or asynchronous allocations between the allocation of a buffer and storing the memory map inside it - when boot services are excited, best practise has shown (looking at linux code) that one should use the same buffer (with some extra capacity) and call exit_boot_services with that buffer at most two times in a loop This makes it hard to come up with an ergonomic solution such as using a Box or any other high-level Rust type. The main simplification of my design is that the MemoryMap type now doesn't has a reference to memory anymore but actually owns it. This also models the real world use case where one typically obtains the memory map once when boot services are exited. A &'static [u8] on the MemoryMap just creates more confusion that it brings any benefit. The MemoryMap now knows whether boot services are still active and frees that memory, or it doesn't if the boot services are exited. This means less fiddling with life-times and less cognitive overhead when - reading the code - calling BootService::memory_map independently of exit_boot_services --- uefi-test-runner/src/boot/memory.rs | 11 +- uefi/CHANGELOG.md | 10 +- uefi/src/table/boot.rs | 152 +++++++++++++++++----------- uefi/src/table/system.rs | 50 ++------- 4 files changed, 110 insertions(+), 113 deletions(-) diff --git a/uefi-test-runner/src/boot/memory.rs b/uefi-test-runner/src/boot/memory.rs index 1855d1fc6..b23b38248 100644 --- a/uefi-test-runner/src/boot/memory.rs +++ b/uefi-test-runner/src/boot/memory.rs @@ -63,17 +63,8 @@ fn alloc_alignment() { fn memory_map(bt: &BootServices) { info!("Testing memory map functions"); - // Get the memory descriptor size and an estimate of the memory map size - let sizes = bt.memory_map_size(); - - // 2 extra descriptors should be enough. - let buf_sz = sizes.map_size + 2 * sizes.desc_size; - - // We will use vectors for convenience. - let mut buffer = vec![0_u8; buf_sz]; - let mut memory_map = bt - .memory_map(&mut buffer) + .memory_map(MemoryType::LOADER_DATA) .expect("Failed to retrieve UEFI memory map"); memory_map.sort(); diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index 4e780f6c4..344766e47 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -16,7 +16,7 @@ - Added `ByteConversionError`. - Re-exported `CapsuleFlags`. - One can now specify in `TimeError` what fields of `Time` are outside its valid - range. `Time::is_valid` has been updated accordingly. + range. `Time::is_valid` has been updated accordingly. ## Changed - `SystemTable::exit_boot_services` is now `unsafe`. See that method's @@ -24,6 +24,14 @@ - `BootServices::allocate_pool` now returns `NonZero` instead of `*mut u8`. - `helpers::system_table` is deprecated, use `table::system_table_boot` instead. +- `BootServices::memory_map` changed its signature from \ + `pub fn memory_map<'buf>(&self, buffer: &'buf mut [u8]) -> Result> {` \ + to \ + `pub fn memory_map(&self, mt: MemoryType) -> Result` + - Allocations now happen automatically internally on the UEFI heap. Also, the + returned type is automatically freed on the UEFI heap, as long as boot + services are not excited. By removing the need for that explicit buffer and + the lifetime, the API is simpler. ## Removed - Removed the `panic-on-logger-errors` feature of the `uefi` crate. Logger diff --git a/uefi/src/table/boot.rs b/uefi/src/table/boot.rs index f5bc295b2..006b83a12 100644 --- a/uefi/src/table/boot.rs +++ b/uefi/src/table/boot.rs @@ -221,37 +221,46 @@ impl BootServices { mmm } - /// Stores the current UEFI memory map in the provided buffer. - /// - /// The allocated buffer must be at least aligned to a [`MemoryDescriptor`] - /// and should be big enough to store the whole map. To estimating how big - /// the map will be, you can call [`Self::memory_map_size`]. - /// - /// The memory map contains entries of type [`MemoryDescriptor`]. However, - /// the relevant step size is always the reported `desc_size` but never - /// `size_of::()`. - /// - /// The returned key is a unique identifier of the current configuration of - /// memory. Any allocations or such will change the memory map's key. - /// - /// If you want to store the resulting memory map without having to keep - /// the buffer around, you can use `.copied().collect()` on the iterator. - /// Note that this will change the current memory map again, if the UEFI - /// allocator is used under the hood. + /// Stores the current UEFI memory map in an UEFI-heap allocated buffer + /// and returns a [`MemoryMap`]. /// /// # Errors /// - /// See section `EFI_BOOT_SERVICES.GetMemoryMap()` in the UEFI Specification for more details. + /// See section `EFI_BOOT_SERVICES.GetMemoryMap()` in the UEFI Specification + /// for more details. /// /// * [`uefi::Status::BUFFER_TOO_SMALL`] /// * [`uefi::Status::INVALID_PARAMETER`] - pub fn memory_map<'buf>(&self, buffer: &'buf mut [u8]) -> Result> { - let mut map_size = buffer.len(); - MemoryDescriptor::assert_aligned(buffer); - let map_buffer = buffer.as_mut_ptr().cast::(); + pub fn memory_map(&self, mt: MemoryType) -> Result { + let mut buffer = MemoryMapBackingMemory::new(mt)?; + + let MemoryMapMeta { + map_size, + map_key, + desc_size, + desc_version, + } = self.get_memory_map(buffer.as_mut_slice())?; + + let len = map_size / desc_size; + assert_eq!(map_size % desc_size, 0); + assert_eq!(desc_version, MemoryDescriptor::VERSION); + Ok(MemoryMap { + key: map_key, + buf: buffer, + desc_size, + len, + }) + } + + /// Calls the underlying `GetMemoryMap` function of UEFI. On success, + /// the buffer is mutated and contains the map. The map might be shorter + /// than the buffer, which is reflected by the return value. + pub(crate) fn get_memory_map(&self, buf: &mut [u8]) -> Result { + let mut map_size = buf.len(); + let map_buffer = buf.as_mut_ptr().cast::(); let mut map_key = MemoryMapKey(0); let mut desc_size = 0; - let mut entry_version = 0; + let mut desc_version = 0; assert_eq!( (map_buffer as usize) % mem::align_of::(), @@ -265,18 +274,14 @@ impl BootServices { map_buffer, &mut map_key.0, &mut desc_size, - &mut entry_version, + &mut desc_version, ) } - .to_result_with_val(move || { - let len = map_size / desc_size; - - MemoryMap { - key: map_key, - buf: buffer, - desc_size, - len, - } + .to_result_with_val(|| MemoryMapMeta { + map_size, + desc_size, + map_key, + desc_version, }) } @@ -1689,6 +1694,14 @@ impl MemoryMapBackingMemory { Self(slice) } + /// Creates an instance from the provided memory, which is not necessarily + /// on the UEFI heap. + #[cfg(test)] + fn from_slice(buffer: &mut [u8]) -> Self { + let len = buffer.len(); + unsafe { Self::from_raw(buffer.as_mut_ptr(), len) } + } + /// Returns a "safe" best-effort size hint for the memory map size with /// some additional bytes in buffer compared to the [`MemoryMapMeta`]. /// This helps @@ -1703,8 +1716,15 @@ impl MemoryMapBackingMemory { mmm.map_size + extra_size } - /// Returns the raw pointer to the beginning of the allocation. - pub fn as_ptr_mut(&mut self) -> *mut u8 { + /// Returns a raw pointer to the beginning of the allocation. + #[must_use] + pub fn as_ptr(&self) -> *const u8 { + self.0.as_ptr().cast() + } + + /// Returns a mutable raw pointer to the beginning of the allocation. + #[must_use] + pub fn as_mut_ptr(&mut self) -> *mut u8 { self.0.as_ptr().cast() } @@ -1788,31 +1808,27 @@ impl MemoryMapMeta { /// /// [0]: https://github.com/tianocore/edk2/blob/7142e648416ff5d3eac6c6d607874805f5de0ca8/MdeModulePkg/Core/PiSmmCore/Page.c#L1059 #[derive(Debug)] -pub struct MemoryMap<'buf> { +pub struct MemoryMap { + /// Backing memory, properly initialized at this point. + buf: MemoryMapBackingMemory, key: MemoryMapKey, - buf: &'buf mut [u8], /// Usually bound to the size of a [`MemoryDescriptor`] but can indicate if /// this field is ever extended by a new UEFI standard. desc_size: usize, len: usize, } -impl<'buf> MemoryMap<'buf> { - /// Creates a [`MemoryMap`] from the given buffer and entry size. - /// The entry size is usually bound to the size of a [`MemoryDescriptor`] - /// but can indicate if this field is ever extended by a new UEFI standard. - /// - /// This allows parsing a memory map provided by a kernel after boot - /// services have already exited. - pub fn from_raw(buf: &'buf mut [u8], desc_size: usize) -> Self { - assert!(!buf.is_empty()); - assert_eq!( - buf.len() % desc_size, - 0, - "The buffer length must be a multiple of the desc_size" - ); +impl MemoryMap { + /// Creates a [`MemoryMap`] from the give initialized memory map behind + /// the buffer and the reported `desc_size` from UEFI. + pub(crate) fn from_initialized_mem(buf: MemoryMapBackingMemory, meta: MemoryMapMeta) -> Self { + let MemoryMapMeta { + map_size, + desc_size, + .. + } = meta; assert!(desc_size >= mem::size_of::()); - let len = buf.len() / desc_size; + let len = map_size / desc_size; MemoryMap { key: MemoryMapKey(0), buf, @@ -1821,6 +1837,20 @@ impl<'buf> MemoryMap<'buf> { } } + #[cfg(test)] + fn from_raw(buf: &mut [u8], desc_size: usize) -> Self { + let mem = MemoryMapBackingMemory::from_slice(buf); + Self::from_initialized_mem( + mem, + MemoryMapMeta { + map_size: buf.len(), + desc_size, + map_key: MemoryMapKey(0), + desc_version: MemoryDescriptor::VERSION, + }, + ) + } + #[must_use] /// Returns the unique [`MemoryMapKey`] associated with the memory map. pub fn key(&self) -> MemoryMapKey { @@ -1915,7 +1945,7 @@ impl<'buf> MemoryMap<'buf> { /// Returns a reference to the [`MemoryDescriptor`] at `index` or `None` if out of bounds. #[must_use] - pub fn get(&self, index: usize) -> Option<&'buf MemoryDescriptor> { + pub fn get(&self, index: usize) -> Option<&MemoryDescriptor> { if index >= self.len { return None; } @@ -1933,7 +1963,7 @@ impl<'buf> MemoryMap<'buf> { /// Returns a mut reference to the [`MemoryDescriptor`] at `index` or `None` if out of bounds. #[must_use] - pub fn get_mut(&mut self, index: usize) -> Option<&'buf mut MemoryDescriptor> { + pub fn get_mut(&mut self, index: usize) -> Option<&mut MemoryDescriptor> { if index >= self.len { return None; } @@ -1950,7 +1980,7 @@ impl<'buf> MemoryMap<'buf> { } } -impl core::ops::Index for MemoryMap<'_> { +impl core::ops::Index for MemoryMap { type Output = MemoryDescriptor; fn index(&self, index: usize) -> &Self::Output { @@ -1958,7 +1988,7 @@ impl core::ops::Index for MemoryMap<'_> { } } -impl core::ops::IndexMut for MemoryMap<'_> { +impl core::ops::IndexMut for MemoryMap { fn index_mut(&mut self, index: usize) -> &mut Self::Output { self.get_mut(index).unwrap() } @@ -1967,13 +1997,13 @@ impl core::ops::IndexMut for MemoryMap<'_> { /// An iterator of [`MemoryDescriptor`]. The underlying memory map is always /// associated with a unique [`MemoryMapKey`]. #[derive(Debug, Clone)] -pub struct MemoryMapIter<'buf> { - memory_map: &'buf MemoryMap<'buf>, +pub struct MemoryMapIter<'a> { + memory_map: &'a MemoryMap, index: usize, } -impl<'buf> Iterator for MemoryMapIter<'buf> { - type Item = &'buf MemoryDescriptor; +impl<'a> Iterator for MemoryMapIter<'a> { + type Item = &'a MemoryDescriptor; fn size_hint(&self) -> (usize, Option) { let sz = self.memory_map.len - self.index; @@ -2224,7 +2254,7 @@ mod tests { } // Added for debug purposes on test failure - impl core::fmt::Display for MemoryMap<'_> { + impl core::fmt::Display for MemoryMap { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { writeln!(f)?; for desc in self.entries() { diff --git a/uefi/src/table/system.rs b/uefi/src/table/system.rs index e27082a2a..014169110 100644 --- a/uefi/src/table/system.rs +++ b/uefi/src/table/system.rs @@ -2,6 +2,7 @@ use core::ffi::c_void; use core::marker::PhantomData; use core::ptr::NonNull; use core::slice; +use uefi::table::boot::{MemoryMapBackingMemory, MemoryMapMeta}; use crate::proto::console::text; use crate::{CStr16, Result, Status, StatusExt}; @@ -151,33 +152,15 @@ impl SystemTable { unsafe { &*(*self.table).boot_services.cast_const().cast() } } - /// Get the size in bytes of the buffer to allocate for storing the memory - /// map in `exit_boot_services`. - /// - /// This map contains some extra room to avoid needing to allocate more than - /// once. - /// - /// Returns `None` on overflow. - fn memory_map_size_for_exit_boot_services(&self) -> Option { - // Allocate space for extra entries beyond the current size of the - // memory map. The value of 8 matches the value in the Linux kernel: - // https://github.com/torvalds/linux/blob/e544a07438/drivers/firmware/efi/libstub/efistub.h#L173 - let extra_entries = 8; - - let memory_map_size = self.boot_services().memory_map_size(); - let extra_size = memory_map_size.desc_size.checked_mul(extra_entries)?; - memory_map_size.map_size.checked_add(extra_size) - } - /// Get the current memory map and exit boot services. unsafe fn get_memory_map_and_exit_boot_services( &self, - buf: &'static mut [u8], - ) -> Result> { + buf: &mut [u8], + ) -> Result { let boot_services = self.boot_services(); // Get the memory map. - let memory_map = boot_services.memory_map(buf)?; + let memory_map = boot_services.get_memory_map(buf)?; // Try to exit boot services using the memory map key. Note that after // the first call to `exit_boot_services`, there are restrictions on @@ -185,7 +168,7 @@ impl SystemTable { // only `get_memory_map` and `exit_boot_services` are allowed. Starting // in UEFI 2.9 other memory allocation functions may also be called. boot_services - .exit_boot_services(boot_services.image_handle(), memory_map.key()) + .exit_boot_services(boot_services.image_handle(), memory_map.map_key) .map(move |()| memory_map) } @@ -247,11 +230,9 @@ impl SystemTable { pub unsafe fn exit_boot_services( self, memory_type: MemoryType, - ) -> (SystemTable, MemoryMap<'static>) { + ) -> (SystemTable, MemoryMap) { crate::helpers::exit(); - let boot_services = self.boot_services(); - // Reboot the device. let reset = |status| -> ! { { @@ -260,19 +241,7 @@ impl SystemTable { } }; - // Get the size of the buffer to allocate. If that calculation - // overflows treat it as an unrecoverable error. - let buf_size = match self.memory_map_size_for_exit_boot_services() { - Some(buf_size) => buf_size, - None => reset(Status::ABORTED), - }; - - // Allocate a byte slice to hold the memory map. If the - // allocation fails treat it as an unrecoverable error. - let buf: *mut u8 = match boot_services.allocate_pool(memory_type, buf_size) { - Ok(buf) => buf.as_ptr(), - Err(err) => reset(err.status()), - }; + let mut buf = MemoryMapBackingMemory::new(memory_type).expect("Failed to allocate memory"); // Calling `exit_boot_services` can fail if the memory map key is not // current. Retry a second time if that occurs. This matches the @@ -280,14 +249,13 @@ impl SystemTable { // https://github.com/torvalds/linux/blob/e544a0743/drivers/firmware/efi/libstub/efi-stub-helper.c#L375 let mut status = Status::ABORTED; for _ in 0..2 { - let buf: &mut [u8] = unsafe { slice::from_raw_parts_mut(buf, buf_size) }; - match unsafe { self.get_memory_map_and_exit_boot_services(buf) } { + match unsafe { self.get_memory_map_and_exit_boot_services(buf.as_mut_slice()) } { Ok(memory_map) => { let st = SystemTable { table: self.table, _marker: PhantomData, }; - return (st, memory_map); + return (st, MemoryMap::from_initialized_mem(buf, memory_map)); } Err(err) => { log::error!("Error retrieving the memory map for exiting the boot services"); From d864ce7a96aeff65bf8c986c20304d17b084a326 Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Fri, 21 Jun 2024 10:50:30 +0200 Subject: [PATCH 79/91] uefi: use MemoryMapMeta in MemoryMap This prepares the next commit. --- uefi/src/table/boot.rs | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/uefi/src/table/boot.rs b/uefi/src/table/boot.rs index 006b83a12..e230fb0ee 100644 --- a/uefi/src/table/boot.rs +++ b/uefi/src/table/boot.rs @@ -234,12 +234,13 @@ impl BootServices { pub fn memory_map(&self, mt: MemoryType) -> Result { let mut buffer = MemoryMapBackingMemory::new(mt)?; + let meta = self.get_memory_map(buffer.as_mut_slice())?; let MemoryMapMeta { map_size, map_key, desc_size, desc_version, - } = self.get_memory_map(buffer.as_mut_slice())?; + } = meta; let len = map_size / desc_size; assert_eq!(map_size % desc_size, 0); @@ -247,7 +248,7 @@ impl BootServices { Ok(MemoryMap { key: map_key, buf: buffer, - desc_size, + meta, len, }) } @@ -1812,9 +1813,7 @@ pub struct MemoryMap { /// Backing memory, properly initialized at this point. buf: MemoryMapBackingMemory, key: MemoryMapKey, - /// Usually bound to the size of a [`MemoryDescriptor`] but can indicate if - /// this field is ever extended by a new UEFI standard. - desc_size: usize, + meta: MemoryMapMeta, len: usize, } @@ -1822,17 +1821,12 @@ impl MemoryMap { /// Creates a [`MemoryMap`] from the give initialized memory map behind /// the buffer and the reported `desc_size` from UEFI. pub(crate) fn from_initialized_mem(buf: MemoryMapBackingMemory, meta: MemoryMapMeta) -> Self { - let MemoryMapMeta { - map_size, - desc_size, - .. - } = meta; - assert!(desc_size >= mem::size_of::()); - let len = map_size / desc_size; + assert!(meta.desc_size >= mem::size_of::()); + let len = meta.entry_count(); MemoryMap { key: MemoryMapKey(0), buf, - desc_size, + meta, len, } } @@ -1914,15 +1908,15 @@ impl MemoryMap { unsafe { ptr::swap_nonoverlapping( - base.add(index1 * self.desc_size), - base.add(index2 * self.desc_size), - self.desc_size, + base.add(index1 * self.meta.desc_size), + base.add(index2 * self.meta.desc_size), + self.meta.desc_size, ); } } fn get_element_phys_addr(&self, index: usize) -> PhysicalAddress { - let offset = index.checked_mul(self.desc_size).unwrap(); + let offset = index.checked_mul(self.meta.desc_size).unwrap(); let elem = unsafe { &*self.buf.as_ptr().add(offset).cast::() }; elem.phys_start } @@ -1954,7 +1948,7 @@ impl MemoryMap { &*self .buf .as_ptr() - .add(self.desc_size * index) + .add(self.meta.desc_size * index) .cast::() }; @@ -1972,7 +1966,7 @@ impl MemoryMap { &mut *self .buf .as_mut_ptr() - .add(self.desc_size * index) + .add(self.meta.desc_size * index) .cast::() }; From c511c52d552d04eb88aa5ce40ec116701b15d93c Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Fri, 21 Jun 2024 10:50:37 +0200 Subject: [PATCH 80/91] uefi: add MemoryMap::raw --- uefi/CHANGELOG.md | 3 +++ uefi/src/table/boot.rs | 15 +++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index 344766e47..975680c24 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -17,6 +17,9 @@ - Re-exported `CapsuleFlags`. - One can now specify in `TimeError` what fields of `Time` are outside its valid range. `Time::is_valid` has been updated accordingly. +- `MemoryMap::as_raw` which provides raw access to the memory map. This is for + example useful if you create your own Multiboot2 bootloader that embeds the + EFI mmap in a Multiboot2 boot information structure. ## Changed - `SystemTable::exit_boot_services` is now `unsafe`. See that method's diff --git a/uefi/src/table/boot.rs b/uefi/src/table/boot.rs index e230fb0ee..a279aa022 100644 --- a/uefi/src/table/boot.rs +++ b/uefi/src/table/boot.rs @@ -1729,6 +1729,12 @@ impl MemoryMapBackingMemory { self.0.as_ptr().cast() } + /// Returns a slice to the underlying memory. + #[must_use] + pub fn as_slice(&self) -> &[u8] { + unsafe { self.0.as_ref() } + } + /// Returns a mutable slice to the underlying memory. #[must_use] pub fn as_mut_slice(&mut self) -> &mut [u8] { @@ -1972,6 +1978,15 @@ impl MemoryMap { Some(desc) } + + /// Provides access to the raw memory map. + /// + /// This is for example useful if you want to embed the memory map into + /// another data structure, such as a Multiboot2 boot information. + #[must_use] + pub fn as_raw(&self) -> (&[u8], MemoryMapMeta) { + (self.buf.as_slice(), self.meta) + } } impl core::ops::Index for MemoryMap { From 55a0ba67406e75d1d923adcb4a49ce383a2ff4fc Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Sun, 26 May 2024 11:58:37 +0200 Subject: [PATCH 81/91] uefi: add memory map unit test based on real-world data --- uefi/src/table/boot.rs | 137 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 136 insertions(+), 1 deletion(-) diff --git a/uefi/src/table/boot.rs b/uefi/src/table/boot.rs index a279aa022..3b59c4784 100644 --- a/uefi/src/table/boot.rs +++ b/uefi/src/table/boot.rs @@ -2161,7 +2161,7 @@ impl<'a> HandleBuffer<'a> { pub struct ProtocolSearchKey(NonNull); #[cfg(test)] -mod tests { +mod tests_mmap_artificial { use core::mem::{size_of, size_of_val}; use crate::table::boot::{MemoryAttribute, MemoryMap, MemoryType}; @@ -2292,3 +2292,138 @@ mod tests { true } } + +#[cfg(test)] +mod tests_mmap_real { + use super::*; + use core::mem::size_of; + + const MMAP_META: MemoryMapMeta = MemoryMapMeta { + map_size: MMAP_RAW.len() * size_of::(), + desc_size: 48, + map_key: MemoryMapKey(0), + desc_version: 1, + }; + /// Sample with 10 entries of a real UEFI memory map extracted from our + /// UEFI test runner. + const MMAP_RAW: [u64; 60] = [ + 3, 0, 0, 1, 15, 0, 7, 4096, 0, 134, 15, 0, 4, 552960, 0, 1, 15, 0, 7, 557056, 0, 24, 15, 0, + 7, 1048576, 0, 1792, 15, 0, 10, 8388608, 0, 8, 15, 0, 7, 8421376, 0, 3, 15, 0, 10, 8433664, + 0, 1, 15, 0, 7, 8437760, 0, 4, 15, 0, 10, 8454144, 0, 240, 15, 0, + ]; + extern crate std; + #[test] + fn basic_functionality() { + let mut buf = MMAP_RAW; + let buf = + unsafe { slice::from_raw_parts_mut(buf.as_mut_ptr().cast::(), MMAP_META.map_size) }; + let mut mmap = MemoryMap::from_raw(buf, MMAP_META.desc_size); + mmap.sort(); + + let entries = mmap.entries().copied().collect::>(); + + let expected = [ + MemoryDescriptor { + ty: MemoryType::BOOT_SERVICES_CODE, + phys_start: 0x0, + virt_start: 0x0, + page_count: 0x1, + att: MemoryAttribute::UNCACHEABLE + | MemoryAttribute::WRITE_COMBINE + | MemoryAttribute::WRITE_THROUGH + | MemoryAttribute::WRITE_BACK, + }, + MemoryDescriptor { + ty: MemoryType::CONVENTIONAL, + phys_start: 0x1000, + virt_start: 0x0, + page_count: 0x86, + att: MemoryAttribute::UNCACHEABLE + | MemoryAttribute::WRITE_COMBINE + | MemoryAttribute::WRITE_THROUGH + | MemoryAttribute::WRITE_BACK, + }, + MemoryDescriptor { + ty: MemoryType::BOOT_SERVICES_DATA, + phys_start: 0x87000, + virt_start: 0x0, + page_count: 0x1, + att: MemoryAttribute::UNCACHEABLE + | MemoryAttribute::WRITE_COMBINE + | MemoryAttribute::WRITE_THROUGH + | MemoryAttribute::WRITE_BACK, + }, + MemoryDescriptor { + ty: MemoryType::CONVENTIONAL, + phys_start: 0x88000, + virt_start: 0x0, + page_count: 0x18, + att: MemoryAttribute::UNCACHEABLE + | MemoryAttribute::WRITE_COMBINE + | MemoryAttribute::WRITE_THROUGH + | MemoryAttribute::WRITE_BACK, + }, + MemoryDescriptor { + ty: MemoryType::CONVENTIONAL, + phys_start: 0x100000, + virt_start: 0x0, + page_count: 0x700, + att: MemoryAttribute::UNCACHEABLE + | MemoryAttribute::WRITE_COMBINE + | MemoryAttribute::WRITE_THROUGH + | MemoryAttribute::WRITE_BACK, + }, + MemoryDescriptor { + ty: MemoryType::ACPI_NON_VOLATILE, + phys_start: 0x800000, + virt_start: 0x0, + page_count: 0x8, + att: MemoryAttribute::UNCACHEABLE + | MemoryAttribute::WRITE_COMBINE + | MemoryAttribute::WRITE_THROUGH + | MemoryAttribute::WRITE_BACK, + }, + MemoryDescriptor { + ty: MemoryType::CONVENTIONAL, + phys_start: 0x808000, + virt_start: 0x0, + page_count: 0x3, + att: MemoryAttribute::UNCACHEABLE + | MemoryAttribute::WRITE_COMBINE + | MemoryAttribute::WRITE_THROUGH + | MemoryAttribute::WRITE_BACK, + }, + MemoryDescriptor { + ty: MemoryType::ACPI_NON_VOLATILE, + phys_start: 0x80b000, + virt_start: 0x0, + page_count: 0x1, + att: MemoryAttribute::UNCACHEABLE + | MemoryAttribute::WRITE_COMBINE + | MemoryAttribute::WRITE_THROUGH + | MemoryAttribute::WRITE_BACK, + }, + MemoryDescriptor { + ty: MemoryType::CONVENTIONAL, + phys_start: 0x80c000, + virt_start: 0x0, + page_count: 0x4, + att: MemoryAttribute::UNCACHEABLE + | MemoryAttribute::WRITE_COMBINE + | MemoryAttribute::WRITE_THROUGH + | MemoryAttribute::WRITE_BACK, + }, + MemoryDescriptor { + ty: MemoryType::ACPI_NON_VOLATILE, + phys_start: 0x810000, + virt_start: 0x0, + page_count: 0xf0, + att: MemoryAttribute::UNCACHEABLE + | MemoryAttribute::WRITE_COMBINE + | MemoryAttribute::WRITE_THROUGH + | MemoryAttribute::WRITE_BACK, + }, + ]; + assert_eq!(entries.as_slice(), &expected); + } +} From b4d70beffb627fb380b52eeca934bb31db13a8af Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Fri, 21 Jun 2024 11:28:37 +0200 Subject: [PATCH 82/91] uefi: improve doc --- uefi/src/lib.rs | 3 ++- uefi/src/table/boot.rs | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/uefi/src/lib.rs b/uefi/src/lib.rs index eef044920..fb658d7c3 100644 --- a/uefi/src/lib.rs +++ b/uefi/src/lib.rs @@ -48,7 +48,8 @@ //! the Rust standard library. For example, methods that return a //! `Vec` rather than filling a statically-sized array. This requires //! a global allocator; you can use the `global_allocator` feature or -//! provide your own. +//! provide your own. This is independent of internal direct usages of the +//! UEFI boot service allocator which may happen anyway, where necessary. //! - `global_allocator`: Set [`allocator::Allocator`] as the global Rust //! allocator. This is a simple allocator that relies on the UEFI pool //! allocator. You can choose to provide your own allocator instead of diff --git a/uefi/src/table/boot.rs b/uefi/src/table/boot.rs index 3b59c4784..1a27de37c 100644 --- a/uefi/src/table/boot.rs +++ b/uefi/src/table/boot.rs @@ -224,6 +224,12 @@ impl BootServices { /// Stores the current UEFI memory map in an UEFI-heap allocated buffer /// and returns a [`MemoryMap`]. /// + /// # Parameters + /// + /// - `mt`: The memory type for the backing memory on the UEFI heap. + /// Usually, this is [`MemoryType::LOADER_DATA`]. You can also use a + /// custom type. + /// /// # Errors /// /// See section `EFI_BOOT_SERVICES.GetMemoryMap()` in the UEFI Specification From e47e36c1fca1597e84095d1332c203678f192043 Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Sun, 26 May 2024 00:19:18 +0200 Subject: [PATCH 83/91] uefi-test-runner: test that BootService::memory_map memory is freed This is now a benefit compared to the old API. This wasn't possible. --- uefi-test-runner/src/boot/memory.rs | 51 ++++++++++++++++------------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/uefi-test-runner/src/boot/memory.rs b/uefi-test-runner/src/boot/memory.rs index b23b38248..133110b43 100644 --- a/uefi-test-runner/src/boot/memory.rs +++ b/uefi-test-runner/src/boot/memory.rs @@ -63,36 +63,41 @@ fn alloc_alignment() { fn memory_map(bt: &BootServices) { info!("Testing memory map functions"); - let mut memory_map = bt - .memory_map(MemoryType::LOADER_DATA) - .expect("Failed to retrieve UEFI memory map"); + // Ensure that the memory map is freed after each iteration (on drop). + // Otherwise, we will have an OOM. + for _ in 0..200000 { + let mut memory_map = bt + .memory_map(MemoryType::LOADER_DATA) + .expect("Failed to retrieve UEFI memory map"); - memory_map.sort(); + memory_map.sort(); - // Collect the descriptors into a vector - let descriptors = memory_map.entries().copied().collect::>(); + // Collect the descriptors into a vector + let descriptors = memory_map.entries().copied().collect::>(); - // Ensured we have at least one entry. - // Real memory maps usually have dozens of entries. - assert!(!descriptors.is_empty(), "Memory map is empty"); + // Ensured we have at least one entry. + // Real memory maps usually have dozens of entries. + assert!(!descriptors.is_empty(), "Memory map is empty"); - let mut curr_value = descriptors[0]; + let mut curr_value = descriptors[0]; - for value in descriptors.iter().skip(1) { - if value.phys_start <= curr_value.phys_start { - panic!("memory map sorting failed"); + for value in descriptors.iter().skip(1) { + if value.phys_start <= curr_value.phys_start { + panic!("memory map sorting failed"); + } + curr_value = *value; } - curr_value = *value; - } - // This is pretty much a sanity test to ensure returned memory isn't filled with random values. - let first_desc = descriptors[0]; + // This is pretty much a basic sanity test to ensure returned memory + // isn't filled with random values. + let first_desc = descriptors[0]; - #[cfg(target_arch = "x86_64")] - { - let phys_start = first_desc.phys_start; - assert_eq!(phys_start, 0, "Memory does not start at address 0"); + #[cfg(target_arch = "x86_64")] + { + let phys_start = first_desc.phys_start; + assert_eq!(phys_start, 0, "Memory does not start at address 0"); + } + let page_count = first_desc.page_count; + assert!(page_count != 0, "Memory map entry has size zero"); } - let page_count = first_desc.page_count; - assert!(page_count != 0, "Memory map entry has zero size"); } From 090182a3e61b6b0edc9c67e071e91405ae73f231 Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Sun, 23 Jun 2024 19:33:12 +0200 Subject: [PATCH 84/91] uefi: simplify usage of Mode --- uefi/CHANGELOG.md | 3 +++ uefi/src/proto/console/gop.rs | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index 975680c24..07bbabc35 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -20,6 +20,7 @@ - `MemoryMap::as_raw` which provides raw access to the memory map. This is for example useful if you create your own Multiboot2 bootloader that embeds the EFI mmap in a Multiboot2 boot information structure. +- `Mode` is now `Copy` and `Clone` ## Changed - `SystemTable::exit_boot_services` is now `unsafe`. See that method's @@ -35,6 +36,8 @@ returned type is automatically freed on the UEFI heap, as long as boot services are not excited. By removing the need for that explicit buffer and the lifetime, the API is simpler. +- `GraphicsOutput::query_mode` is now private. Use `GraphicsOutput::modes` + instead. ## Removed - Removed the `panic-on-logger-errors` feature of the `uefi` crate. Logger diff --git a/uefi/src/proto/console/gop.rs b/uefi/src/proto/console/gop.rs index 351dc0c89..5ae81596d 100644 --- a/uefi/src/proto/console/gop.rs +++ b/uefi/src/proto/console/gop.rs @@ -76,7 +76,7 @@ pub struct GraphicsOutput(GraphicsOutputProtocol); impl GraphicsOutput { /// Returns information for an available graphics mode that the graphics /// device and the set of active video output devices supports. - pub fn query_mode(&self, index: u32, bs: &BootServices) -> Result { + fn query_mode(&self, index: u32, bs: &BootServices) -> Result { let mut info_sz = 0; let mut info_heap_ptr = ptr::null(); // query_mode allocates a buffer and stores the heap ptr in the provided @@ -100,7 +100,7 @@ impl GraphicsOutput { }) } - /// Returns information about all available graphics modes. + /// Returns a [`ModeIter`]. #[must_use] pub fn modes<'a>(&'a self, bs: &'a BootServices) -> ModeIter { ModeIter { @@ -336,7 +336,7 @@ pub enum PixelFormat { } /// Represents a graphics mode compatible with a given graphics device. -#[derive(Debug)] +#[derive(Copy, Clone, Debug)] pub struct Mode { index: u32, info_sz: usize, From 0606024685a1b0e7209637182e131fafe99dfd20 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 24 Jun 2024 02:00:50 +0000 Subject: [PATCH 85/91] chore(deps): update crate-ci/typos action to v1.22.9 --- .github/workflows/qa.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index 77ff2b498..080857889 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -7,4 +7,4 @@ jobs: steps: - uses: actions/checkout@v4 # Executes "typos ." - - uses: crate-ci/typos@v1.22.7 + - uses: crate-ci/typos@v1.22.9 From d246add0df9f33de95e1d79134aa44b7fe4aa544 Mon Sep 17 00:00:00 2001 From: Jeff Li Date: Tue, 25 Jun 2024 22:02:44 +0800 Subject: [PATCH 86/91] template: fix build failure Signed-off-by: Jeff Li --- template/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/template/Cargo.toml b/template/Cargo.toml index 109736564..c880f8803 100644 --- a/template/Cargo.toml +++ b/template/Cargo.toml @@ -5,4 +5,4 @@ edition = "2021" publish = false [dependencies] -uefi = { version = "0.28.0", features = ["alloc"] } +uefi = { version = "0.28.0", features = ["panic_handler"] } From 7313fdf69c7e48fa8822c25da2531fe3424b60da Mon Sep 17 00:00:00 2001 From: andre-braga Date: Thu, 20 Jun 2024 13:50:05 +0000 Subject: [PATCH 87/91] uefi: Add TryFrom<&[u8]> for Time I am implementing a UEFI application which needs to convert part of a byte splice (returned by the variable runtime service) into a `Time`. I wanted to see if it was worth upstreaming, in case others might also need of it. --- uefi/CHANGELOG.md | 3 +- uefi/src/table/runtime.rs | 148 +++++++++++++++++++++++++++++++++++++- 2 files changed, 149 insertions(+), 2 deletions(-) diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index 07bbabc35..5e5356449 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -20,7 +20,8 @@ - `MemoryMap::as_raw` which provides raw access to the memory map. This is for example useful if you create your own Multiboot2 bootloader that embeds the EFI mmap in a Multiboot2 boot information structure. -- `Mode` is now `Copy` and `Clone` +- `Mode` is now `Copy` and `Clone`. +- Added `TryFrom<&[u8]>` for `Time`. ## Changed - `SystemTable::exit_boot_services` is now `unsafe`. See that method's diff --git a/uefi/src/table/runtime.rs b/uefi/src/table/runtime.rs index f5945ac4a..97674bc95 100644 --- a/uefi/src/table/runtime.rs +++ b/uefi/src/table/runtime.rs @@ -4,7 +4,7 @@ use super::Revision; use crate::table::boot::MemoryDescriptor; use crate::{CStr16, Error, Result, Status, StatusExt}; use core::fmt::{self, Debug, Display, Formatter}; -use core::mem::MaybeUninit; +use core::mem::{size_of, MaybeUninit}; use core::ptr; pub use uefi_raw::capsule::{CapsuleBlockDescriptor, CapsuleFlags, CapsuleHeader}; @@ -582,6 +582,69 @@ impl Display for Time { } } +/// Error returned from failing to convert a byte slice into a [`Time`]. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum TimeByteConversionError { + /// One or more fields of the converted [`Time`] is invalid. + InvalidFields(TimeError), + /// The byte slice is not large enough to hold a [`Time`]. + InvalidSize, +} + +impl Display for TimeByteConversionError { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + match self { + Self::InvalidFields(error) => write!(f, "{error}"), + Self::InvalidSize => write!( + f, + "the byte slice is not large enough to hold a Time struct" + ), + } + } +} + +impl TryFrom<&[u8]> for Time { + type Error = TimeByteConversionError; + + fn try_from(bytes: &[u8]) -> core::result::Result { + if size_of::