/**
 * @file SetupConfigUpdateDxeLightningRidgeEXECB2.h
 *
 * @brief Header for UBA (Unified Board Architecture) Setup Configuration Update
 *        DXE driver -- LightningRidgeEXECB2 platform variant.
 *
 * This driver is dispatched by the DXE core and performs the following:
 *   1. Saves and validates gImageHandle, gST, gBS, gRT (from boot services lib).
 *   2. Locates the HOB (Hand-Off Block) list from SystemTable->ConfigurationTable
 *      by matching gEfiHobListGuid.
 *   3. Locates the UBA board-type protocol (mUbaBoardTypeProtocolGuid) via
 *      gBS->LocateProtocol().
 *   4. Calls the protocol's RegisterSetupConfig entry point with a
 *      UBA_SETUP_CONFIG_DATA descriptor to register board-specific setup
 *      configuration for the LightningRidgeEXECB2 platform.
 *
 * Build info (from debug strings):
 *   Build path: e:\hs\Build\...\PurleyRpPkg\Uba\UbaMain\Dxe\...
 *   Toolchain: VS2015, X64 DEBUG build
 *   Module: SetupConfigUpdateDxeLightningRidgeEXECB2
 */

#ifndef SETUP_CONFIG_UPDATE_DXE_LIGHTNING_RIDGE_EXECB2_H
#define SETUP_CONFIG_UPDATE_DXE_LIGHTNING_RIDGE_EXECB2_H

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

/*=============================================================================
 * GUIDs specific to this module
 *============================================================================*/

/** GUID used in sub_498() to locate the protocol via gBS->LocateProtocol().
 *  This is a debug/output protocol GUID (not the standard UEFI one).
 *  Address in binary: 0xB40
 *  Value: {36232936-0E76-31C8-A13A-3AF2FC1C3932} */
#define DEBUG_PROTOCOL_GUID \
    { 0x36232936, 0x0E76, 0x31C8, \
      { 0xA1, 0x3A, 0x3A, 0xF2, 0xFC, 0x1C, 0x39, 0x32 } }

/** GUID for the UBA board-type protocol (LightningRidgeEXECB2).
 *  This is the protocol looked up by _ModuleEntryPoint to get the
 *  RegisterSetupConfig function.
 *  Address in binary: 0xB50
 *  Value: {E03E0D46-5263-4845-B0A4-58D57B3177E2} */
#define UBA_BOARD_TYPE_PROTOCOL_GUID_LIGHTNING_RIDGE_EXECB2 \
    { 0xE03E0D46, 0x5263, 0x4845, \
      { 0xB0, 0xA4, 0x58, 0xD5, 0x7B, 0x31, 0x77, 0xE2 } }

/** EFI_HOB_LIST_GUID -- standard UEFI GUID used to locate the HOB list
 *  from SystemTable->ConfigurationTable.
 *  Address in binary: 0xB60
 *  Value: {7739F24C-93D7-11D4-9A3A-0090273FC14D} */
#define EFI_HOB_LIST_GUID \
    { 0x7739F24C, 0x93D7, 0x11D4, \
      { 0x9A, 0x3A, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D } }

/** GUID for the registered setup config protocol (platform-specific).
 *  Passed to RegisterSetupConfig as the protocol GUID to register.
 *  Address in binary: 0xB70
 *  Value: {CD1F9574-DD03-4196-96AD-4965146F9665} */
#define UBA_SETUP_CONFIG_PROTOCOL_GUID_LIGHTNING_RIDGE_EXECB2 \
    { 0xCD1F9574, 0xDD03, 0x4196, \
      { 0x96, 0xAD, 0x49, 0x65, 0x14, 0x6F, 0x96, 0x65 } }

/*=============================================================================
 * UBA Setup Configuration Data structure (at 0xB80 in .data)
 *============================================================================*/

/**
 * UBA_SETUP_CONFIG_DATA signature ('PSET' = 0x54455350).
 * Note: "PSET" is "SETP" in ASCII -- likely a partial or reversed encoding
 * of "SETUP" fitting in 4 bytes.
 */
#define UBA_SETUP_CONFIG_DATA_SIGNATURE  0x54455350

/**
 * Current version of the UBA setup config data format.
 */
#define UBA_SETUP_CONFIG_DATA_VERSION    1

/**
 * Size of the setup configuration data for this platform.
 * Value: 0x48C (1164 bytes).
 */
#define UBA_SETUP_CONFIG_DATA_SIZE       0x48C

