diff --git a/res/lumine.zon b/res/lumine.zon index cc3d07363bc1746edddff47b57bc9a9f1f260d59..41e24a873fb13a333003729ebcc6601a97b4361a 100644 --- a/res/lumine.zon +++ b/res/lumine.zon @@ -2,7 +2,9 @@ .{ .boot = .{ .linux = .{ .kernel_path = .{ .boot = "/linux/vmlinuz" }, - .initrd_path = .{ .boot = "/linux/initrd" }, + .initrd_paths = .{ + .{ .boot = "/linux/initrd" }, + }, .kernel_cmdline = "console=ttyS0", }, }, diff --git a/src/Config.zig b/src/Config.zig index 374059b0757ece64fae0b068bf666643746bd07a..8a8621d87120818847817f3b187d64b1fc172f67 100644 --- a/src/Config.zig +++ b/src/Config.zig @@ -18,7 +18,7 @@ chainload: Path, linux: struct { kernel_path: Path, kernel_cmdline: []const u8 = &.{}, - initrd_path: Path, + initrd_paths: []const Path = &.{}, }, }; diff --git a/src/boot/linux/Initrd.zig b/src/boot/linux/Initrd.zig index 8a5707cb51a64df1da28fab1b21978c2ef94f0de..f2e0fc75d1b06682fae29e34036d9d9f20e55a8a 100644 --- a/src/boot/linux/Initrd.zig +++ b/src/boot/linux/Initrd.zig @@ -1,5 +1,6 @@ const std = @import("std"); const uefi = std.os.uefi; +const log = std.log; const luefi = @import("../../luefi.zig"); const Path = @import("../../Config.zig").Path; @@ -8,20 +9,52 @@ const Initrd = @This(); protocol: LoadFile2 = .{}, -buffer: []align(4096) u8, -pages: usize, +initrd_buf: []align(4096) u8, +initrd_pages: usize, + +pub fn load(paths: []const Path) !*Initrd { + const File = struct { file: *uefi.protocol.File, size: usize }; + + var files: std.ArrayList(File) = try .initCapacity(uefi.pool_allocator, paths.len); + defer files.deinit(uefi.pool_allocator); + + defer for (files.items) |f| f.file.close() catch unreachable; -pub fn load(path: Path) !*Initrd { - const buffer, const pages = blk: { + var total_size: usize = 0; + for (paths) |path| { + log.info("loading initrd {f}", .{path}); const file = try luefi.fileOpen(path); - defer file.close() catch unreachable; + errdefer file.close() catch unreachable; + + const size = try luefi.fileSize(file); + try files.append(uefi.pool_allocator, .{ .file = file, .size = size }); + + total_size += size; + } + + const pages_count = try std.math.divCeil(usize, total_size, 4096); + + const boot_svc = uefi.system_table.boot_services.?; + + const initrd_pages = try boot_svc.allocatePages(.any, .loader_data, pages_count); + errdefer boot_svc.freePages(initrd_pages) catch unreachable; - break :blk try luefi.fileReadAlloc(file); - }; - errdefer luefi.freePages(buffer, pages); + const initrd_buf_ptr: [*]align(4096) u8 = @ptrCast(initrd_pages); + const initrd_buf = initrd_buf_ptr[0..total_size]; + + var start_pos: usize = 0; + for (files.items) |file| { + const slice = initrd_buf[start_pos .. start_pos + file.size]; + try luefi.fileReadSlice(file.file, slice); + start_pos += file.size; + } const self = try uefi.pool_allocator.create(Initrd); - self.* = .{ .buffer = buffer, .pages = pages }; + + self.* = .{ + .initrd_buf = initrd_buf, + .initrd_pages = pages_count, + }; try luefi.installProtocols(.{ &device_path, &self.protocol }); @@ -29,7 +62,7 @@ return self; } pub fn deinit(self: *Initrd) void { - luefi.freePages(self.buffer, self.pages); + luefi.freePages(self.initrd_buf, self.initrd_pages); uefi.pool_allocator.destroy(self); } @@ -45,12 +78,12 @@ 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; + if (buf_out == null or buf_size.* < initrd.initrd_buf.len) { + buf_size.* = initrd.initrd_buf.len; return .buffer_too_small; } - @memcpy(buf_out.?, initrd.buffer); + @memcpy(buf_out.?, initrd.initrd_buf); return .success; } diff --git a/src/boot/linux/Kernel.zig b/src/boot/linux/Kernel.zig index 3b54c20e1c0099005e5039119e43dabcdf91b252..5401c04123dbd3cb37b6b8151e1c1bcd28be4184 100644 --- a/src/boot/linux/Kernel.zig +++ b/src/boot/linux/Kernel.zig @@ -1,5 +1,6 @@ const std = @import("std"); const uefi = std.os.uefi; +const log = std.log; const Chainload = @import("../Chainload.zig"); @@ -11,6 +12,7 @@ chainload: Chainload, pub fn load(path: Path) !Kernel { + log.info("loading kernel {f}", .{path}); return .{ .chainload = try .load(path) }; } diff --git a/src/main.zig b/src/main.zig index 638f39ad577a17641526348cff460cdf0dc5ee15..d736ad92c5ca902cae0f1d35f6aa989d1ecfd67d 100644 --- a/src/main.zig +++ b/src/main.zig @@ -49,12 +49,10 @@ return chainload.start(); }, .linux => |linux_conf| { - log.info("loading kernel {f}", .{linux_conf.kernel_path}); const kernel: linux.Kernel = try .load(linux_conf.kernel_path); defer kernel.deinit(); - log.info("loading initrd {f}", .{linux_conf.initrd_path}); - const initrd: *linux.Initrd = try .load(linux_conf.initrd_path); + const initrd: *linux.Initrd = try .load(linux_conf.initrd_paths); defer initrd.deinit(); return kernel.start(linux_conf.kernel_cmdline);