const std = @import("std"); const uefi = std.os.uefi; const luefi = @import("../luefi.zig"); const Path = @import("../Config.zig").Path; const log = std.log.scoped(.linux); const Kernel = @This(); kernel_pages: usize, kernel_buf: []align(4096) u8, pub fn load(path: Path) !Kernel { const boot_svc = uefi.system_table.boot_services.?; log.info("loading kernel from {f}", .{path}); const file = try luefi.fileOpen(path); defer file.close() catch unreachable; const size = try luefi.fileSize(file); const page_count = try std.math.divCeil(usize, size, 4096); const pages = try boot_svc.allocatePages(.any, .loader_data, page_count); errdefer boot_svc.freePages(pages) catch unreachable; const slice = @as([*]align(4096) u8, @ptrCast(pages))[0..size]; try luefi.fileReadSlice(file, slice); return .{ .kernel_buf = slice, .kernel_pages = size, }; } pub fn deinit(self: Kernel) void { const boot_svc = uefi.system_table.boot_services.?; const pages = @as([*]align(4096) [4096]u8, @ptrCast(self.kernel_buf)); boot_svc.freePages(pages[0..self.kernel_pages]) catch unreachable; } pub fn start(self: Kernel, cmdline: []const u8) !void { const boot_svc = uefi.system_table.boot_services.?; const allocator = uefi.pool_allocator; const cmdline_utf16 = try std.unicode.utf8ToUtf16LeAllocZ(allocator, cmdline); defer allocator.free(cmdline_utf16); const img_handle = try boot_svc.loadImage(false, uefi.handle, .{ .buffer = self.kernel_buf }); defer _ = boot_svc.unloadImage(img_handle) catch unreachable; const loaded_img = try boot_svc.openProtocol(uefi.protocol.LoadedImage, img_handle, .{ .get_protocol = .{ .agent = uefi.handle }, }) orelse unreachable; loaded_img.load_options = @ptrCast(cmdline_utf16); loaded_img.load_options_size = @intCast(cmdline_utf16.len * @sizeOf(u16)); const exit_data = try boot_svc.startImage(img_handle); log.err("kernel image exited with exit code {t}", .{exit_data.code}); return error.KernelExited; }