136 lines
4.2 KiB
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;
|
|
},
|
|
}
|
|
}
|