/**
 * UBA_SETUP_CONFIG_DATA descriptor.
 * This 24-byte structure describes the platform's setup configuration data
 * block to the UBA core. The signature "PSET" (0x54455350) identifies
 * this as a setup configuration registration.
 *
 * Binary layout at offset 0x40 into .data (absolute 0xB80):
 *   +0x00  UINT32  Signature   = 'PSET' (0x54455350)
 *   +0x04  UINT32  Version     = 1
 *   +0x08  UINT64  Size        = 0x48C
 *   +0x10  UINT64  SizeDuplicate = 0x48C
 */
typedef struct {
    UINT32    Signature;         ///< 'PSET' (0x54455350)
    UINT32    Version;           ///< Data format version (=1)
    UINT64    DataSize;          ///< Size of setup config data (=0x48C)
    UINT64    DataSizeDuplicate; ///< Duplicate of DataSize (=0x48C)
} UBA_SETUP_CONFIG_DATA;

/*=============================================================================
 * UBA Board-Type Protocol (found by LocateProtocol)
 *============================================================================*/

/**
 * Forward declaration of the UBA board-type protocol.
 * _ModuleEntryPoint receives this protocol via gBS->LocateProtocol()
 * and invokes its RegisterSetupConfig function (at offset +16).
 *
 * Protocol interface layout:
 *   +0x00  UINT64 (unknown, possibly reserved)
 *   +0x08  UINT64 (unknown, possibly reserved)
 *   +0x10  UINT64 (*RegisterSetupConfig)()  -- function pointer
 *
 * RegisterSetupConfig expects:
 *   @param[in] This       Pointer to the protocol instance
 *   @param[in] Guid       GUID identifying the setup config type
 *   @param[in] ConfigData Pointer to UBA_SETUP_CONFIG_DATA
 *   @param[in] Size       Size of the config data (24)
 *
 *   @retval EFI_SUCCESS   Config registered.
 */
typedef struct _UBA_BOARD_TYPE_PROTOCOL {
    UINT64    Reserved0;                   ///< Unknown
    UINT64    Reserved1;                   ///< Unknown
    UINT64    RegisterSetupConfig;         ///< Function pointer at +16
} UBA_BOARD_TYPE_PROTOCOL;

/*=============================================================================
 * UEFI Debug Library Protocol (lazily resolved by sub_498())
 *============================================================================*/

/**
 * Forward declaration of the DebugLib protocol interface used for
 * ASSERT and DebugPrint calls.
 *
 * Protocol interface layout:
 *   +0x00  DebugPrint function pointer
 *   +0x08  DebugAssert function pointer
 */
typedef struct _DEBUG_LIB_PROTOCOL {
    UINT64    DebugPrint;                  ///< DebugPrint function at +0
    UINT64    DebugAssert;                 ///< DebugAssert function at +8
} DEBUG_LIB_PROTOCOL;

/*=============================================================================
 * Constants
 *============================================================================*/

/**
 * CMOS RTC register index for platform debug level.
 * Accessed via I/O ports 0x70/0x71.
 */
#define CMOS_REG_DEBUG_LEVEL    0x4B

/**
 * Bitmask to preserve the top bit (NMI enable) in CMOS address port.
 */
#define CMOS_NMI_ENABLE_BIT     0x80

/**
 * RTC CMOS I/O ports.
 */
#define CMOS_ADDRESS_PORT       0x70
#define CMOS_DATA_PORT          0x71

/**
 * MMIO address for board configuration register (fallback debug level source).
 */
#define BOARD_CONFIG_MMIO_ADDR  0xFDAF0490ULL

/**
 * Maximum index for string position scan in SMBIOS string update.
 */
#define SMBIOS_MAX_INDEX        0x40

/**
 * Maximum ASCII string length for AsciiStrLen.
 */
#define MAX_ASCII_STRING_LENGTH 0xF4240

/**
 * Error mask for debug print filtering.
 * Bits used: bit 6 = info, bit 31 = error
 */
#define DEBUG_PRINT_ERROR_MASK  0x80000000LL
#define DEBUG_PRINT_FILTER_MASK 0x80000006LL

/*=============================================================================
 * Global Variables (defined in .c)
 *============================================================================*/

/**
 * System table pointer (gST equivalent).
 * Binary address: 0xB98.
 * Initialized in ModuleEntryPoint from entry arg SystemTable.
 */
extern EFI_SYSTEM_TABLE *gSystemTable;

/**
 * Boot services pointer (gBS equivalent).
 * Binary address: 0xBA0.
 * Cached from SystemTable->BootServices.
 */
extern EFI_BOOT_SERVICES *gBootServices;

/**
 * Image handle (gImageHandle equivalent).
 * Binary address: 0xBA8.
 * Saved from entry arg ImageHandle.
 */
extern EFI_HANDLE gImageHandle;

