/**
 * @file SetupConfigUpdateDxeLightningRidgeEXECB3.h
 * @brief UEFI DXE driver for UBA (Unified Board Architecture) setup configuration
 *        update on LightningRidgeEXECB3 platform.
 *
 * This module is one of many platform-specific UBA DXE drivers in the HR650X BIOS.
 * It identifies the HOB (Hand-Off Block) list from the system configuration table,
 * resolves the UBA board-type protocol specific to LightningRidgeEXECB3, then
 * registers a 1164-byte setup configuration data block via the protocol's
 * RegisterSetupConfig callback.
 *
 * Build info:
 *   Toolchain: VS2015, X64 DEBUG build
 *   Workspace: HR6N0XMLK
 *   Source: PurleyRpPkg/Uba/UbaMain/Dxe/TypeLightningRidgeEXECB3/SetupCfgUpdateDxe/
 *
 * GUID Summary:
 *   {36232936-0E76-31C8-A13A-3AF2FC1C3932} - DebugLib protocol
 *   {E03E0D46-5263-4845-B0A4-58D57B3177E2} - UBA board-type protocol (LightningRidgeEXECB3)
 *   {7739F24C-93D7-11D4-9A3A-0090273FC14D} - EFI_HOB_LIST_GUID
 *   {CD1F9574-DD03-4196-96AD-4965146F9665} - UBA Setup Config protocol
 */

#ifndef __SETUP_CONFIG_UPDATE_DXE_LIGHTNING_RIDGE_EXECB3_H__
#define __SETUP_CONFIG_UPDATE_DXE_LIGHTNING_RIDGE_EXECB3_H__

#include "../uefi_headers/Uefi.h"

//=============================================================================
// GUID Definitions
//=============================================================================

/// DebugLib protocol GUID - used to locate the UEFI debug library protocol
/// at runtime for debug print and assertion services.
#define DEBUG_LIB_PROTOCOL_GUID \
    { 0x36232936, 0x0E76, 0x31C8, { 0xA1, 0x3A, 0x3A, 0xF2, 0xFC, 0x1C, 0x39, 0x32 } }

/// UBA board-type protocol GUID for LightningRidgeEXECB3.
/// This GUID identifies the platform-specific UBA protocol instance that
/// provides the RegisterSetupConfig callback.
#define UBA_BOARD_TYPE_PROTOCOL_GUID \
    { 0xE03E0D46, 0x5263, 0x4845, { 0xB0, 0xA4, 0x58, 0xD5, 0x7B, 0x31, 0x77, 0xE2 } }

/// Standard UEFI HOB (Hand-Off Block) list GUID.
/// Used to locate the HOB list pointer from the system configuration table.
#define EFI_HOB_LIST_GUID \
    { 0x7739F24C, 0x93D7, 0x11D4, { 0x9A, 0x3A, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D } }

/// UBA Setup Config protocol GUID.
/// The protocol instance's offset +0x10 contains the RegisterSetupConfig
/// function pointer that registers platform-specific setup configuration data.
#define UBA_SETUP_CONFIG_PROTOCOL_GUID \
    { 0xCD1F9574, 0xDD03, 0x4196, { 0x96, 0xAD, 0x49, 0x65, 0x14, 0x6F, 0x96, 0x65 } }

//=============================================================================
// Constants
//=============================================================================

/// Setup configuration data size in bytes.
/// The module registers a 0x48C-byte configuration block containing
/// platform-specific setup data for LightningRidgeEXECB3.
#define SETUP_CONFIG_DATA_SIZE  0x48C

/// Signature for UBA_SETUP_CONFIG_DATA ("PSET" = partial "SETUP" encoding).
#define SETUP_CONFIG_SIGNATURE  0x54455350  // "PSET"

/// Version of the setup config data structure.
#define SETUP_CONFIG_VERSION    1

/// Debug print error level mask for EFI_NOT_FOUND (default).
#define DEBUG_ERROR_LEVEL_NOT_FOUND  0x80000000

/// Debug print error level mask for EFI_ERROR (default).
#define DEBUG_ERROR_LEVEL_ERROR      0x80000006

/// Debug print error level mask for error-only messages.
#define DEBUG_ERROR_LEVEL_ERROR_ONLY 0x80000004

/// EFI_NOT_FOUND status code.
#define EFI_NOT_FOUND  0x800000000000000EULL

