/*
 * Copyright (c) 2026, Chloe M.
 * Provided under the BSD-3 clause.
 *
 * Description:  Boot protocol abstraction layer
 * Author:       Chloe M.
 */

#ifndef _KE_BPAL_H_
#define _KE_BPAL_H_ 1

#include <stapi/status.h>
#include <stdef.h>

/*
 * Valid memory types
 */
typedef enum {
    MEMORY_USABLE,
    MEMORY_RESERVED,
    MEMORY_ACPI_RECLAIM,
    MEMORY_ACPI_NVS,
    MEMORY_BAD,
    MEMORY_BOOTLOADER,
    MEMORY_KERNEL,
    MEMORY_FRAMEBUFFER,
    MEMORY_ACPI_TABLES
} MEM_TYPE;

/*
 * Memory map entry
 *
 * @Base:   Entry base
 * @Length: Entry length
 * @Type:   Entry type
 */
typedef struct {
    UQUAD Base;
    UQUAD Length;
    UQUAD Type;
} MEMMAP_ENTRY;

/*
 * Represents a framebuffer
 */
typedef struct {
    VOID *Address;
    UQUAD Width;
    UQUAD Height;
    UQUAD Pitch;
    SHORT Bpp;
    UCHAR RedMaskSize;
    UCHAR RedMaskShift;
    UCHAR GreenMaskSize;
    UCHAR GreenMaskShift;
    UCHAR BlueMaskSize;
    UCHAR BlueMaskShift;
} BPAL_FRAMEBUFFER;

/*
 * Bootloader module
 *
 * @Data: Data backed by module
 * @Length: Length of data in bytes
 */
typedef struct {
    VOID *Data;
    USIZE Length;
} BPAL_MODULE;

/*
 * Boot protocol abstraction handle
 *
 * @KernelBase:     Kernel load base
 * @Framebuffer:    Framebuffer info
 * @RsdpBase:       ACPI RSDP base
 * @MemEntryIdx:    Callback to get memory map entry by index
 * @ModuleLookup:   Lookup a module
 * @CommandLine:    Kernel command line
 */
typedef struct {
    UPTR KernelBase;
    BPAL_FRAMEBUFFER Framebuffer;
    VOID *RsdpBase;
    ST_STATUS(*MemEntryIdx)(USIZE Idx, MEMMAP_ENTRY *Result);
    ST_STATUS(*ModuleLookup)(CHAR *Path, BPAL_MODULE *Result);
    const CHAR *CommandLine;
} BPAL_HANDLE;

/*
 * Initialize the boot protocol abstraction layer
 */
VOID KeBpalInit(VOID);

/*
 * Obtain the boot protocol handle
 *
 * @Result: Result is written here
 */
VOID KeBpalGetHandle(BPAL_HANDLE *Result);

/*
 * Returns true if the BPAL is initialized
 */
BOOLEAN KeBpalIsInit(VOID);

/*
 * Obtain the kernel load virtual memory base
 */
ALWAYS_INLINE static inline UPTR
KeBpalLoadBase(VOID)
{
    BPAL_HANDLE Handle;

    KeBpalGetHandle(&Handle);
    return Handle.KernelBase;
}

/* Backend init functions */
VOID KeBpalLimineInit(BPAL_HANDLE *Handle);

#endif  /* !_KE_BPAL_H_ */
