λ

lumine

UEFI x86_64 bootloader for linux kernel images

settings

src/boot/linux/Kernel.zig

1483 bytes raw

const std = @import("std");
const uefi = std.os.uefi;
const builtin = @import("builtin");

const Path = @import("../../Config.zig").Path;
const luefi = @import("../../luefi.zig");
const Chainload = @import("../Chainload.zig");

const log = std.log.scoped(.linux);

const Kernel = @This();

img_buffer: []align(4096) u8,
img_pages: usize,

pub fn load(path: Path) !Kernel {
    log.info("loading kernel {f}", .{path});

    const buffer, const pages = try luefi.pathReadAlloc(path);
    return .{ .img_buffer = buffer, .img_pages = pages };
}

pub fn deinit(self: Kernel) void {
    luefi.freePages(self.img_buffer, self.img_pages);
}

pub fn start(self: Kernel, cmdline: []const u8) !uefi.Status {
    const allocator = uefi.pool_allocator;
    const boot_svc = uefi.system_table.boot_services.?;

    if (builtin.target.cpu.arch == .x86_64) {
        const cmdline_utf16 = try std.unicode.utf8ToUtf16LeAllocZ(allocator, cmdline);
        defer allocator.free(cmdline_utf16);

        const handle, const loaded = try luefi.loadImage(self.img_buffer);
        defer luefi.unloadImage(handle);

        loaded.load_options = @ptrCast(cmdline_utf16);
        loaded.load_options_size = @intCast(cmdline_utf16.len * @sizeOf(u16));

        const exit_data = try boot_svc.startImage(handle);
        try exit_data.code.err();
        return .aborted;
    } else {
        log.err("this architecture doesnt support linux boot", .{});
        return error.UnsupportedArchitecture;
    }
}