// 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
//!
//! Defines the Multiboot2 header for GRUB/QEMU and the bare-metal entry point.
//! Handles BSS clearing and stack initialization before jumping to the Nim kernel.
//!
//! SAFETY: Executed in the earliest boot stage with no environment initialized.

const std = @import("std");

// =========================================================
// Multiboot2 Header (for GRUB/QEMU)
// =========================================================

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(),
};

// =========================================================
// Entry Point
// =========================================================

extern fn kmain() noreturn;

export fn _start() callconv(.Naked) noreturn {
    // Clear BSS, set up stack, then jump to Nim
    asm volatile (
        \\  // Set up stack
        \\  la sp, __stack_top
        \\  
        \\  // 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 Nim kmain
        \\  call kmain
        \\  
        \\  // Should never return
        \\  wfi
        \\  j 2b
    );
}
