feat(loader, kernel): impl part of loader and initialize kernel structure

This commit is contained in:
2026-04-11 09:42:09 +08:00
parent 1233ae9e9b
commit 34ccf69569
53 changed files with 1743 additions and 777 deletions

View File

@@ -0,0 +1,57 @@
const std = @import("std");
const Compress = std.compress.flate.Compress;
const Dir = std.Io.Dir;
const SIZE_ALIGN: usize = 0x200;
pub fn main(init: std.process.Init) !void {
const args = try init.minimal.args.toSlice(init.arena.allocator());
if (args.len != 4) {
std.debug.print("Usage: {s} <kernel_bin> <output_file> <assembly_file>\n", .{args[0]});
std.process.exit(1);
}
const kernel_bin_path = args[1];
const output_path = args[2];
const assembly_path = args[3];
std.debug.print("Compressing kernel: {s} -> {s}\n", .{kernel_bin_path, output_path});
const kernel_file = try Dir.cwd().openFile(init.io, kernel_bin_path, .{});
defer kernel_file.close(init.io);
const compressed_file = try Dir.cwd().createFile(init.io, output_path, .{ .truncate = true });
defer compressed_file.close(init.io);
var read_buffer: [4096]u8 = undefined;
var write_buffer: [4096]u8 = undefined;
var work_buffer: [std.compress.flate.max_window_len]u8 = undefined;
var writer = compressed_file.writer(init.io, &write_buffer);
var reader = kernel_file.reader(init.io, &[0]u8{});
var compressor = try Compress.init(&writer.interface, &work_buffer, .gzip, .best);
var compressor_writer = &compressor.writer;
var total_read: usize = 0;
while (true) {
const read_bytes = try reader.interface.readSliceShort(&read_buffer);
if (read_bytes == 0) break;
total_read += read_bytes;
try compressor_writer.writeAll(read_buffer[0..read_bytes]);
}
try compressor_writer.flush();
const aligned_size = (total_read + SIZE_ALIGN - 1) & ~(SIZE_ALIGN - 1);
var assembly_file = try Dir.cwd().createFile(init.io, assembly_path, .{ .truncate = true });
defer assembly_file.close(init.io);
var assembly_writer = assembly_file.writer(init.io, &[0]u8{});
try assembly_writer.interface.print(
\\/* Auto-generated compressed kernel data */
\\ .section .rodata.compressed,"a"
\\ .global compressed_kernel_data
\\compressed_kernel_data:
\\ .incbin "{s}"
\\compressed_end:
\\ .set compressed_kernel_size, compressed_end - compressed_kernel_data
\\ .set uncompressed_kernel_size, {d}
\\ .global compressed_kernel_size
\\ .global uncompressed_kernel_size
, .{output_path, aligned_size});
try assembly_writer.interface.flush();
std.debug.print("Uncompressed aligned size: 0x{x} bytes\n", .{aligned_size});
}

View File

@@ -0,0 +1,50 @@
const std = @import("std");
const Dir = std.Io.Dir;
const ALIGN_SIZE: usize = 4096;
pub fn main(init: std.process.Init) !void {
const args = try init.minimal.args.toSlice(init.arena.allocator());
if (args.len != 4) {
std.debug.print("Usage: {s} <header_file> <kcapsule_file> <output_file>\n", .{args[0]});
std.process.exit(1);
}
const header_path = args[1];
const kcapsule_path = args[2];
const output_path = args[3];
var image = try Dir.cwd().createFile(init.io, output_path, .{ .truncate = true });
defer image.close(init.io);
var image_buffer: [4096]u8 = undefined;
var w = image.writer(init.io, &image_buffer);
var read_buffer: [4096]u8 = undefined;
const header_file = try Dir.cwd().openFile(init.io, header_path, .{});
var r = header_file.reader(init.io, &[0]u8{});
var written: usize = 0;
while (true) {
const read_bytes = try r.interface.readSliceShort(&read_buffer);
if (read_bytes == 0) break;
try w.interface.writeAll(read_buffer[0..read_bytes]);
written += read_bytes;
}
header_file.close(init.io);
if (written % ALIGN_SIZE != 0) {
var padding_size = ALIGN_SIZE - (written % ALIGN_SIZE);
@memset(read_buffer[0..@min(padding_size, read_buffer.len)], 0);
while (padding_size > 0) {
const to_write = @min(padding_size, read_buffer.len);
try w.interface.writeAll(read_buffer[0..to_write]);
padding_size -= to_write;
}
}
const kcapsule_file = try Dir.cwd().openFile(init.io, kcapsule_path, .{});
r = kcapsule_file.reader(init.io, &[0]u8{});
while (true) {
const read_bytes = try r.interface.readSliceShort(&read_buffer);
if (read_bytes == 0) break;
try w.interface.writeAll(read_buffer[0..read_bytes]);
written += read_bytes;
}
kcapsule_file.close(init.io);
try w.interface.flush();
}

View File

@@ -0,0 +1,41 @@
const std = @import("std");
const Dir = std.Io.Dir;
const elfy = @import("elfy");
const mvzr = @import("mvzr");
pub fn main(init: std.process.Init) !void {
var gpa: std.heap.DebugAllocator(.{}) = .init;
const allocator = gpa.allocator();
defer _ = gpa.deinit();
const args = try init.minimal.args.toSlice(init.arena.allocator());
if (args.len != 5) {
std.debug.print("Usage: {s} <source_file> <pattern> <prefix> <output_file>\n", .{args[0]});
std.process.exit(1);
}
const input_path = args[1];
const pattern = args[2];
const prefix = args[3];
const output_path = args[4];
const re = mvzr.compile(pattern) orelse @panic("Failed to compile regex pattern");
var file = try Dir.cwd().createFile(init.io, output_path, .{ .truncate = true });
defer file.close(init.io);
var w = file.writer(init.io, &[0]u8{});
_ = try w.interface.write("/* Auto-generated symbol extract header */\n#pragma once\n");
var binary = try elfy.Elf.init(init.io, input_path, .ReadOnly, allocator);
defer binary.deinit();
var symbols = try binary.getIterator(elfy.ElfSymbol);
while (try symbols.next()) |symbol| {
const name = try binary.getSymbolName(symbol);
if (re.isMatch(name)) {
try w.interface.print("#define {s}{s} 0x{x}\n", .{prefix, name, symbol.getValue()});
}
}
try w.interface.flush();
}