Skip to content

Add uefi::runtime module #1249

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 31 additions & 1 deletion uefi-test-runner/src/runtime/mod.rs
Original file line number Diff line number Diff line change
@@ -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::ADJUST_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);
}
2 changes: 2 additions & 0 deletions uefi/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
Expand Down
1 change: 1 addition & 0 deletions uefi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
57 changes: 57 additions & 0 deletions uefi/src/runtime.rs
Original file line number Diff line number Diff line change
@@ -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<uefi_raw::table::runtime::RuntimeServices> {
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<Time> {
let rt = runtime_services_raw_panicking();
let rt = unsafe { rt.as_ref() };

let mut time = Time::invalid();
let time_ptr: *mut Time = &mut time;
unsafe { (rt.get_time)(time_ptr.cast(), ptr::null_mut()) }.to_result_with_val(|| time)
}

/// Query the current time and date information and the RTC capabilities.
pub fn get_time_and_caps() -> Result<(Time, TimeCapabilities)> {
let rt = runtime_services_raw_panicking();
let rt = unsafe { rt.as_ref() };

let mut time = Time::invalid();
let time_ptr: *mut Time = &mut time;
let mut caps = TimeCapabilities::default();
unsafe { (rt.get_time)(time_ptr.cast(), &mut caps) }.to_result_with_val(|| (time, caps))
}

/// Sets the current local time and date information
///
/// During runtime, if a PC-AT CMOS device is present in the platform, the
/// caller must synchronize access to the device before calling `set_time`.
///
/// # Safety
///
/// Undefined behavior could happen if multiple tasks try to
/// use this function at the same time without synchronisation.
pub unsafe fn set_time(time: &Time) -> Result {
let rt = runtime_services_raw_panicking();
let rt = unsafe { rt.as_ref() };

let time: *const Time = time;
(rt.set_time)(time.cast()).to_result()
}