lumine
UEFI x86_64 bootloader for linux kernel images
src/Console.zig
1737 bytes raw
1const std = @import("std");
2const Io = std.Io;
3const uefi = std.os.uefi;
4
5const Console = @This();
6
7interface: Io.Writer,
8protocol: *uefi.protocol.SimpleTextOutput,
9
10pub fn init(buffer: []u8, protocol: *uefi.protocol.SimpleTextOutput) Console {
11 return .{
12 .protocol = protocol,
13 .interface = .{
14 .buffer = buffer,
15 .vtable = &.{ .drain = drainFn },
16 },
17 };
18}
19
20pub fn stdout(buffer: []u8) Console {
21 return .init(buffer, uefi.system_table.con_out.?);
22}
23
24pub fn stderr(buffer: []u8) Console {
25 return .init(buffer, uefi.system_table.std_err.?);
26}
27
28pub fn write(self: *Console, data: []const u8) !void {
29 var buffer: [64:0]u16 = @splat(undefined);
30 var buflen: usize = 0;
31 for (data) |b| {
32 buffer[buflen] = @intCast(b);
33 buflen += 1;
34 if (buflen == buffer.len) {
35 _ = self.protocol.outputString(&buffer) catch unreachable;
36 buflen = 0;
37 }
38 }
39 if (buflen > 0) {
40 buffer[buflen] = 0;
41 _ = self.protocol.outputString(buffer[0..buflen :0]) catch unreachable;
42 }
43}
44
45fn drainFn(io_w: *Io.Writer, data: []const []const u8, splat: usize) Io.Writer.Error!usize {
46 const self: *Console = @fieldParentPtr("interface", io_w);
47
48 {
49 const buf = io_w.buffered();
50 if (buf.len > 0) {
51 try self.write(buf);
52 _ = io_w.consumeAll();
53 }
54 }
55
56 var written: usize = 0;
57
58 if (data.len > 1) {
59 for (data[0 .. data.len - 1]) |buf| {
60 try self.write(buf);
61 written += buf.len;
62 }
63 }
64
65 const buf = data[data.len - 1];
66 for (0..splat) |_| {
67 try self.write(buf);
68 written += buf.len;
69 }
70
71 return written;
72}