λ

lumine

UEFI x86_64 bootloader for linux kernel images

settings

src/boot/linux/Initrd.zig

2540 bytes raw

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

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

const Initrd = @This();

protocol: LoadFile2 = .{},

buffer: []align(4096) u8,
pages: usize,

pub fn load(path: Path) !*Initrd {
    const buffer, const pages = blk: {
        const file = try luefi.fileOpen(path);
        defer file.close() catch unreachable;

        break :blk try luefi.fileReadAlloc(file);
    };
    errdefer luefi.freePages(buffer, pages);

    const self = try uefi.pool_allocator.create(Initrd);
    self.* = .{ .buffer = buffer, .pages = pages };

    try luefi.installProtocols(.{ &device_path, &self.protocol });

    return self;
}

pub fn deinit(self: *Initrd) void {
    luefi.freePages(self.buffer, self.pages);
    uefi.pool_allocator.destroy(self);
}

pub const LoadFile2 = extern struct {
    loadFile: *const @TypeOf(impl) = impl,

    pub fn impl(
        protocol: *LoadFile2,
        _: *uefi.protocol.DevicePath,
        _: bool,
        buf_size: *usize,
        buf_out: ?[*]u8,
    ) callconv(uefi.cc) uefi.Status {
        const initrd: *Initrd = @fieldParentPtr("protocol", protocol);

        if (buf_out == null or buf_size.* < initrd.buffer.len) {
            buf_size.* = initrd.buffer.len;
            return .buffer_too_small;
        }

        @memcpy(buf_out.?, initrd.buffer);

        return .success;
    }

    pub const guid: uefi.Guid = .{
        .time_low = 0x4006c0c1,
        .time_mid = 0xfcb3,
        .time_high_and_version = 0x403e,
        .clock_seq_high_and_reserved = 0x99,
        .clock_seq_low = 0x6d,
        .node = [_]u8{ 0x4a, 0x6c, 0x87, 0x24, 0xe0, 0x6d },
    };
};

pub var device_path = struct {
    vendor: uefi.DevicePath.Media.VendorDevicePath,
    end: uefi.DevicePath.End.EndEntireDevicePath,

    pub const guid = uefi.protocol.DevicePath.guid;
}{
    .vendor = uefi.DevicePath.Media.VendorDevicePath{
        .type = .media,
        .subtype = .vendor,
        .length = @sizeOf(uefi.DevicePath.Media.VendorDevicePath),
        .guid = .{
            .time_low = 0x5568e427,
            .time_mid = 0x68fc,
            .time_high_and_version = 0x4f3d,
            .clock_seq_high_and_reserved = 0xac,
            .clock_seq_low = 0x74,
            .node = [_]u8{ 0xca, 0x55, 0x52, 0x31, 0xcc, 0x68 },
        },
    },
    .end = uefi.DevicePath.End.EndEntireDevicePath{
        .type = .end,
        .subtype = .end_entire,
        .length = @sizeOf(uefi.DevicePath.End.EndEntireDevicePath),
    },
};