diff options
| author | hachem <im@hachem.wtf> | 2026-09-10 05:49:32 +0200 |
|---|---|---|
| committer | hachem <im@hachem.wtf> | 2026-09-10 05:49:32 +0200 |
| commit | d8b53a78fcb131235c1e83fe7d6600ab50560420 (patch) | |
| tree | c51c4340826f391e576e484d39d8b9b4e04a5245 /boot | |
| parent | 5dfeadc5e32790c34b1d413d7be41771f68a5e95 (diff) | |
setup: initialize repo + limine as a bootloader
Diffstat (limited to 'boot')
| -rw-r--r-- | boot/boot.zig | 22 | ||||
| -rw-r--r-- | boot/limine.conf | 5 | ||||
| -rw-r--r-- | boot/limine.zig | 27 | ||||
| -rw-r--r-- | boot/linker.ld | 52 |
4 files changed, 106 insertions, 0 deletions
diff --git a/boot/boot.zig b/boot/boot.zig new file mode 100644 index 0000000..0f6c92c --- /dev/null +++ b/boot/boot.zig @@ -0,0 +1,22 @@ +const std = @import("std"); +const limine = @import("limine.zig"); + +// We need a panic handler otherwise zig won't be happy, +// std usually formats a message through std.Io.Writer which +// emits SSE instructions which I haven't enabled. For now +// we just halt. +pub const panic = std.debug.FullPanic(struct { + fn halt(_: []const u8, _: ?usize) noreturn { + while (true) asm volatile ("hlt"); + } +}.halt); + +// Check `linker.ld` +export var base_revision: limine.BaseRevision linksection(".limine_requests") = limine.BaseRevision.init(3); +export var requests_start: limine.RequestsStartMarker linksection(".limine_requests_start") = .{}; +export var requests_end: limine.RequestsEndMarker linksection(".limine_requests_end") = .{}; + +// ENTRY(_start) +export fn _start() callconv(.c) noreturn { + while (true) asm volatile ("hlt"); +} diff --git a/boot/limine.conf b/boot/limine.conf new file mode 100644 index 0000000..7398dca --- /dev/null +++ b/boot/limine.conf @@ -0,0 +1,5 @@ +timeout: 0 + +/Revel + protocol: limine + path: boot():/boot/revel diff --git a/boot/limine.zig b/boot/limine.zig new file mode 100644 index 0000000..e9aac9c --- /dev/null +++ b/boot/limine.zig @@ -0,0 +1,27 @@ +// Limine scans the loaded image for these magic numbers, +// BaseRevision is a handshake, essentially we ask limine +// for rev 3, and if it supports it, limine zeros it out +pub const BaseRevision = extern struct { + magic0: u64 = 0xf9562b2d5c95a6c8, + magic1: u64 = 0x6a7b384944536bdc, + revision: u64, + + pub fn init(revision: u64) BaseRevision { + return .{ .revision = revision }; + } +}; + +// Bracketing markers, they are pretty optional but when +// we add proper limine requests, having these here comes +// handy +pub const RequestsStartMarker = extern struct { + m0: u64 = 0xf6b8f4b39de7d1ae, + m1: u64 = 0xfab91a6940fcb9cf, + m2: u64 = 0x785c6ed015d3e316, + m3: u64 = 0x181e920a7852b9d9, +}; + +pub const RequestsEndMarker = extern struct { + m0: u64 = 0xadc0e0531bb10d03, + m1: u64 = 0x9572709f31764c62, +}; diff --git a/boot/linker.ld b/boot/linker.ld new file mode 100644 index 0000000..e15ed10 --- /dev/null +++ b/boot/linker.ld @@ -0,0 +1,52 @@ +/* the higher half of the kernel link maps + * at the top 2 GiB is where Limine maps us. */ + +OUTPUT_FORMAT(elf64-x86-64) +ENTRY(_start) + +PHDRS +{ + limine_requests PT_LOAD; + text PT_LOAD; + rodata PT_LOAD; + data PT_LOAD; +} + +SECTIONS +{ + . = 0xffffffff80000000; + + /* The loader hunts for the magic numbers here + * these are referenced in `boot/` */ + .limine_requests : { + KEEP(*(.limine_requests_start)) + KEEP(*(.limine_requests)) + KEEP(*(.limine_requests_end)) + } :limine_requests + + . = ALIGN(CONSTANT(MAXPAGESIZE)); + .text : { + *(.text .text.*) + } :text + + . = ALIGN(CONSTANT(MAXPAGESIZE)); + .rodata : { + *(.rodata .rodata.*) + } :rodata + + . = ALIGN(CONSTANT(MAXPAGESIZE)); + .data : { + *(.data .data.*) + } :data + + .bss : { + *(.bss .bss.*) + *(COMMON) + } :data + + /* no unwind tables or note sections. */ + /DISCARD/ : { + *(.eh_frame*) + *(.note .note.*) + } +} |
