Run unit tests under the building architecture
This also removed the need for `@intCase()` Also move the making directories and copying to a script to the build is simpler. Install qemu earler Added chmod +x Fixed copy elf Added missing switch for qemu binary Spelling Make makeiso.sh executable No longer chmod makeiso.sh Use the cache root to set the output directory
This commit is contained in:
parent
a095fd3947
commit
0746048a00
8 changed files with 114 additions and 84 deletions
8
.github/workflows/main.yml
vendored
8
.github/workflows/main.yml
vendored
|
@ -19,14 +19,14 @@ jobs:
|
||||||
wget $(curl -s 'https://ziglang.org/download/index.json' | python3 -c "import sys, json; print(json.load(sys.stdin)['master']['x86_64-linux']['tarball'])")
|
wget $(curl -s 'https://ziglang.org/download/index.json' | python3 -c "import sys, json; print(json.load(sys.stdin)['master']['x86_64-linux']['tarball'])")
|
||||||
sudo apt-get install mtools
|
sudo apt-get install mtools
|
||||||
tar -xvf zig*
|
tar -xvf zig*
|
||||||
- name: Build kernel
|
|
||||||
run: zig*/zig build ${{ matrix.build_mode }}
|
|
||||||
- name: Run unit tests
|
|
||||||
run: zig*/zig build test ${{ matrix.build_mode }}
|
|
||||||
- name: Install qemu
|
- name: Install qemu
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install qemu qemu-system --fix-missing
|
sudo apt-get install qemu qemu-system --fix-missing
|
||||||
|
- name: Build kernel
|
||||||
|
run: zig*/zig build ${{ matrix.build_mode }}
|
||||||
|
- name: Run unit tests
|
||||||
|
run: zig*/zig build test ${{ matrix.build_mode }}
|
||||||
- name: Run runtime tests
|
- name: Run runtime tests
|
||||||
run: zig*/zig build test -Drt-test=true ${{ matrix.build_mode }}
|
run: zig*/zig build test -Drt-test=true ${{ matrix.build_mode }}
|
||||||
- name: Check formatting
|
- name: Check formatting
|
||||||
|
|
123
build.zig
123
build.zig
|
@ -9,90 +9,49 @@ const Mode = builtin.Mode;
|
||||||
|
|
||||||
pub fn build(b: *Builder) !void {
|
pub fn build(b: *Builder) !void {
|
||||||
const target = Target{
|
const target = Target{
|
||||||
.Cross = std.build.CrossTarget{
|
.Cross = Target.Cross{
|
||||||
.arch = .i386,
|
.arch = .i386,
|
||||||
.os = .freestanding,
|
.os = .freestanding,
|
||||||
.abi = .gnu,
|
.abi = .gnu,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const test_target = Target{
|
||||||
|
.Cross = Target.Cross{
|
||||||
|
.arch = .i386,
|
||||||
|
.os = .linux,
|
||||||
|
.abi = .gnu,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
const target_str = switch (target.getArch()) {
|
const target_str = switch (target.getArch()) {
|
||||||
.i386 => "x86",
|
.i386 => "x86",
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const main_src = "src/kernel/kmain.zig";
|
||||||
|
const constants_path = try fs.path.join(b.allocator, &[_][]const u8{ "src/kernel/arch", target_str, "constants.zig" });
|
||||||
|
|
||||||
const build_mode = b.standardReleaseOptions();
|
const build_mode = b.standardReleaseOptions();
|
||||||
const rt_test = b.option(bool, "rt-test", "enable/disable runtime testing") orelse false;
|
const rt_test = b.option(bool, "rt-test", "enable/disable runtime testing") orelse false;
|
||||||
|
|
||||||
const main_src = "src/kernel/kmain.zig";
|
|
||||||
|
|
||||||
const exec = b.addExecutable("pluto", main_src);
|
const exec = b.addExecutable("pluto", main_src);
|
||||||
const constants_path = try fs.path.join(b.allocator, &[_][]const u8{ "src/kernel/arch", target_str, "constants.zig" });
|
|
||||||
exec.addPackagePath("constants", constants_path);
|
exec.addPackagePath("constants", constants_path);
|
||||||
exec.setBuildMode(build_mode);
|
exec.setOutputDir(b.cache_root);
|
||||||
exec.addBuildOption(bool, "rt_test", rt_test);
|
exec.addBuildOption(bool, "rt_test", rt_test);
|
||||||
|
exec.setBuildMode(build_mode);
|
||||||
exec.setLinkerScriptPath("link.ld");
|
exec.setLinkerScriptPath("link.ld");
|
||||||
exec.setTheTarget(target);
|
exec.setTheTarget(target);
|
||||||
|
|
||||||
const iso_path = try fs.path.join(b.allocator, &[_][]const u8{ b.exe_dir, "pluto.iso" });
|
const output_iso = try fs.path.join(b.allocator, &[_][]const u8{ b.exe_dir, "pluto.iso" });
|
||||||
const grub_build_path = try fs.path.join(b.allocator, &[_][]const u8{ b.exe_dir, "iso", "boot" });
|
|
||||||
const iso_dir_path = try fs.path.join(b.allocator, &[_][]const u8{ b.exe_dir, "iso" });
|
const iso_dir_path = try fs.path.join(b.allocator, &[_][]const u8{ b.exe_dir, "iso" });
|
||||||
|
const boot_path = try fs.path.join(b.allocator, &[_][]const u8{ b.exe_dir, "iso", "boot" });
|
||||||
const mkdir_cmd = b.addSystemCommand(&[_][]const u8{ "mkdir", "-p", fs.path.dirname(grub_build_path).? });
|
|
||||||
|
|
||||||
const grub_cmd = b.addSystemCommand(&[_][]const u8{ "cp", "-r", "grub", grub_build_path });
|
|
||||||
grub_cmd.step.dependOn(&mkdir_cmd.step);
|
|
||||||
|
|
||||||
const cp_elf_cmd = b.addSystemCommand(&[_][]const u8{"cp"});
|
|
||||||
const elf_path = try fs.path.join(b.allocator, &[_][]const u8{ grub_build_path, "pluto.elf" });
|
|
||||||
cp_elf_cmd.addArtifactArg(exec);
|
|
||||||
cp_elf_cmd.addArg(elf_path);
|
|
||||||
cp_elf_cmd.step.dependOn(&grub_cmd.step);
|
|
||||||
cp_elf_cmd.step.dependOn(&exec.step);
|
|
||||||
|
|
||||||
const modules_path = try fs.path.join(b.allocator, &[_][]const u8{ b.exe_dir, "iso", "modules" });
|
const modules_path = try fs.path.join(b.allocator, &[_][]const u8{ b.exe_dir, "iso", "modules" });
|
||||||
const mkdir_modules_cmd = b.addSystemCommand(&[_][]const u8{ "mkdir", "-p", modules_path });
|
|
||||||
|
|
||||||
const map_file_path = try fs.path.join(b.allocator, &[_][]const u8{ modules_path, "kernel.map" });
|
const make_iso = b.addSystemCommand(&[_][]const u8{ "./makeiso.sh", boot_path, modules_path, iso_dir_path, exec.getOutputPath(), output_iso });
|
||||||
const map_file_cmd = b.addSystemCommand(&[_][]const u8{ "./make_map.sh", elf_path, map_file_path });
|
|
||||||
map_file_cmd.step.dependOn(&cp_elf_cmd.step);
|
|
||||||
map_file_cmd.step.dependOn(&mkdir_modules_cmd.step);
|
|
||||||
|
|
||||||
const iso_cmd = b.addSystemCommand(&[_][]const u8{ "grub-mkrescue", "-o", iso_path, iso_dir_path });
|
make_iso.step.dependOn(&exec.step);
|
||||||
iso_cmd.step.dependOn(&map_file_cmd.step);
|
b.default_step.dependOn(&make_iso.step);
|
||||||
b.default_step.dependOn(&iso_cmd.step);
|
|
||||||
|
|
||||||
const run_step = b.step("run", "Run with qemu");
|
|
||||||
const run_debug_step = b.step("debug-run", "Run with qemu and wait for a gdb connection");
|
|
||||||
|
|
||||||
const qemu_bin = switch (target.getArch()) {
|
|
||||||
.i386 => "qemu-system-i386",
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
const qemu_args = &[_][]const u8{
|
|
||||||
qemu_bin,
|
|
||||||
"-cdrom",
|
|
||||||
iso_path,
|
|
||||||
"-boot",
|
|
||||||
"d",
|
|
||||||
"-serial",
|
|
||||||
"stdio",
|
|
||||||
};
|
|
||||||
const qemu_cmd = b.addSystemCommand(qemu_args);
|
|
||||||
const qemu_debug_cmd = b.addSystemCommand(qemu_args);
|
|
||||||
qemu_debug_cmd.addArgs(&[_][]const u8{ "-s", "-S" });
|
|
||||||
|
|
||||||
if (rt_test) {
|
|
||||||
const qemu_rt_test_args = &[_][]const u8{ "-display", "none" };
|
|
||||||
qemu_cmd.addArgs(qemu_rt_test_args);
|
|
||||||
qemu_debug_cmd.addArgs(qemu_rt_test_args);
|
|
||||||
}
|
|
||||||
|
|
||||||
qemu_cmd.step.dependOn(&iso_cmd.step);
|
|
||||||
qemu_debug_cmd.step.dependOn(&iso_cmd.step);
|
|
||||||
|
|
||||||
run_step.dependOn(&qemu_cmd.step);
|
|
||||||
run_debug_step.dependOn(&qemu_debug_cmd.step);
|
|
||||||
|
|
||||||
const test_step = b.step("test", "Run tests");
|
const test_step = b.step("test", "Run tests");
|
||||||
if (rt_test) {
|
if (rt_test) {
|
||||||
|
@ -108,11 +67,53 @@ pub fn build(b: *Builder) !void {
|
||||||
unit_tests.addBuildOption(bool, "rt_test", rt_test);
|
unit_tests.addBuildOption(bool, "rt_test", rt_test);
|
||||||
unit_tests.addBuildOption([]const u8, "mock_path", mock_path);
|
unit_tests.addBuildOption([]const u8, "mock_path", mock_path);
|
||||||
unit_tests.addBuildOption([]const u8, "arch_mock_path", arch_mock_path);
|
unit_tests.addBuildOption([]const u8, "arch_mock_path", arch_mock_path);
|
||||||
|
|
||||||
|
const qemu_bin = switch (test_target.getArch()) {
|
||||||
|
.i386 => "qemu-i386",
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
|
|
||||||
|
// We need this as the build as the make() doesn't handle it properly
|
||||||
|
unit_tests.setExecCmd(&[_]?[]const u8{ qemu_bin, null });
|
||||||
|
unit_tests.setTheTarget(test_target);
|
||||||
|
|
||||||
test_step.dependOn(&unit_tests.step);
|
test_step.dependOn(&unit_tests.step);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const run_step = b.step("run", "Run with qemu");
|
||||||
|
const run_debug_step = b.step("debug-run", "Run with qemu and wait for a gdb connection");
|
||||||
|
|
||||||
|
const qemu_bin = switch (target.getArch()) {
|
||||||
|
.i386 => "qemu-system-i386",
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
|
const qemu_args = &[_][]const u8{
|
||||||
|
qemu_bin,
|
||||||
|
"-cdrom",
|
||||||
|
output_iso,
|
||||||
|
"-boot",
|
||||||
|
"d",
|
||||||
|
"-serial",
|
||||||
|
"stdio",
|
||||||
|
};
|
||||||
|
const qemu_cmd = b.addSystemCommand(qemu_args);
|
||||||
|
const qemu_debug_cmd = b.addSystemCommand(qemu_args);
|
||||||
|
qemu_debug_cmd.addArgs(&[_][]const u8{ "-s", "-S" });
|
||||||
|
|
||||||
|
if (rt_test) {
|
||||||
|
const qemu_rt_test_args = &[_][]const u8{ "-display", "none" };
|
||||||
|
qemu_cmd.addArgs(qemu_rt_test_args);
|
||||||
|
qemu_debug_cmd.addArgs(qemu_rt_test_args);
|
||||||
|
}
|
||||||
|
|
||||||
|
qemu_cmd.step.dependOn(&make_iso.step);
|
||||||
|
qemu_debug_cmd.step.dependOn(&make_iso.step);
|
||||||
|
|
||||||
|
run_step.dependOn(&qemu_cmd.step);
|
||||||
|
run_debug_step.dependOn(&qemu_debug_cmd.step);
|
||||||
|
|
||||||
const debug_step = b.step("debug", "Debug with gdb and connect to a running qemu instance");
|
const debug_step = b.step("debug", "Debug with gdb and connect to a running qemu instance");
|
||||||
const symbol_file_arg = try std.mem.join(b.allocator, " ", &[_][]const u8{ "symbol-file", elf_path });
|
const symbol_file_arg = try std.mem.join(b.allocator, " ", &[_][]const u8{ "symbol-file", exec.getOutputPath() });
|
||||||
const debug_cmd = b.addSystemCommand(&[_][]const u8{
|
const debug_cmd = b.addSystemCommand(&[_][]const u8{
|
||||||
"gdb",
|
"gdb",
|
||||||
"-ex",
|
"-ex",
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
# Read the symbols from the binary, remove all the unnecessary columns with awk and emit to a map file
|
|
||||||
readelf -s $1 | grep -F "FUNC" | awk '{$1=$3=$4=$5=$6=$7=""; print $0}' | sort -k 1 > $2
|
|
||||||
echo "" >> $2
|
|
31
makeiso.sh
Executable file
31
makeiso.sh
Executable file
|
@ -0,0 +1,31 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
BOOT_DIR=$1
|
||||||
|
MODULES_DIR=$2
|
||||||
|
ISO_DIR=$3
|
||||||
|
PLUTO_ELF=$4
|
||||||
|
OUTPUT_FILE=$5
|
||||||
|
|
||||||
|
MAP_FILE=$MODULES_DIR/'kernel.map'
|
||||||
|
|
||||||
|
exit_missing() {
|
||||||
|
printf "$_ must be installed\n";
|
||||||
|
exit 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check dependencies
|
||||||
|
which xorriso > /dev/null || exit_missing
|
||||||
|
which grub-mkrescue > /dev/null || exit_missing
|
||||||
|
which readelf > /dev/null || exit_missing
|
||||||
|
|
||||||
|
mkdir -p $BOOT_DIR
|
||||||
|
mkdir -p $MODULES_DIR
|
||||||
|
|
||||||
|
cp -r grub $BOOT_DIR
|
||||||
|
cp $PLUTO_ELF $BOOT_DIR/"pluto.elf"
|
||||||
|
|
||||||
|
# Read the symbols from the binary, remove all the unnecessary columns with awk and emit to a map file
|
||||||
|
readelf -s $PLUTO_ELF | grep -F "FUNC" | awk '{$1=$3=$4=$5=$6=$7=""; print $0}' | sort -k 1 > $MAP_FILE
|
||||||
|
echo "" >> $MAP_FILE
|
||||||
|
|
||||||
|
grub-mkrescue -o $OUTPUT_FILE $ISO_DIR
|
|
@ -426,10 +426,10 @@ pub fn setTssStack(esp0: u32) void {
|
||||||
pub fn init() void {
|
pub fn init() void {
|
||||||
log.logInfo("Init gdt\n", .{});
|
log.logInfo("Init gdt\n", .{});
|
||||||
// Initiate TSS
|
// Initiate TSS
|
||||||
gdt_entries[TSS_INDEX] = makeEntry(@intCast(u32, @ptrToInt(&tss)), @sizeOf(TtsEntry) - 1, TSS_SEGMENT, NULL_FLAGS);
|
gdt_entries[TSS_INDEX] = makeEntry(@ptrToInt(&tss), @sizeOf(TtsEntry) - 1, TSS_SEGMENT, NULL_FLAGS);
|
||||||
|
|
||||||
// Set the base address where all the GDT entries are.
|
// Set the base address where all the GDT entries are.
|
||||||
gdt_ptr.base = @intCast(u32, @ptrToInt(&gdt_entries[0]));
|
gdt_ptr.base = @ptrToInt(&gdt_entries[0]);
|
||||||
|
|
||||||
// Load the GDT
|
// Load the GDT
|
||||||
arch.lgdt(&gdt_ptr);
|
arch.lgdt(&gdt_ptr);
|
||||||
|
@ -444,7 +444,7 @@ pub fn init() void {
|
||||||
|
|
||||||
fn mock_lgdt(ptr: *const GdtPtr) void {
|
fn mock_lgdt(ptr: *const GdtPtr) void {
|
||||||
expectEqual(TABLE_SIZE, ptr.limit);
|
expectEqual(TABLE_SIZE, ptr.limit);
|
||||||
expectEqual(@intCast(u32, @ptrToInt(&gdt_entries[0])), ptr.base);
|
expectEqual(@ptrToInt(&gdt_entries[0]), ptr.base);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "GDT entries" {
|
test "GDT entries" {
|
||||||
|
|
|
@ -172,7 +172,7 @@ pub fn openInterruptGate(index: u8, handler: InterruptHandler) IdtError!void {
|
||||||
return IdtError.IdtEntryExists;
|
return IdtError.IdtEntryExists;
|
||||||
}
|
}
|
||||||
|
|
||||||
idt_entries[index] = makeEntry(@intCast(u32, @ptrToInt(handler)), gdt.KERNEL_CODE_OFFSET, INTERRUPT_GATE, PRIVILEGE_RING_0);
|
idt_entries[index] = makeEntry(@ptrToInt(handler), gdt.KERNEL_CODE_OFFSET, INTERRUPT_GATE, PRIVILEGE_RING_0);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
|
@ -181,7 +181,7 @@ pub fn openInterruptGate(index: u8, handler: InterruptHandler) IdtError!void {
|
||||||
pub fn init() void {
|
pub fn init() void {
|
||||||
log.logInfo("Init idt\n", .{});
|
log.logInfo("Init idt\n", .{});
|
||||||
|
|
||||||
idt_ptr.base = @intCast(u32, @ptrToInt(&idt_entries));
|
idt_ptr.base = @ptrToInt(&idt_entries);
|
||||||
|
|
||||||
arch.lidt(&idt_ptr);
|
arch.lidt(&idt_ptr);
|
||||||
log.logInfo("Done\n", .{});
|
log.logInfo("Done\n", .{});
|
||||||
|
@ -194,7 +194,7 @@ fn testHandler1() callconv(.Naked) void {}
|
||||||
|
|
||||||
fn mock_lidt(ptr: *const IdtPtr) void {
|
fn mock_lidt(ptr: *const IdtPtr) void {
|
||||||
expectEqual(TABLE_SIZE, ptr.limit);
|
expectEqual(TABLE_SIZE, ptr.limit);
|
||||||
expectEqual(@intCast(u32, @ptrToInt(&idt_entries[0])), ptr.base);
|
expectEqual(@ptrToInt(&idt_entries[0]), ptr.base);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "IDT entries" {
|
test "IDT entries" {
|
||||||
|
@ -244,8 +244,8 @@ test "openInterruptGate" {
|
||||||
openInterruptGate(index, testHandler0) catch unreachable;
|
openInterruptGate(index, testHandler0) catch unreachable;
|
||||||
expectError(IdtError.IdtEntryExists, openInterruptGate(index, testHandler0));
|
expectError(IdtError.IdtEntryExists, openInterruptGate(index, testHandler0));
|
||||||
|
|
||||||
const test_fn_0_addr = @intCast(u32, @ptrToInt(testHandler0));
|
const test_fn_0_addr = @ptrToInt(testHandler0);
|
||||||
const test_fn_1_addr = @intCast(u32, @ptrToInt(testHandler1));
|
const test_fn_1_addr = @ptrToInt(testHandler1);
|
||||||
|
|
||||||
const expected_entry0 = IdtEntry{
|
const expected_entry0 = IdtEntry{
|
||||||
.base_low = @truncate(u16, test_fn_0_addr),
|
.base_low = @truncate(u16, test_fn_0_addr),
|
||||||
|
@ -313,7 +313,7 @@ test "init" {
|
||||||
init();
|
init();
|
||||||
|
|
||||||
// Post testing
|
// Post testing
|
||||||
expectEqual(@intCast(u32, @ptrToInt(&idt_entries)), idt_ptr.base);
|
expectEqual(@ptrToInt(&idt_entries), idt_ptr.base);
|
||||||
|
|
||||||
// Reset
|
// Reset
|
||||||
idt_ptr.base = 0;
|
idt_ptr.base = 0;
|
||||||
|
|
|
@ -205,7 +205,7 @@ fn mapDirEntry(dir: *Directory, virt_start: usize, virt_end: usize, phys_start:
|
||||||
table = &(try allocator.alignedAlloc(Table, @truncate(u29, PAGE_SIZE_4KB), 1))[0];
|
table = &(try allocator.alignedAlloc(Table, @truncate(u29, PAGE_SIZE_4KB), 1))[0];
|
||||||
@memset(@ptrCast([*]u8, table), 0, @sizeOf(Table));
|
@memset(@ptrCast([*]u8, table), 0, @sizeOf(Table));
|
||||||
const table_phys_addr = @ptrToInt(mem.virtToPhys(table));
|
const table_phys_addr = @ptrToInt(mem.virtToPhys(table));
|
||||||
dir_entry.* |= @intCast(u32, DENTRY_PAGE_ADDR & table_phys_addr);
|
dir_entry.* |= DENTRY_PAGE_ADDR & table_phys_addr;
|
||||||
dir.tables[entry] = table;
|
dir.tables[entry] = table;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,7 +243,7 @@ fn mapTableEntry(entry: *align(1) TableEntry, phys_addr: usize) PagingError!void
|
||||||
entry.* |= TENTRY_WRITE_THROUGH;
|
entry.* |= TENTRY_WRITE_THROUGH;
|
||||||
entry.* &= ~TENTRY_CACHE_DISABLED;
|
entry.* &= ~TENTRY_CACHE_DISABLED;
|
||||||
entry.* &= ~TENTRY_GLOBAL;
|
entry.* &= ~TENTRY_GLOBAL;
|
||||||
entry.* |= TENTRY_PAGE_ADDR & @intCast(u32, phys_addr);
|
entry.* |= TENTRY_PAGE_ADDR & phys_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
|
@ -385,7 +385,7 @@ fn checkTableEntry(entry: TableEntry, page_phys: usize) void {
|
||||||
expectEqual(entry & TENTRY_CACHE_DISABLED, 0);
|
expectEqual(entry & TENTRY_CACHE_DISABLED, 0);
|
||||||
expectEqual(entry & TENTRY_ZERO, 0);
|
expectEqual(entry & TENTRY_ZERO, 0);
|
||||||
expectEqual(entry & TENTRY_GLOBAL, 0);
|
expectEqual(entry & TENTRY_GLOBAL, 0);
|
||||||
expectEqual(entry & TENTRY_PAGE_ADDR, @intCast(u32, page_phys));
|
expectEqual(entry & TENTRY_PAGE_ADDR, page_phys);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "virtToDirEntryIdx" {
|
test "virtToDirEntryIdx" {
|
||||||
|
|
|
@ -15,10 +15,12 @@ const panic_root = if (is_test) @import(mock_path ++ "panic_mock.zig") else @imp
|
||||||
const options = @import("build_options");
|
const options = @import("build_options");
|
||||||
|
|
||||||
comptime {
|
comptime {
|
||||||
|
if (!is_test) {
|
||||||
switch (builtin.arch) {
|
switch (builtin.arch) {
|
||||||
.i386 => _ = @import("arch/x86/boot.zig"),
|
.i386 => _ = @import("arch/x86/boot.zig"),
|
||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is for unit testing as we need to export KERNEL_ADDR_OFFSET as it is no longer available
|
// This is for unit testing as we need to export KERNEL_ADDR_OFFSET as it is no longer available
|
||||||
|
|
Loading…
Reference in a new issue