lumine
UEFI x86_64 bootloader for linux kernel images
src/linux/Kernel.zig
2078 bytes raw
1const std = @import("std");
2const uefi = std.os.uefi;
3
4const luefi = @import("../luefi.zig");
5const Path = @import("../Config.zig").Path;
6
7const log = std.log.scoped(.linux);
8
9const Kernel = @This();
10
11kernel_pages: usize,
12kernel_buf: []align(4096) u8,
13
14pub fn load(path: Path) !Kernel {
15 const boot_svc = uefi.system_table.boot_services.?;
16
17 log.info("loading kernel from {f}", .{path});
18 const file = try luefi.fileOpen(path);
19 defer file.close() catch unreachable;
20
21 const size = try luefi.fileSize(file);
22 const page_count = try std.math.divCeil(usize, size, 4096);
23
24 const pages = try boot_svc.allocatePages(.any, .loader_data, page_count);
25 errdefer boot_svc.freePages(pages) catch unreachable;
26
27 const slice = @as([*]align(4096) u8, @ptrCast(pages))[0..size];
28 try luefi.fileReadSlice(file, slice);
29
30 return .{
31 .kernel_buf = slice,
32 .kernel_pages = size,
33 };
34}
35
36pub fn deinit(self: Kernel) void {
37 const boot_svc = uefi.system_table.boot_services.?;
38 const pages = @as([*]align(4096) [4096]u8, @ptrCast(self.kernel_buf));
39 boot_svc.freePages(pages[0..self.kernel_pages]) catch unreachable;
40}
41
42pub fn start(self: Kernel, cmdline: []const u8) !void {
43 const boot_svc = uefi.system_table.boot_services.?;
44 const allocator = uefi.pool_allocator;
45
46 const cmdline_utf16 = try std.unicode.utf8ToUtf16LeAllocZ(allocator, cmdline);
47 defer allocator.free(cmdline_utf16);
48
49 const img_handle = try boot_svc.loadImage(false, uefi.handle, .{ .buffer = self.kernel_buf });
50 defer _ = boot_svc.unloadImage(img_handle) catch unreachable;
51
52 const loaded_img = try boot_svc.openProtocol(uefi.protocol.LoadedImage, img_handle, .{
53 .get_protocol = .{ .agent = uefi.handle },
54 }) orelse unreachable;
55
56 loaded_img.load_options = @ptrCast(cmdline_utf16);
57 loaded_img.load_options_size = @intCast(cmdline_utf16.len * @sizeOf(u16));
58
59 const exit_data = try boot_svc.startImage(img_handle);
60 log.err("kernel image exited with exit code {t}", .{exit_data.code});
61
62 return error.KernelExited;
63}