From 707ff9fac7ba24d5f6d62fa348b4a68b803dac42 Mon Sep 17 00:00:00 2001 From: Ayush Singh Date: Fri, 26 Jan 2024 01:37:15 +0530 Subject: [PATCH] Implement SystemTime for UEFI - Uses SystemTable->RuntimeServices->GetTime() Signed-off-by: Ayush Singh --- library/std/src/sys/pal/uefi/helpers.rs | 8 ++ library/std/src/sys/pal/uefi/mod.rs | 1 - library/std/src/sys/pal/uefi/tests.rs | 20 +++++ library/std/src/sys/pal/uefi/time.rs | 107 ++++++++++++++++++++++++ 4 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 library/std/src/sys/pal/uefi/time.rs diff --git a/library/std/src/sys/pal/uefi/helpers.rs b/library/std/src/sys/pal/uefi/helpers.rs index 9837cc89f2d39..ba53ed88f3765 100644 --- a/library/std/src/sys/pal/uefi/helpers.rs +++ b/library/std/src/sys/pal/uefi/helpers.rs @@ -146,3 +146,11 @@ pub(crate) fn image_handle_protocol(protocol_guid: Guid) -> Option let system_handle = uefi::env::try_image_handle()?; open_protocol(system_handle, protocol_guid).ok() } + +/// Get RuntimeServices +pub(crate) fn runtime_services() -> Option> { + let system_table: NonNull = + crate::os::uefi::env::try_system_table()?.cast(); + let runtime_services = unsafe { (*system_table.as_ptr()).runtime_services }; + NonNull::new(runtime_services) +} diff --git a/library/std/src/sys/pal/uefi/mod.rs b/library/std/src/sys/pal/uefi/mod.rs index 9ee753aa1a0c1..687e7d99d134a 100644 --- a/library/std/src/sys/pal/uefi/mod.rs +++ b/library/std/src/sys/pal/uefi/mod.rs @@ -38,7 +38,6 @@ pub mod thread; pub mod thread_local_key; #[path = "../unsupported/thread_parking.rs"] pub mod thread_parking; -#[path = "../unsupported/time.rs"] pub mod time; mod helpers; diff --git a/library/std/src/sys/pal/uefi/tests.rs b/library/std/src/sys/pal/uefi/tests.rs index 8806eda3ac0a6..5eb36da922b54 100644 --- a/library/std/src/sys/pal/uefi/tests.rs +++ b/library/std/src/sys/pal/uefi/tests.rs @@ -1,4 +1,6 @@ use super::alloc::*; +use super::time::*; +use crate::time::Duration; #[test] fn align() { @@ -19,3 +21,21 @@ fn align() { } } } + +#[test] +fn epoch() { + let t = r_efi::system::Time { + year: 1970, + month: 1, + day: 1, + hour: 0, + minute: 0, + second: 0, + nanosecond: 0, + timezone: r_efi::efi::UNSPECIFIED_TIMEZONE, + daylight: 0, + pad1: 0, + pad2: 0, + }; + assert_eq!(system_time_internal::uefi_time_to_duration(t), Duration::new(0, 0)); +} diff --git a/library/std/src/sys/pal/uefi/time.rs b/library/std/src/sys/pal/uefi/time.rs new file mode 100644 index 0000000000000..10326819611f1 --- /dev/null +++ b/library/std/src/sys/pal/uefi/time.rs @@ -0,0 +1,107 @@ +use crate::time::Duration; + +const SECS_IN_MINUTE: u64 = 60; +const SECS_IN_HOUR: u64 = SECS_IN_MINUTE * 60; +const SECS_IN_DAY: u64 = SECS_IN_HOUR * 24; + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] +pub struct Instant(Duration); + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] +pub struct SystemTime(Duration); + +pub const UNIX_EPOCH: SystemTime = SystemTime(Duration::from_secs(0)); + +impl Instant { + pub fn now() -> Instant { + panic!("time not implemented on this platform") + } + + pub fn checked_sub_instant(&self, other: &Instant) -> Option { + self.0.checked_sub(other.0) + } + + pub fn checked_add_duration(&self, other: &Duration) -> Option { + Some(Instant(self.0.checked_add(*other)?)) + } + + pub fn checked_sub_duration(&self, other: &Duration) -> Option { + Some(Instant(self.0.checked_sub(*other)?)) + } +} + +impl SystemTime { + pub fn now() -> SystemTime { + system_time_internal::now() + .unwrap_or_else(|| panic!("time not implemented on this platform")) + } + + pub fn sub_time(&self, other: &SystemTime) -> Result { + self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0) + } + + pub fn checked_add_duration(&self, other: &Duration) -> Option { + Some(SystemTime(self.0.checked_add(*other)?)) + } + + pub fn checked_sub_duration(&self, other: &Duration) -> Option { + Some(SystemTime(self.0.checked_sub(*other)?)) + } +} + +pub(crate) mod system_time_internal { + use super::super::helpers; + use super::*; + use crate::mem::MaybeUninit; + use crate::ptr::NonNull; + use r_efi::efi::{RuntimeServices, Time}; + + pub fn now() -> Option { + let runtime_services: NonNull = helpers::runtime_services()?; + let mut t: MaybeUninit