lumine
UEFI x86_64 bootloader for linux kernel images
src/main.zig
2470 bytes raw
1const std = @import("std");
2const uefi = std.os.uefi;
3const log = std.log;
4const Io = std.Io;
5
6const Config = @import("./Config.zig");
7const Console = @import("./Console.zig");
8const linux = @import("./linux.zig");
9const luefi = @import("./luefi.zig");
10
11const config_paths: []const Config.Path = &.{
12 .{ .boot = "/lumine.zon" },
13 .{ .boot = "/lumine/lumine.zon" },
14 .{ .boot = "/lumine/config.zon" },
15};
16
17pub fn bmain() !void {
18 const allocator = uefi.pool_allocator;
19
20 const config: Config = try config: {
21 var file = reader: {
22 for (config_paths) |path| {
23 break :reader luefi.fileOpen(path) catch continue;
24 }
25
26 log.err("failed to detect config, tried paths:", .{});
27 for (config_paths) |path| log.err("\t{f}", .{path});
28 return error.NoConfig;
29 };
30 defer file.close() catch unreachable;
31
32 const source = try allocator.allocSentinel(u8, try luefi.fileSize(file), 0);
33 defer allocator.free(source);
34
35 try luefi.fileReadSlice(file, source);
36
37 break :config std.zon.parse.fromSliceAlloc(Config, allocator, source, null, .{});
38 };
39 defer std.zon.parse.free(allocator, config);
40
41 switch (config.boot) {
42 .linux => |linux_conf| {
43 const kernel: linux.Kernel = try .load(linux_conf.kernel_path);
44 defer kernel.deinit();
45
46 try kernel.start(linux_conf.kernel_cmdline);
47 },
48 }
49}
50
51pub fn main() uefi.Status {
52 bmain() catch |err| {
53 log.err("unrecoverable error in bmain: {}", .{err});
54 return .aborted;
55 };
56
57 log.err("bootloader exited successfully, this shouldnt happen", .{});
58 while (true) std.atomic.spinLoopHint();
59}
60
61pub fn logFn(
62 comptime level: log.Level,
63 comptime scope: @EnumLiteral(),
64 comptime format: []const u8,
65 args: anytype,
66) void {
67 // stderr should be equivalent to stdout?
68 // but i dont see logs on my hardware if i use stderr
69 var stderr_buf: [512]u8 = undefined;
70 var stderr: Console = .stdout(&stderr_buf);
71 stderr.interface.print("{t}({}): ", .{ level, scope }) catch return;
72 stderr.interface.print(format ++ "\r\n", args) catch return;
73 stderr.interface.flush() catch return;
74}
75
76pub fn panicFn(msg: []const u8, _: ?usize) noreturn {
77 logFn(.err, .panic, "{s}", .{msg});
78 @trap();
79}
80
81pub const panic = std.debug.FullPanic(panicFn);
82pub const std_options: std.Options = .{ .logFn = logFn };