/// CMOS RTC address port for debug level register.
#define CMOS_ADDRESS_PORT  0x70

/// CMOS RTC data port for debug level register.
#define CMOS_DATA_PORT     0x71

/// CMOS register index for board revision / debug level.
#define CMOS_REGISTER_DEBUG  0x4B

/// Memory-mapped board configuration register (fallback for CMOS debug level).
#define BOARD_CONFIG_REGISTER  0xFDAF0490ULL

/// Pool allocation type for environment validation.
#define POOL_ALLOC_SIZE_CHECK  31

/// Maximum valid allocation pointer value for environment validation.
#define MAX_VALID_ALLOC_PTR  0x10

//=============================================================================
// Type Definitions
//=============================================================================

/**
 * UBA Debug Library protocol interface.
 * Located dynamically via gBS->LocateProtocol(&gDebugProtocolGuid).
 */
typedef struct {
    EFI_STATUS (*DebugPrint)(
        IN  VOID   *This,
        IN  CHAR8  *Format,
        IN  ...
        );                       ///< +0x00: Debug print function
    EFI_STATUS (*DebugAssert)(
        IN  VOID   *This,
        IN  CHAR8  *FileName,
        IN  UINTN  LineNumber,
        IN  CHAR8  *Description
        );                       ///< +0x08: Assertion handler function
} UBA_DEBUG_PROTOCOL;

/**
 * UBA Board-Type protocol interface.
 * Located dynamically via gBS->LocateProtocol(&gUbaBoardTypeProtocolGuid).
 */
typedef struct {
    UINT64  Reserved0;           ///< +0x00: Reserved
    UINT64  Reserved1;           ///< +0x08: Reserved
    EFI_STATUS (*RegisterSetupConfig)(
        IN  VOID   *This,
        IN  VOID   *ProtocolGuid,
        IN  VOID   *ConfigData,
        IN  UINTN  ConfigDataSize
        );                       ///< +0x10: Register configuration callback
} UBA_BOARD_TYPE_PROTOCOL;

/**
 * UBA Setup Configuration Data descriptor.
 * Registered with the platform via RegisterSetupConfig.
 * Structure stored at 0xB80 in .data section.
 */
typedef struct {
    UINT32  Signature;           ///< +0x00: "PSET" (0x54455350)
    UINT32  Version;             ///< +0x04: 1
    UINT64  DataSize;            ///< +0x08: 0x48C (1164)
    UINT64  DataSizeDuplicate;   ///< +0x10: 0x48C (1164, duplicate)
} UBA_SETUP_CONFIG_DATA;

/**
 * System Configuration Table Entry format.
 * Iterated to find the HOB list GUID entry.
 */
typedef struct {
    EFI_GUID  VendorGuid;        ///< +0x00: 16-byte GUID
    VOID      *VendorTable;      ///< +0x10: 8-byte pointer
} CONFIG_TABLE_ENTRY;            ///< Total: 0x18 (24 bytes)

//=============================================================================
// External Global Variables (set by ModuleEntryPoint)
//=============================================================================

extern EFI_HANDLE               gImageHandle;       ///< Driver image handle (0xBA8)
extern EFI_SYSTEM_TABLE         *gSystemTable;      ///< System table pointer (0xB98)
extern EFI_BOOT_SERVICES        *gBootServices;     ///< Boot services pointer (0xBA0)
extern EFI_RUNTIME_SERVICES     *gRuntimeServices;  ///< Runtime services pointer (0xBB0)
extern UBA_DEBUG_PROTOCOL       *gDebugProtocol;    ///< Cached debug protocol (0xBB8)
extern VOID                     *gHobList;          ///< Cached HOB list pointer (0xBC0)
extern UINT8                    gCmosDebugLevel;    ///< Cached CMOS debug level (0xBC8)

//=============================================================================
// Function Declarations
//=============================================================================

/**
 * Module entry point. Called by the DXE dispatcher.
 *
 * Initializes UEFI global pointers (gImageHandle, gSystemTable, gBootServices,
 * gRuntimeServices), locates the HOB list from the system configuration table,
 * logs a platform identification string via the debug protocol, then locates
 * the UBA board-type protocol and registers the setup configuration data
 * descriptor.
 *
 * @param[in] ImageHandle  Handle for this driver image.
 * @param[in] SystemTable  Pointer to the UEFI system table.
 *
 * @return EFI_STATUS from RegisterSetupConfig, or error from LocateProtocol.
 */
