1use bitfield_struct::bitfield;
7use core::fmt::Display;
8use static_assertions::const_assert_eq;
9use zerocopy::FromBytes;
10use zerocopy::FromZeros;
11use zerocopy::Immutable;
12use zerocopy::IntoBytes;
13use zerocopy::KnownLayout;
14
15#[repr(C)]
30#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout, PartialEq, Eq)]
31#[cfg_attr(feature = "inspect", derive(inspect::Inspect), inspect(display))]
32pub struct EFI_TIME {
33 pub year: u16,
34 pub month: u8,
35 pub day: u8,
36 pub hour: u8,
37 pub minute: u8,
38 pub second: u8,
39 pub pad1: u8,
40 pub nanosecond: u32,
41 pub timezone: EfiTimezone,
42 pub daylight: EfiDaylight,
43 pub pad2: u8,
44}
45
46impl Default for EFI_TIME {
49 fn default() -> Self {
50 Self::new_zeroed()
51 }
52}
53
54const_assert_eq!(size_of::<EFI_TIME>(), 16);
55
56impl EFI_TIME {
57 pub const ZEROED: EFI_TIME = EFI_TIME {
59 year: 0,
60 month: 0,
61 day: 0,
62 hour: 0,
63 minute: 0,
64 second: 0,
65 pad1: 0,
66 nanosecond: 0,
67 timezone: EfiTimezone(0),
68 daylight: EfiDaylight::new(),
69 pad2: 0,
70 };
71}
72
73impl Display for EFI_TIME {
74 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
75 write!(
77 f,
78 "{:04}-{:02}-{:02}T{:02}:{:02}:{:02}",
79 self.year, self.month, self.day, self.hour, self.minute, self.second
80 )?;
81 if self.nanosecond != 0 {
82 write!(f, ".{:09}", self.nanosecond)?;
83 }
84 if self.timezone.0 == 0 {
85 write!(f, "Z")?;
86 } else if self.timezone != EFI_UNSPECIFIED_TIMEZONE {
87 let sign = if self.timezone.0 > 0 { '+' } else { '-' };
88 let timezone = (self.timezone.0 as i32).abs();
89 write!(f, "{sign}{:02}:{:02}", timezone / 60, timezone % 60)?;
90 }
91 Ok(())
92 }
93}
94
95pub const EFI_UNSPECIFIED_TIMEZONE: EfiTimezone = EfiTimezone(0x07FF);
98
99#[derive(Copy, Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout, PartialEq, Eq)]
103#[repr(transparent)]
104#[cfg_attr(feature = "inspect", derive(inspect::Inspect), inspect(transparent))]
105pub struct EfiTimezone(pub i16);
106
107impl EfiTimezone {
108 pub fn valid(&self) -> bool {
109 self.0 > -1440 && (self.0 < 1440 || *self == EFI_UNSPECIFIED_TIMEZONE)
110 }
111}
112
113#[bitfield(u8)]
116#[derive(IntoBytes, FromBytes, Immutable, KnownLayout, PartialEq, Eq)]
117#[cfg_attr(feature = "inspect", derive(inspect::Inspect), inspect(transparent))]
118pub struct EfiDaylight {
119 pub adjust_daylight: bool,
123
124 pub in_daylight: bool,
128
129 #[bits(6)]
130 rsvd: u8,
131}
132
133impl EfiDaylight {
134 pub fn valid(&self) -> bool {
135 self.rsvd() == 0
136 }
137}