/*
    * BootInfo.hpp
    * The Montauk Boot Contract (MBC)
    * Copyright (c) 2026 Daniel Hammer
*/

#pragma once
#include <cstdint>

// ====================================================================
// The Montauk Boot Contract (MBC)
// ====================================================================
//
// This header is the SOLE interface between the MontaukOS kernel and
// whatever bootloader brought it to life.  The kernel does not know, and
// must not care, whether it was loaded by Limine, by a future bespoke
// "Montauk Loader", by a UEFI stub, or by a hypervisor shim.  It knows
// only that *something* fulfilled this contract and handed it a fully
// populated `BootInfo`.
//
// A bootloader fulfills the contract in two halves:
//
//   1. The HANDOFF STATE (machine state on entry to `kmain`).  This part
//      of the contract cannot be expressed in a struct; it is documented
//      in detail in BootContract.hpp and must be honoured before the first
//      instruction of the kernel runs.
//
//   2. This `BootInfo` STRUCTURE, produced by a per-bootloader adapter
//      that implements `montauk::boot::Acquire()` (declared in
//      BootProtocol.hpp).  Exactly one adapter is linked into the kernel.
//
// DESIGN RULES (so a novel bootloader can genuinely satisfy the contract):
//
//   * No type in this file may name, include, or depend on any particular
//     bootloader's headers.  Everything here is plain Montauk-native POD.
//   * Every field has a single, fully-specified meaning (units, physical
//     vs. virtual, ownership/lifetime).  Adapters translate; they do not
//     reinterpret.
//   * Optional capabilities are advertised through `features`.  A field
//     guarded by a feature bit is only meaningful when that bit is set.
//
// MEMORY / LIFETIME MODEL:
//
//   The arrays referenced by BootInfo (memory regions, modules, CPUs, the
//   EFI memory map) are NOT owned by the kernel.  They live in memory the
//   bootloader marked "bootloader-reclaimable".  The kernel must consume
//   everything it needs from them during early boot, BEFORE it reclaims
//   that memory.  After early boot the pointers in BootInfo must be treated
//   as dangling.  `BootInfo` itself is a value owned by the kernel (it lives
//   in kernel .bss; see Boot.cpp), so it survives reclamation, but the
//   things it points at do not.
//
// ADDRESS CONVENTIONS (read carefully -- they are not all the same):
//
//   * "physical"  -- a raw physical address.  The kernel reaches it with
//                    Memory::HHDM(addr).
//   * "HHDM/direct-mapped virtual" -- a pointer already valid in the
//                    higher-half direct map; dereference it as-is.
//   The doc comment on each field states which one it is.
// ====================================================================

namespace montauk::boot {

    // The version of THIS contract that the kernel was compiled against.
    // An adapter stamps the contract revision it produced into
    // BootInfo::contractVersion; Boot.cpp refuses to continue on mismatch.
    // Bump this whenever the meaning or layout of BootInfo changes.
    static constexpr uint32_t ContractVersion = 1;

    // ----------------------------------------------------------------
    // Optional-capability advertisement.
    // A bit set in BootInfo::features means the corresponding sub-struct
    // has been populated and may be used.  A bit clear means the kernel
    // must behave as if that information does not exist.
    // ----------------------------------------------------------------
    enum Feature : uint32_t {
        FeatureFramebuffer    = 1u << 0,  // BootInfo::framebuffer is valid
        FeatureRsdp           = 1u << 1,  // BootInfo::rsdpPhysical is valid
        FeatureModules        = 1u << 2,  // BootInfo::modules is valid
        FeatureEfiSystemTable = 1u << 3,  // BootInfo::efi.systemTablePhysical valid
        FeatureEfiMemoryMap   = 1u << 4,  // BootInfo::efi memory-map fields valid
        FeatureSmp            = 1u << 5,  // BootInfo::smp is valid (>1 CPU available)
    };

    // ----------------------------------------------------------------
    // Physical memory map.
    // ----------------------------------------------------------------
    //
    // Normalised classification of a physical memory region.  Adapters map
    // their bootloader's native types onto these.  The kernel only strictly
    // distinguishes Usable from everything else (the page-frame allocator
    // claims Usable regions), but the full taxonomy is preserved so future
    // code (e.g. reclaiming BootloaderReclaimable, honouring AcpiNvs across
    // S3) has the information it needs.
    enum class MemoryKind : uint32_t {
        Usable,                 // free RAM the kernel may allocate from
        Reserved,               // firmware/hardware reserved; never touch
        AcpiReclaimable,        // ACPI tables; reclaimable after parsing
        AcpiNvs,                // ACPI non-volatile storage; preserve
        BadMemory,              // known-faulty RAM; never use
        BootloaderReclaimable,  // bootloader structures; reclaimable post-boot
        KernelAndModules,       // the kernel image and loaded modules
        Framebuffer,            // the linear framebuffer region
        Unknown,                // adapter could not classify; treat as Reserved
    };

    struct MemoryRegion {
        uint64_t   base;    // physical base address (page-aligned)
        uint64_t   length;  // length in bytes (page-multiple)
        MemoryKind kind;
    };

    struct MemoryMap {
        MemoryRegion* regions;  // HHDM/direct-mapped virtual; `count` entries
        uint64_t      count;    // number of valid entries
    };

