Skip to content

Commit 05a8c47

Browse files
authored
Merge pull request #18962 from fifty-six/master
std.builtin.panic(uefi): usability improvements
2 parents d2c9a51 + 22d964f commit 05a8c47

File tree

1 file changed

+37
-23
lines changed

1 file changed

+37
-23
lines changed

lib/std/builtin.zig

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -799,41 +799,55 @@ pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace, ret_addr
799799
.uefi => {
800800
const uefi = std.os.uefi;
801801

802+
const Formatter = struct {
803+
pub fn fmt(exit_msg: []const u8, out: []u16) ![:0]u16 {
804+
var u8_buf: [256]u8 = undefined;
805+
const slice = try std.fmt.bufPrint(&u8_buf, "err: {s}\r\n", .{exit_msg});
806+
// We pass len - 1 because we need to add a null terminator after
807+
const len = try std.unicode.utf8ToUtf16Le(out[0 .. out.len - 1], slice);
808+
809+
out[len] = 0;
810+
811+
return out[0..len :0];
812+
}
813+
};
814+
802815
const ExitData = struct {
803-
pub fn create_exit_data(exit_msg: []const u8, exit_size: *usize) ![*:0]u16 {
816+
pub fn create_exit_data(exit_msg: [:0]u16, exit_size: *usize) ![*:0]u16 {
804817
// Need boot services for pool allocation
805818
if (uefi.system_table.boot_services == null) {
806819
return error.BootServicesUnavailable;
807820
}
808821

809-
// ExitData buffer must be allocated using boot_services.allocatePool
810-
var utf16: []u16 = try uefi.raw_pool_allocator.alloc(u16, 256);
811-
errdefer uefi.raw_pool_allocator.free(utf16);
812-
813-
if (exit_msg.len > 255) {
814-
return error.MessageTooLong;
815-
}
816-
817-
var fmt: [256]u8 = undefined;
818-
const slice = try std.fmt.bufPrint(&fmt, "\r\nerr: {s}\r\n", .{exit_msg});
819-
const len = try std.unicode.utf8ToUtf16Le(utf16, slice);
820-
821-
utf16[len] = 0;
822+
// ExitData buffer must be allocated using boot_services.allocatePool (spec: page 220)
823+
const exit_data: []u16 = try uefi.raw_pool_allocator.alloc(u16, exit_msg.len + 1);
822824

823-
exit_size.* = 256;
825+
@memcpy(exit_data[0 .. exit_msg.len + 1], exit_msg[0 .. exit_msg.len + 1]);
826+
exit_size.* = exit_msg.len + 1;
824827

825-
return @as([*:0]u16, @ptrCast(utf16.ptr));
828+
return @as([*:0]u16, @ptrCast(exit_data.ptr));
826829
}
827830
};
828831

829-
var exit_size: usize = 0;
830-
const exit_data = ExitData.create_exit_data(msg, &exit_size) catch null;
832+
var buf: [256]u16 = undefined;
833+
const utf16 = Formatter.fmt(msg, &buf) catch null;
831834

832-
if (exit_data) |data| {
833-
if (uefi.system_table.std_err) |out| {
834-
_ = out.setAttribute(uefi.protocol.SimpleTextOutput.red);
835-
_ = out.outputString(data);
836-
_ = out.setAttribute(uefi.protocol.SimpleTextOutput.white);
835+
var exit_size: usize = 0;
836+
const exit_data = if (utf16) |u|
837+
ExitData.create_exit_data(u, &exit_size) catch null
838+
else
839+
null;
840+
841+
if (utf16) |str| {
842+
// Output to both std_err and con_out, as std_err is easier
843+
// to read in stuff like QEMU at times, but, unlike con_out,
844+
// isn't visible on actual hardware if directly booted into
845+
inline for ([_]?*uefi.protocol.SimpleTextOutput{ uefi.system_table.std_err, uefi.system_table.con_out }) |o| {
846+
if (o) |out| {
847+
_ = out.setAttribute(uefi.protocol.SimpleTextOutput.red);
848+
_ = out.outputString(str);
849+
_ = out.setAttribute(uefi.protocol.SimpleTextOutput.white);
850+
}
837851
}
838852
}
839853

0 commit comments

Comments
 (0)