use bitfield_struct::bitfield;
use core::fmt::Display;
use static_assertions::const_assert_eq;
use zerocopy::AsBytes;
use zerocopy::FromBytes;
use zerocopy::FromZeroes;
#[repr(C)]
#[derive(Copy, Clone, Debug, AsBytes, FromBytes, FromZeroes, PartialEq, Eq)]
#[cfg_attr(feature = "inspect", derive(inspect::Inspect), inspect(display))]
pub struct EFI_TIME {
pub year: u16,
pub month: u8,
pub day: u8,
pub hour: u8,
pub minute: u8,
pub second: u8,
pub pad1: u8,
pub nanosecond: u32,
pub timezone: EfiTimezone,
pub daylight: EfiDaylight,
pub pad2: u8,
}
impl Default for EFI_TIME {
fn default() -> Self {
Self::new_zeroed()
}
}
const_assert_eq!(size_of::<EFI_TIME>(), 16);
impl EFI_TIME {
pub const ZEROED: EFI_TIME = EFI_TIME {
year: 0,
month: 0,
day: 0,
hour: 0,
minute: 0,
second: 0,
pad1: 0,
nanosecond: 0,
timezone: EfiTimezone(0),
daylight: EfiDaylight::new(),
pad2: 0,
};
}
impl Display for EFI_TIME {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(
f,
"{:04}-{:02}-{:02}T{:02}:{:02}:{:02}",
self.year, self.month, self.day, self.hour, self.minute, self.second
)?;
if self.nanosecond != 0 {
write!(f, ".{:09}", self.nanosecond)?;
}
if self.timezone.0 == 0 {
write!(f, "Z")?;
} else if self.timezone != EFI_UNSPECIFIED_TIMEZONE {
let sign = if self.timezone.0 > 0 { '+' } else { '-' };
let timezone = (self.timezone.0 as i32).abs();
write!(f, "{sign}{:02}:{:02}", timezone / 60, timezone % 60)?;
}
Ok(())
}
}
pub const EFI_UNSPECIFIED_TIMEZONE: EfiTimezone = EfiTimezone(0x07FF);
#[derive(Copy, Clone, Debug, AsBytes, FromBytes, FromZeroes, PartialEq, Eq)]
#[repr(transparent)]
#[cfg_attr(feature = "inspect", derive(inspect::Inspect), inspect(transparent))]
pub struct EfiTimezone(pub i16);
impl EfiTimezone {
pub fn valid(&self) -> bool {
self.0 > -1440 && (self.0 < 1440 || *self == EFI_UNSPECIFIED_TIMEZONE)
}
}
#[bitfield(u8)]
#[derive(AsBytes, FromBytes, FromZeroes, PartialEq, Eq)]
#[cfg_attr(feature = "inspect", derive(inspect::Inspect), inspect(transparent))]
pub struct EfiDaylight {
pub adjust_daylight: bool,
pub in_daylight: bool,
#[bits(6)]
rsvd: u8,
}
impl EfiDaylight {
pub fn valid(&self) -> bool {
self.rsvd() == 0
}
}