EFI_STATUS
EFIAPI
ModuleEntryPoint(
    IN  EFI_HANDLE        ImageHandle,
    IN  EFI_SYSTEM_TABLE  *SystemTable
    );

/**
 * Returns EFI_NOT_FOUND constant.
 * This is a library stub with no callers in this module.
 *
 * @return 0x800000000000000E (EFI_NOT_FOUND).
 */
UINT64
ReturnNotFound(
    VOID
    );

/**
 * Resolves and caches the DebugLib protocol.
 *
 * Allocates and frees a pool buffer as an environment validation guard
 * (checks if UEFI boot services are operational), then calls
 * gBS->LocateProtocol(&gDebugProtocolGuid) to obtain the protocol interface.
 * Result is cached in gDebugProtocol.
 *
 * @return Pointer to UBA_DEBUG_PROTOCOL, or NULL if not found.
 */
UBA_DEBUG_PROTOCOL *
GetDebugProtocol(
    VOID
    );

/**
 * Debug print with platform-aware filtering.
 *
 * Before calling the debug protocol's DebugPrint function, reads CMOS
 * register 0x4B through RTC ports to determine the platform debug verbosity
 * level. Falls back to MMIO 0xFDAF0490 (bit 1) if CMOS level is 0.
 * Filters the call against ErrorLevel mask -- only ErrorLevel matches
 * that include the current board type filter pass through to the print
 * function. Non-matching calls return silently.
 *
 * @param[in] ErrorLevel  Debug error level mask.
 * @param[in] Format      Format string.
 * @param[in] ...         Variable arguments.
 *
 * @return Non-zero if the message was printed, 0 if filtered or no protocol.
 */
UINT8
DebugPrint(
    IN  UINTN   ErrorLevel,
    IN  CHAR8   *Format,
    ...
    );

/**
 * ASSERT failure handler via DebugLib protocol.
 *
 * Calls the DebugAssert function at offset +0x08 of the cached
 * UBA_DEBUG_PROTOCOL interface.
 *
 * @param[in] FileName    Source file name of the ASSERT.
 * @param[in] LineNumber  Source line number of the ASSERT.
 * @param[in] Description ASSERT description string.
 */
VOID
DebugAssert(
    IN  CHAR8   *FileName,
    IN  UINTN   LineNumber,
    IN  CHAR8   *Description
    );

/**
 * Locates and caches the HOB list pointer.
 *
 * Scans SystemTable->ConfigurationTable[] for the entry with
 * EFI_HOB_LIST_GUID. Each table entry is 0x18 bytes: 16-byte GUID
 * + 8-byte pointer. Asserts if the HOB list is not found.
 * Result is cached in gHobList.
 *
 * The ConfigurationTable is an array of CONFIG_TABLE_ENTRY structures
 * at gST->ConfigurationTable. The count is at gST->NumberOfTableEntries
 * (offset +0x68 in EFI_SYSTEM_TABLE).
 */
VOID *
GetHobList(
    VOID
    );

/**
 * Compares two GUIDs using 64-bit unaligned reads.
 *
 * Avoids full CompareGuid() by comparing (Data1+Data2+part of Data3)
 * as first QWORD, and (rest of Data3+Data4) as second QWORD. Uses
 * ReadUnaligned64 for each half.
 *
 * @param[in] Guid1  Pointer to first EFI_GUID.
 * @param[in] Guid2  Pointer to second EFI_GUID (from ConfigTable entry).
 *
 * @return TRUE if GUIDs match, FALSE otherwise.
 */
BOOLEAN
IsGuidMatch(
    IN  EFI_GUID  *Guid1,
    IN  EFI_GUID  *Guid2
    );

/**
 * Reads a UINT64 from a potentially unaligned address with NULL assertion.
 *
 * Dereferences the pointer as UINT64*. Asserts if the input pointer is NULL.
 *
 * @param[in] Buffer  Pointer to read from (must not be NULL).
 *
 * @return The UINT64 value at the pointer.
 */
UINT64
ReadUnaligned64(
    IN  VOID   *Buffer
    );

#endif /* __SETUP_CONFIG_UPDATE_DXE_LIGHTNING_RIDGE_EXECB3_H__ */