const std = @import("std"); const uefi = std.os.uefi; const unicode = std.unicode; const SimpleTextOutput = uefi.protocol.SimpleTextOutput; pub const UefiConsole = struct { console_out: ?*SimpleTextOutput = null, pub fn init(system_table: *uefi.tables.SystemTable) UefiConsole { var console = UefiConsole{}; var con_out = system_table.con_out orelse return console; con_out.clearScreen() catch return console; con_out.setCursorPosition(0, 0) catch return console; console.console_out = con_out; UefiWriter.UEFI_WRITER_VTABLE = .{ .drain = UefiWriter.drain, }; return console; } pub const UefiWriter = struct { console: *UefiConsole, interface: std.Io.Writer, var UEFI_WRITER_VTABLE: std.io.Writer.VTable = .{ .drain = undefined, }; pub fn drain(ptr: *std.Io.Writer, buf: []const []const u8, splat: usize) !usize { _ = splat; const self: *UefiWriter = @fieldParentPtr("interface", ptr); if (self.console.console_out) |out| { var written: usize = 0; for (buf) |b| { var start: usize = 0; var ucs2_buf = [_]u16{0} ** 65; while (start < buf.len) { const len = unicode.utf8ToUtf16Le(ucs2_buf[0..64], b[start..@min(start + 64, b.len)]) catch { return error.WriteFailed; }; ucs2_buf[len] = 0; _ = out.outputString(@ptrCast(&ucs2_buf)) catch { return error.WriteFailed; }; start += len; } written += b.len; } return written; } else { return 0; } } }; pub fn writer(self: *UefiConsole) UefiWriter { const w = UefiWriter{ .console = self, .interface = .{ .vtable = @call(.never_inline, getVtable, .{}), .buffer = &[0]u8{}, .end = 0 }, }; return w; } fn getVtable() *const std.Io.Writer.VTable { return &UefiWriter.UEFI_WRITER_VTABLE; } }; pub var uc: UefiConsole = undefined; pub fn initUefiConsole(system_table: *uefi.tables.SystemTable) void { uc = UefiConsole.init(system_table); } pub fn info(comptime fmt: []const u8, args: anytype) void { var w = uc.writer(); w.interface.print(fmt, args) catch {}; }