authorgravatar for ybham6@gmail.comYusuf Bham <ybham6@gmail.com> 2024-02-16 14:08:23-05:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2024-07-22 16:23:10+03:00
log22d964fe22f2e154640f71ef52c1ed552be518bd
tree76b6ec9b97c5bc5a72fa8a247e94d57ad713f169
parentc16aeda8a66451e77c0113b5d160413f97fc72b0

std.builtin.panic(uefi): stack allocate panic message

In the case that the allocator is unavailable (OOM, etc.), we can possibly still output the panic message - so now we stack allocate the message and copy it to the exit data for passing to boot services.

1 files changed, 28 insertions(+), 19 deletions(-)

lib/std/builtin.zig+28-19
...@@ -799,44 +799,53 @@ pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace, ret_addr...@@ -799,44 +799,53 @@ pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace, ret_addr
799 .uefi => {799 .uefi => {
800 const uefi = std.os.uefi;800 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
802 const ExitData = struct {815 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 {
804 // Need boot services for pool allocation817 // Need boot services for pool allocation
805 if (uefi.system_table.boot_services == null) {818 if (uefi.system_table.boot_services == null) {
806 return error.BootServicesUnavailable;819 return error.BootServicesUnavailable;
807 }820 }
808821
809 // ExitData buffer must be allocated using boot_services.allocatePool822 // ExitData buffer must be allocated using boot_services.allocatePool (spec: page 220)
810 var utf16: []u16 = try uefi.raw_pool_allocator.alloc(u16, 256);823 const exit_data: []u16 = try uefi.raw_pool_allocator.alloc(u16, exit_msg.len + 1);
811 errdefer uefi.raw_pool_allocator.free(utf16);
812824
813 if (exit_msg.len > 255) {825 @memcpy(exit_data[0 .. exit_msg.len + 1], exit_msg[0 .. exit_msg.len + 1]);
814 return error.MessageTooLong;826 exit_size.* = exit_msg.len + 1;
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;
822827
823 exit_size.* = 256;828 return @as([*:0]u16, @ptrCast(exit_data.ptr));
824
825 return @as([*:0]u16, @ptrCast(utf16.ptr));
826 }829 }
827 };830 };
828831
832 var buf: [256]u16 = undefined;
833 const utf16 = Formatter.fmt(msg, &buf) catch null;
834
829 var exit_size: usize = 0;835 var exit_size: usize = 0;
830 const exit_data = ExitData.create_exit_data(msg, &exit_size) catch null;836 const exit_data = if (utf16) |u|
837 ExitData.create_exit_data(u, &exit_size) catch null
838 else
839 null;
831840
832 if (exit_data) |data| {841 if (utf16) |str| {
833 // Output to both std_err and con_out, as std_err is easier842 // Output to both std_err and con_out, as std_err is easier
834 // to read in stuff like QEMU at times, but, unlike con_out,843 // to read in stuff like QEMU at times, but, unlike con_out,
835 // isn't visible on actual hardware if directly booted into844 // isn't visible on actual hardware if directly booted into
836 inline for ([_]?*uefi.protocol.SimpleTextOutput{ uefi.system_table.std_err, uefi.system_table.con_out }) |o| {845 inline for ([_]?*uefi.protocol.SimpleTextOutput{ uefi.system_table.std_err, uefi.system_table.con_out }) |o| {
837 if (o) |out| {846 if (o) |out| {
838 _ = out.setAttribute(uefi.protocol.SimpleTextOutput.red);847 _ = out.setAttribute(uefi.protocol.SimpleTextOutput.red);
839 _ = out.outputString(data);848 _ = out.outputString(str);
840 _ = out.setAttribute(uefi.protocol.SimpleTextOutput.white);849 _ = out.setAttribute(uefi.protocol.SimpleTextOutput.white);
841 }850 }
842 }851 }