From a86cd9138960fc3d229d8aad3daa6d7f350e2a21 Mon Sep 17 00:00:00 2001 From: Tristan Ross Date: Tue, 19 Dec 2023 23:42:47 -0800 Subject: [PATCH 1/3] os.uefi: add time to epoch conversion --- lib/std/os/uefi.zig | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/lib/std/os/uefi.zig b/lib/std/os/uefi.zig index 7ad01e58e7..51702c4923 100644 --- a/lib/std/os/uefi.zig +++ b/lib/std/os/uefi.zig @@ -131,6 +131,30 @@ pub const Time = extern struct { /// Time is to be interpreted as local time pub const unspecified_timezone: i16 = 0x7ff; + + fn daysInYear(year: u16, maxMonth: u4) u32 { + const leapYear: std.time.epoch.YearLeapKind = if (std.time.epoch.isLeapYear(year)) .leap else .not_leap; + var days: u32 = 0; + var month: u4 = 0; + while (month < maxMonth) : (month += 1) { + days += std.time.epoch.getDaysInMonth(leapYear, @enumFromInt(month + 1)); + } + return days; + } + + pub fn toEpoch(self: std.os.uefi.Time) u64 { + var year: u16 = 0; + var days: u32 = 0; + + while (year < (self.year - 1971)) : (year += 1) { + days += daysInYear(year + 1970, 12); + } + + days += daysInYear(self.year, @as(u4, @intCast(self.month)) - 1) + self.day; + const hours = self.hour + (days * 24); + const minutes = self.minute + (hours * 60); + return self.second + (minutes * 60); + } }; /// Capabilities of the clock device From 23adf095798b8345997b2cbe182c7f109fe1da49 Mon Sep 17 00:00:00 2001 From: Tristan Ross Date: Tue, 19 Dec 2023 23:43:10 -0800 Subject: [PATCH 2/3] time: add uefi support --- lib/std/time.zig | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/std/time.zig b/lib/std/time.zig index c078e97793..56927eae4c 100644 --- a/lib/std/time.zig +++ b/lib/std/time.zig @@ -114,6 +114,13 @@ pub fn nanoTimestamp() i128 { return ns; } + if (builtin.os.tag == .uefi) { + var value: std.os.uefi.Time = undefined; + const status = std.os.uefi.system_table.runtime_services.getTime(&value, null); + assert(status == .Success); + return @as(i128, @intCast(value.toEpoch())) * ms_per_s; + } + var ts: os.timespec = undefined; os.clock_gettime(os.CLOCK.REALTIME, &ts) catch |err| switch (err) { error.UnsupportedClock, error.Unexpected => return 0, // "Precision of timing depends on hardware and OS". @@ -176,7 +183,7 @@ pub const Instant = struct { // true if we should use clock_gettime() const is_posix = switch (builtin.os.tag) { .wasi => builtin.link_libc, - .windows => false, + .windows, .uefi => false, else => true, }; @@ -197,6 +204,13 @@ pub const Instant = struct { return Instant{ .timestamp = ns }; } + if (builtin.os.tag == .uefi) { + var value: std.os.uefi.Time = undefined; + const status = std.os.uefi.system_table.runtime_services.getTime(&value, null); + if (status != .Success) return error.Unsupported; + return Instant{ .timestamp = value.toEpoch() }; + } + // On darwin, use UPTIME_RAW instead of MONOTONIC as it ticks while suspended. // On linux, use BOOTTIME instead of MONOTONIC as it ticks while suspended. // On freebsd derivatives, use MONOTONIC_FAST as currently there's no precision tradeoff. From 97fd100471ea74acd3a18c5bbc95efc8f8978b93 Mon Sep 17 00:00:00 2001 From: Tristan Ross Date: Wed, 20 Dec 2023 09:33:59 -0800 Subject: [PATCH 3/3] os.uefi: add ns to epoch --- lib/std/os/uefi.zig | 3 ++- lib/std/time.zig | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/std/os/uefi.zig b/lib/std/os/uefi.zig index 51702c4923..165c3df249 100644 --- a/lib/std/os/uefi.zig +++ b/lib/std/os/uefi.zig @@ -153,7 +153,8 @@ pub const Time = extern struct { days += daysInYear(self.year, @as(u4, @intCast(self.month)) - 1) + self.day; const hours = self.hour + (days * 24); const minutes = self.minute + (hours * 60); - return self.second + (minutes * 60); + const seconds = self.second + (minutes * std.time.s_per_min); + return self.nanosecond + (seconds * std.time.ns_per_s); } }; diff --git a/lib/std/time.zig b/lib/std/time.zig index 56927eae4c..dad81385e9 100644 --- a/lib/std/time.zig +++ b/lib/std/time.zig @@ -118,7 +118,7 @@ pub fn nanoTimestamp() i128 { var value: std.os.uefi.Time = undefined; const status = std.os.uefi.system_table.runtime_services.getTime(&value, null); assert(status == .Success); - return @as(i128, @intCast(value.toEpoch())) * ms_per_s; + return value.toEpoch(); } var ts: os.timespec = undefined;