rumpk/boot/header.zig

136 lines
4.2 KiB
Zig

// SPDX-License-Identifier: LCL-1.0
// Copyright (c) 2026 Markus Maiwald
// Stewardship: Self Sovereign Society Foundation
//
// This file is part of the Nexus Commonwealth.
// See legal/LICENSE_COMMONWEALTH.md for license terms.
//! Rumpk Boot Header
//!
//! Architecture-dispatched entry point for bare-metal boot.
//! Handles BSS clearing and stack initialization before jumping to HAL init.
//!
//! SAFETY: Executed in the earliest boot stage with no environment initialized.
const std = @import("std");
const builtin = @import("builtin");
// =========================================================
// Multiboot2 Header (for GRUB/QEMU — x86 only)
// =========================================================
const MULTIBOOT2_MAGIC: u32 = 0xe85250d6;
const MULTIBOOT2_ARCH_I386: u32 = 0;
const MULTIBOOT2_HEADER_LENGTH: u32 = @sizeOf(Multiboot2Header);
const Multiboot2Header = extern struct {
magic: u32 = MULTIBOOT2_MAGIC,
architecture: u32 = MULTIBOOT2_ARCH_I386,
header_length: u32 = MULTIBOOT2_HEADER_LENGTH,
checksum: u32,
// End tag
end_tag_type: u16 = 0,
end_tag_flags: u16 = 0,
end_tag_size: u32 = 8,
};
fn computeChecksum() u32 {
return @bitCast(-%@as(i32, @bitCast(MULTIBOOT2_MAGIC +% MULTIBOOT2_ARCH_I386 +% MULTIBOOT2_HEADER_LENGTH)));
}
export const multiboot2_header linksection(".multiboot2") = Multiboot2Header{
.checksum = computeChecksum(),
};
// =========================================================
// Arch-Specific HAL Entry Points
// =========================================================
extern fn riscv_init() noreturn;
extern fn aarch64_init() void; // Returns void (calls rumpk_halt internally)
// =========================================================
// Entry Point (Architecture Dispatched)
// =========================================================
// 1MB Kernel Stack
const STACK_SIZE = 0x100000;
export var kernel_stack: [STACK_SIZE]u8 align(16) linksection(".bss.stack") = undefined;
export fn _start() callconv(.naked) noreturn {
switch (builtin.cpu.arch) {
.riscv64 => {
asm volatile (
\\ // Set up stack
\\ la sp, kernel_stack
\\ li t0, %[stack_size]
\\ add sp, sp, t0
\\
\\ // Clear BSS
\\ la t0, __bss_start
\\ la t1, __bss_end
\\1:
\\ bge t0, t1, 2f
\\ sd zero, (t0)
\\ addi t0, t0, 8
\\ j 1b
\\2:
\\ // Jump to RISC-V HAL Init
\\ call riscv_init
\\
\\ // Should never return
\\ wfi
\\ j 2b
:
: [stack_size] "i" (STACK_SIZE),
);
},
.aarch64 => {
asm volatile (
// Mask all exceptions
\\ msr daifset, #0xf
//
// Enable FP/SIMD (CPACR_EL1.FPEN = 0b11)
\\ mov x0, #(3 << 20)
\\ msr cpacr_el1, x0
\\ isb
//
// Disable alignment check (SCTLR_EL1.A = 0)
\\ mrs x0, sctlr_el1
\\ bic x0, x0, #(1 << 1)
\\ msr sctlr_el1, x0
\\ isb
//
// Set up stack
\\ adrp x0, kernel_stack
\\ add x0, x0, :lo12:kernel_stack
\\ mov x1, #0x100000
\\ add sp, x0, x1
//
// Clear BSS
\\ adrp x0, __bss_start
\\ add x0, x0, :lo12:__bss_start
\\ adrp x1, __bss_end
\\ add x1, x1, :lo12:__bss_end
\\ 1: cmp x0, x1
\\ b.ge 2f
\\ str xzr, [x0], #8
\\ b 1b
\\ 2:
//
// Jump to ARM64 HAL Init
\\ bl aarch64_init
//
// Should never return
\\ 3: wfe
\\ b 3b
);
},
else => {
// Unsupported architecture
unreachable;
},
}
}