-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improvements for UEFI #19486
Improvements for UEFI #19486
Conversation
c6294b0
to
7d817aa
Compare
Correct me if I'm wrong, but my assumption would be that UEFI should be using WTF-16 <-> WTF-8 conversion instead of UTF-16 <-> UTF-8 (see #19005 for context). (links to any resources about these sorts of UEFI details would be appreciated if anyone has them handy) Either way, the doc comments of either the |
@squeek502 The UEFI spec mentions UTF-16 and UTF-8 but not WTF-8 or WTF-16. |
https://uefi.org/specs/UEFI/2.10/02_Overview.html?highlight=char16#data-types
|
https://www.ibm.com/docs/en/i/7.4?topic=unicode-ucs-2-its-relationship-utf-16
So should we implement UCS-2 specific functions in the Unicode module or stick with the UTF-16 methods? |
The situation with UEFI sounds like it is the same as the situation with Windows (arbitrary sequences of (WTF-16 is an informal name for potentially ill-formed UTF-16, or UTF-16 with potentially unpaired surrogates). See the motivation section of the WTF-8 spec: https://simonsapin.github.io/wtf-8/#motivation and the description of #19005 |
Yeah, well UEFI takes similarities from Windows so no surprise there.
Has anyone tried WTF-8/16 encodings on UEFI? I've only seen UTF-8/16. |
From the linked specs, UEFI uses UCS-2 which is essentially just sequences of WTF-16 is functionally equivalent to UCS-2 for our purposes, and WTF-8 is a superset of UTF-8 that allows the codepoints If you'd like to test whether or not WTF-16 is needed, the way to go would be to create a file with any value from |
Well, I can give it a try. I'm currently porting over @truemedian's UEFI stuff from their own fork so this PR will include file system operations. |
I've merged @truemedian's Zig branch for the uefi-rework into this one and added a couple of improvements along the way. |
3b55c17
to
23d4f64
Compare
44da3f7
to
17a8713
Compare
lib/std/os/uefi/bits.zig
Outdated
} | ||
|
||
/// Returns the time in nanoseconds since 1900-01-01 00:00:00. | ||
pub fn toEpochNanoseconds(self: Time) u128 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method is causing an integer overflow panic.
const std = @import("std");
pub fn main() !void {
const stat = try std.posix.fstat(std.fs.cwd().fd);
std.debug.print("{} ", .{stat.atim});
std.debug.print("{}\n", .{stat.atime()});
std.debug.print("{} ", .{stat.mtim});
std.debug.print("{}\n", .{stat.mtime()});
std.debug.print("{} ", .{stat.ctim});
std.debug.print("{}\n", .{stat.ctime()});
}
os.uefi.bits.Time{ .year = 2024, .month = 3, .day = 31, .hour = 0, .minute = 0, .second = 0, .nanosecond = 0, .timezone = 2047, .daylight = os.uefi.bits.Time.Time__struct_1282{ ._pad1 = 0, .in_daylight = false, .adjust_daylight = false } } 3920832000
os.uefi.bits.Time{ .year = 2024, .month = 3, .day = 31, .hour = 22, .minute = 28, .second = 8, .nanosecond = 0, .timezone = 2047, .daylight = os.uefi.bits.Time.Time__struct_1282{ ._pad1 = 0, .in_daylight = false, .adjust_daylight = false } } 3920912888
os.uefi.bits.Time{ .year = 1980, .month = 0, .day = 0, .hour = 0, .minute = 0, .second = 0, .nanosecond = 0, .timezone = 2047, .daylight = os.uefi.bits.Time.Time__struct_1282{ ._pad1 = 0, .in_daylight = false, .adjust_daylight = false } } panic: integer overflow 3186494919
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correction: this is with toEpochSeconds
and not toEpochNanoseconds
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My suspicion would be days += self.day - 1;
. Based on the doc comment for day
, it should be between 1 and 31, but you're passing a struct with .day = 0
, so something looks to be out of sync.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I am not sure why it is like that. My implementation didn't do this (the one currently in upstream). This comes from @truemedian's branch which I incorporated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Going further with this test program, I get this output:
os.uefi.bits.Time{ .year = 2024, .month = 3, .day = 31, .hour = 0, .minute = 0, .second = 0, .nanosecond = 0, .timezone = 2047, .daylight = os.uefi.bits.Time.Time__struct_1283{ ._pad1 = 0, .in_daylight = false, .adjust_daylight = false } } 3920832000
os.uefi.bits.Time{ .year = 2024, .month = 3, .day = 31, .hour = 22, .minute = 51, .second = 46, .nanosecond = 0, .timezone = 2047, .daylight = os.uefi.bits.Time.Time__struct_1283{ ._pad1 = 0, .in_daylight = false, .adjust_daylight = false } } 3920914306
os.uefi.bits.Time{ .year = 1980, .month = 0, .day = 0, .hour = 0, .minute = 0, .second = 0, .nanosecond = 0, .timezone = 2047, .daylight = os.uefi.bits.Time.Time__struct_1283{ ._pad1 = 0, .in_daylight = false, .adjust_daylight = false } }
Days in years: 29219
Days in months: 29219
panic: integer overflow 3186465173
Panicked during a panic. Aborting
const std = @import("std");
fn toEpochSeconds(self: std.os.uefi.bits.Time) u64 {
var year: u16 = 1900;
var days: u32 = 0;
while (year < self.year) : (year += 1) {
days += std.time.epoch.getDaysInYear(year);
}
std.debug.print("\nDays in years: {}\n", .{days});
var month: u8 = 1;
while (month < self.month) : (month += 1) {
const leap_kind: std.time.epoch.YearLeapKind = if (std.time.epoch.isLeapYear(self.year)) .leap else .not_leap;
days += std.time.epoch.getDaysInMonth(leap_kind, @enumFromInt(month));
}
std.debug.print("\nDays in months: {}\n", .{days});
days += self.day - 1;
std.debug.print("Days: {}\n", .{days});
const hours = @as(u32, self.hour) * std.time.s_per_hour;
std.debug.print("Hours: {}\n", .{hours});
const minutes = @as(u16, self.minute) * std.time.s_per_min;
std.debug.print("Minutes: {}\n", .{minutes});
const days_as_sec = days * std.time.s_per_day;
std.debug.print("Days as seconds: {}\n", .{days_as_sec});
return days_as_sec +
hours +
minutes +
self.second;
}
pub fn main() !void {
const stat = try std.posix.fstat(std.fs.cwd().fd);
std.debug.print("{} ", .{stat.atim});
std.debug.print("{}\n", .{stat.atime()});
std.debug.print("{} ", .{stat.mtim});
std.debug.print("{}\n", .{stat.mtime()});
std.debug.print("{} ", .{stat.ctim});
std.debug.print("{}\n", .{toEpochSeconds(stat.ctim)});
}
So I think @ianprime0509 is right on this one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@RossComputerGuy You don't even have to @intCast()
to convert from u64
to u128
:
pub fn main() void {
const v: u64 = std.math.maxInt(u64);
std.debug.print("{d}\n", .{ @as(u128, v) });
}
If you give a full stack trace I can help debug.
You may be able to avoid some integer casts if you refactor all your second and subsecond methods to be in terms of nanoseconds.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you give a full stack trace I can help debug.
Word of warning: we still cannot produce stack traces on UEFI, we're missing the information required to walk the stack backwards.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not even int casting. @nektro has tried helping me with this problem as well on Discord. I traced the issue to the @as(u128, v)
call with print calls.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, that's very strange. Is there a way to run behavior and stdlib tests on UEFI?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Kinda, however there are more important issues we need to get through first. Like zig actually being able to find itself in UEFI.
a9bc276
to
d877e8a
Compare
…ports and move to bits.zig
* don't even attempt stack unwinding on UEFI, no unwinding information is available yet. std.pdb: include the address *after* the last instruction as part of the function. This is required when using `@returnAddress` on a tailcall function. This is possible with panics.
d877e8a
to
ca28a79
Compare
d1723fc
to
4ec3b02
Compare
7b079e7
to
471889c
Compare
Some progress has been made. |
d7dfe19
to
b3a24d5
Compare
b3a24d5
to
6473f74
Compare
6473f74
to
ab302cb
Compare
draft status for > 30 days |
Just run:
zig build -Dtarget=x86_64-uefi -Dsingle-threaded --zig-lib-dir lib
This PR introduces several improvements for UEFI, so far:
std.process.ArgvIterator
supportstd.process.totalSystemMemory
supportPlanned:
std.process.EnvMap
support