/**
 * Runtime services pointer (gRT equivalent).
 * Binary address: 0xBB0.
 * Cached from SystemTable->RuntimeServices.
 */
extern EFI_RUNTIME_SERVICES *gRuntimeServices;

/**
 * Cached debug protocol interface pointer.
 * Binary address: 0xBB8.
 * Lazily resolved by GetDebugProtocol().
 * NULL until first call.
 */
extern VOID *gDebugProtocol;

/**
 * Cached HOB list pointer.
 * Binary address: 0xBC0.
 * NULL until resolved by GetHobList().
 */
extern VOID *gHobList;

/**
 * Cached CMOS debug level byte.
 * Binary address: 0xBC8.
 * Read from CMOS register 0x4B during debug print.
 */
extern UINT8 gCmosDebugLevel;

/*=============================================================================
 * GUID data structures in module (in .data section)
 *============================================================================*/

/**
 * DebugLib protocol GUID for gBS->LocateProtocol().
 * At binary address 0xB40.
 * Value: {36232936-0E76-31C8-A13A-3AF2FC1C3932}
 */
extern EFI_GUID gDebugProtocolGuid;

/**
 * UBA LightningRidgeEXECB2 board-type protocol GUID.
 * At binary address 0xB50.
 * Value: {E03E0D46-5263-4845-B0A4-58D57B3177E2}
 */
extern EFI_GUID gUbaBoardTypeProtocolGuid;

/**
 * EFI HOB list GUID (standard UEFI).
 * At binary address 0xB60.
 * Value: {7739F24C-93D7-11D4-9A3A-0090273FC14D}
 */
extern EFI_GUID gEfiHobListGuid;

/**
 * Two halves of the HOB list GUID for inline GUID comparison
 * (avoid full CompareGuid overhead in GetHobList).
 * mEfiHobListGuidFirstHalf at 0xB60-0xB67
 * mEfiHobListGuidSecondHalf at 0xB68-0xB6F
 */
extern UINT64 gEfiHobListGuidFirstHalf;   ///< First 8 bytes of EFI_HOB_LIST_GUID
extern UINT64 gEfiHobListGuidSecondHalf;  ///< Second 8 bytes of EFI_HOB_LIST_GUID

/**
 * LightningRidgeEXECB2 setup config protocol GUID.
 * At binary address 0xB70.
 * Value: {CD1F9574-DD03-4196-96AD-4965146F9665}
 */
extern EFI_GUID gUbaSetupConfigProtocolGuid;

/**
 * UBA_SETUP_CONFIG_DATA descriptor for LightningRidgeEXECB2.
 * At binary address 0xB80. 24 bytes.
 */
extern UBA_SETUP_CONFIG_DATA gSetupConfigData;

/*=============================================================================
 * Function Prototypes
 *============================================================================*/

/**
 * Module entry point -- called by DXE dispatcher.
 *
 * 1. Saves and validates gImageHandle, gSystemTable, gBootServices, gRuntimeServices.
 * 2. Calls GetHobList() to locate HOB list.
 * 3. Calls DebugPrint() with platform identification string.
 * 4. Calls gBS->LocateProtocol(&gUbaBoardTypeProtocolGuid) to get UBA protocol.
 * 5. Calls protocol->RegisterSetupConfig() with UBA_SETUP_CONFIG_DATA.
 *
 * @param ImageHandle  Module's image handle.
 * @param SystemTable  UEFI system table pointer.
 *
 * @return EFI_STATUS  Result of RegisterSetupConfig, or error from LocateProtocol.
 */
EFI_STATUS
EFIAPI
ModuleEntryPoint (
    IN EFI_HANDLE        ImageHandle,
    IN EFI_SYSTEM_TABLE  *SystemTable
    );

/**
 * Returns EFI_NOT_FOUND status code.
 *
 * This is a tiny leaf helper that returns the constant 0x800000000000000E
 * (EFI_NOT_FOUND). Used as a status code supplier.
 *
 * @return EFI_NOT_FOUND (0x800000000000000E).
 */
EFI_STATUS
ReturnNotFound (
    VOID
    );

/**
 * Lazily resolves the DebugLib protocol interface using gBS->LocateProtocol().
 *
 * If the protocol has been cached already in gDebugProtocol (0xBB8), returns
 * the cached pointer. Otherwise, validates the boot services environment
 * (alloc/free pool) then calls LocateProtocol() with gDebugProtocolGuid.
 *
 * @return Pointer to DEBUG_LIB_PROTOCOL, or NULL if not found.
 */
VOID *
GetDebugProtocol (
    VOID
    );

