From d160ec2364fc0613b2966815ddb6b0e945e1225e Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Fri, 19 Jul 2024 11:50:36 -0400 Subject: [PATCH] Add uefi::runtime module The initial version here just provides functions for getting and setting the system time. Later commits will add functions to get/set variables, handle update capsules, etc. Also added some tests for the new code in the test runner (note that there were no existing tests for the time-related functions of `RuntimeServices`). --- uefi-test-runner/src/runtime/mod.rs | 32 +++++++++++++++- uefi/CHANGELOG.md | 2 + uefi/src/lib.rs | 1 + uefi/src/runtime.rs | 57 +++++++++++++++++++++++++++++ 4 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 uefi/src/runtime.rs diff --git a/uefi-test-runner/src/runtime/mod.rs b/uefi-test-runner/src/runtime/mod.rs index 9babae774..41c6d6344 100644 --- a/uefi-test-runner/src/runtime/mod.rs +++ b/uefi-test-runner/src/runtime/mod.rs @@ -1,8 +1,38 @@ +mod vars; + +use uefi::runtime::{self, Daylight, Time, TimeParams}; use uefi::table::runtime::RuntimeServices; pub fn test(rt: &RuntimeServices) { info!("Testing runtime services"); vars::test(rt); + test_time(); } -mod vars; +fn test_time() { + // Print the current time and time capabilities. + info!( + "Time with caps: {:?}", + runtime::get_time_and_caps().unwrap() + ); + + // Set the time. + let time = Time::new(TimeParams { + year: 2020, + month: 1, + day: 2, + hour: 3, + minute: 4, + second: 5, + nanosecond: 6, + time_zone: None, + daylight: Daylight::IN_DAYLIGHT, + }) + .unwrap(); + unsafe { runtime::set_time(&time).unwrap() }; + + // Print the new time and check that the year was successfully changed. + let now = runtime::get_time().unwrap(); + info!("After setting time: {}", now); + assert_eq!(now.year(), 2020); +} diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index c00f2a651..c757db4fb 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -3,6 +3,8 @@ ## Added - `uefi::system` is a new module that provides freestanding functions for accessing fields of the global system table. +- `uefi::runtime` is a new module that provides freestanding functions for + runtime services using the global system table. - Add standard derives for `ConfigTableEntry`. - `PcrEvent`/`PcrEventInputs` impl `Align`, `Eq`, and `PartialEq`. - Added `PcrEvent::new_in_box` and `PcrEventInputs::new_in_box`. diff --git a/uefi/src/lib.rs b/uefi/src/lib.rs index a40d4edac..52ff54cbb 100644 --- a/uefi/src/lib.rs +++ b/uefi/src/lib.rs @@ -119,6 +119,7 @@ pub use uguid::guid; mod result; pub use result::{Error, Result, ResultExt, Status, StatusExt}; +pub mod runtime; pub mod system; pub mod table; diff --git a/uefi/src/runtime.rs b/uefi/src/runtime.rs new file mode 100644 index 000000000..56015bc60 --- /dev/null +++ b/uefi/src/runtime.rs @@ -0,0 +1,57 @@ +//! UEFI runtime services. +//! +//! These services are available both before and after exiting boot +//! services. Note that various restrictions apply when calling runtime services +//! functions after exiting boot services; see the "Calling Convention" section +//! of the UEFI specification for details. + +use crate::table::{self}; +use crate::{Result, StatusExt}; +use core::ptr::{self, NonNull}; + +pub use crate::table::runtime::{Daylight, Time, TimeCapabilities, TimeError, TimeParams}; + +fn runtime_services_raw_panicking() -> NonNull { + let st = table::system_table_raw_panicking(); + // SAFETY: valid per requirements of `set_system_table`. + let st = unsafe { st.as_ref() }; + NonNull::new(st.runtime_services).expect("runtime services are not active") +} + +/// Query the current time and date information. +pub fn get_time() -> Result