    // ----------------------------------------------------------------
    // Linear framebuffer (valid iff FeatureFramebuffer).
    // The kernel's console and graphics stack render directly into this.
    // ----------------------------------------------------------------
    struct Framebuffer {
        uint64_t address;        // HHDM/direct-mapped virtual base of the
                                 // pixel buffer (write pixels here directly)
        uint64_t width;          // visible width in pixels
        uint64_t height;         // visible height in pixels
        uint64_t pitch;          // bytes per scanline (>= width*bpp/8)
        uint16_t bpp;            // bits per pixel (typically 32)

        // RGB channel placement within a pixel, as size+shift pairs.
        // value = ((channel & ((1<<size)-1)) << shift).
        uint8_t  redMaskSize,   redMaskShift;
        uint8_t  greenMaskSize, greenMaskShift;
        uint8_t  blueMaskSize,  blueMaskShift;
    };

    // ----------------------------------------------------------------
    // Boot modules / ramdisk (valid iff FeatureModules).
    // The kernel locates its ramdisk by matching `name`.
    // ----------------------------------------------------------------
    struct Module {
        void*       address;  // HHDM/direct-mapped virtual base of the blob
        uint64_t    size;     // size of the blob in bytes
        const char* name;     // null-terminated identifier the loader was
                              // asked to tag this module with (e.g. "ramdisk").
                              // May be empty but never null.
    };

    struct ModuleList {
        Module*  modules;  // HHDM/direct-mapped virtual; `count` entries
        uint64_t count;
    };

    // ----------------------------------------------------------------
    // UEFI services (fields valid per FeatureEfiSystemTable /
    // FeatureEfiMemoryMap).  Absent on legacy-BIOS boots.
    // ----------------------------------------------------------------
    struct EfiInfo {
        // Physical address of the EFI_SYSTEM_TABLE.  Reach it via
        // Memory::HHDM(systemTablePhysical).  Valid iff FeatureEfiSystemTable.
        uint64_t systemTablePhysical;

        // The raw UEFI memory map, exactly as returned by GetMemoryMap().
        // Used to discover EFI runtime-services regions.  All fields valid
        // iff FeatureEfiMemoryMap.
        void*    memoryMap;          // HHDM/direct-mapped virtual; array of
                                     // descriptors, each `descriptorSize` bytes
        uint64_t memoryMapSize;      // total bytes in `memoryMap`
        uint64_t descriptorSize;     // bytes per descriptor (>= sizeof(desc))
        uint32_t descriptorVersion;  // EFI memory descriptor version
    };

    // ----------------------------------------------------------------
    // Symmetric multiprocessing (valid iff FeatureSmp).
    // ----------------------------------------------------------------
    //
    // The contract models AP startup as a capability rather than a data
    // snapshot, because waking an application processor is an ACTION that
    // only the bootloader (which parked the AP in a known state) can
    // perform.  The kernel fills in `extraArgument` for each CPU it wants
    // to bring up, then calls SmpInfo::startCpu.  The bootloader resumes
    // the parked AP such that it begins executing `entry(cpu)` on a stack
    // the bootloader provides, with the same handoff machine state the BSP
    // received (long mode, paging on, kernel mapped).  `entry` recovers its
    // per-CPU context from `cpu->extraArgument`.
    struct BootCpu;

    struct SmpInfo {
        uint64_t cpuCount;     // total CPUs reported (including the BSP)
        uint32_t bspLapicId;   // local-APIC ID of the bootstrap processor

        BootCpu* cpus;         // HHDM/direct-mapped virtual; `cpuCount` entries.
                               // The entry whose lapicId == bspLapicId is the BSP
                               // and must NOT be started (it is already running).

        // Wake `cpu`, causing it to begin executing `entry(cpu)`.  Returns
        // true if the start request was accepted.  `entry` runs on a
        // bootloader-supplied stack; it never returns.  Implemented by the
        // active adapter.  Safe to call once per AP.
        bool (*startCpu)(BootCpu* cpu, void (*entry)(BootCpu*));
    };

    struct BootCpu {
        uint32_t lapicId;        // local-APIC ID of this CPU
        uint64_t extraArgument;  // free for the kernel: stash a per-CPU
                                 // pointer here before calling startCpu; it is
                                 // handed back to `entry` via `cpu->extraArgument`.
        void   (*entry)(BootCpu*);  // set by startCpu; do not touch directly
        void*    native;            // adapter-private back-reference; opaque to
                                    // the kernel
    };

    // ----------------------------------------------------------------
    // The complete boot contract, owned by the kernel.
    // ----------------------------------------------------------------
    struct BootInfo {
        uint32_t    contractVersion;  // MUST equal ContractVersion
        uint32_t    features;         // bitmask of Feature
        const char* loaderName;       // human-readable, e.g. "Limine"; never null

        // ---- Always required (no feature bit; absence is a fatal error) ----
        uint64_t  hhdmBase;   // virtual base of the higher-half direct map:
                              // virtual = physical + hhdmBase for all RAM
        MemoryMap memoryMap;  // the physical memory map

        // ---- Optional, guarded by `features` ----
        uint64_t    rsdpPhysical;  // FeatureRsdp: physical addr of ACPI RSDP
        Framebuffer framebuffer;   // FeatureFramebuffer
        ModuleList  modules;       // FeatureModules
        EfiInfo     efi;           // FeatureEfiSystemTable / FeatureEfiMemoryMap
        SmpInfo     smp;           // FeatureSmp

        bool has(Feature f) const { return (features & f) != 0; }
    };

}
