Skip to main content

virtfw_libefi/
types.rs

1//! efi data types
2
3use core::cmp::Ordering;
4use core::fmt;
5use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
6
7#[cfg(feature = "std")]
8use chrono::{Datelike, Timelike, Utc};
9
10/// EFI_TIME in edk2
11#[repr(C)]
12#[derive(
13    Debug, Clone, Copy, FromBytes, IntoBytes, KnownLayout, Immutable, Eq, PartialEq, Default,
14)]
15pub struct EfiTime {
16    pub year: u16,
17    pub month: u8,
18    pub day: u8,
19    pub hour: u8,
20    pub minute: u8,
21    pub second: u8,
22    _pad1: u8,
23    pub nanosecond: u32,
24    pub timezone: i16,
25    pub daylight: u8,
26    _pad2: u8,
27}
28
29impl EfiTime {
30    pub fn new(year: u16, month: u8, day: u8, hour: u8, minute: u8, second: u8) -> Self {
31        Self {
32            year,
33            month,
34            day,
35            hour,
36            minute,
37            second,
38            ..Default::default()
39        }
40    }
41
42    #[cfg(feature = "std")]
43    pub fn now() -> Self {
44        let t = Utc::now();
45        Self {
46            year: t.year() as u16,
47            month: t.month() as u8,
48            day: t.day() as u8,
49            hour: t.hour() as u8,
50            minute: t.minute() as u8,
51            second: t.second() as u8,
52            nanosecond: t.nanosecond(),
53            ..Default::default()
54        }
55    }
56
57    pub fn initial() -> Self {
58        // should be old enough that it predates any secure boot
59        // related authenticated variable time stamps.
60        Self {
61            year: 2010,
62            month: 1,
63            day: 1,
64            ..Default::default()
65        }
66    }
67}
68
69#[cfg(feature = "x509")]
70impl From<&der::DateTime> for EfiTime {
71    fn from(dt: &der::DateTime) -> Self {
72        Self {
73            year: dt.year(),
74            month: dt.month(),
75            day: dt.day(),
76            hour: dt.hour(),
77            minute: dt.minutes(),
78            second: dt.seconds(),
79            ..Default::default()
80        }
81    }
82}
83
84impl PartialOrd for EfiTime {
85    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
86        Some(self.cmp(other))
87    }
88}
89
90impl Ord for EfiTime {
91    fn cmp(&self, other: &Self) -> Ordering {
92        if self.year != other.year {
93            return self.year.cmp(&other.year);
94        }
95        if self.month != other.month {
96            return self.month.cmp(&other.month);
97        }
98        if self.day != other.day {
99            return self.day.cmp(&other.day);
100        }
101        if self.hour != other.hour {
102            return self.hour.cmp(&other.hour);
103        }
104        if self.minute != other.minute {
105            return self.minute.cmp(&other.minute);
106        }
107        if self.second != other.second {
108            return self.second.cmp(&other.second);
109        }
110        if self.nanosecond != other.nanosecond {
111            return self.nanosecond.cmp(&other.nanosecond);
112        }
113        Ordering::Equal
114    }
115}
116
117impl fmt::Display for EfiTime {
118    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
119        write!(f, "{:04}-{:02}-{:02}", self.year, self.month, self.day)
120    }
121}