feat(loader, kernel): impl part of loader and initialize kernel structure
This commit is contained in:
9
.gitignore
vendored
9
.gitignore
vendored
@@ -1,8 +1,3 @@
|
|||||||
zig-out
|
|
||||||
.zig-cache
|
.zig-cache
|
||||||
|
zig-out
|
||||||
yukiImage
|
zig-pkg
|
||||||
kcapsule
|
|
||||||
*.img
|
|
||||||
|
|
||||||
|
|
||||||
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
@@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"files.associations": {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
1
arch/x86/boot/.gitignore
vendored
1
arch/x86/boot/.gitignore
vendored
@@ -1 +0,0 @@
|
|||||||
offset.h
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
const std = @import("std");
|
|
||||||
const kernel_build = @import("../../../kernel/build.zig");
|
|
||||||
const Step = std.Build.Step;
|
|
||||||
|
|
||||||
pub fn buildSetup(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, kcapsule: *Step.Compile) *Step.Compile {
|
|
||||||
const offset_generate = b.addSystemCommand(&[_][]const u8{
|
|
||||||
"sh",
|
|
||||||
"arch/x86/boot/helper.sh",
|
|
||||||
"generate_offset_header",
|
|
||||||
});
|
|
||||||
offset_generate.addFileArg(kcapsule.getEmittedBin());
|
|
||||||
offset_generate.step.dependOn(&kcapsule.step);
|
|
||||||
const setup = b.addExecutable(.{
|
|
||||||
.name = "setup",
|
|
||||||
.use_lld = true,
|
|
||||||
.use_llvm = true,
|
|
||||||
.root_module = b.createModule(.{
|
|
||||||
.root_source_file = b.path("arch/x86/boot/setup/stage1.zig"),
|
|
||||||
.target = target,
|
|
||||||
.optimize = optimize,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
setup.step.dependOn(&offset_generate.step);
|
|
||||||
setup.step.addWatchInput(b.path("arch/x86/boot/offset.h")) catch {};
|
|
||||||
setup.addAssemblyFile(b.path("arch/x86/boot/header.S"));
|
|
||||||
setup.addIncludePath(b.path("include"));
|
|
||||||
setup.addIncludePath(b.path("arch/x86/boot"));
|
|
||||||
setup.setLinkerScript(b.path("arch/x86/boot/setup.ld"));
|
|
||||||
return setup;
|
|
||||||
}
|
|
||||||
pub fn buildKcapsule(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode) *Step.Compile {
|
|
||||||
const kernel = kernel_build.buildKernelBin(b, target, optimize);
|
|
||||||
const kcapsule = b.addExecutable(.{
|
|
||||||
.name = "kcapsule",
|
|
||||||
.use_lld = true,
|
|
||||||
.use_llvm = true,
|
|
||||||
.root_module = b.createModule(.{
|
|
||||||
.root_source_file = b.path("arch/x86/boot/extractor.zig"),
|
|
||||||
.target = target,
|
|
||||||
.optimize = optimize,
|
|
||||||
.pic = true,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
const efi_target = b.resolveTargetQuery(.{
|
|
||||||
.cpu_arch = .x86_64,
|
|
||||||
.os_tag = .freestanding,
|
|
||||||
.abi = .msvc,
|
|
||||||
});
|
|
||||||
const efi_loader = b.addObject(.{
|
|
||||||
.name = "efi_loader",
|
|
||||||
.use_lld = true,
|
|
||||||
.use_llvm = true,
|
|
||||||
.root_module = b.createModule(.{
|
|
||||||
.root_source_file = b.path("drivers/firmware/efi/x86.zig"),
|
|
||||||
.target = efi_target,
|
|
||||||
.optimize = optimize,
|
|
||||||
.pic = true,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
kcapsule.pie = true;
|
|
||||||
kcapsule.entry = .{ .symbol_name = "efi_pe_entry" };
|
|
||||||
kcapsule.addObject(efi_loader);
|
|
||||||
kcapsule.addAssemblyFile(b.path("arch/x86/boot/payload.S"));
|
|
||||||
kcapsule.setLinkerScript(b.path("arch/x86/boot/kcapsule.ld"));
|
|
||||||
kcapsule.step.dependOn(&kernel.step);
|
|
||||||
|
|
||||||
return kcapsule;
|
|
||||||
}
|
|
||||||
pub fn buildImage(b: *std.Build, optimize: std.builtin.OptimizeMode) *Step {
|
|
||||||
const target = b.resolveTargetQuery(.{ .cpu_arch = .x86_64, .os_tag = .freestanding, .abi = .none });
|
|
||||||
|
|
||||||
const kcapsule = buildKcapsule(b, target, optimize);
|
|
||||||
const setup = buildSetup(b, target, optimize, kcapsule);
|
|
||||||
const image = b.addSystemCommand(&[_][]const u8{
|
|
||||||
"sh",
|
|
||||||
"arch/x86/boot/helper.sh",
|
|
||||||
"build_image",
|
|
||||||
});
|
|
||||||
|
|
||||||
image.addFileArg(setup.getEmittedBin());
|
|
||||||
image.addFileArg(kcapsule.getEmittedBin());
|
|
||||||
image.step.dependOn(&setup.step);
|
|
||||||
image.step.dependOn(&kcapsule.step);
|
|
||||||
|
|
||||||
return &image.step;
|
|
||||||
}
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
#include "format/pe.h"
|
|
||||||
#include "offset.h"
|
|
||||||
.set salign, 0x1000
|
|
||||||
.set falign, 0x200
|
|
||||||
.section ".bstext", "ax" // allocatable, executable
|
|
||||||
.word IMAGE_DOS_SIGNATURE
|
|
||||||
.org 0x3c
|
|
||||||
.long pe_header
|
|
||||||
.global pe_header
|
|
||||||
pe_header:
|
|
||||||
.long IMAGE_NT_SIGNATURE
|
|
||||||
coff_header:
|
|
||||||
.word IMAGE_FILE_MACHINE_AMD64
|
|
||||||
.word section_count
|
|
||||||
.long 0 /* TimeDateStamp */
|
|
||||||
.long 0 /* PointerToSymbolTable */
|
|
||||||
.long 0 /* NumberOfSymbols */
|
|
||||||
.word section_table - optional_header /* SizeOfOptionalHeader */
|
|
||||||
.word IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DEBUG_STRIPPED | IMAGE_FILE_LINE_NUMS_STRIPPED /* Characteristics */
|
|
||||||
optional_header:
|
|
||||||
.word IMAGE_NT_OPTIONAL_HDR64_MAGIC /* Magic */
|
|
||||||
.byte 0 /* MajorLinkerVersion */
|
|
||||||
.byte 0 /* MinorLinkerVersion */
|
|
||||||
.long CAP__data /* SizeOfCode */
|
|
||||||
.long CAP__end - CAP__data /* SizeOfInitializedData */
|
|
||||||
.long 0 /* SizeOfUninitializedData */
|
|
||||||
.long setup_size + efi_pe_entry /* AddressOfEntryPoint */
|
|
||||||
.long setup_size /* BaseOfCode */
|
|
||||||
extra_header_fields:
|
|
||||||
.quad 0 /* ImageBase */
|
|
||||||
.long salign /* SectionAlignment */
|
|
||||||
.long falign /* FileAlignment */
|
|
||||||
.word 0 /* MajorOperatingSystemVersion */
|
|
||||||
.word 0 /* MinorOperatingSystemVersion */
|
|
||||||
.word 0 /* MajorImageVersion */
|
|
||||||
.word 0 /* MinorImageVersion */
|
|
||||||
.word 0 /* MajorSubsystemVersion */
|
|
||||||
.word 0 /* MinorSubsystemVersion */
|
|
||||||
.long 0 /* Win32VersionValue */
|
|
||||||
|
|
||||||
.long setup_size + CAP__end /* SizeOfImage */
|
|
||||||
|
|
||||||
.long salign /* SizeOfHeaders */
|
|
||||||
.long 0 /* CheckSum */
|
|
||||||
.word IMAGE_SUBSYSTEM_EFI_APPLICATION /* Subsystem */
|
|
||||||
.word IMAGE_DLLCHARACTERISTICS_NX_COMPAT /* DllCharacteristics */
|
|
||||||
.quad 0 /* SizeOfStackReserve */
|
|
||||||
.quad 0 /* SizeOfStackCommit */
|
|
||||||
.quad 0 /* SizeOfHeapReserve */
|
|
||||||
.quad 0 /* SizeOfHeapCommit */
|
|
||||||
.long 0 /* LoaderFlags */
|
|
||||||
.long (section_table - .) / 8 /* NumberOfRvaAndSizes */
|
|
||||||
.quad 0
|
|
||||||
.quad 0
|
|
||||||
.quad 0
|
|
||||||
.quad 0
|
|
||||||
.quad 0
|
|
||||||
.quad 0
|
|
||||||
|
|
||||||
section_table:
|
|
||||||
# .ascii ".setup\0\0"
|
|
||||||
# .long setup_size - salign /* VirtualSize */
|
|
||||||
# .long salign /* VirtualAddress */
|
|
||||||
# .long setup_size - salign /* SizeOfRawData */
|
|
||||||
# .long salign /* PointerToRawData */
|
|
||||||
# .long 0,0,0
|
|
||||||
# .long IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE
|
|
||||||
|
|
||||||
.ascii ".text\0\0\0"
|
|
||||||
.long text_size /* VirtualSize */
|
|
||||||
.long setup_size /* VirtualAddress */
|
|
||||||
.long text_size /* SizeOfRawData */
|
|
||||||
.long setup_size /* PointerToRawData */
|
|
||||||
.long 0,0,0
|
|
||||||
.long IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE
|
|
||||||
|
|
||||||
.ascii ".data\0\0\0"
|
|
||||||
.long CAP__end - CAP__data /* VirtualSize */
|
|
||||||
.long setup_size + CAP__data /* VirtualAddress */
|
|
||||||
.long CAP__edata - CAP__data /* SizeOfRawData */
|
|
||||||
.long setup_size + CAP__data /* PointerToRawData */
|
|
||||||
.long 0,0,0
|
|
||||||
.long IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE
|
|
||||||
|
|
||||||
.set text_size, CAP__data
|
|
||||||
.set section_count, (. - section_table) / 40
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
generate_offset_header() {
|
|
||||||
echo "processing $1"
|
|
||||||
nm -n "$1" \
|
|
||||||
| grep -e ' _\(end\|edata\|data\)$' \
|
|
||||||
| awk '{print "#define CAP_" $3 " 0x" $1}' \
|
|
||||||
> arch/x86/boot/offset.h
|
|
||||||
nm -n "$1" \
|
|
||||||
| grep -e ' efi_pe_entry$' \
|
|
||||||
| awk '{print "#define efi_pe_entry 0x" $1}' \
|
|
||||||
>> arch/x86/boot/offset.h
|
|
||||||
}
|
|
||||||
build_image() {
|
|
||||||
echo "building image from $1 and $2"
|
|
||||||
(dd if=$1 bs=4k conv=sync; cat $2) > yukiImage
|
|
||||||
}
|
|
||||||
# Main dispatcher
|
|
||||||
case "$1" in
|
|
||||||
generate_offset_header)
|
|
||||||
generate_offset_header "$2"
|
|
||||||
;;
|
|
||||||
build_image)
|
|
||||||
build_image "$2" "$3"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "Usage: $0 {generate_offset_header|build_image} [args...]"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
OUTPUT_ARCH(i386:x86_64)
|
|
||||||
SECTIONS {
|
|
||||||
. = 0x1000;
|
|
||||||
.text : {
|
|
||||||
_text = .;
|
|
||||||
*(.text)
|
|
||||||
*(.text.*)
|
|
||||||
_etext = .;
|
|
||||||
}
|
|
||||||
.rodata : {
|
|
||||||
_rodata = .;
|
|
||||||
*(.rodata)
|
|
||||||
*(.rodata.*)
|
|
||||||
_erodata = .;
|
|
||||||
}
|
|
||||||
. = ALIGN(0x1000);
|
|
||||||
.data : {
|
|
||||||
_data = .;
|
|
||||||
*(.data)
|
|
||||||
*(.data.*)
|
|
||||||
. = ALIGN(0x1000);
|
|
||||||
_edata = .;
|
|
||||||
}
|
|
||||||
.bss : {
|
|
||||||
_bss = .;
|
|
||||||
*(.bss)
|
|
||||||
*(.bss.*)
|
|
||||||
*(COMMON)
|
|
||||||
_ebss = .;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pgtable : {
|
|
||||||
_pgtable = .;
|
|
||||||
*(.pgtable)
|
|
||||||
_epgtable = .;
|
|
||||||
}
|
|
||||||
|
|
||||||
. = ALIGN(0x1000);
|
|
||||||
_end = .;
|
|
||||||
.got.plt (INFO) : {
|
|
||||||
*(.got.plt)
|
|
||||||
}
|
|
||||||
ASSERT(SIZEOF(.got.plt) == 0 ||
|
|
||||||
SIZEOF(.got.plt) == 0x18,
|
|
||||||
"Unexpected GOT/PLT entries detected!")
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Sections that should stay zero sized, which is safer to
|
|
||||||
* explicitly check instead of blindly discarding.
|
|
||||||
*/
|
|
||||||
.got : {
|
|
||||||
*(.got)
|
|
||||||
}
|
|
||||||
ASSERT(SIZEOF(.got) == 0, "Unexpected GOT entries detected!")
|
|
||||||
|
|
||||||
.plt : {
|
|
||||||
*(.plt) *(.plt.*)
|
|
||||||
}
|
|
||||||
ASSERT(SIZEOF(.plt) == 0, "Unexpected run-time procedure linkages detected!")
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
OUTPUT_FORMAT(binary)
|
|
||||||
OUTPUT_ARCH(i386)
|
|
||||||
ENTRY(_start)
|
|
||||||
|
|
||||||
SECTIONS {
|
|
||||||
. = 0;
|
|
||||||
|
|
||||||
.bstext : {
|
|
||||||
*(.bstext)
|
|
||||||
. = 495;
|
|
||||||
} =0xffffffff
|
|
||||||
.text : {*(.text .text.*)}
|
|
||||||
. = ALIGN(16);
|
|
||||||
.rodata : {*(.rodata .rodata.*)}
|
|
||||||
. = ALIGN(16);
|
|
||||||
.data : {*(.data .data.*)}
|
|
||||||
|
|
||||||
setup_size = ALIGN(ABSOLUTE(.), 4096);
|
|
||||||
|
|
||||||
. = ALIGN(16);
|
|
||||||
.bss : {*(.bss) }
|
|
||||||
. = ALIGN(16);
|
|
||||||
|
|
||||||
/DISCARD/ : {
|
|
||||||
*(.note*)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
OUTPUT_ARCH(i386:x86_64)
|
|
||||||
ENTRY(kernel_start)
|
|
||||||
SECTIONS {
|
|
||||||
.text : {
|
|
||||||
*(.text)
|
|
||||||
*(.text.*)
|
|
||||||
}
|
|
||||||
|
|
||||||
.rodata : {
|
|
||||||
*(.rodata)
|
|
||||||
*(.rodata.*)
|
|
||||||
}
|
|
||||||
|
|
||||||
.data : {
|
|
||||||
*(.data)
|
|
||||||
*(.data.*)
|
|
||||||
}
|
|
||||||
.bss : {
|
|
||||||
*(.bss)
|
|
||||||
*(.bss.*)
|
|
||||||
*(COMMON)
|
|
||||||
}
|
|
||||||
|
|
||||||
.pgtable : {
|
|
||||||
*(.pgtable)
|
|
||||||
}
|
|
||||||
|
|
||||||
. = ALIGN(0x1000);
|
|
||||||
}
|
|
||||||
3
arch/x86_64/arch.zig
Normal file
3
arch/x86_64/arch.zig
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
pub const io = @import("io.zig");
|
||||||
|
pub const processor = @import("processor.zig");
|
||||||
|
pub const mem = @import("mem.zig");
|
||||||
7
arch/x86_64/boot/boot.zig
Normal file
7
arch/x86_64/boot/boot.zig
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
const boot_consts = @cImport({
|
||||||
|
@cInclude("boot.h");
|
||||||
|
});
|
||||||
|
|
||||||
|
pub const BOOT_HEAP_SIZE: usize = boot_consts.BOOT_HEAP_SIZE;
|
||||||
|
pub const BOOT_STACK_SIZE: usize = boot_consts.BOOT_STACK_SIZE;
|
||||||
|
pub const LOAD_PHYSICAL_ADDR: usize = boot_consts.LOAD_PHYSICAL_ADDR;
|
||||||
159
arch/x86_64/boot/build_boot.zig
Normal file
159
arch/x86_64/boot/build_boot.zig
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const Step = std.Build.Step;
|
||||||
|
const OptimizeMode = std.builtin.OptimizeMode;
|
||||||
|
|
||||||
|
fn getTarget(b: *std.Build) std.Build.ResolvedTarget {
|
||||||
|
var query: std.Target.Query = .{
|
||||||
|
.cpu_arch = .x86_64,
|
||||||
|
.os_tag = .freestanding,
|
||||||
|
.abi = .none,
|
||||||
|
};
|
||||||
|
const Features = std.Target.x86.Feature;
|
||||||
|
query.cpu_features_sub.addFeature(@intFromEnum(Features.mmx));
|
||||||
|
query.cpu_features_sub.addFeature(@intFromEnum(Features.sse));
|
||||||
|
query.cpu_features_sub.addFeature(@intFromEnum(Features.sse2));
|
||||||
|
query.cpu_features_sub.addFeature(@intFromEnum(Features.sse3));
|
||||||
|
query.cpu_features_sub.addFeature(@intFromEnum(Features.ssse3));
|
||||||
|
query.cpu_features_sub.addFeature(@intFromEnum(Features.sse4_1));
|
||||||
|
query.cpu_features_sub.addFeature(@intFromEnum(Features.sse4_2));
|
||||||
|
query.cpu_features_sub.addFeature(@intFromEnum(Features.avx));
|
||||||
|
query.cpu_features_sub.addFeature(@intFromEnum(Features.avx2));
|
||||||
|
query.cpu_features_add.addFeature(@intFromEnum(Features.soft_float));
|
||||||
|
const target = b.resolveTargetQuery(query);
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
var tool_extract_symbol: *Step.InstallArtifact = undefined;
|
||||||
|
var tool_generate_image: *Step.InstallArtifact = undefined;
|
||||||
|
var tool_compress_kernel: *Step.InstallArtifact = undefined;
|
||||||
|
|
||||||
|
fn buildTool(b: *std.Build) void {
|
||||||
|
const mvzr = b.dependency("mvzr", .{}).module("mvzr");
|
||||||
|
const elfy = b.dependency("elfy", .{}).module("elfy");
|
||||||
|
const compile_extract_symbol = b.addExecutable(.{
|
||||||
|
.name = "symbol_extract",
|
||||||
|
.root_module = b.addModule("symbol_extract", .{
|
||||||
|
.root_source_file = b.path("arch/x86_64/boot/build_tool/symbol_extract.zig"),
|
||||||
|
.target = b.resolveTargetQuery(.{
|
||||||
|
.cpu_arch = @import("builtin").target.cpu.arch,
|
||||||
|
}),
|
||||||
|
.optimize = OptimizeMode.ReleaseSafe,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
compile_extract_symbol.root_module.addImport("mvzr", mvzr);
|
||||||
|
compile_extract_symbol.root_module.addImport("elfy", elfy);
|
||||||
|
tool_extract_symbol = b.addInstallArtifact(compile_extract_symbol, .{
|
||||||
|
.dest_dir = .{ .override = .{ .custom = "build_tool" } }
|
||||||
|
});
|
||||||
|
const compile_generate_image = b.addExecutable(.{
|
||||||
|
.name = "generate_image",
|
||||||
|
.root_module = b.addModule("generate_image", .{
|
||||||
|
.root_source_file = b.path("arch/x86_64/boot/build_tool/generate_image.zig"),
|
||||||
|
.target = b.resolveTargetQuery(.{
|
||||||
|
.cpu_arch = @import("builtin").target.cpu.arch,
|
||||||
|
}),
|
||||||
|
.optimize = OptimizeMode.ReleaseSafe,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
tool_generate_image = b.addInstallArtifact(compile_generate_image, .{
|
||||||
|
.dest_dir = .{ .override = .{ .custom = "build_tool" } }
|
||||||
|
});
|
||||||
|
const compile_compress_kernel = b.addExecutable(.{
|
||||||
|
.name = "compress_kernel",
|
||||||
|
.root_module = b.addModule("compress_kernel", .{
|
||||||
|
.root_source_file = b.path("arch/x86_64/boot/build_tool/compress_kernel.zig"),
|
||||||
|
.target = b.resolveTargetQuery(.{
|
||||||
|
.cpu_arch = @import("builtin").target.cpu.arch,
|
||||||
|
}),
|
||||||
|
.optimize = OptimizeMode.ReleaseSafe,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
tool_compress_kernel = b.addInstallArtifact(compile_compress_kernel, .{
|
||||||
|
.dest_dir = .{ .override = .{ .custom = "build_tool" } }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
fn buildHeader(b: *std.Build, optimize: OptimizeMode, kcapsule: *Step.Compile) *Step.ObjCopy {
|
||||||
|
const target = getTarget(b);
|
||||||
|
const copy_header = b.addWriteFiles();
|
||||||
|
const include_dir = copy_header.addCopyDirectory(b.path("arch/x86_64/boot/include"), "include", .{});
|
||||||
|
const symbol_extract = b.addRunArtifact(tool_extract_symbol.artifact);
|
||||||
|
symbol_extract.step.dependOn(&tool_extract_symbol.step);
|
||||||
|
symbol_extract.addFileArg(kcapsule.getEmittedBin());
|
||||||
|
symbol_extract.addArgs(&[_][] const u8{
|
||||||
|
"^(_end|_edata|startup_32|startup_64)$",
|
||||||
|
"CAP_"
|
||||||
|
});
|
||||||
|
symbol_extract.addFileArg(include_dir.join(b.allocator, "kcapsule.h") catch @panic("OOM"));
|
||||||
|
symbol_extract.step.dependOn(©_header.step);
|
||||||
|
symbol_extract.step.dependOn(&kcapsule.step);
|
||||||
|
const header_elf = b.addExecutable(.{
|
||||||
|
.name = "header.bin",
|
||||||
|
.root_module = b.addModule("header", .{
|
||||||
|
.root_source_file = null,
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
header_elf.root_module.addAssemblyFile(b.path("arch/x86_64/boot/header.S"));
|
||||||
|
header_elf.root_module.addIncludePath(include_dir);
|
||||||
|
header_elf.setLinkerScript(b.path("arch/x86_64/boot/header.ld"));
|
||||||
|
header_elf.step.dependOn(&symbol_extract.step);
|
||||||
|
const header = b.addObjCopy(header_elf.getEmittedBin(), .{
|
||||||
|
.format = .bin,
|
||||||
|
});
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
fn buildKcapsule(b: *std.Build,
|
||||||
|
optimize: OptimizeMode,
|
||||||
|
kernel: *Step.Compile) *Step.Compile {
|
||||||
|
const target = getTarget(b);
|
||||||
|
const compress = b.addRunArtifact(tool_compress_kernel.artifact);
|
||||||
|
compress.step.dependOn(&kernel.step);
|
||||||
|
compress.addFileArg(kernel.getEmittedBin());
|
||||||
|
const kernelz_path = kernel.getEmittedBinDirectory().join(b.allocator, "kernelz") catch @panic("OOM");
|
||||||
|
const payload_asm_path = kernel.getEmittedBinDirectory().join(b.allocator, "payload.S") catch @panic("OOM");
|
||||||
|
compress.addFileArg(kernelz_path);
|
||||||
|
compress.addFileArg(payload_asm_path);
|
||||||
|
|
||||||
|
const arch_module = b.addModule("arch", .{
|
||||||
|
.root_source_file = b.path("arch/x86_64/arch.zig"),
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
.pic = true,
|
||||||
|
});
|
||||||
|
const loader_module = b.addModule("loader", .{
|
||||||
|
.root_source_file = b.path("arch/x86_64/boot/extractor.zig"),
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
.pic = true,
|
||||||
|
});
|
||||||
|
loader_module.addImport("arch", arch_module);
|
||||||
|
loader_module.addIncludePath(b.path("arch/x86_64/boot/include"));
|
||||||
|
loader_module.addAssemblyFile(payload_asm_path);
|
||||||
|
const kcapsule = b.addExecutable(.{
|
||||||
|
.name = "kcapsule",
|
||||||
|
.use_lld = true,
|
||||||
|
.use_llvm = true,
|
||||||
|
.root_module = loader_module,
|
||||||
|
});
|
||||||
|
kcapsule.pie = true;
|
||||||
|
kcapsule.setLinkerScript(b.path("arch/x86_64/boot/kcapsule.ld"));
|
||||||
|
kcapsule.root_module.addAssemblyFile(b.path("arch/x86_64/boot/head.S"));
|
||||||
|
kcapsule.step.dependOn(&compress.step);
|
||||||
|
return kcapsule;
|
||||||
|
}
|
||||||
|
pub fn buildBootImage(b: *std.Build, kernel: *Step.Compile) void {
|
||||||
|
buildTool(b);
|
||||||
|
const optimize = OptimizeMode.Debug;
|
||||||
|
const kcapsule = buildKcapsule(b, optimize, kernel);
|
||||||
|
const header = buildHeader(b, optimize, kcapsule);
|
||||||
|
const kcapsule_install = b.addInstallArtifact(kcapsule, .{});
|
||||||
|
const kcapsule_bin = b.addObjCopy(kcapsule.getEmittedBin(), .{
|
||||||
|
.format = .bin,
|
||||||
|
});
|
||||||
|
const image = b.addRunArtifact(tool_generate_image.artifact);
|
||||||
|
image.addFileArg(header.getOutput());
|
||||||
|
image.addFileArg(kcapsule_bin.getOutput());
|
||||||
|
image.addArg(std.fs.path.join(b.allocator, &[_][]const u8{ b.install_path, "yukiImage" }) catch @panic("OOM"));
|
||||||
|
b.getInstallStep().dependOn(&kcapsule_install.step);
|
||||||
|
b.getInstallStep().dependOn(&image.step);
|
||||||
|
}
|
||||||
57
arch/x86_64/boot/build_tool/compress_kernel.zig
Normal file
57
arch/x86_64/boot/build_tool/compress_kernel.zig
Normal 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});
|
||||||
|
}
|
||||||
50
arch/x86_64/boot/build_tool/generate_image.zig
Normal file
50
arch/x86_64/boot/build_tool/generate_image.zig
Normal 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();
|
||||||
|
}
|
||||||
41
arch/x86_64/boot/build_tool/symbol_extract.zig
Normal file
41
arch/x86_64/boot/build_tool/symbol_extract.zig
Normal 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();
|
||||||
|
}
|
||||||
|
|
||||||
82
arch/x86_64/boot/cmdline.zig
Normal file
82
arch/x86_64/boot/cmdline.zig
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
fn isWhitespace(c: u8) bool {
|
||||||
|
return c == ' ' or c == '\t' or c == '\n' or c == '\r';
|
||||||
|
}
|
||||||
|
pub const Cmdline = struct {
|
||||||
|
ptr: []const u8,
|
||||||
|
pub fn init(ptr: []const u8) Cmdline {
|
||||||
|
return Cmdline{
|
||||||
|
.ptr = ptr,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
fn _parseArg(self: *const Cmdline, key: []const u8, buf: []u8) ?usize {
|
||||||
|
var state: union(enum) {
|
||||||
|
search_key,
|
||||||
|
compare_key: usize,
|
||||||
|
copy_value: usize,
|
||||||
|
skip_arg
|
||||||
|
} = .search_key;
|
||||||
|
var i: usize = 0;
|
||||||
|
while (i < self.ptr.len) {
|
||||||
|
const c = self.ptr[i];
|
||||||
|
switch (state) {
|
||||||
|
.search_key => {
|
||||||
|
if (isWhitespace(c)) {
|
||||||
|
i = i + 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
state = .{ .compare_key = 0};
|
||||||
|
},
|
||||||
|
.compare_key => |key_index| {
|
||||||
|
if (key_index < key.len) {
|
||||||
|
if (c == key[key_index]) {
|
||||||
|
state = .{ .compare_key = key_index + 1 };
|
||||||
|
} else {
|
||||||
|
state = .skip_arg;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (c == '=') {
|
||||||
|
state = .{ .copy_value = 0 };
|
||||||
|
} else if (isWhitespace(c)) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
state = .skip_arg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i = i + 1;
|
||||||
|
},
|
||||||
|
.skip_arg => {
|
||||||
|
if (isWhitespace(c)) {
|
||||||
|
state = .search_key;
|
||||||
|
}
|
||||||
|
i = i + 1;
|
||||||
|
},
|
||||||
|
.copy_value => |buf_index| {
|
||||||
|
if (isWhitespace(c) or buf_index >= buf.len) {
|
||||||
|
return buf_index;
|
||||||
|
}
|
||||||
|
buf[buf_index] = c;
|
||||||
|
state = .{ .copy_value = buf_index + 1 };
|
||||||
|
i = i + 1;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch (state) {
|
||||||
|
.copy_value => |buf_index| return buf_index,
|
||||||
|
else => return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn parseArg(self: *const Cmdline, key: []const u8, buf: []u8) ?usize {
|
||||||
|
return self._parseArg(key, buf);
|
||||||
|
}
|
||||||
|
pub fn parseArgBool(self: *const Cmdline, key: []const u8) bool {
|
||||||
|
const result = self._parseArg(key, &[_]u8{});
|
||||||
|
if (result) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
118
arch/x86_64/boot/early_serial_console.zig
Normal file
118
arch/x86_64/boot/early_serial_console.zig
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const Cmdline = @import("cmdline.zig").Cmdline;
|
||||||
|
const io = @import("arch").io;
|
||||||
|
|
||||||
|
const PREDEFINED_PORTS: [2]u16 = .{
|
||||||
|
0x3F8, // ttyS0
|
||||||
|
0x2F8, // ttyS1
|
||||||
|
};
|
||||||
|
var serial_writer: ?SerialWriter = null;
|
||||||
|
// Parse earlyprintk argument from cmdline
|
||||||
|
// Format: earlyprintk=serial,port,baudrate, port can either be ioport address (e.g., 0x3F8) or
|
||||||
|
// a predefined name (e.g., ttyS0/ttyS1).
|
||||||
|
fn parseEarlyprintk(cmdline: *const Cmdline) ?struct { port: u16, baudrate: u32 } {
|
||||||
|
var buf = [_]u8{0} ** 32;
|
||||||
|
const len = cmdline.parseArg("earlyprintk", &buf) orelse 0;
|
||||||
|
if (len == 0) return null;
|
||||||
|
const arg = buf[0..len];
|
||||||
|
var it = std.mem.splitAny(u8, arg, ",");
|
||||||
|
if(std.mem.eql(u8, it.next() orelse "", "serial") == false) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const port_str = it.next() orelse return null;
|
||||||
|
var port: u16 = undefined;
|
||||||
|
if (port_str.len == 5 and std.mem.startsWith(u8, port_str, "ttyS")) {
|
||||||
|
const port_idx = std.fmt.parseInt(u8, port_str[4..5], 10) catch return null;
|
||||||
|
if (port_idx >= PREDEFINED_PORTS.len) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
port = PREDEFINED_PORTS[port_idx];
|
||||||
|
} else if (std.fmt.parseInt(u16, port_str, 16) catch null) |port_val| {
|
||||||
|
port = port_val;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const baudrate_str = it.next() orelse return null;
|
||||||
|
const baudrate = std.fmt.parseInt(u32, baudrate_str, 10) catch return null;
|
||||||
|
return .{ .port = port, .baudrate = baudrate };
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialInit(port: u16, baudrate: u32) void {
|
||||||
|
const divisor: u16 = @intCast(115200 / baudrate);
|
||||||
|
// Disable interrupts
|
||||||
|
io.outb(port + 1, 0x00);
|
||||||
|
// Disable FIFO
|
||||||
|
io.outb(port + 2, 0x00);
|
||||||
|
// Set 8 data bits, 1 stop bit, no parity
|
||||||
|
io.outb(port + 3, 0x80);
|
||||||
|
const c = io.inb(port + 3);
|
||||||
|
// Enable DLAB
|
||||||
|
io.outb(port + 3, c | 0x80);
|
||||||
|
// Set divisor low byte
|
||||||
|
io.outb(port + 0, @intCast(divisor & 0x00FF));
|
||||||
|
// Set divisor high byte
|
||||||
|
io.outb(port + 1, @intCast((divisor >> 8) & 0x00FF));
|
||||||
|
io.outb(port + 3, c & ~@as(u8, 0x80));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn earlyConsoleInit(cmdline: *const Cmdline) void {
|
||||||
|
const result = parseEarlyprintk(cmdline) orelse return;
|
||||||
|
serialInit(result.port, result.baudrate);
|
||||||
|
serial_writer = SerialWriter.init(result.port);
|
||||||
|
}
|
||||||
|
const SerialWriter = struct {
|
||||||
|
port: u16,
|
||||||
|
interface: std.Io.Writer,
|
||||||
|
var WRITER_VTABLE: std.Io.Writer.VTable = undefined;
|
||||||
|
pub fn init(port: u16) SerialWriter {
|
||||||
|
WRITER_VTABLE = .{
|
||||||
|
.drain = SerialWriter.drain,
|
||||||
|
};
|
||||||
|
var sw = SerialWriter{
|
||||||
|
.port = port,
|
||||||
|
.interface = undefined,
|
||||||
|
};
|
||||||
|
sw.interface = .{
|
||||||
|
.buffer = &[0]u8{},
|
||||||
|
.vtable = @call(.never_inline, getWriterVTable, .{}),
|
||||||
|
};
|
||||||
|
return sw;
|
||||||
|
}
|
||||||
|
pub fn writer(self: *SerialWriter) *std.Io.Writer {
|
||||||
|
return &self.interface;
|
||||||
|
}
|
||||||
|
fn getWriterVTable() *const std.Io.Writer.VTable {
|
||||||
|
return &WRITER_VTABLE;
|
||||||
|
}
|
||||||
|
// fn getWriterDrain() *const @TypeOf(SerialWriter.drain) {
|
||||||
|
// return SerialWriter.drain;
|
||||||
|
// }
|
||||||
|
fn drain(self: *std.Io.Writer, buf: []const []const u8, splat: usize) error{}!usize {
|
||||||
|
const sw: *SerialWriter = @fieldParentPtr("interface", self);
|
||||||
|
var written: usize = 0;
|
||||||
|
for (buf, 0..buf.len) |part, i| {
|
||||||
|
const repeat = if (i == buf.len - 1) splat else 1;
|
||||||
|
for (0..repeat) |_| {
|
||||||
|
for (part) |c| {
|
||||||
|
SerialWriter.putchar(sw, c);
|
||||||
|
written += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return written;
|
||||||
|
}
|
||||||
|
fn putchar(self: *const SerialWriter, c: u8) void {
|
||||||
|
var timeout: usize = 0xffff;
|
||||||
|
while(io.inb(self.port + 5) & 0x20 == 0 and timeout > 0) {
|
||||||
|
timeout -= 1;
|
||||||
|
asm volatile ("pause"
|
||||||
|
::: .{ .memory = true }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
io.outb(self.port, c);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
pub fn dprint(comptime fmt: []const u8, args: anytype) void {
|
||||||
|
var sw = serial_writer orelse return;
|
||||||
|
_ = sw.writer().print(fmt, args) catch {};
|
||||||
|
}
|
||||||
46
arch/x86_64/boot/extractor.zig
Normal file
46
arch/x86_64/boot/extractor.zig
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const BootParams = @import("params.zig").BootParams;
|
||||||
|
const early_serial_console = @import("early_serial_console.zig");
|
||||||
|
const Cmdline = @import("cmdline.zig").Cmdline;
|
||||||
|
const payload = @import("payload.zig");
|
||||||
|
const multiboot = @import("multiboot.zig");
|
||||||
|
const Decompress = std.compress.flate.Decompress;
|
||||||
|
const relocate = @import("relocate.zig");
|
||||||
|
const ident_map = @import("ident_map.zig");
|
||||||
|
|
||||||
|
comptime {
|
||||||
|
@export(&relocate.relocateSelf, .{
|
||||||
|
.name = "relocateSelf",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
fn decompress(target_addr: [*]u8) !void {
|
||||||
|
var data_reader = std.Io.Reader.fixed(payload.getCompressedKernelData());
|
||||||
|
var work_buffer: [std.compress.flate.max_window_len]u8 = undefined;
|
||||||
|
var decompressor = Decompress.init(&data_reader, .gzip, &work_buffer);
|
||||||
|
var decompressor_reader = &decompressor.reader;
|
||||||
|
var decompress_buf = target_addr;
|
||||||
|
while (true) {
|
||||||
|
const read_bytes = try decompressor_reader.readSliceShort(decompress_buf[0..4096]);
|
||||||
|
if (read_bytes == 0) break;
|
||||||
|
decompress_buf = decompress_buf[read_bytes..];
|
||||||
|
if ((@intFromPtr(decompress_buf) - @intFromPtr(target_addr) ) % 10240 == 0) {
|
||||||
|
early_serial_console.dprint("Decompressed {d} bytes...\n", .{@intFromPtr(decompress_buf) - @intFromPtr(target_addr)});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export fn extractKernel(multiboot_info: *u8,
|
||||||
|
target_addr: usize) callconv(.c) noreturn {
|
||||||
|
const params = multiboot.parseMultibootInfo(multiboot_info);
|
||||||
|
const cmdline = Cmdline.init(params.cmdline);
|
||||||
|
early_serial_console.earlyConsoleInit(&cmdline);
|
||||||
|
early_serial_console.dprint("Starting kernel extraction...\n", .{});
|
||||||
|
early_serial_console.dprint("Kernel compressed size {d} bytes\n", .{payload.getCompressedKernelData().len});
|
||||||
|
early_serial_console.dprint("Kernel uncompressed size {d} bytes\n", .{payload.getUncompressedKernelSize()});
|
||||||
|
decompress(@ptrFromInt(target_addr)) catch |err| {
|
||||||
|
early_serial_console.dprint("Kernel decompression failed: {s}\n", .{@errorName(err)});
|
||||||
|
while(true){}
|
||||||
|
};
|
||||||
|
early_serial_console.dprint("Kernel extraction completed.\n", .{});
|
||||||
|
|
||||||
|
while(true){}
|
||||||
|
}
|
||||||
181
arch/x86_64/boot/head.S
Normal file
181
arch/x86_64/boot/head.S
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
#include "boot.h"
|
||||||
|
#include "processor_flags.h"
|
||||||
|
|
||||||
|
#define rva(x) ((x)-startup_32)
|
||||||
|
#define __BOOT_DS (3*8)
|
||||||
|
#define __KERNEL32_CS (1*8)
|
||||||
|
#define __KERNEL_CS (2*8)
|
||||||
|
|
||||||
|
.section .head.text, "ax"
|
||||||
|
.global _start
|
||||||
|
_start: // just make linker happy
|
||||||
|
.code32
|
||||||
|
.global startup_32
|
||||||
|
.type startup_32, %function
|
||||||
|
startup_32:
|
||||||
|
movl $0x50000, %edx
|
||||||
|
movl $0xdeadbeef, (%edx)
|
||||||
|
cld
|
||||||
|
cli
|
||||||
|
// Actually multiboot doesn't give us a scartch area to use as stack,
|
||||||
|
// so we temporaily save the 2nd 32bit of boot information and use it as the stack.
|
||||||
|
movl 4(%ebx), %ecx
|
||||||
|
leal 8(%ebx), %esp
|
||||||
|
call 1f
|
||||||
|
1: popl %ebp
|
||||||
|
movl %ecx, 4(%ebx)
|
||||||
|
subl $rva(1b), %ebp
|
||||||
|
leal rva(gdt)(%ebp), %eax
|
||||||
|
mov %eax, 2(%eax)
|
||||||
|
lgdt (%eax)
|
||||||
|
|
||||||
|
mov $__BOOT_DS, %ax
|
||||||
|
mov %ax, %ds
|
||||||
|
mov %ax, %es
|
||||||
|
mov %ax, %fs
|
||||||
|
mov %ax, %gs
|
||||||
|
mov %ax, %ss
|
||||||
|
|
||||||
|
leal rva(boot_stack_end)(%ebp), %esp
|
||||||
|
|
||||||
|
pushl $__KERNEL32_CS
|
||||||
|
leal rva(1f)(%ebp), %eax
|
||||||
|
pushl %eax
|
||||||
|
lret
|
||||||
|
1:
|
||||||
|
movl %cr4, %eax
|
||||||
|
orl $X86_CR4_PAE, %eax
|
||||||
|
movl %eax, %cr4
|
||||||
|
|
||||||
|
leal rva(pgtable)(%ebp), %edi
|
||||||
|
xorl %eax, %eax
|
||||||
|
movl $(BOOT_INIT_PGTABLE_SIZE/4), %ecx
|
||||||
|
rep stosl
|
||||||
|
|
||||||
|
leal rva(pgtable)(%ebp), %edi
|
||||||
|
leal 0x1007(%edi), %eax
|
||||||
|
movl %eax, 0(%edi)
|
||||||
|
|
||||||
|
leal rva(pgtable + 0x1000)(%ebp), %edi
|
||||||
|
leal 0x1007(%edi), %eax
|
||||||
|
movl $4, %ecx
|
||||||
|
1: movl %eax, 0(%edi)
|
||||||
|
addl $0x1000, %eax
|
||||||
|
addl $8, %edi
|
||||||
|
decl %ecx
|
||||||
|
jnz 1b
|
||||||
|
|
||||||
|
leal rva(pgtable + 0x2000)(%ebp), %edi
|
||||||
|
movl $0x183, %eax
|
||||||
|
movl $2048, %ecx
|
||||||
|
1: movl %eax, 0(%edi)
|
||||||
|
addl $0x200000, %eax
|
||||||
|
addl $8, %edi
|
||||||
|
decl %ecx
|
||||||
|
jnz 1b
|
||||||
|
|
||||||
|
leal rva(pgtable)(%ebp), %eax
|
||||||
|
movl %eax, %cr3
|
||||||
|
movl $MSR_EFER, %ecx
|
||||||
|
rdmsr
|
||||||
|
btsl $_EFER_LME, %eax
|
||||||
|
wrmsr
|
||||||
|
|
||||||
|
leal rva(startup_64)(%ebp), %eax
|
||||||
|
pushl $__KERNEL_CS
|
||||||
|
pushl %eax
|
||||||
|
|
||||||
|
movl $CR0_STATE, %eax
|
||||||
|
movl %eax, %cr0
|
||||||
|
|
||||||
|
lret
|
||||||
|
#define rva64(x) ((x)-startup_64)
|
||||||
|
#define STARTUP64_OFFSET 0x200
|
||||||
|
.code64
|
||||||
|
.global startup_64
|
||||||
|
.type startup_64, %function
|
||||||
|
.org STARTUP64_OFFSET
|
||||||
|
startup_64:
|
||||||
|
cld
|
||||||
|
cli
|
||||||
|
|
||||||
|
xorl %eax, %eax
|
||||||
|
movl %eax, %ds
|
||||||
|
movl %eax, %es
|
||||||
|
movl %eax, %ss
|
||||||
|
movl %eax, %fs
|
||||||
|
movl %eax, %gs
|
||||||
|
|
||||||
|
movq %rbx, %rsi
|
||||||
|
|
||||||
|
movq $LOAD_PHYSICAL_ADDR, %rbp
|
||||||
|
// movl has the side effect of zero-extending the upper 32 bits of rbx
|
||||||
|
movl $uncompressed_kernel_size, %ebx
|
||||||
|
// there's no need to copy the code before startup_64
|
||||||
|
addq %rbp, %rbx
|
||||||
|
|
||||||
|
leaq rva64(boot_stack_end)(%rbx), %rsp
|
||||||
|
movq %rsi, %r15
|
||||||
|
leaq (_bss - 8)(%rip), %rsi
|
||||||
|
leaq rva64(_bss - 8)(%rbx), %rdi
|
||||||
|
movl $rva64(_bss), %ecx
|
||||||
|
shrl $3, %ecx
|
||||||
|
std
|
||||||
|
rep movsq
|
||||||
|
cld
|
||||||
|
|
||||||
|
leaq rva64(gdt64)(%rbx), %rax
|
||||||
|
leaq rva64(gdt)(%rbx), %rdx
|
||||||
|
movq %rdx, 2(%rax)
|
||||||
|
lgdt (%rax)
|
||||||
|
|
||||||
|
leaq rva64(relocated)(%rbx), %rax
|
||||||
|
jmp *%rax
|
||||||
|
|
||||||
|
.text
|
||||||
|
relocated:
|
||||||
|
// clear bss
|
||||||
|
xorl %eax, %eax
|
||||||
|
leaq _bss(%rip), %rdi
|
||||||
|
leaq _ebss(%rip), %rcx
|
||||||
|
subq %rdi, %rcx
|
||||||
|
shrq $3, %rcx
|
||||||
|
rep stosq
|
||||||
|
|
||||||
|
mov %rbx, %rdi
|
||||||
|
subq $STARTUP64_OFFSET, %rdi
|
||||||
|
call relocateSelf
|
||||||
|
|
||||||
|
movq %r15, %rdi // boot params pointer
|
||||||
|
movq %rbp, %rsi // load physical address
|
||||||
|
call extractKernel
|
||||||
|
|
||||||
|
|
||||||
|
hlt
|
||||||
|
.data
|
||||||
|
gdt64:
|
||||||
|
.word gdt_end - gdt - 1
|
||||||
|
.quad gdt - gdt64
|
||||||
|
gdt64_end:
|
||||||
|
.balign 8
|
||||||
|
gdt:
|
||||||
|
.word gdt_end - gdt - 1
|
||||||
|
.long 0
|
||||||
|
.word 0
|
||||||
|
.quad 0x00cf9a000000ffff // __KERNEL32_CS
|
||||||
|
.quad 0x00af9a000000ffff // __KERNEL_CS
|
||||||
|
.quad 0x00cf92000000ffff // __KERNEL_DS
|
||||||
|
gdt_end:
|
||||||
|
.bss
|
||||||
|
.balign 4
|
||||||
|
boot_heap:
|
||||||
|
.space BOOT_HEAP_SIZE
|
||||||
|
boot_stack:
|
||||||
|
.space BOOT_STACK_SIZE
|
||||||
|
boot_stack_end:
|
||||||
|
|
||||||
|
.section ".pgtable","aw",@nobits
|
||||||
|
.balign 4096
|
||||||
|
pgtable:
|
||||||
|
.space BOOT_PGTABLE_SIZE
|
||||||
|
pgtable_end:
|
||||||
69
arch/x86_64/boot/header.S
Normal file
69
arch/x86_64/boot/header.S
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
#include "multiboot2.h"
|
||||||
|
#include "kcapsule.h" // Auto-generated file
|
||||||
|
#include "boot.h"
|
||||||
|
.set falign, 0x200
|
||||||
|
.code16
|
||||||
|
.section ".header", "a"
|
||||||
|
.global _start
|
||||||
|
_start: // Just make linker happy
|
||||||
|
yuki_header:
|
||||||
|
.ascii "YUKIOS"
|
||||||
|
.quad 0x131084C
|
||||||
|
|
||||||
|
.org 0x50
|
||||||
|
.balign 8
|
||||||
|
multiboot2_header:
|
||||||
|
.long MULTIBOOT2_HEADER_MAGIC
|
||||||
|
.long MULTIBOOT_ARCHITECTURE_I386
|
||||||
|
.long multiboot2_header_end - multiboot2_header
|
||||||
|
.long -(MULTIBOOT2_HEADER_MAGIC + MULTIBOOT_ARCHITECTURE_I386 + (multiboot2_header_end - multiboot2_header))
|
||||||
|
.balign 8
|
||||||
|
address_tag:
|
||||||
|
.short MULTIBOOT_HEADER_TAG_ADDRESS
|
||||||
|
.short 0
|
||||||
|
.long address_tag_end - address_tag
|
||||||
|
.long LOAD_PHYSICAL_ADDR + multiboot2_header
|
||||||
|
.long -1
|
||||||
|
.long 0
|
||||||
|
.long 0
|
||||||
|
address_tag_end:
|
||||||
|
.balign 8
|
||||||
|
entry_tag:
|
||||||
|
.short MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS
|
||||||
|
.short MULTIBOOT_HEADER_TAG_OPTIONAL
|
||||||
|
.long entry_tag_end - entry_tag
|
||||||
|
.long LOAD_PHYSICAL_ADDR + header_size + CAP_startup_32
|
||||||
|
entry_tag_end:
|
||||||
|
// entry_efi_i386_tag:
|
||||||
|
// .short MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32
|
||||||
|
// .short MULTIBOOT_HEADER_TAG_OPTIONAL
|
||||||
|
// .long entry_efi_i386_tag_end - entry_efi_i386_tag
|
||||||
|
// .long header_size + CAP_startup_32
|
||||||
|
// entry_efi_i386_tag_end:
|
||||||
|
// entry_efi_amd64_tag:
|
||||||
|
// .short MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64
|
||||||
|
// .short MULTIBOOT_HEADER_TAG_OPTIONAL
|
||||||
|
// .long entry_efi_amd64_tag_end - entry_efi_amd64_tag
|
||||||
|
// .long header_size + CAP_startup_64
|
||||||
|
// entry_efi_amd64_tag_end:
|
||||||
|
.balign 8
|
||||||
|
framebuffer_tag:
|
||||||
|
.short MULTIBOOT_HEADER_TAG_FRAMEBUFFER
|
||||||
|
.short MULTIBOOT_HEADER_TAG_OPTIONAL
|
||||||
|
.long framebuffer_tag_end - framebuffer_tag
|
||||||
|
.long 0
|
||||||
|
.long 0
|
||||||
|
.long 0
|
||||||
|
framebuffer_tag_end:
|
||||||
|
// .balign 8
|
||||||
|
// relocatable_tag:
|
||||||
|
// .short MULTIBOOT_HEADER_TAG_RELOCATABLE
|
||||||
|
// .short MULTIBOOT_HEADER_TAG_OPTIONAL
|
||||||
|
// .long relocatable_tag_end - relocatable_tag
|
||||||
|
// .long 0x0 /* min_addr */
|
||||||
|
// .long 0xf0000000 /* max_addr */
|
||||||
|
// .long falign /* align */
|
||||||
|
// .long 0x0
|
||||||
|
// relocatable_tag_end:
|
||||||
|
multiboot2_header_end:
|
||||||
|
.balign falign
|
||||||
9
arch/x86_64/boot/header.ld
Normal file
9
arch/x86_64/boot/header.ld
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
OUTPUT_ARCH(x86_64)
|
||||||
|
|
||||||
|
SECTIONS {
|
||||||
|
. = 0;
|
||||||
|
.header : {
|
||||||
|
KEEP(*(.header))
|
||||||
|
}
|
||||||
|
header_size = ALIGN(ABSOLUTE(.), 4096);
|
||||||
|
}
|
||||||
62
arch/x86_64/boot/ident_map.zig
Normal file
62
arch/x86_64/boot/ident_map.zig
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const processor = @import("arch").processor;
|
||||||
|
const mem = @import("arch").mem;
|
||||||
|
const PFType = mem.PFType;
|
||||||
|
const early_serial_console = @import("early_serial_console.zig");
|
||||||
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
|
var pgtable_buffer: struct {
|
||||||
|
buffer: [*][mem.PAGE_SIZE]u8,
|
||||||
|
size: usize,
|
||||||
|
used_pages: usize,
|
||||||
|
} = undefined;
|
||||||
|
|
||||||
|
fn allocPgtablePage() error.OutOfMemory![4096]u8 {
|
||||||
|
// if (used + mem.PAGE_SIZE > size) {
|
||||||
|
// early_serial_console.dprint("Out of page table memory!\n", .{});
|
||||||
|
// return error.OutOfMemory;
|
||||||
|
// }
|
||||||
|
// const page = buffer + used;
|
||||||
|
// return page;
|
||||||
|
}
|
||||||
|
// fn pgdIdentInit() {
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn pudIdentInit() {
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
fn kernelAddIdentityMap(pgdt_page: [*]mem.PGDEntry, start: u64, end: u64) void {
|
||||||
|
assert(start % mem.PMD_SIZE == 0);
|
||||||
|
assert(end % mem.PMD_SIZE == 0);
|
||||||
|
var address = start;
|
||||||
|
while (address < end) {
|
||||||
|
// var pgd = &pgdt_page[mem.PGDEntry.getIndex(address)];
|
||||||
|
// if ()
|
||||||
|
address += mem.PMD_SIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export fn initializeIdentMap() void {
|
||||||
|
// var pgd_table = processor.readCr3();
|
||||||
|
// if (pgdtable == _pgtable) {
|
||||||
|
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
fn printPF(msg: []const u8, errorCode: u64, faultAddress: u64, ip: u64) void {
|
||||||
|
early_serial_console.dprint(
|
||||||
|
\\{s}:
|
||||||
|
\\error code: 0x{x}
|
||||||
|
\\fault address: 0x{x}
|
||||||
|
\\instruction pointer: 0x{x}
|
||||||
|
\\
|
||||||
|
, .{msg, errorCode, faultAddress, ip});
|
||||||
|
}
|
||||||
|
export fn doBootPageFault(regs: processor.PtRegs, errorCode: u64) void {
|
||||||
|
const faultAddress = processor.readCr2();
|
||||||
|
if (errorCode & (PFType.PROT | PFType.USER | PFType.RSVD) == 0) {
|
||||||
|
printPF("Unexpected page fault", errorCode, faultAddress, regs.ip);
|
||||||
|
}
|
||||||
|
const address = faultAddress & mem.PMD_MASK;
|
||||||
|
kernelAddIdentityMap(address, address + mem.PMD_SIZE);
|
||||||
|
}
|
||||||
23
arch/x86_64/boot/idt.zig
Normal file
23
arch/x86_64/boot/idt.zig
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
const desc = @import("arch").desc;
|
||||||
|
const mem = @import("arch").mem;
|
||||||
|
const TrapType = @import("arch").trap.TrapType;
|
||||||
|
extern const __KERNEL_CS: u8;
|
||||||
|
|
||||||
|
var idt_table: [256]desc.IdtEntry align(mem.PAGE_SIZE) = .{.{}} ** 256;
|
||||||
|
extern const boot_page_fault: u8;
|
||||||
|
extern const boot_nmi: u8;
|
||||||
|
|
||||||
|
fn setIdtEntry(vec: usize, handler: anytype) void {
|
||||||
|
var entry = desc.IdtEntry{};
|
||||||
|
entry.setOffset(@intFromPtr(handler));
|
||||||
|
entry.selector = @intFromPtr(&__KERNEL_CS);
|
||||||
|
entry.gate_type = .trap;
|
||||||
|
entry.present = 1;
|
||||||
|
idt_table[vec] = entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
export fn loadLoaderIdt() void {
|
||||||
|
setIdtEntry(TrapType.PF, &boot_page_fault);
|
||||||
|
setIdtEntry(TrapType.NMI, &boot_nmi);
|
||||||
|
desc.loadIdt(&idt_table);
|
||||||
|
}
|
||||||
56
arch/x86_64/boot/idt_handlers.S
Normal file
56
arch/x86_64/boot/idt_handlers.S
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
|
||||||
|
.macro EXCEPTION_HANDLER name function error_code=0
|
||||||
|
.global \name
|
||||||
|
.type \name, @function
|
||||||
|
\name:
|
||||||
|
if \error_code == 0
|
||||||
|
pushq $0
|
||||||
|
end
|
||||||
|
|
||||||
|
pushq %rdi
|
||||||
|
pushq %rsi
|
||||||
|
pushq %rdx
|
||||||
|
pushq %rcx
|
||||||
|
pushq %rax
|
||||||
|
pushq %r8
|
||||||
|
pushq %r9
|
||||||
|
pushq %r10
|
||||||
|
pushq %r11
|
||||||
|
pushq %rbx
|
||||||
|
pushq %rbp
|
||||||
|
pushq %r12
|
||||||
|
pushq %r13
|
||||||
|
pushq %r14
|
||||||
|
pushq %r15
|
||||||
|
|
||||||
|
movq %rsp, %rdi
|
||||||
|
/* Error code is second parameter */
|
||||||
|
movq 120(%rsp), %rsi
|
||||||
|
call \function
|
||||||
|
|
||||||
|
/* Restore regs */
|
||||||
|
popq %r15
|
||||||
|
popq %r14
|
||||||
|
popq %r13
|
||||||
|
popq %r12
|
||||||
|
popq %rbp
|
||||||
|
popq %rbx
|
||||||
|
popq %r11
|
||||||
|
popq %r10
|
||||||
|
popq %r9
|
||||||
|
popq %r8
|
||||||
|
popq %rax
|
||||||
|
popq %rcx
|
||||||
|
popq %rdx
|
||||||
|
popq %rsi
|
||||||
|
popq %rdi
|
||||||
|
|
||||||
|
addq $8, %rsp
|
||||||
|
|
||||||
|
iretq
|
||||||
|
.endm
|
||||||
|
.text
|
||||||
|
.code64
|
||||||
|
|
||||||
|
EXCEPTION_HANDLER boot_page_fault doBootPageFault error_code=1
|
||||||
|
EXCEPTION_HANDLER boot_nmi doBootNMI
|
||||||
6
arch/x86_64/boot/include/boot.h
Normal file
6
arch/x86_64/boot/include/boot.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#define BOOT_HEAP_SIZE (512 * 1024)
|
||||||
|
#define BOOT_STACK_SIZE (64 * 1024)
|
||||||
|
#define LOAD_PHYSICAL_ADDR (0x100000)
|
||||||
|
|
||||||
|
#define BOOT_PGTABLE_SIZE (32 * 4096)
|
||||||
|
#define BOOT_INIT_PGTABLE_SIZE (6 * 4096)
|
||||||
39
arch/x86_64/boot/include/multiboot2.h
Normal file
39
arch/x86_64/boot/include/multiboot2.h
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
/* How many bytes from the start of the file we search for the header. */
|
||||||
|
#define MULTIBOOT_SEARCH 32768
|
||||||
|
#define MULTIBOOT_HEADER_ALIGN 8
|
||||||
|
|
||||||
|
/* The magic field should contain this. */
|
||||||
|
#define MULTIBOOT2_HEADER_MAGIC 0xe85250d6
|
||||||
|
|
||||||
|
/* Alignment of multiboot modules. */
|
||||||
|
#define MULTIBOOT_MOD_ALIGN 0x00001000
|
||||||
|
|
||||||
|
/* Alignment of the multiboot info structure. */
|
||||||
|
#define MULTIBOOT_INFO_ALIGN 0x00000008
|
||||||
|
|
||||||
|
|
||||||
|
#define MULTIBOOT_HEADER_TAG_END 0
|
||||||
|
#define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1
|
||||||
|
#define MULTIBOOT_HEADER_TAG_ADDRESS 2
|
||||||
|
#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS 3
|
||||||
|
#define MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS 4
|
||||||
|
#define MULTIBOOT_HEADER_TAG_FRAMEBUFFER 5
|
||||||
|
#define MULTIBOOT_HEADER_TAG_MODULE_ALIGN 6
|
||||||
|
#define MULTIBOOT_HEADER_TAG_EFI_BS 7
|
||||||
|
#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32 8
|
||||||
|
#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 9
|
||||||
|
#define MULTIBOOT_HEADER_TAG_RELOCATABLE 10
|
||||||
|
|
||||||
|
#define MULTIBOOT_ARCHITECTURE_I386 0
|
||||||
|
#define MULTIBOOT_ARCHITECTURE_MIPS32 4
|
||||||
|
#define MULTIBOOT_HEADER_TAG_OPTIONAL 1
|
||||||
|
|
||||||
|
#define MULTIBOOT_LOAD_PREFERENCE_NONE 0
|
||||||
|
#define MULTIBOOT_LOAD_PREFERENCE_LOW 1
|
||||||
|
#define MULTIBOOT_LOAD_PREFERENCE_HIGH 2
|
||||||
|
|
||||||
|
#define MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED 1
|
||||||
|
#define MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED 2
|
||||||
|
|
||||||
15
arch/x86_64/boot/include/processor_flags.h
Normal file
15
arch/x86_64/boot/include/processor_flags.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#define X86_CR0_PE 0x00000001
|
||||||
|
#define X86_CR0_MP 0x00000002
|
||||||
|
#define X86_CR0_ET 0x00000004
|
||||||
|
#define X86_CR0_NE 0x00000020
|
||||||
|
#define X86_CR0_WP 0x00010000
|
||||||
|
#define X86_CR0_AM 0x00040000
|
||||||
|
#define X86_CR0_PG 0x80000000
|
||||||
|
#define CR0_STATE (X86_CR0_PE | X86_CR0_MP | X86_CR0_ET | \
|
||||||
|
X86_CR0_NE | X86_CR0_WP | X86_CR0_AM | \
|
||||||
|
X86_CR0_PG)
|
||||||
|
#define X86_CR4_PAE 0x00000020
|
||||||
|
#define X86_CR4_OSFXSR 0x00000200
|
||||||
|
#define X86_CR4_OSXMMEXCPT 0x00000400
|
||||||
|
#define MSR_EFER 0xc0000080
|
||||||
|
#define _EFER_LME 8
|
||||||
59
arch/x86_64/boot/kcapsule.ld
Normal file
59
arch/x86_64/boot/kcapsule.ld
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
OUTPUT_ARCH(i386:x86_64)
|
||||||
|
|
||||||
|
ENTRY(startup_32)
|
||||||
|
|
||||||
|
SECTIONS {
|
||||||
|
. = 0;
|
||||||
|
.head.text : {
|
||||||
|
KEEP(*(.head.text))
|
||||||
|
}
|
||||||
|
.rodata.compressed : {
|
||||||
|
*(.rodata.compressed)
|
||||||
|
}
|
||||||
|
.text : {
|
||||||
|
_text = .;
|
||||||
|
*(.text)
|
||||||
|
*(.text.*)
|
||||||
|
_etext = .;
|
||||||
|
}
|
||||||
|
.rodata : {
|
||||||
|
_rodata = .;
|
||||||
|
*(.rodata)
|
||||||
|
*(.rodata.*)
|
||||||
|
_erodata = .;
|
||||||
|
}
|
||||||
|
.data : ALIGN(0x1000) {
|
||||||
|
_data = .;
|
||||||
|
*(.data)
|
||||||
|
*(.data.*)
|
||||||
|
. = ALIGN(. + 4, 0x200);
|
||||||
|
_edata = .;
|
||||||
|
}
|
||||||
|
.rela.dyn : {
|
||||||
|
__rela_dyn_start = .;
|
||||||
|
*(.rela.dyn)
|
||||||
|
__rela_dyn_end = .;
|
||||||
|
}
|
||||||
|
. = ALIGN(8);
|
||||||
|
.bss : {
|
||||||
|
_bss = .;
|
||||||
|
*(.bss)
|
||||||
|
*(.bss.*)
|
||||||
|
*(COMMON)
|
||||||
|
. = ALIGN(8);
|
||||||
|
_ebss = .;
|
||||||
|
}
|
||||||
|
. = ALIGN(4096);
|
||||||
|
.pgtable : {
|
||||||
|
_pgtable = .;
|
||||||
|
*(.pgtable)
|
||||||
|
_epgtable = .;
|
||||||
|
}
|
||||||
|
_end = .;
|
||||||
|
/DISCARD/ : {
|
||||||
|
*(.dynamic) *(.dynsym) *(.dynstr) *(.dynbss)
|
||||||
|
*(.hash) *(.gnu.hash)
|
||||||
|
*(.note.*)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
250
arch/x86_64/boot/multiboot.zig
Normal file
250
arch/x86_64/boot/multiboot.zig
Normal file
@@ -0,0 +1,250 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const BootParams = @import("params.zig").BootParams;
|
||||||
|
pub const MULTIBOOT_TAG_ALIGN: usize = 8;
|
||||||
|
pub const MultibootTagType = enum(u32) {
|
||||||
|
end,
|
||||||
|
cmdline,
|
||||||
|
boot_loader_name,
|
||||||
|
module,
|
||||||
|
basic_meminfo,
|
||||||
|
bootdev,
|
||||||
|
mmap,
|
||||||
|
vbe,
|
||||||
|
framebuffer,
|
||||||
|
elf_sections,
|
||||||
|
apm,
|
||||||
|
efi32,
|
||||||
|
efi64,
|
||||||
|
smbios,
|
||||||
|
acpi_old,
|
||||||
|
acpi_new,
|
||||||
|
network,
|
||||||
|
efi_mmap,
|
||||||
|
efi_bs,
|
||||||
|
efi32_ih,
|
||||||
|
efi64_ih,
|
||||||
|
load_base_addr,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const MultibootTag = extern struct {
|
||||||
|
type: u32 align(1),
|
||||||
|
size: u32 align(1),
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const MultibootTagCmdline = extern struct {
|
||||||
|
type: u32 align(1),
|
||||||
|
size: u32 align(1),
|
||||||
|
string: [0]u8 align(1),
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const MultibootTagModule = extern struct {
|
||||||
|
type: u32 align(1),
|
||||||
|
size: u32 align(1),
|
||||||
|
mod_start: u32 align(1),
|
||||||
|
mod_end: u32 align(1),
|
||||||
|
cmdline: [0]u8 align(1),
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const MultibootTagBasicMeminfo = extern struct {
|
||||||
|
type: u32 align(1),
|
||||||
|
size: u32 align(1),
|
||||||
|
mem_lower: u32 align(1),
|
||||||
|
mem_upper: u32 align(1),
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const MultibootTagBootdev = extern struct {
|
||||||
|
type: u32 align(1),
|
||||||
|
size: u32 align(1),
|
||||||
|
biosdev: u32 align(1),
|
||||||
|
slice: u32 align(1),
|
||||||
|
part: u32 align(1),
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const MultibootMmapEntry = extern struct {
|
||||||
|
addr: u64 align(1),
|
||||||
|
len: u64 align(1),
|
||||||
|
type: u32 align(1),
|
||||||
|
zero: u32 align(1),
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const MultibootTagMmap = extern struct {
|
||||||
|
type: u32 align(1),
|
||||||
|
size: u32 align(1),
|
||||||
|
entry_size: u32 align(1),
|
||||||
|
entry_version: u32 align(1),
|
||||||
|
entries: [0]MultibootMmapEntry align(1),
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const MultibootVbeInfoBlock = extern struct {
|
||||||
|
external_specification: [512]u8 align(1),
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const MultibootVbeModeInfoBlock = extern struct {
|
||||||
|
external_specification: [256]u8 align(1),
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const MultibootTagVbe = extern struct {
|
||||||
|
type: u32 align(1),
|
||||||
|
size: u32 align(1),
|
||||||
|
|
||||||
|
vbe_mode: u16 align(1),
|
||||||
|
vbe_interface_seg: u16 align(1),
|
||||||
|
vbe_interface_off: u16 align(1),
|
||||||
|
vbe_interface_len: u16 align(1),
|
||||||
|
|
||||||
|
vbe_control_info: MultibootVbeInfoBlock align(1),
|
||||||
|
vbe_mode_info: MultibootVbeModeInfoBlock align(1),
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED = 0;
|
||||||
|
pub const MULTIBOOT_FRAMEBUFFER_TYPE_RGB = 1;
|
||||||
|
pub const MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT = 2;
|
||||||
|
|
||||||
|
pub const MultibootColor = extern struct {
|
||||||
|
red: u8 align(1),
|
||||||
|
green: u8 align(1),
|
||||||
|
blue: u8 align(1),
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const MultibootTagFramebufferCommon = extern struct {
|
||||||
|
type: u32 align(1),
|
||||||
|
size: u32 align(1),
|
||||||
|
|
||||||
|
framebuffer_addr: u64 align(1),
|
||||||
|
framebuffer_pitch: u32 align(1),
|
||||||
|
framebuffer_width: u32 align(1),
|
||||||
|
framebuffer_height: u32 align(1),
|
||||||
|
framebuffer_bpp: u8 align(1),
|
||||||
|
framebuffer_type: u8 align(1),
|
||||||
|
reserved: u16 align(1),
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const MultibootTagFramebuffer = extern struct {
|
||||||
|
common: MultibootTagFramebufferCommon align(1),
|
||||||
|
|
||||||
|
details: extern union {
|
||||||
|
indexed: extern struct {
|
||||||
|
framebuffer_palette_num_colors: u16 align(1),
|
||||||
|
framebuffer_palette: [*]MultibootColor align(1),
|
||||||
|
} align(1),
|
||||||
|
rgb: extern struct {
|
||||||
|
framebuffer_red_field_position: u8 align(1),
|
||||||
|
framebuffer_red_mask_size: u8 align(1),
|
||||||
|
framebuffer_green_field_position: u8 align(1),
|
||||||
|
framebuffer_green_mask_size: u8 align(1),
|
||||||
|
framebuffer_blue_field_position: u8 align(1),
|
||||||
|
framebuffer_blue_mask_size: u8 align(1),
|
||||||
|
} align(1),
|
||||||
|
} align(1),
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const MultibootTagElfSections = extern struct {
|
||||||
|
type: u32 align(1),
|
||||||
|
size: u32 align(1),
|
||||||
|
num: u32 align(1),
|
||||||
|
entsize: u32 align(1),
|
||||||
|
shndx: u32 align(1),
|
||||||
|
sections: [*]u8 align(1),
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const MultibootTagApm = extern struct {
|
||||||
|
type: u32 align(1),
|
||||||
|
size: u32 align(1),
|
||||||
|
version: u16 align(1),
|
||||||
|
cseg: u16 align(1),
|
||||||
|
offset: u32 align(1),
|
||||||
|
cseg_16: u16 align(1),
|
||||||
|
dseg: u16 align(1),
|
||||||
|
flags: u16 align(1),
|
||||||
|
cseg_len: u16 align(1),
|
||||||
|
cseg_16_len: u16 align(1),
|
||||||
|
dseg_len: u16 align(1),
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const MultibootTagEfi32 = extern struct {
|
||||||
|
type: u32 align(1),
|
||||||
|
size: u32 align(1),
|
||||||
|
pointer: u32 align(1),
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const MultibootTagEfi64 = extern struct {
|
||||||
|
type: u32 align(1),
|
||||||
|
size: u32 align(1),
|
||||||
|
pointer: u64 align(1),
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const MultibootTagSmbios = extern struct {
|
||||||
|
type: u32 align(1),
|
||||||
|
size: u32 align(1),
|
||||||
|
major: u8 align(1),
|
||||||
|
minor: u8 align(1),
|
||||||
|
reserved: [6]u8 align(1),
|
||||||
|
tables: [*]u8 align(1),
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const MultibootTagOldAcpi = extern struct {
|
||||||
|
type: u32 align(1),
|
||||||
|
size: u32 align(1),
|
||||||
|
rsdp: [*]u8 align(1),
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const MultibootTagNewAcpi = extern struct {
|
||||||
|
type: u32 align(1),
|
||||||
|
size: u32 align(1),
|
||||||
|
rsdp: [*]u8 align(1),
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const MultibootTagNetwork = extern struct {
|
||||||
|
type: u32 align(1),
|
||||||
|
size: u32 align(1),
|
||||||
|
dhcpack: [*]u8 align(1),
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const MultibootTagEfiMmap = extern struct {
|
||||||
|
type: u32 align(1),
|
||||||
|
size: u32 align(1),
|
||||||
|
descr_size: u32 align(1),
|
||||||
|
descr_vers: u32 align(1),
|
||||||
|
efi_mmap: [*]u8 align(1),
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const MultibootTagEfi32Ih = extern struct {
|
||||||
|
type: u32 align(1),
|
||||||
|
size: u32 align(1),
|
||||||
|
pointer: u32 align(1),
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const MultibootTagEfi64Ih = extern struct {
|
||||||
|
type: u32 align(1),
|
||||||
|
size: u32 align(1),
|
||||||
|
pointer: u64 align(1),
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const MultibootTagLoadBaseAddr = extern struct {
|
||||||
|
type: u32 align(1),
|
||||||
|
size: u32 align(1),
|
||||||
|
load_base_addr: u32 align(1),
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn parseMultibootInfo(multiboot_info: *u8) BootParams {
|
||||||
|
var params = BootParams{
|
||||||
|
.cmdline = &[_]u8{},
|
||||||
|
};
|
||||||
|
var offset: usize = @sizeOf(MultibootTag);
|
||||||
|
while (true) {
|
||||||
|
const tag: *MultibootTag = @ptrFromInt(@intFromPtr(multiboot_info) + offset);
|
||||||
|
if (tag.type == @intFromEnum(MultibootTagType.end)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch (@as(MultibootTagType, @enumFromInt(tag.type))) {
|
||||||
|
MultibootTagType.cmdline => {
|
||||||
|
const cmdline_tag: *MultibootTagCmdline = @ptrCast(tag);
|
||||||
|
const sentinel_cmdline = @as([*:0]u8, @ptrCast(&cmdline_tag.string));
|
||||||
|
params.cmdline = sentinel_cmdline[0..std.mem.len(sentinel_cmdline)];
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
offset += (tag.size + MULTIBOOT_TAG_ALIGN - 1) & ~(MULTIBOOT_TAG_ALIGN - 1);
|
||||||
|
}
|
||||||
|
return params;
|
||||||
|
}
|
||||||
52
arch/x86_64/boot/params.zig
Normal file
52
arch/x86_64/boot/params.zig
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
// // const e820 = @import("e820.zig");
|
||||||
|
// const video = @import("video.zig");
|
||||||
|
|
||||||
|
// pub const SetupHeader = extern struct {
|
||||||
|
// _pad1: [15]u8 align(1),
|
||||||
|
// jump: u16 align(1),
|
||||||
|
// header: u32 align(1),
|
||||||
|
// version: u16 align(1),
|
||||||
|
// _pad2: [8]u8 align(1),
|
||||||
|
// type_of_loader: u8 align(1),
|
||||||
|
// loadflags: u8 align(1),
|
||||||
|
// _pad3: [22]u8 align(1),
|
||||||
|
// cmd_line_ptr: u32 align(1),
|
||||||
|
// _pad4: [4]u8 align(1),
|
||||||
|
// kernel_alignment: u32 align(1),
|
||||||
|
// relocatable_kernel: u8 align(1),
|
||||||
|
// min_alignment: u8 align(1),
|
||||||
|
// xloadflags: u16 align(1),
|
||||||
|
// cmdline_size: u32 align(1),
|
||||||
|
// _pad5: [36]u8 align(1),
|
||||||
|
// init_size: u32 align(1),
|
||||||
|
// _pad6: [8]u8 align(1),
|
||||||
|
// };
|
||||||
|
|
||||||
|
// const E820_MAX_ENTRIES_BP = 128;
|
||||||
|
|
||||||
|
// pub const BootParams = extern struct {
|
||||||
|
// screen_info: video.ScreenInfo align(1), // 0x000
|
||||||
|
// _pad1: [0x30]u8 align(1), // 0x040
|
||||||
|
// acpi_rsdp_addr: u64 align(1), // 0x070
|
||||||
|
// _pad2: [0x50]u8 align(1), // 0x078
|
||||||
|
// ext_cmd_line_ptr: u32 align(1), // 0x0c8
|
||||||
|
// _pad3: [0x74]u8 align(1), // 0x0cc
|
||||||
|
// edid_info: [0x80]u8 align(1), // 0x140 reserve for future use
|
||||||
|
// _pad4: [0x28]u8 align(1), // 0x1c0
|
||||||
|
// e820_entries: u8 align(1), // 0x1e8
|
||||||
|
// _pad5: [0x8]u8 align(1), // 0x1e9
|
||||||
|
// hdr: SetupHeader align(1), // 0x1f1
|
||||||
|
// _pad6: [0x2d0 - 0x1f1 - @sizeOf(SetupHeader)]u8 align(1),
|
||||||
|
// // e820_table: [E820_MAX_ENTRIES_BP]e820.E820Entry align(1), // 0x2d0
|
||||||
|
// _pad7: [0x330]u8 align(1), // 0xcd0
|
||||||
|
// };
|
||||||
|
|
||||||
|
// comptime {
|
||||||
|
// const assert = std.debug.assert;
|
||||||
|
// // assert(@sizeOf(BootParams) == 0x1000);
|
||||||
|
// assert(@sizeOf(SetupHeader) == 0x07b);
|
||||||
|
// }
|
||||||
|
pub const BootParams = struct {
|
||||||
|
cmdline: []u8
|
||||||
|
};
|
||||||
13
arch/x86_64/boot/payload.zig
Normal file
13
arch/x86_64/boot/payload.zig
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
extern const compressed_kernel_data: u8;
|
||||||
|
extern const compressed_kernel_size: u8;
|
||||||
|
extern const uncompressed_kernel_size: u8;
|
||||||
|
|
||||||
|
pub fn getCompressedKernelData() []const u8 {
|
||||||
|
return @as([*]const u8, @ptrCast(&compressed_kernel_data))[0..@as(usize, @intFromPtr(&compressed_kernel_size))];
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getUncompressedKernelSize() usize {
|
||||||
|
return @as(usize, @intFromPtr(&uncompressed_kernel_size));
|
||||||
|
}
|
||||||
20
arch/x86_64/boot/relocate.zig
Normal file
20
arch/x86_64/boot/relocate.zig
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const elf = std.elf;
|
||||||
|
|
||||||
|
extern var __rela_dyn_start: u8;
|
||||||
|
extern var __rela_dyn_end: u8;
|
||||||
|
|
||||||
|
pub fn relocateSelf(base_addr: usize) callconv(.c) void {
|
||||||
|
const rela_size = (@intFromPtr(&__rela_dyn_end) - @intFromPtr(&__rela_dyn_start)) / @sizeOf(elf.Elf64_Rela);
|
||||||
|
const relas = @as([*]elf.Elf64_Rela, @ptrCast(@alignCast(&__rela_dyn_start)))[0..rela_size];
|
||||||
|
for (relas) |rela| {
|
||||||
|
const offset = rela.r_offset;
|
||||||
|
const addend = rela.r_addend;
|
||||||
|
// const sym_index = rela.r_info >> 32;
|
||||||
|
const type_ = rela.r_info & 0xffffffff;
|
||||||
|
if (type_ == @intFromEnum(elf.R_X86_64.RELATIVE)) {
|
||||||
|
const reloc_addr: *u64 = @ptrFromInt(offset + base_addr);
|
||||||
|
reloc_addr.* = base_addr + @as(usize, @intCast(addend));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
67
arch/x86_64/boot/video.zig
Normal file
67
arch/x86_64/boot/video.zig
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
|
||||||
|
// Ported from Linux kernel include/uapi/linux/screen_info.h
|
||||||
|
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub const ScreenInfo = extern struct{
|
||||||
|
orig_x: u8 align(1), // 0x00
|
||||||
|
orig_y: u8 align(1), // 0x01
|
||||||
|
ext_mem_k: u16 align(1), // 0x02
|
||||||
|
orig_video_page: u16 align(1), // 0x04
|
||||||
|
orig_video_mode: u8 align(1), // 0x06
|
||||||
|
orig_video_cols: u8 align(1), // 0x07
|
||||||
|
flags: u8 align(1), // 0x08
|
||||||
|
unused2: u8 align(1), // 0x09
|
||||||
|
orig_video_ega_bx: u16 align(1), // 0x0a
|
||||||
|
unused3: u16 align(1), // 0x0c
|
||||||
|
orig_video_lines: u8 align(1), // 0x0e
|
||||||
|
orig_video_isVGA: u8 align(1), // 0x0f
|
||||||
|
orig_video_points: u16 align(1), // 0x10
|
||||||
|
|
||||||
|
// VESA graphic mode -- linear frame buffer
|
||||||
|
lfb_width: u16 align(1), // 0x12
|
||||||
|
lfb_height: u16 align(1), // 0x14
|
||||||
|
lfb_depth: u16 align(1), // 0x16
|
||||||
|
lfb_base: u32 align(1), // 0x18
|
||||||
|
lfb_size: u32 align(1), // 0x1c
|
||||||
|
cl_magic: u16 align(1), // 0x20
|
||||||
|
cl_offset: u16 align(1), // 0x22
|
||||||
|
lfb_linelength: u16 align(1), // 0x24
|
||||||
|
red_size: u8 align(1), // 0x26
|
||||||
|
red_pos: u8 align(1), // 0x27
|
||||||
|
green_size: u8 align(1), // 0x28
|
||||||
|
green_pos: u8 align(1), // 0x29
|
||||||
|
blue_size: u8 align(1), // 0x2a
|
||||||
|
blue_pos: u8 align(1), // 0x2b
|
||||||
|
rsvd_size: u8 align(1), // 0x2c
|
||||||
|
rsvd_pos: u8 align(1), // 0x2d
|
||||||
|
vesapm_seg: u16 align(1), // 0x2e
|
||||||
|
vesapm_off: u16 align(1), // 0x30
|
||||||
|
pages: u16 align(1), // 0x32
|
||||||
|
vesa_attributes: u16 align(1), // 0x34
|
||||||
|
capabilities: u32 align(1), // 0x36
|
||||||
|
ext_lfb_base: u32 align(1), // 0x3a
|
||||||
|
_reserved: [2]u8 align(1), // 0x3e
|
||||||
|
};
|
||||||
|
|
||||||
|
// Common video types
|
||||||
|
pub const VideoType = enum(u8) {
|
||||||
|
MDA = 0x10, // Monochrome Text Display
|
||||||
|
CGA = 0x11, // CGA Display
|
||||||
|
EGAM = 0x20, // EGA/VGA in Monochrome Mode
|
||||||
|
EGAC = 0x21, // EGA in Color Mode
|
||||||
|
VGAC = 0x22, // VGA+ in Color Mode
|
||||||
|
VLFB = 0x23, // VESA VGA in graphic mode
|
||||||
|
EFI = 0x70, // EFI graphic mode
|
||||||
|
};
|
||||||
|
|
||||||
|
// Video flags
|
||||||
|
pub const VIDEO_FLAGS_NOCURSOR: u8 = 1 << 0; // The video mode has no cursor set
|
||||||
|
|
||||||
|
// Video capabilities
|
||||||
|
pub const VIDEO_CAPABILITY_SKIP_QUIRKS: u32 = 1 << 0;
|
||||||
|
pub const VIDEO_CAPABILITY_64BIT_BASE: u32 = 1 << 1; // Frame buffer base is 64-bit
|
||||||
|
|
||||||
|
comptime {
|
||||||
|
std.debug.assert(@sizeOf(ScreenInfo) == 0x40);
|
||||||
|
}
|
||||||
26
arch/x86_64/build_arch.zig
Normal file
26
arch/x86_64/build_arch.zig
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const Step = std.Build.Step;
|
||||||
|
const boot_build = @import("boot/build_boot.zig");
|
||||||
|
|
||||||
|
fn buildKernel(b: *std.Build, optimize: std.builtin.OptimizeMode) *Step.Compile {
|
||||||
|
const target = b.resolveTargetQuery(.{
|
||||||
|
.cpu_arch = .x86_64,
|
||||||
|
.os_tag = .freestanding,
|
||||||
|
.abi = .none,
|
||||||
|
});
|
||||||
|
const kernel = b.addExecutable(.{
|
||||||
|
.name = "kernel",
|
||||||
|
.root_module = b.addModule("kernel", .{
|
||||||
|
.root_source_file = b.path("kernel/main.zig"),
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
kernel.entry = .{ .symbol_name = "start_kernel" };
|
||||||
|
return kernel;
|
||||||
|
}
|
||||||
|
pub fn buildImage(b: *std.Build) void {
|
||||||
|
const optimize = b.standardOptimizeOption(.{});
|
||||||
|
const kernel = buildKernel(b, optimize);
|
||||||
|
boot_build.buildBootImage(b, kernel);
|
||||||
|
}
|
||||||
43
arch/x86_64/desc.zig
Normal file
43
arch/x86_64/desc.zig
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
const processor = @import("processor.zig");
|
||||||
|
|
||||||
|
pub const GateDesc = packed struct {
|
||||||
|
offset_1: u16 = 0,
|
||||||
|
selector: u16 = 0,
|
||||||
|
ist: u3 = 0,
|
||||||
|
_reserved_1: u5 = 0,
|
||||||
|
gate_type: GateType = .interrupt,
|
||||||
|
_padding: u1 = 0,
|
||||||
|
dpl: processor.PrivilegeLevel = .Kernel,
|
||||||
|
present: u1 = 0,
|
||||||
|
offset_2: u16 = 0,
|
||||||
|
offset_3: u32 = 0,
|
||||||
|
_reserved_2: u32 = 0,
|
||||||
|
pub const GateType = enum(u4) {
|
||||||
|
interrupt = 0xe,
|
||||||
|
trap = 0xf,
|
||||||
|
};
|
||||||
|
pub fn getOffset(self: *const GateDesc) u64 {
|
||||||
|
return (@as(u64, self.offset_3) << 32) | (@as(u64, self.offset_2) << 16) | self.offset_1;
|
||||||
|
}
|
||||||
|
pub fn setOffset(self: *GateDesc, offset: u64) void {
|
||||||
|
self.offset_1 = @as(u16, offset & 0xFFFF);
|
||||||
|
self.offset_2 = @as(u16, (offset >> 16) & 0xFFFF);
|
||||||
|
self.offset_3 = @as(u32, (offset >> 32) & 0xFFFFFFFF);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn loadIdt(idt_table: []const GateDesc) void {
|
||||||
|
var idt_ptr: packed struct {
|
||||||
|
limit: u16,
|
||||||
|
base: u64,
|
||||||
|
} = .{
|
||||||
|
.limit = @as(u16, @sizeOf(GateDesc) * idt_table.len - 1),
|
||||||
|
.base = @intFromPtr(&idt_table[0]),
|
||||||
|
};
|
||||||
|
asm volatile (
|
||||||
|
\\ lidt %rax
|
||||||
|
:
|
||||||
|
: [idt_ptr] "{rax}" (&idt_ptr)
|
||||||
|
: .{}
|
||||||
|
);
|
||||||
|
}
|
||||||
19
arch/x86_64/io.zig
Normal file
19
arch/x86_64/io.zig
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
pub fn outb(port: u16, value: u8) void {
|
||||||
|
asm volatile (
|
||||||
|
\\outb %al, %dx
|
||||||
|
:
|
||||||
|
: [port] "{dx}" (port), [value] "{al}" (value)
|
||||||
|
: .{}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn inb(port: u16) u8 {
|
||||||
|
var value: u8 = 0;
|
||||||
|
asm volatile (
|
||||||
|
\\inb %dx, %al
|
||||||
|
: [value] "={al}" (value)
|
||||||
|
: [port] "{dx}" (port)
|
||||||
|
: .{}
|
||||||
|
);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
43
arch/x86_64/mem.zig
Normal file
43
arch/x86_64/mem.zig
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
pub const PAGE_SHIFT: usize = 12;
|
||||||
|
pub const PAGE_SIZE: usize = 1 << PAGE_SHIFT;
|
||||||
|
|
||||||
|
pub const PTE_SHIFT: u32 = 12;
|
||||||
|
pub const PMD_SHIFT: u32 = 21;
|
||||||
|
pub const PUD_SHIFT: u32 = 30;
|
||||||
|
pub const PGD_SHIFT: u32 = 39;
|
||||||
|
|
||||||
|
pub const PTE_SIZE: usize = 1 << PTE_SHIFT;
|
||||||
|
pub const PMD_SIZE: usize = 1 << PMD_SHIFT;
|
||||||
|
pub const PUD_SIZE: usize = 1 << PUD_SHIFT;
|
||||||
|
pub const PGD_SIZE: usize = 1 << PGD_SHIFT;
|
||||||
|
|
||||||
|
pub const PTE_MASK: usize = 1 << PTE_SHIFT - 1;
|
||||||
|
pub const PMD_MASK: usize = 1 << PMD_SHIFT - 1;
|
||||||
|
pub const PUD_MASK: usize = 1 << PUD_SHIFT - 1;
|
||||||
|
pub const PGD_MASK: usize = 1 << PGD_SHIFT - 1;
|
||||||
|
|
||||||
|
pub const ENTRIES_PER_TABLE: usize = PAGE_SIZE / 64;
|
||||||
|
|
||||||
|
pub const PFType = struct{
|
||||||
|
pub const PROT: usize = 0;
|
||||||
|
pub const WRITE: usize = 1<<1;
|
||||||
|
pub const USER: usize = 1<<2;
|
||||||
|
pub const RSVD: usize = 1<<3;
|
||||||
|
pub const INSTR: usize = 1<<4;
|
||||||
|
pub const PK: usize = 1<<5;
|
||||||
|
pub const SHSTK: usize = 1<<6;
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const PGDEntry = packed struct {
|
||||||
|
present: u1,
|
||||||
|
write: u1,
|
||||||
|
supervisor: u1,
|
||||||
|
write_through: u1,
|
||||||
|
cache_disable: u1,
|
||||||
|
accessed: u1,
|
||||||
|
_padding_1: u6,
|
||||||
|
addr: u40,
|
||||||
|
pub fn getIndex(self: usize) usize {
|
||||||
|
return (self >> PGD_SHIFT) & 0x1FF;
|
||||||
|
}
|
||||||
|
};
|
||||||
44
arch/x86_64/processor.zig
Normal file
44
arch/x86_64/processor.zig
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
pub fn readCr2() u64 {
|
||||||
|
return asm volatile (
|
||||||
|
\\ mov %cr2, %rax
|
||||||
|
: [ret] "={rax}" (-> u64),
|
||||||
|
:
|
||||||
|
: .{});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn readCr3() u64 {
|
||||||
|
return asm volatile (
|
||||||
|
\\ mov %cr3, %rax
|
||||||
|
: [ret] "={rax}" (-> u64),
|
||||||
|
:
|
||||||
|
: .{});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const PrivilegeLevel = enum(u4) {
|
||||||
|
Kernel = 0,
|
||||||
|
User = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const PtRegs = struct {
|
||||||
|
r15: usize,
|
||||||
|
r14: usize,
|
||||||
|
r13: usize,
|
||||||
|
r12: usize,
|
||||||
|
bp: usize,
|
||||||
|
bx: usize,
|
||||||
|
r11: usize,
|
||||||
|
r10: usize,
|
||||||
|
r9: usize,
|
||||||
|
r8: usize,
|
||||||
|
ax: usize,
|
||||||
|
cx: usize,
|
||||||
|
dx: usize,
|
||||||
|
si: usize,
|
||||||
|
di: usize,
|
||||||
|
code: usize,
|
||||||
|
ip: usize,
|
||||||
|
cs: usize,
|
||||||
|
flags: usize,
|
||||||
|
sp: usize,
|
||||||
|
ss: usize,
|
||||||
|
};
|
||||||
26
arch/x86_64/trap.zig
Normal file
26
arch/x86_64/trap.zig
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
pub const TrapType = enum(u8) {
|
||||||
|
DE = 0, // Divide-by-zero
|
||||||
|
DB = 1, // Debug
|
||||||
|
NMI = 2, // Non-maskable Interrupt
|
||||||
|
BP = 3, // Breakpoint
|
||||||
|
OF = 4, // Overflow
|
||||||
|
BR = 5, // Bound Range Exceeded
|
||||||
|
UD = 6, // Invalid Opcode
|
||||||
|
NM = 7, // Device Not Available
|
||||||
|
DF = 8, // Double Fault
|
||||||
|
OLD_MF = 9, // Coprocessor Segment Overrun
|
||||||
|
TS = 10, // Invalid TSS
|
||||||
|
NP = 11, // Segment Not Present
|
||||||
|
SS = 12, // Stack Segment Fault
|
||||||
|
GP = 13, // General Protection Fault
|
||||||
|
PF = 14, // Page Fault
|
||||||
|
SPURIOUS = 15, // Spurious Interrupt
|
||||||
|
MF = 16, // x87 Floating-Point Exception
|
||||||
|
AC = 17, // Alignment Check
|
||||||
|
MC = 18, // Machine Check
|
||||||
|
XF = 19, // SIMD Floating-Point Exception
|
||||||
|
VE = 20, // Virtualization Exception
|
||||||
|
CP = 21, // Control Protection Exception
|
||||||
|
VC = 29, // VMM Communication Exception
|
||||||
|
IRET = 32, // IRET Exception
|
||||||
|
};
|
||||||
50
build.zig
50
build.zig
@@ -1,35 +1,25 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const kernel_build = @import("kernel/build.zig");
|
|
||||||
fn buildImage(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode) *std.Build.Step {
|
|
||||||
switch (target.result.cpu.arch) {
|
|
||||||
.x86_64 => {
|
|
||||||
const arch_build = @import("arch/x86/boot/build.zig");
|
|
||||||
return arch_build.buildImage(b, optimize);
|
|
||||||
},
|
|
||||||
else => {
|
|
||||||
@panic("target architecture unsupported");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn build(b: *std.Build) void {
|
pub fn build(b: *std.Build) void {
|
||||||
const kernel_only_step = b.step("kernel", "Build the kernel only");
|
var arch_build_image: ?*const fn(*std.Build)void = null;
|
||||||
const full_step = b.step("full", "Build the full OS image");
|
const target = b.standardTargetOptions(.{
|
||||||
const qemu_step = b.step("qemu", "Build and run in QEMU");
|
.default_target = .{
|
||||||
const target = b.resolveTargetQuery(.{
|
.cpu_arch = .x86_64,
|
||||||
.cpu_arch = .x86_64,
|
.os_tag = .freestanding,
|
||||||
.os_tag = .freestanding,
|
.abi = .none,
|
||||||
.abi = .none
|
}
|
||||||
});
|
});
|
||||||
const optimize = b.standardOptimizeOption(.{});
|
if (target.query.cpu_arch) |arch| {
|
||||||
|
switch (arch) {
|
||||||
const kernel_install = kernel_build.buildKernelBin(b, target, optimize);
|
.x86_64 => {
|
||||||
kernel_only_step.dependOn(&kernel_install.step);
|
arch_build_image = @import("arch/x86_64/build_arch.zig").buildImage;
|
||||||
const image_step = buildImage(b, target, optimize);
|
},
|
||||||
b.getInstallStep().dependOn(image_step);
|
else => {},
|
||||||
full_step.dependOn(image_step);
|
}
|
||||||
|
}
|
||||||
qemu_step.dependOn(image_step);
|
if (arch_build_image) |build_fn| {
|
||||||
|
build_fn(b);
|
||||||
|
} else {
|
||||||
|
@panic("Architecture not specified or unsupported");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,81 +1,27 @@
|
|||||||
.{
|
.{
|
||||||
// This is the default name used by packages depending on this one. For
|
|
||||||
// example, when a user runs `zig fetch --save <url>`, this field is used
|
|
||||||
// as the key in the `dependencies` table. Although the user can choose a
|
|
||||||
// different name, most users will stick with this provided value.
|
|
||||||
//
|
|
||||||
// It is redundant to include "zig" in this name because it is already
|
|
||||||
// within the Zig package namespace.
|
|
||||||
.name = .YukiOS,
|
.name = .YukiOS,
|
||||||
// This is a [Semantic Version](https://semver.org/).
|
|
||||||
// In a future version of Zig it will be used for package deduplication.
|
|
||||||
.version = "0.0.0",
|
.version = "0.0.0",
|
||||||
// Together with name, this represents a globally unique package
|
.fingerprint = 0x85d3440a268a6d56, // Changing this has security and trust implications.
|
||||||
// identifier. This field is generated by the Zig toolchain when the
|
.minimum_zig_version = "0.16.0-dev.2471+e9eadee00",
|
||||||
// package is first created, and then *never changes*. This allows
|
|
||||||
// unambiguous detection of one package being an updated version of
|
|
||||||
// another.
|
|
||||||
//
|
|
||||||
// When forking a Zig project, this id should be regenerated (delete the
|
|
||||||
// field and run `zig build`) if the upstream project is still maintained.
|
|
||||||
// Otherwise, the fork is *hostile*, attempting to take control over the
|
|
||||||
// original project's identity. Thus it is recommended to leave the comment
|
|
||||||
// on the following line intact, so that it shows up in code reviews that
|
|
||||||
// modify the field.
|
|
||||||
.fingerprint = 0x85d3440a21cff096, // Changing this has security and trust implications.
|
|
||||||
// Tracks the earliest Zig version that the package considers to be a
|
|
||||||
// supported use case.
|
|
||||||
.minimum_zig_version = "0.15.2",
|
|
||||||
// This field is optional.
|
|
||||||
// Each dependency must either provide a `url` and `hash`, or a `path`.
|
|
||||||
// `zig build --fetch` can be used to fetch all dependencies of a package, recursively.
|
|
||||||
// Once all dependencies are fetched, `zig build` no longer requires
|
|
||||||
// internet connectivity.
|
|
||||||
.dependencies = .{
|
.dependencies = .{
|
||||||
// See `zig fetch --save <url>` for a command-line interface for adding dependencies.
|
.elfy = .{
|
||||||
//.example = .{
|
.url = "https://github.com/Hydrostic/elfy.zig/archive/refs/tags/v0.1.1.tar.gz",
|
||||||
// // When updating this field to a new URL, be sure to delete the corresponding
|
.hash = "elfy-0.1.0-BML8MtggAQCLYjG-mEkO20uMf3-6cfU0_s3Xht3tSFWW",
|
||||||
// // `hash`, otherwise you are communicating that you expect to find the old hash at
|
.lazy = false,
|
||||||
// // the new URL. If the contents of a URL change this will result in a hash mismatch
|
},
|
||||||
// // which will prevent zig from using it.
|
.mvzr = .{
|
||||||
// .url = "https://example.com/foo.tar.gz",
|
.url = "https://github.com/mnemnion/mvzr/archive/refs/tags/v0.3.7.tar.gz",
|
||||||
//
|
.hash = "mvzr-0.3.7-ZSOky5FtAQB2VrFQPNbXHQCFJxWTMAYEK7ljYEaMR6jt",
|
||||||
// // This is computed from the file contents of the directory of files that is
|
.lazy = false,
|
||||||
// // obtained after fetching `url` and applying the inclusion rules given by
|
}
|
||||||
// // `paths`.
|
|
||||||
// //
|
|
||||||
// // This field is the source of truth; packages do not come from a `url`; they
|
|
||||||
// // come from a `hash`. `url` is just one of many possible mirrors for how to
|
|
||||||
// // obtain a package matching this `hash`.
|
|
||||||
// //
|
|
||||||
// // Uses the [multihash](https://multiformats.io/multihash/) format.
|
|
||||||
// .hash = "...",
|
|
||||||
//
|
|
||||||
// // When this is provided, the package is found in a directory relative to the
|
|
||||||
// // build root. In this case the package's hash is irrelevant and therefore not
|
|
||||||
// // computed. This field and `url` are mutually exclusive.
|
|
||||||
// .path = "foo",
|
|
||||||
//
|
|
||||||
// // When this is set to `true`, a package is declared to be lazily
|
|
||||||
// // fetched. This makes the dependency only get fetched if it is
|
|
||||||
// // actually used.
|
|
||||||
// .lazy = false,
|
|
||||||
//},
|
|
||||||
},
|
},
|
||||||
// Specifies the set of files and directories that are included in this package.
|
|
||||||
// Only files and directories listed here are included in the `hash` that
|
|
||||||
// is computed for this package. Only files listed here will remain on disk
|
|
||||||
// when using the zig package manager. As a rule of thumb, one should list
|
|
||||||
// files required for compilation plus any license(s).
|
|
||||||
// Paths are relative to the build root. Use the empty string (`""`) to refer to
|
|
||||||
// the build root itself.
|
|
||||||
// A directory listed here means that all files within, recursively, are included.
|
|
||||||
.paths = .{
|
.paths = .{
|
||||||
"build.zig",
|
"build.zig",
|
||||||
"build.zig.zon",
|
"build.zig.zon",
|
||||||
"src",
|
"arch",
|
||||||
// For example...
|
"drivers",
|
||||||
//"LICENSE",
|
"fs",
|
||||||
//"README.md",
|
"kernel",
|
||||||
|
"mm",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,75 +0,0 @@
|
|||||||
const std = @import("std");
|
|
||||||
const uefi = std.os.uefi;
|
|
||||||
const unicode = std.unicode;
|
|
||||||
const SimpleTextOutput = uefi.protocol.SimpleTextOutput;
|
|
||||||
|
|
||||||
pub const UefiConsole = struct {
|
|
||||||
console_out: ?*SimpleTextOutput = null,
|
|
||||||
pub fn init(system_table: *uefi.tables.SystemTable) UefiConsole {
|
|
||||||
var console = UefiConsole{};
|
|
||||||
var con_out = system_table.con_out orelse return console;
|
|
||||||
con_out.clearScreen() catch return console;
|
|
||||||
con_out.setCursorPosition(0, 0) catch return console;
|
|
||||||
console.console_out = con_out;
|
|
||||||
UefiWriter.UEFI_WRITER_VTABLE = .{
|
|
||||||
.drain = UefiWriter.drain,
|
|
||||||
};
|
|
||||||
return console;
|
|
||||||
}
|
|
||||||
pub const UefiWriter = struct {
|
|
||||||
console: *UefiConsole,
|
|
||||||
interface: std.Io.Writer,
|
|
||||||
var UEFI_WRITER_VTABLE: std.io.Writer.VTable = .{
|
|
||||||
.drain = undefined,
|
|
||||||
};
|
|
||||||
pub fn drain(ptr: *std.Io.Writer, buf: []const []const u8, splat: usize) !usize {
|
|
||||||
_ = splat;
|
|
||||||
const self: *UefiWriter = @fieldParentPtr("interface", ptr);
|
|
||||||
if (self.console.console_out) |out| {
|
|
||||||
var written: usize = 0;
|
|
||||||
for (buf) |b| {
|
|
||||||
|
|
||||||
var start: usize = 0;
|
|
||||||
var ucs2_buf = [_]u16{0} ** 65;
|
|
||||||
while (start < buf.len) {
|
|
||||||
const len = unicode.utf8ToUtf16Le(ucs2_buf[0..64], b[start..@min(start + 64, b.len)]) catch {
|
|
||||||
return error.WriteFailed;
|
|
||||||
};
|
|
||||||
ucs2_buf[len] = 0;
|
|
||||||
_ = out.outputString(@ptrCast(&ucs2_buf)) catch {
|
|
||||||
return error.WriteFailed;
|
|
||||||
};
|
|
||||||
start += len;
|
|
||||||
}
|
|
||||||
written += b.len;
|
|
||||||
}
|
|
||||||
return written;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
pub fn writer(self: *UefiConsole) UefiWriter {
|
|
||||||
const w = UefiWriter{
|
|
||||||
.console = self,
|
|
||||||
.interface = .{
|
|
||||||
.vtable = @call(.never_inline, getVtable, .{}),
|
|
||||||
.buffer = &[0]u8{},
|
|
||||||
.end = 0
|
|
||||||
},
|
|
||||||
};
|
|
||||||
return w;
|
|
||||||
}
|
|
||||||
fn getVtable() *const std.Io.Writer.VTable {
|
|
||||||
return &UefiWriter.UEFI_WRITER_VTABLE;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
pub var uc: UefiConsole = undefined;
|
|
||||||
pub fn initUefiConsole(system_table: *uefi.tables.SystemTable) void {
|
|
||||||
uc = UefiConsole.init(system_table);
|
|
||||||
}
|
|
||||||
pub fn info(comptime fmt: []const u8, args: anytype) void {
|
|
||||||
var w = uc.writer();
|
|
||||||
w.interface.print(fmt, args) catch {};
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
const std = @import("std");
|
|
||||||
const console = @import("console.zig");
|
|
||||||
const uefi = std.os.uefi;
|
|
||||||
const SystemTable = uefi.tables.SystemTable;
|
|
||||||
|
|
||||||
export fn efi_pe_entry(image_handle: uefi.Handle, system_table: *SystemTable) callconv(.{ .x86_64_win = .{} }) uefi.Status {
|
|
||||||
const mark_ptr: *usize = @ptrFromInt(0x10000);
|
|
||||||
mark_ptr.* = 0xdeadbeef;
|
|
||||||
_ = image_handle;
|
|
||||||
if (system_table.hdr.signature != SystemTable.signature) {
|
|
||||||
return uefi.Status.invalid_parameter;
|
|
||||||
}
|
|
||||||
console.initUefiConsole(system_table);
|
|
||||||
console.info("Booting YukiOS kernel\n", .{});
|
|
||||||
while(true) {}
|
|
||||||
return .success;
|
|
||||||
}
|
|
||||||
@@ -1,211 +0,0 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0 */
|
|
||||||
/*
|
|
||||||
* Portable Executable (PE) format definitions.
|
|
||||||
*
|
|
||||||
* This file is derived from the Linux kernel source:
|
|
||||||
* include/linux/pe.h
|
|
||||||
*
|
|
||||||
* Copyright holders of the original Linux kernel code retain their copyright.
|
|
||||||
* See the original Linux kernel source for full copyright and licensing details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define IMAGE_DOS_SIGNATURE 0x5a4d /* "MZ" */
|
|
||||||
|
|
||||||
#define IMAGE_NT_SIGNATURE 0x00004550 /* "PE\0\0" */
|
|
||||||
|
|
||||||
#define IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x0107 /* ROM image (for R3000/R4000/R10000/ALPHA), without MZ and PE\0\0 sign */
|
|
||||||
#define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x010b /* PE32 executable image */
|
|
||||||
#define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x020b /* PE32+ executable image */
|
|
||||||
|
|
||||||
/* machine type */
|
|
||||||
#define IMAGE_FILE_MACHINE_UNKNOWN 0x0000 /* Unknown architecture */
|
|
||||||
#define IMAGE_FILE_MACHINE_TARGET_HOST 0x0001 /* Interacts with the host and not a WOW64 guest (not for file image) */
|
|
||||||
#define IMAGE_FILE_MACHINE_ALPHA_OLD 0x0183 /* DEC Alpha AXP 32-bit (old images) */
|
|
||||||
#define IMAGE_FILE_MACHINE_ALPHA 0x0184 /* DEC Alpha AXP 32-bit */
|
|
||||||
#define IMAGE_FILE_MACHINE_ALPHA64 0x0284 /* DEC Alpha AXP 64-bit (with 8kB page size) */
|
|
||||||
#define IMAGE_FILE_MACHINE_AXP64 IMAGE_FILE_MACHINE_ALPHA64
|
|
||||||
#define IMAGE_FILE_MACHINE_AM33 0x01d3 /* Matsushita AM33, now Panasonic MN103 */
|
|
||||||
#define IMAGE_FILE_MACHINE_AMD64 0x8664 /* AMD64 (x64) */
|
|
||||||
#define IMAGE_FILE_MACHINE_ARM 0x01c0 /* ARM Little-Endian (ARMv4) */
|
|
||||||
#define IMAGE_FILE_MACHINE_THUMB 0x01c2 /* ARM Thumb Little-Endian (ARMv4T) */
|
|
||||||
#define IMAGE_FILE_MACHINE_ARMNT 0x01c4 /* ARM Thumb-2 Little-Endian (ARMv7) */
|
|
||||||
#define IMAGE_FILE_MACHINE_ARMV7 IMAGE_FILE_MACHINE_ARMNT
|
|
||||||
#define IMAGE_FILE_MACHINE_ARM64 0xaa64 /* ARM64 Little-Endian (Classic ABI) */
|
|
||||||
#define IMAGE_FILE_MACHINE_ARM64EC 0xa641 /* ARM64 Little-Endian (Emulation Compatible ABI for AMD64) */
|
|
||||||
#define IMAGE_FILE_MACHINE_ARM64X 0xa64e /* ARM64 Little-Endian (fat binary with both Classic ABI and EC ABI code) */
|
|
||||||
#define IMAGE_FILE_MACHINE_CEE 0xc0ee /* COM+ Execution Engine (CLR pure MSIL object files) */
|
|
||||||
#define IMAGE_FILE_MACHINE_CEF 0x0cef /* Windows CE 3.0 Common Executable Format (CEF bytecode) */
|
|
||||||
#define IMAGE_FILE_MACHINE_CHPE_X86 0x3a64 /* ARM64 Little-Endian (Compiled Hybrid PE ABI for I386) */
|
|
||||||
#define IMAGE_FILE_MACHINE_HYBRID_X86 IMAGE_FILE_MACHINE_CHPE_X86
|
|
||||||
#define IMAGE_FILE_MACHINE_EBC 0x0ebc /* EFI/UEFI Byte Code */
|
|
||||||
#define IMAGE_FILE_MACHINE_I386 0x014c /* Intel 386 (x86) */
|
|
||||||
#define IMAGE_FILE_MACHINE_I860 0x014d /* Intel 860 (N10) */
|
|
||||||
#define IMAGE_FILE_MACHINE_IA64 0x0200 /* Intel IA-64 (with 8kB page size) */
|
|
||||||
#define IMAGE_FILE_MACHINE_LOONGARCH32 0x6232 /* LoongArch 32-bit processor family */
|
|
||||||
#define IMAGE_FILE_MACHINE_LOONGARCH64 0x6264 /* LoongArch 64-bit processor family */
|
|
||||||
#define IMAGE_FILE_MACHINE_M32R 0x9041 /* Mitsubishi M32R 32-bit Little-Endian */
|
|
||||||
#define IMAGE_FILE_MACHINE_M68K 0x0268 /* Motorola 68000 series */
|
|
||||||
#define IMAGE_FILE_MACHINE_MIPS16 0x0266 /* MIPS III with MIPS16 ASE Little-Endian */
|
|
||||||
#define IMAGE_FILE_MACHINE_MIPSFPU 0x0366 /* MIPS III with FPU Little-Endian */
|
|
||||||
#define IMAGE_FILE_MACHINE_MIPSFPU16 0x0466 /* MIPS III with MIPS16 ASE and FPU Little-Endian */
|
|
||||||
#define IMAGE_FILE_MACHINE_MPPC_601 0x0601 /* PowerPC 32-bit Big-Endian */
|
|
||||||
#define IMAGE_FILE_MACHINE_OMNI 0xace1 /* Microsoft OMNI VM (omniprox.dll) */
|
|
||||||
#define IMAGE_FILE_MACHINE_PARISC 0x0290 /* HP PA-RISC */
|
|
||||||
#define IMAGE_FILE_MACHINE_POWERPC 0x01f0 /* PowerPC 32-bit Little-Endian */
|
|
||||||
#define IMAGE_FILE_MACHINE_POWERPCFP 0x01f1 /* PowerPC 32-bit with FPU Little-Endian */
|
|
||||||
#define IMAGE_FILE_MACHINE_POWERPCBE 0x01f2 /* PowerPC 64-bit Big-Endian */
|
|
||||||
#define IMAGE_FILE_MACHINE_R3000 0x0162 /* MIPS I Little-Endian */
|
|
||||||
#define IMAGE_FILE_MACHINE_R3000_BE 0x0160 /* MIPS I Big-Endian */
|
|
||||||
#define IMAGE_FILE_MACHINE_R4000 0x0166 /* MIPS III Little-Endian (with 1kB or 4kB page size) */
|
|
||||||
#define IMAGE_FILE_MACHINE_R10000 0x0168 /* MIPS IV Little-Endian */
|
|
||||||
#define IMAGE_FILE_MACHINE_RISCV32 0x5032 /* RISC-V 32-bit address space */
|
|
||||||
#define IMAGE_FILE_MACHINE_RISCV64 0x5064 /* RISC-V 64-bit address space */
|
|
||||||
#define IMAGE_FILE_MACHINE_RISCV128 0x5128 /* RISC-V 128-bit address space */
|
|
||||||
#define IMAGE_FILE_MACHINE_SH3 0x01a2 /* Hitachi SH-3 32-bit Little-Endian (with 1kB page size) */
|
|
||||||
#define IMAGE_FILE_MACHINE_SH3DSP 0x01a3 /* Hitachi SH-3 DSP 32-bit (with 1kB page size) */
|
|
||||||
#define IMAGE_FILE_MACHINE_SH3E 0x01a4 /* Hitachi SH-3E Little-Endian (with 1kB page size) */
|
|
||||||
#define IMAGE_FILE_MACHINE_SH4 0x01a6 /* Hitachi SH-4 32-bit Little-Endian (with 1kB page size) */
|
|
||||||
#define IMAGE_FILE_MACHINE_SH5 0x01a8 /* Hitachi SH-5 64-bit */
|
|
||||||
#define IMAGE_FILE_MACHINE_TAHOE 0x07cc /* Intel EM machine */
|
|
||||||
#define IMAGE_FILE_MACHINE_TRICORE 0x0520 /* Infineon AUDO 32-bit */
|
|
||||||
#define IMAGE_FILE_MACHINE_WCEMIPSV2 0x0169 /* MIPS Windows CE v2 Little-Endian */
|
|
||||||
|
|
||||||
/* flags */
|
|
||||||
#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 /* Relocation info stripped from file */
|
|
||||||
#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 /* File is executable (i.e. no unresolved external references) */
|
|
||||||
#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 /* Line nunbers stripped from file */
|
|
||||||
#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 /* Local symbols stripped from file */
|
|
||||||
#define IMAGE_FILE_AGGRESSIVE_WS_TRIM 0x0010 /* Aggressively trim working set */
|
|
||||||
#define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020 /* App can handle >2gb addresses (image can be loaded at address above 2GB) */
|
|
||||||
#define IMAGE_FILE_16BIT_MACHINE 0x0040 /* 16 bit word machine */
|
|
||||||
#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 /* Bytes of machine word are reversed (should be set together with IMAGE_FILE_BYTES_REVERSED_HI) */
|
|
||||||
#define IMAGE_FILE_32BIT_MACHINE 0x0100 /* 32 bit word machine */
|
|
||||||
#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 /* Debugging info stripped from file in .DBG file */
|
|
||||||
#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 /* If Image is on removable media, copy and run from the swap file */
|
|
||||||
#define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 /* If Image is on Net, copy and run from the swap file */
|
|
||||||
#define IMAGE_FILE_SYSTEM 0x1000 /* System kernel-mode file (can't be loaded in user-mode) */
|
|
||||||
#define IMAGE_FILE_DLL 0x2000 /* File is a DLL */
|
|
||||||
#define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 /* File should only be run on a UP (uniprocessor) machine */
|
|
||||||
#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 /* Bytes of machine word are reversed (should be set together with IMAGE_FILE_BYTES_REVERSED_LO) */
|
|
||||||
|
|
||||||
/* subsys */
|
|
||||||
#define IMAGE_SUBSYSTEM_UNKNOWN 0 /* Unknown subsystem */
|
|
||||||
#define IMAGE_SUBSYSTEM_NATIVE 1 /* No subsystem required (NT device drivers and NT native system processes) */
|
|
||||||
#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 /* Windows graphical user interface (GUI) subsystem */
|
|
||||||
#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 /* Windows character-mode user interface (CUI) subsystem */
|
|
||||||
#define IMAGE_SUBSYSTEM_WINDOWS_OLD_CE_GUI 4 /* Old Windows CE subsystem */
|
|
||||||
#define IMAGE_SUBSYSTEM_OS2_CUI 5 /* OS/2 CUI subsystem */
|
|
||||||
#define IMAGE_SUBSYSTEM_RESERVED_6 6
|
|
||||||
#define IMAGE_SUBSYSTEM_POSIX_CUI 7 /* POSIX CUI subsystem */
|
|
||||||
#define IMAGE_SUBSYSTEM_MMOSA 8 /* MMOSA/Native Win32E */
|
|
||||||
#define IMAGE_SUBSYSTEM_WINDOWS_CE_GUI 9 /* Windows CE subsystem */
|
|
||||||
#define IMAGE_SUBSYSTEM_EFI_APPLICATION 10 /* Extensible Firmware Interface (EFI) application */
|
|
||||||
#define IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11 /* EFI driver with boot services */
|
|
||||||
#define IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12 /* EFI driver with run-time services */
|
|
||||||
#define IMAGE_SUBSYSTEM_EFI_ROM_IMAGE 13 /* EFI ROM image */
|
|
||||||
#define IMAGE_SUBSYSTEM_XBOX 14 /* Xbox system */
|
|
||||||
#define IMAGE_SUBSYSTEM_RESERVED_15 15
|
|
||||||
#define IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION 16 /* Windows Boot application */
|
|
||||||
#define IMAGE_SUBSYSTEM_XBOX_CODE_CATALOG 17 /* Xbox Code Catalog */
|
|
||||||
|
|
||||||
/* dll_flags */
|
|
||||||
#define IMAGE_LIBRARY_PROCESS_INIT 0x0001 /* DLL initialization function called just after process initialization */
|
|
||||||
#define IMAGE_LIBRARY_PROCESS_TERM 0x0002 /* DLL initialization function called just before process termination */
|
|
||||||
#define IMAGE_LIBRARY_THREAD_INIT 0x0004 /* DLL initialization function called just after thread initialization */
|
|
||||||
#define IMAGE_LIBRARY_THREAD_TERM 0x0008 /* DLL initialization function called just before thread initialization */
|
|
||||||
#define IMAGE_DLLCHARACTERISTICS_RESERVED_4 0x0010
|
|
||||||
#define IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA 0x0020 /* ASLR with 64 bit address space (image can be loaded at address above 4GB) */
|
|
||||||
#define IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE 0x0040 /* The DLL can be relocated at load time */
|
|
||||||
#define IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY 0x0080 /* Code integrity checks are forced */
|
|
||||||
#define IMAGE_DLLCHARACTERISTICS_NX_COMPAT 0x0100 /* Image is compatible with data execution prevention */
|
|
||||||
#define IMAGE_DLLCHARACTERISTICS_NO_ISOLATION 0x0200 /* Image is isolation aware, but should not be isolated (prevents loading of manifest file) */
|
|
||||||
#define IMAGE_DLLCHARACTERISTICS_NO_SEH 0x0400 /* Image does not use SEH, no SE handler may reside in this image */
|
|
||||||
#define IMAGE_DLLCHARACTERISTICS_NO_BIND 0x0800 /* Do not bind the image */
|
|
||||||
#define IMAGE_DLLCHARACTERISTICS_X86_THUNK 0x1000 /* Image is a Wx86 Thunk DLL (for non-x86/risc DLL files) */
|
|
||||||
#define IMAGE_DLLCHARACTERISTICS_APPCONTAINER 0x1000 /* Image should execute in an AppContainer (for EXE Metro Apps in Windows 8) */
|
|
||||||
#define IMAGE_DLLCHARACTERISTICS_WDM_DRIVER 0x2000 /* A WDM driver */
|
|
||||||
#define IMAGE_DLLCHARACTERISTICS_GUARD_CF 0x4000 /* Image supports Control Flow Guard */
|
|
||||||
#define IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE 0x8000 /* The image is terminal server (Remote Desktop Services) aware */
|
|
||||||
|
|
||||||
/* IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS flags */
|
|
||||||
#define IMAGE_DLLCHARACTERISTICS_EX_CET_COMPAT 0x0001 /* Image is Control-flow Enforcement Technology Shadow Stack compatible */
|
|
||||||
#define IMAGE_DLLCHARACTERISTICS_EX_CET_COMPAT_STRICT_MODE 0x0002 /* CET is enforced in strict mode */
|
|
||||||
#define IMAGE_DLLCHARACTERISTICS_EX_CET_SET_CONTEXT_IP_VALIDATION_RELAXED_MODE 0x0004 /* Relaxed mode for Context IP Validation under CET is allowed */
|
|
||||||
#define IMAGE_DLLCHARACTERISTICS_EX_CET_DYNAMIC_APIS_ALLOW_IN_PROC 0x0008 /* Use of dynamic APIs is restricted to processes only */
|
|
||||||
#define IMAGE_DLLCHARACTERISTICS_EX_CET_RESERVED_1 0x0010
|
|
||||||
#define IMAGE_DLLCHARACTERISTICS_EX_CET_RESERVED_2 0x0020
|
|
||||||
#define IMAGE_DLLCHARACTERISTICS_EX_FORWARD_CFI_COMPAT 0x0040 /* All branch targets in all image code sections are annotated with forward-edge control flow integrity guard instructions */
|
|
||||||
#define IMAGE_DLLCHARACTERISTICS_EX_HOTPATCH_COMPATIBLE 0x0080 /* Image can be modified while in use, hotpatch-compatible */
|
|
||||||
|
|
||||||
/* section_header flags */
|
|
||||||
#define IMAGE_SCN_SCALE_INDEX 0x00000001 /* address of tls index is scaled = multiplied by 4 (for .tls section on MIPS only) */
|
|
||||||
#define IMAGE_SCN_TYPE_NO_LOAD 0x00000002 /* reserved */
|
|
||||||
#define IMAGE_SCN_TYPE_GROUPED 0x00000004 /* obsolete (used for 16-bit offset code) */
|
|
||||||
#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 /* .o only - don't pad - obsolete (same as IMAGE_SCN_ALIGN_1BYTES) */
|
|
||||||
#define IMAGE_SCN_TYPE_COPY 0x00000010 /* reserved */
|
|
||||||
#define IMAGE_SCN_CNT_CODE 0x00000020 /* .text */
|
|
||||||
#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 /* .data */
|
|
||||||
#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 /* .bss */
|
|
||||||
#define IMAGE_SCN_LNK_OTHER 0x00000100 /* .o only - other type than code, data or info */
|
|
||||||
#define IMAGE_SCN_LNK_INFO 0x00000200 /* .o only - .drectve comments */
|
|
||||||
#define IMAGE_SCN_LNK_OVERLAY 0x00000400 /* section contains overlay */
|
|
||||||
#define IMAGE_SCN_LNK_REMOVE 0x00000800 /* .o only - scn to be rm'd*/
|
|
||||||
#define IMAGE_SCN_LNK_COMDAT 0x00001000 /* .o only - COMDAT data */
|
|
||||||
#define IMAGE_SCN_RESERVED_13 0x00002000 /* spec omits this */
|
|
||||||
#define IMAGE_SCN_MEM_PROTECTED 0x00004000 /* section is memory protected (for M68K) */
|
|
||||||
#define IMAGE_SCN_NO_DEFER_SPEC_EXC 0x00004000 /* reset speculative exceptions handling bits in the TLB entries (for non-M68K) */
|
|
||||||
#define IMAGE_SCN_MEM_FARDATA 0x00008000 /* section uses FAR_EXTERNAL relocations (for M68K) */
|
|
||||||
#define IMAGE_SCN_GPREL 0x00008000 /* global pointer referenced data (for non-M68K) */
|
|
||||||
#define IMAGE_SCN_MEM_SYSHEAP 0x00010000 /* use system heap (for M68K) */
|
|
||||||
#define IMAGE_SCN_MEM_PURGEABLE 0x00020000 /* section can be released from RAM (for M68K) */
|
|
||||||
#define IMAGE_SCN_MEM_16BIT 0x00020000 /* section is 16-bit (for non-M68K where it makes sense: I386, THUMB, MIPS16, MIPSFPU16, ...) */
|
|
||||||
#define IMAGE_SCN_MEM_LOCKED 0x00040000 /* prevent the section from being moved (for M68K and .o I386) */
|
|
||||||
#define IMAGE_SCN_MEM_PRELOAD 0x00080000 /* section is preload to RAM (for M68K and .o I386) */
|
|
||||||
/* and here they just stuck a 1-byte integer in the middle of a bitfield */
|
|
||||||
#define IMAGE_SCN_ALIGN_1BYTES 0x00100000 /* .o only - it does what it says on the box */
|
|
||||||
#define IMAGE_SCN_ALIGN_2BYTES 0x00200000
|
|
||||||
#define IMAGE_SCN_ALIGN_4BYTES 0x00300000
|
|
||||||
#define IMAGE_SCN_ALIGN_8BYTES 0x00400000
|
|
||||||
#define IMAGE_SCN_ALIGN_16BYTES 0x00500000
|
|
||||||
#define IMAGE_SCN_ALIGN_32BYTES 0x00600000
|
|
||||||
#define IMAGE_SCN_ALIGN_64BYTES 0x00700000
|
|
||||||
#define IMAGE_SCN_ALIGN_128BYTES 0x00800000
|
|
||||||
#define IMAGE_SCN_ALIGN_256BYTES 0x00900000
|
|
||||||
#define IMAGE_SCN_ALIGN_512BYTES 0x00a00000
|
|
||||||
#define IMAGE_SCN_ALIGN_1024BYTES 0x00b00000
|
|
||||||
#define IMAGE_SCN_ALIGN_2048BYTES 0x00c00000
|
|
||||||
#define IMAGE_SCN_ALIGN_4096BYTES 0x00d00000
|
|
||||||
#define IMAGE_SCN_ALIGN_8192BYTES 0x00e00000
|
|
||||||
#define IMAGE_SCN_ALIGN_RESERVED 0x00f00000
|
|
||||||
#define IMAGE_SCN_ALIGN_MASK 0x00f00000
|
|
||||||
#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 /* .o only - extended relocations */
|
|
||||||
#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 /* scn can be discarded */
|
|
||||||
#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 /* cannot be cached */
|
|
||||||
#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 /* not pageable */
|
|
||||||
#define IMAGE_SCN_MEM_SHARED 0x10000000 /* can be shared */
|
|
||||||
#define IMAGE_SCN_MEM_EXECUTE 0x20000000 /* can be executed as code */
|
|
||||||
#define IMAGE_SCN_MEM_READ 0x40000000 /* readable */
|
|
||||||
#define IMAGE_SCN_MEM_WRITE 0x80000000 /* writeable */
|
|
||||||
|
|
||||||
#define IMAGE_DEBUG_TYPE_UNKNOWN 0 /* Unknown value, ignored by all tools */
|
|
||||||
#define IMAGE_DEBUG_TYPE_COFF 1 /* COFF debugging information */
|
|
||||||
#define IMAGE_DEBUG_TYPE_CODEVIEW 2 /* CodeView debugging information or Visual C++ Program Database debugging information */
|
|
||||||
#define IMAGE_DEBUG_TYPE_FPO 3 /* Frame pointer omission (FPO) information */
|
|
||||||
#define IMAGE_DEBUG_TYPE_MISC 4 /* Location of DBG file with CodeView debugging information */
|
|
||||||
#define IMAGE_DEBUG_TYPE_EXCEPTION 5 /* Exception information, copy of .pdata section */
|
|
||||||
#define IMAGE_DEBUG_TYPE_FIXUP 6 /* Fixup information */
|
|
||||||
#define IMAGE_DEBUG_TYPE_OMAP_TO_SRC 7 /* The mapping from an RVA in image to an RVA in source image */
|
|
||||||
#define IMAGE_DEBUG_TYPE_OMAP_FROM_SRC 8 /* The mapping from an RVA in source image to an RVA in image */
|
|
||||||
#define IMAGE_DEBUG_TYPE_BORLAND 9 /* Borland debugging information */
|
|
||||||
#define IMAGE_DEBUG_TYPE_RESERVED10 10 /* Coldpath / Hotpatch debug information */
|
|
||||||
#define IMAGE_DEBUG_TYPE_CLSID 11 /* CLSID */
|
|
||||||
#define IMAGE_DEBUG_TYPE_VC_FEATURE 12 /* Visual C++ counts / statistics */
|
|
||||||
#define IMAGE_DEBUG_TYPE_POGO 13 /* COFF group information, data for profile-guided optimization */
|
|
||||||
#define IMAGE_DEBUG_TYPE_ILTCG 14 /* Incremental link-time code generation */
|
|
||||||
#define IMAGE_DEBUG_TYPE_MPX 15 /* Intel Memory Protection Extensions */
|
|
||||||
#define IMAGE_DEBUG_TYPE_REPRO 16 /* PE determinism or reproducibility */
|
|
||||||
#define IMAGE_DEBUG_TYPE_EMBEDDED_PORTABLE_PDB 17 /* Embedded Portable PDB debugging information */
|
|
||||||
#define IMAGE_DEBUG_TYPE_SPGO 18 /* Sample profile-guided optimization */
|
|
||||||
#define IMAGE_DEBUG_TYPE_PDBCHECKSUM 19 /* PDB Checksum */
|
|
||||||
#define IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS 20 /* Extended DLL characteristics bits */
|
|
||||||
#define IMAGE_DEBUG_TYPE_PERFMAP 21 /* Location of associated Ready To Run PerfMap file */
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
export fn kernel_start() noreturn {
|
|
||||||
while (true) {}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
const std = @import("std");
|
|
||||||
|
|
||||||
pub fn buildKernelBin(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode) *std.Build.Step.Compile {
|
|
||||||
const kernel = b.addExecutable(.{
|
|
||||||
.name = "kernel.bin",
|
|
||||||
.use_llvm = true,
|
|
||||||
.use_lld = true,
|
|
||||||
.root_module = b.createModule(.{
|
|
||||||
.root_source_file = b.path("init/main.zig"),
|
|
||||||
.target = target,
|
|
||||||
.optimize = optimize,
|
|
||||||
.code_model = .kernel,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
switch (target.result.cpu.arch) {
|
|
||||||
.x86_64 => {
|
|
||||||
kernel.setLinkerScript(b.path("arch/x86/kernel_bin.ld"));
|
|
||||||
},
|
|
||||||
else => {
|
|
||||||
@panic("target architecture unsupported");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
kernel.entry = .{
|
|
||||||
.symbol_name = "kernel_start",
|
|
||||||
};
|
|
||||||
kernel.link_gc_sections = false;
|
|
||||||
return kernel;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn buildKernelBinInstall(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode) *std.Build.Step.InstallArtifact {
|
|
||||||
return b.addInstallArtifact(buildKernelBin(b, target, optimize), .{});
|
|
||||||
}
|
|
||||||
4
kernel/main.zig
Normal file
4
kernel/main.zig
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export fn start_kernel() callconv(.c) noreturn {
|
||||||
|
// Placeholder for kernel start function
|
||||||
|
while (true) {}
|
||||||
|
}
|
||||||
@@ -1,11 +1,12 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -e
|
set -e
|
||||||
|
zig build
|
||||||
|
|
||||||
IMG=disk.img
|
IMG=zig-out/disk.img
|
||||||
SIZE=256M
|
SIZE=256M
|
||||||
MNT=/tmp/$(tr -dc 'A-Za-z0-9' </dev/urandom | head -c 16)
|
MNT=/tmp/$(tr -dc 'A-Za-z0-9' </dev/urandom | head -c 16)
|
||||||
LIMINE_DIR=$HOME/Limine
|
LIMINE_DIR=$HOME/Limine
|
||||||
KERNEL=./yukiImage
|
KERNEL=zig-out/yukiImage
|
||||||
|
|
||||||
echo "[*] Creating disk image..."
|
echo "[*] Creating disk image..."
|
||||||
rm -f "$IMG"
|
rm -f "$IMG"
|
||||||
@@ -43,8 +44,9 @@ sudo tee "$MNT/boot/limine.conf" > /dev/null << 'EOF'
|
|||||||
timeout: 1
|
timeout: 1
|
||||||
|
|
||||||
/Yuki OS
|
/Yuki OS
|
||||||
protocol: efi
|
protocol: multiboot2
|
||||||
path: boot():/boot/yukiImage
|
path: boot():/boot/yukiImage
|
||||||
|
cmdline: earlyprintk=serial,ttyS0,115200
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
echo "[*] Syncing..."
|
echo "[*] Syncing..."
|
||||||
@@ -53,5 +55,6 @@ sync
|
|||||||
echo "[*] Unmounting..."
|
echo "[*] Unmounting..."
|
||||||
sudo umount "$MNT"
|
sudo umount "$MNT"
|
||||||
sudo losetup -d "$LOOP"
|
sudo losetup -d "$LOOP"
|
||||||
|
sudo chown $USER:$USER "$IMG"
|
||||||
|
rmdir "$MNT"
|
||||||
echo "[+] Done: $IMG created successfully"
|
echo "[+] Done: $IMG created successfully"
|
||||||
7
tools/run_qemu.sh
Normal file
7
tools/run_qemu.sh
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
qemu-system-x86_64 \
|
||||||
|
-enable-kvm -cpu host \
|
||||||
|
-drive file=zig-out/disk.img,format=raw \
|
||||||
|
-drive if=pflash,readonly=on,file=/usr/share/edk2/ovmf/OVMF_CODE.fd \
|
||||||
|
-serial stdio
|
||||||
|
# -s -S
|
||||||
Reference in New Issue
Block a user