/**
 * Debug print wrapper with platform-specific filtering.
 *
 * Before printing, reads CMOS register 0x4B (via RTC ports 0x70/0x71) to
 * determine the debug verbosity level. If level > 3 (indicating an invalid
 * or uninitialized value), falls back to MMIO 0xFDAF0490 for platform
 * configuration. If CMOS level is 0, treats it as uninitialized and uses
 * the MMIO fallback.
 *
 * The error level mask is 0x80000006 (bits 1, 2, 31 set). If the input
 * ErrorLevel (a1) has any matching bits set, the print is forwarded to
 * the DebugLib protocol's DebugPrint entry at offset 0.
 *
 * @param ErrorLevel  Debug error level mask (a1).
 * @param Format      Print format string.
 * @param ...         Variable arguments for the format string.
 *
 * @return CHAR8   Non-zero if the message was printed, 0 if filtered or
 *                 no DebugLib protocol available.
 */
CHAR8
DebugPrint (
    IN UINTN   ErrorLevel,
    IN CHAR8   *Format,
    ...
    );

/**
 * ASSERT failure handler.
 *
 * Calls the DebugLib protocol's assertion handler (at protocol offset 0x08)
 * with the source file name, line number, and assertion expression string.
 *
 * @param FileName   Source file name string.
 * @param LineNumber Line number of the assertion.
 * @param Expression Assertion expression text.
 */
VOID
DebugAssert (
    IN CHAR8   *FileName,
    IN UINTN   LineNumber,
    IN CHAR8   *Expression
    );

/**
 * Locates and caches the HOB (Hand-Off Block) list pointer.
 *
 * Scans SystemTable->ConfigurationTable[] for an entry whose GUID matches
 * EFI_HOB_LIST_GUID (gEfiHobListGuid). Each table entry is 24 bytes:
 *   16-byte EFI_GUID + 8-byte VOID*.
 *
 * If the matching entry is not found, fires an ASSERT_EFI_ERROR and
 * then asserts that mHobList is non-null (causing a halt).
 *
 * The HOB list pointer is cached in gHobList (0xBC0) for subsequent calls.
 *
 * @param ImageHandle  (unused, passed as context) -- not actually used in
 *                     the function body; the field is just a dummy argument
 *                     on the stack.
 *
 * @return VOID*  Pointer to the first HOB / HOB list, or NULL on failure.
 */
VOID *
GetHobList (
    IN EFI_HANDLE  ImageHandle   ///< [unused]
    );

/**
 * Compares a configuration table entry's GUID against EFI_HOB_LIST_GUID.
 *
 * Uses ReadUnaligned64() to compare the GUID in two 8-byte halves, avoiding
 * the overhead of a full CompareGuid().
 *
 * @param a1  Unused context parameter.
 * @param a2  Pointer to an EFI_CONFIGURATION_TABLE entry (at least 16 bytes
 *            containing an EFI_GUID).
 *
 * @return TRUE  if the GUID at a2 matches EFI_HOB_LIST_GUID.
 * @return FALSE otherwise.
 */
BOOLEAN
IsHobListGuid (
    IN UINT64  a1,         ///< [unused]
    IN VOID    *a2         ///< Pointer to GUID in configuration table entry
    );

/**
 * Reads an unaligned UINT64 value with a NULL-pointer assertion guard.
 *
 * Dereferences the given pointer as UINT64*. If the pointer is NULL,
 * triggers an ASSERT via DebugAssert.
 *
 * @param Buffer  Pointer to read from (must not be NULL).
 *
 * @return UINT64  The 8-byte value at the given address.
 */
UINT64
ReadUnaligned64 (
    IN VOID    *Buffer
    );

/**
 * Writes setup configuration data to the UBA protocol (board-specific).
 *
 * Called by the SMBIOS data update path or protocol installation loop.
 * Resolves the UBA protocol, then writes through it to register the
 * platform-specific setup configuration for LightningRidgeEXECB2.
 *
 * @param a1  Unused context parameter.
 *
 * @return EFI_STATUS  Status of the write operation.
 */
EFI_STATUS
WriteSetupConfig (
    IN EFI_HANDLE  a1
    );

/**
 * UBA protocol callback to submit a config update entry.
 *
 * This is called by the loop in sub_1FB4 to submit individual entries
 * from the setup configuration table.
 *
 * @param a1   Protocol context.
 * @param a2   Entry data (platform-specific).
 * @param a3   Entry length or flags.
 *
 * @return EFI_STATUS  Result of the submission.
 */
EFI_STATUS
SubmitConfigEntry (
    IN CHAR8   a1,
    IN UINT64  a2,
    IN UINT64  a3
    );

#endif /* SETUP_CONFIG_UPDATE_DXE_LIGHTNING_RIDGE_EXECB2_H */