/*
 * Copyright (c) 2026, Chloe M., et al
 * Provided under the BSD-3 clause.
 *
 * Description:  System bringup core
 * Author:       Chloe M.
 */

#include <ptdef.h>
#include <ke/bpal.h>
#include <ke/bugcheck.h>
#include <ke/sched.h>
#include <ex/trace.h>
#include <ex/pbi.h>
#include <ex/loader.h>
#include <ps/process.h>
#include <ps/thread.h>
#include <mm/pm.h>
#include <mm/vm.h>
#include <hal/prim.h>
#include <hal/serial.h>
#include <hal/thread.h>
#include <hal/kpcr.h>
#include <hal/mp.h>
#include <drivers/bootvid/fbio.h>
#include <drivers/acpi/acpi.h>
#include <string.h>

/* Globals */
static KPCR BootstrapCore;
static PROCESS *RootProcess;
static THREAD *RootThread;

/*
 * Display the copyright for legal reasons
 */
static VOID
Copyright(VOID)
{
    TRACE("~ Plural Technology ~\n");
    TRACE("Copyright (c) 2026, Chloe M., et al\n");
}

/*
 * Initialize the first process
 */
static VOID
InitializeRootProcess(VOID)
{
    PT_STATUS Status;
    PBI_FILE File;
    LOADER_PROGRAM Csrts;

    /* Create the client server runtime service */
    Status = PsCreateProcess(
        "csrts.sys",
        PS_USER,
        &RootProcess
    );

    if (PT_ERROR(Status)) {
        KeBugCheck(
            BUGCHECK_MISC,
            "could not create csrts.sys process\n"
        );
    }

    /* Get the CSRTS binary */
    Status = ExPbiLookup("/boot/csrts.sys", &File);
    if (PT_ERROR(Status)) {
        KeBugCheck(
            BUGCHECK_MISC,
            "unable to locate /boot/csrts.sys\n"
        );
    }

    /* Now load the program */
    Status = ExLoadProgramOf(
        LOADER_ELF64,
        &RootProcess->Vas,
        File.Data,
        &Csrts
    );

    if (PT_ERROR(Status)) {
        KeBugCheck(
            BUGCHECK_MISC,
            "unable to load csrts.sys\n"
        );
    }

    Status = PsCreateThread(
        RootProcess,
        0,
        Csrts.EntryPoint,
        &RootThread
    );

    KeSchedEnqueue(&BootstrapCore.SchedQueue, RootThread);
}

/*
 * Starting here is where the world is brought up and system
 * components are initialized.
 */
VOID
KiKernelInit(VOID)
{
    /* Initialize the boot protocol abstraction layer */
    KeBpalInit();

    /* Initialize the serial driver */
    HalSerialInit();

    /* Display the copyright */
    Copyright();

    /* Initialize the boot video driver */
    BootVidInit();

    /* Initialize the boot video console */
    BootVidInitCons(NULL);

    /* Initialize physical memory */
    MmPmInit();

    /* Phase 1 init of bootstrap core */
    HalKpcrP1Init(&BootstrapCore);

    /* Initialize virtual memory */
    MmVmInit();

    /* Initialize ACPI */
    AcpiInit();

    /* Phase 2 init of bootstrap core */
    HalKpcrP2Init(&BootstrapCore);

    /* Initialize threading */
    PsThreadInit();

    /* Initialize the PBI manager */
    ExPbiInit();

    /* Initialize the root process */
    InitializeRootProcess();

    /* Bootstrap all other cores */
    HalMpBootstrap();

    /* Prime the scheduler timer */
    HalPrimeThreadTimer(SCHED_MIN_QUANTUM);

    for (;;) {
        HalCpuSpinWait();
    }
}
