From 0ccbe8fc71173bf5d2e348e5b3ed6cb344db913b Mon Sep 17 00:00:00 2001 From: Ayush Singh Date: Mon, 14 Apr 2025 18:55:04 +0530 Subject: [PATCH 1/2] std: sys: pal: uefi: Overhaul Time Use a time representation with 1900-01-01-00:00:00 at timezone -1440 min as anchor. This is the earliest time supported in UEFI. Signed-off-by: Ayush Singh --- library/std/src/sys/pal/uefi/tests.rs | 3 + library/std/src/sys/pal/uefi/time.rs | 125 ++++++++++++++++++++++---- 2 files changed, 110 insertions(+), 18 deletions(-) diff --git a/library/std/src/sys/pal/uefi/tests.rs b/library/std/src/sys/pal/uefi/tests.rs index 49e75a1a70d7d..6a15c03184cf0 100644 --- a/library/std/src/sys/pal/uefi/tests.rs +++ b/library/std/src/sys/pal/uefi/tests.rs @@ -1,3 +1,6 @@ +//! These tests are not run automatically right now. Please run these tests manually by copying them +//! to a separate project when modifying any related code. + use super::alloc::*; use super::time::*; use crate::io::{IoSlice, IoSliceMut}; diff --git a/library/std/src/sys/pal/uefi/time.rs b/library/std/src/sys/pal/uefi/time.rs index eeb2c35ffbbc9..32c3cfd143c36 100644 --- a/library/std/src/sys/pal/uefi/time.rs +++ b/library/std/src/sys/pal/uefi/time.rs @@ -1,16 +1,28 @@ 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); +/// When a Timezone is specified, the stored Duration is in UTC. If timezone is unspecified, then +/// the timezone is assumed to be in UTC. +/// +/// UEFI SystemTime is stored as Duration from 1900-01-01-00:00:00 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] pub struct SystemTime(Duration); -pub const UNIX_EPOCH: SystemTime = SystemTime(Duration::from_secs(0)); +pub const UNIX_EPOCH: SystemTime = SystemTime::from_uefi(r_efi::efi::Time { + year: 1970, + month: 1, + day: 1, + hour: 0, + minute: 0, + second: 0, + nanosecond: 0, + timezone: 0, + daylight: 0, + pad1: 0, + pad2: 0, +}); impl Instant { pub fn now() -> Instant { @@ -40,6 +52,14 @@ impl Instant { } impl SystemTime { + pub(crate) const fn from_uefi(t: r_efi::efi::Time) -> Self { + Self(system_time_internal::from_uefi(&t)) + } + + pub(crate) const fn to_uefi(self, timezone: i16, daylight: u8) -> Option { + system_time_internal::to_uefi(&self.0, timezone, daylight) + } + pub fn now() -> SystemTime { system_time_internal::now() .unwrap_or_else(|| panic!("time not implemented on this platform")) @@ -50,11 +70,17 @@ impl SystemTime { } pub fn checked_add_duration(&self, other: &Duration) -> Option { - Some(SystemTime(self.0.checked_add(*other)?)) + let temp = Self(self.0.checked_add(*other)?); + + // Check if can be represented in UEFI + if temp.to_uefi(0, 0).is_some() { Some(temp) } else { None } } pub fn checked_sub_duration(&self, other: &Duration) -> Option { - Some(SystemTime(self.0.checked_sub(*other)?)) + let temp = Self(self.0.checked_sub(*other)?); + + // Check if can be represented in UEFI + if temp.to_uefi(0, 0).is_some() { Some(temp) } else { None } } } @@ -66,51 +92,114 @@ pub(crate) mod system_time_internal { use crate::mem::MaybeUninit; use crate::ptr::NonNull; + const SECS_IN_MINUTE: u64 = 60; + const SECS_IN_HOUR: u64 = SECS_IN_MINUTE * 60; + const SECS_IN_DAY: u64 = SECS_IN_HOUR * 24; + const TIMEZONE_DELTA: u64 = 1440 * SECS_IN_MINUTE; + pub fn now() -> Option { let runtime_services: NonNull = helpers::runtime_services()?; let mut t: MaybeUninit