| author | |
| committer | |
| log | 94c63f31f2775fed9402ebe9c1155e38300b3641 |
| tree | 954fe478342cee14f8e1987a23dec772baa70783 |
| parent | cd302771420f0e36b1321f922b83e99f7e0ad51d |
| parent | 97fd100471ea74acd3a18c5bbc95efc8f8978b93 |
| signature |
std: add support for getting the time in UEFI2 files changed, 40 insertions(+), 1 deletions(-)
lib/std/os/uefi.zig+25| ... | ... | @@ -131,6 +131,31 @@ pub const Time = extern struct { |
| 131 | 131 | |
| 132 | 132 | /// Time is to be interpreted as local time |
| 133 | 133 | 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 | } | |
| 134 | 159 | }; |
| 135 | 160 | |
| 136 | 161 | /// Capabilities of the clock device |
lib/std/time.zig+15-1| ... | ... | @@ -114,6 +114,13 @@ pub fn nanoTimestamp() i128 { |
| 114 | 114 | return ns; |
| 115 | 115 | } |
| 116 | 116 | |
| 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 | ||
| 117 | 124 | var ts: os.timespec = undefined; |
| 118 | 125 | os.clock_gettime(os.CLOCK.REALTIME, &ts) catch |err| switch (err) { |
| 119 | 126 | error.UnsupportedClock, error.Unexpected => return 0, // "Precision of timing depends on hardware and OS". |
| ... | ... | @@ -176,7 +183,7 @@ pub const Instant = struct { |
| 176 | 183 | // true if we should use clock_gettime() |
| 177 | 184 | const is_posix = switch (builtin.os.tag) { |
| 178 | 185 | .wasi => builtin.link_libc, |
| 179 | .windows => false, | |
| 186 | .windows, .uefi => false, | |
| 180 | 187 | else => true, |
| 181 | 188 | }; |
| 182 | 189 | |
| ... | ... | @@ -197,6 +204,13 @@ pub const Instant = struct { |
| 197 | 204 | return Instant{ .timestamp = ns }; |
| 198 | 205 | } |
| 199 | 206 | |
| 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 | ||
| 200 | 214 | // On darwin, use UPTIME_RAW instead of MONOTONIC as it ticks while suspended. |
| 201 | 215 | // On linux, use BOOTTIME instead of MONOTONIC as it ticks while suspended. |
| 202 | 216 | // On freebsd derivatives, use MONOTONIC_FAST as currently there's no precision tradeoff. |