authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-12-26 01:03:10+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-12-26 01:03:10+02:00
log94c63f31f2775fed9402ebe9c1155e38300b3641
tree954fe478342cee14f8e1987a23dec772baa70783
parentcd302771420f0e36b1321f922b83e99f7e0ad51d
parent97fd100471ea74acd3a18c5bbc95efc8f8978b93
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #18328 from ExpidusOS/feat/uefi-time

std: add support for getting the time in UEFI

2 files changed, 40 insertions(+), 1 deletions(-)

lib/std/os/uefi.zig+25
......@@ -131,6 +131,31 @@ pub const Time = extern struct {
131131
132132 /// Time is to be interpreted as local time
133133 pub const unspecified_timezone: i16 = 0x7ff;
134
135 fn daysInYear(year: u16, maxMonth: u4) u32 {
136 const leapYear: std.time.epoch.YearLeapKind = if (std.time.epoch.isLeapYear(year)) .leap else .not_leap;
137 var days: u32 = 0;
138 var month: u4 = 0;
139 while (month < maxMonth) : (month += 1) {
140 days += std.time.epoch.getDaysInMonth(leapYear, @enumFromInt(month + 1));
141 }
142 return days;
143 }
144
145 pub fn toEpoch(self: std.os.uefi.Time) u64 {
146 var year: u16 = 0;
147 var days: u32 = 0;
148
149 while (year < (self.year - 1971)) : (year += 1) {
150 days += daysInYear(year + 1970, 12);
151 }
152
153 days += daysInYear(self.year, @as(u4, @intCast(self.month)) - 1) + self.day;
154 const hours = self.hour + (days * 24);
155 const minutes = self.minute + (hours * 60);
156 const seconds = self.second + (minutes * std.time.s_per_min);
157 return self.nanosecond + (seconds * std.time.ns_per_s);
158 }
134159};
135160
136161/// Capabilities of the clock device
lib/std/time.zig+15-1
......@@ -114,6 +114,13 @@ pub fn nanoTimestamp() i128 {
114114 return ns;
115115 }
116116
117 if (builtin.os.tag == .uefi) {
118 var value: std.os.uefi.Time = undefined;
119 const status = std.os.uefi.system_table.runtime_services.getTime(&value, null);
120 assert(status == .Success);
121 return value.toEpoch();
122 }
123
117124 var ts: os.timespec = undefined;
118125 os.clock_gettime(os.CLOCK.REALTIME, &ts) catch |err| switch (err) {
119126 error.UnsupportedClock, error.Unexpected => return 0, // "Precision of timing depends on hardware and OS".
......@@ -176,7 +183,7 @@ pub const Instant = struct {
176183 // true if we should use clock_gettime()
177184 const is_posix = switch (builtin.os.tag) {
178185 .wasi => builtin.link_libc,
179 .windows => false,
186 .windows, .uefi => false,
180187 else => true,
181188 };
182189
......@@ -197,6 +204,13 @@ pub const Instant = struct {
197204 return Instant{ .timestamp = ns };
198205 }
199206
207 if (builtin.os.tag == .uefi) {
208 var value: std.os.uefi.Time = undefined;
209 const status = std.os.uefi.system_table.runtime_services.getTime(&value, null);
210 if (status != .Success) return error.Unsupported;
211 return Instant{ .timestamp = value.toEpoch() };
212 }
213
200214 // On darwin, use UPTIME_RAW instead of MONOTONIC as it ticks while suspended.
201215 // On linux, use BOOTTIME instead of MONOTONIC as it ticks while suspended.
202216 // On freebsd derivatives, use MONOTONIC_FAST as currently there's no precision tradeoff.