/**
 * IioCfgUpdateDxeNeonCityFPGA.h
 *
 * Header for the IIO Configuration Update DXE driver targeting the
 * NeonCityFPGA platform. This module registers platform-specific IIO
 * (Integrated IO) configuration tables with the UBA (Unified Board
 * Architecture) framework during DXE initialization.
 *
 * The IIO subsystem controls the PCIe root complex configuration on
 * Intel Xeon platforms, including lane partitioning, bifurcation,
 * and port configuration. This driver provides the NeonCityFPGA
 * board-specific register settings.
 *
 * Source: HR650X BIOS, PE file index 0011
 * PDB: e:\hs\Build\HR6N0XMLK\DEBUG_VS2015\X64\PurleyRpPkg\Uba\UbaMain\Dxe\
 *      TypeNeonCityFPGA\IioCfgUpdateDxe\IioCfgUpdateDxe\DEBUG\
 *      IioCfgUpdateDxeNeonCityFPGA.pdb
 */

#ifndef __IIO_CFG_UPDATE_DXE_NEON_CITY_FPGA_H__
#define __IIO_CFG_UPDATE_DXE_NEON_CITY_FPGA_H__

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

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

/**
 * GUID for the UBA board-type protocol on NeonCityFPGA platform.
 * Used to locate the UBA protocol interface that provides the
 * RegisterIioCfg() function.
 *
 * Note: This is the same board-type GUID used by other NeonCityFPGA
 * UBA drivers (RomLayoutDxe, SetupConfigUpdateDxe).
 */
#define UBA_BOARD_TYPE_PROTOCOL_GUID \
  { 0xE03E0D46, 0x5263, 0x4845, { 0xB0, 0xA4, 0x58, 0xD5, 0x7B, 0x31, 0x77, 0xE2 } }

/**
 * GUID for the DebugLib protocol.
 * Lazily resolved and cached for debug output and assertion handling.
 */
#define DEBUG_LIB_PROTOCOL_GUID \
  { 0x36232936, 0x0E76, 0x31C8, { 0xA1, 0x3A, 0x3A, 0xF2, 0xFC, 0x1C, 0x39, 0x32 } }

/**
 * GUID for the HOB (Hand-Off Block) list in the system configuration table.
 * Standard UEFI GUID for locating the HOB list passed from PEI to DXE.
 */
#define EFI_HOB_LIST_GUID \
  { 0x7739F24C, 0x93D7, 0x11D4, { 0x9A, 0x3A, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D } }

/**
 * GUID for IIO Configuration Table 0.
 */
#define IIO_CFG_TABLE_0_GUID \
  { 0x6FE6C559, 0x4F35, 0x4111, { 0x98, 0xE1, 0x33, 0x2A, 0x25, 0x15, 0x12, 0xF3 } }

/**
 * GUID for IIO Configuration Table 1.
 */
#define IIO_CFG_TABLE_1_GUID \
  { 0x0F722F2A, 0x650F, 0x448A, { 0xAB, 0xB7, 0x04, 0xEE, 0xCD, 0x75, 0xBB, 0x30 } }

/**
 * GUID for IIO Configuration Table 2.
 */
#define IIO_CFG_TABLE_2_GUID \
  { 0xEBD11A00, 0x8C5C, 0x4F71, { 0xBB, 0x9E, 0x53, 0x94, 0x03, 0x2B, 0x01, 0xF4 } }

/**
 * GUID for IIO Configuration Table 3.
 */
#define IIO_CFG_TABLE_3_GUID \
  { 0x123BD082, 0x3201, 0x465C, { 0xB1, 0x39, 0x0C, 0xB8, 0xC7, 0x72, 0x08, 0xF8 } }

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

/**
 * PIIO table header - describes the layout of one IIO configuration table.
 *
 * Each PIIO table begins with this 48-byte header followed by an array
 * of entry descriptors (12 bytes each). The header describes the total
 * table size, number of entries, and the expected data record size
 * that each entry maps to in the configuration space.
 *
 * The "PIIO" signature stands for "Platform IIO Config" (ASCII 0x5049494F).
 */
typedef struct {
  UINT32  Signature;      /* +0x00: "PIIO" (0x4F494950) signature */
  UINT32  Version;        /* +0x04: Version (always 1) */
  UINT64  TotalSize;      /* +0x08: Total table size in bytes */
  UINT64  NumEntries;     /* +0x10: Number of configuration entries */
  UINT64  DataOffset;     /* +0x18: Offset to entry data from table base */
  UINT64  DataSize;       /* +0x20: Total size of entry data */
  UINT64  EntrySize;      /* +0x28: Size of each configuration entry */
} PIIO_TABLE_HEADER;      /* Total: 48 bytes */

/* Verify header size */
_Static_assert(sizeof(PIIO_TABLE_HEADER) == 48, "PIIO_TABLE_HEADER size mismatch");

/**
 * IIO configuration descriptor - describes one field within the
 * IIO register configuration space.
 *
 * Each descriptor specifies:
 *  - The register/field ID within the IIO config space
 *  - Flags controlling access type
 *  - An AND mask for clearing bits
 *  - An OR value for setting bits
 *
 * Multiple descriptors follow each PIIO_TABLE_HEADER, with the count
 * specified by NumEntries.
 */
typedef struct {
  UINT8   RegisterId;     /* +0x00: IIO register/field offset */
  UINT8   Flags;          /* +0x01: Access flags */
  UINT16  AndMask;        /* +0x02: Bitwise AND mask (16-bit) */
  UINT16  AndMaskExt;     /* +0x04: Extended AND mask */
  UINT16  OrValue;        /* +0x06: Bitwise OR value (16-bit) */
  UINT16  OrValueExt;     /* +0x08: Extended OR value */
  UINT16  Attributes;     /* +0x0A: Additional attributes/bus info */
} IIO_CFG_DESCRIPTOR;     /* Total: 12 bytes */

/**
 * UBA IIO configuration protocol interface.
 *
 * Registered by RomLayoutDxe and consumed by this driver.
 * The protocol provides a single function at offset +0x10 to register
 * IIO configuration tables.
 */
typedef struct {
  UINT64    Reserved0;                      /* +0x00 */
  UINT64    Reserved1;                      /* +0x08 */
  EFI_STATUS (EFIAPI *RegisterIioCfg)(      /* +0x10 */
    IN VOID           *This,
    IN EFI_GUID       *IioCfgGuid,          /* GUID identifying the config table */
    IN PIIO_TABLE_HEADER *IioCfgData,       /* PIIO table header + descriptors */
    IN UINT64         DataSize              /* Size of data (always 48 = header size) */
    );
} UBA_IIO_CFG_PROTOCOL;

/*===========================================================================
 * Debug Library Protocol (minimal definition)
 *===========================================================================*/

/**
 * Minimal DebugLib protocol definition. Only the two functions
 * actually called by this driver are declared.
 */
typedef struct {
  UINT64    (EFIAPI *DebugPrint)(           /* +0x00 */
    IN UINT64         ErrorLevel,
    IN CONST CHAR8    *Format,
    ...
    );
  VOID      (EFIAPI *DebugAssert)(          /* +0x08 */
    IN CONST CHAR8    *FileName,
    IN UINT64         LineNumber,
    IN CONST CHAR8    *Description
    );
} DEBUG_LIB_PROTOCOL;

/*===========================================================================
 * Global Variables (exported by this module)
 *===========================================================================*/

/* Boot services globals, populated in ModuleEntryPoint */
extern EFI_SYSTEM_TABLE    *gST;
extern EFI_BOOT_SERVICES   *gBS;
extern EFI_RUNTIME_SERVICES *gRT;
extern EFI_HANDLE           gImageHandle;

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

/**
 * Module entry point - called by DXE dispatcher.
 * Initializes global UEFI service pointers, locates the HOB list,
 * resolves the UBA board-type protocol, and registers four
 * IIO configuration tables.
 *
 * @param[in] ImageHandle  The firmware allocated handle for the EFI image.
 * @param[in] SystemTable  A pointer to the EFI System Table.
 * @return EFI_SUCCESS on successful initialization.
 */
EFI_STATUS
EFIAPI
ModuleEntryPoint(
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE *SystemTable
  );

/**
 * Registers all IIO configuration tables with the UBA framework.
 *
 * Prints the "UBA:IioCfgUpdate-TypeNeonCityFPGA" banner, then
 * resolves the UBA board-type protocol and calls RegisterIioCfg()
 * for each of the 4 configuration tables.
 *
 * @return EFI_SUCCESS on success, or error from LocateProtocol.
 */
EFI_STATUS
RegisterIioConfigTables(
  VOID
  );

/**
 * Returns a fixed EFI_SUCCESS value. (thunk/unused)
 *
 * This is a stub function that simply returns 0. It is present
 * in the binary but never called from within the module.
 *
 * @return EFI_SUCCESS (0)
 */
EFI_STATUS
ReturnSuccess(
  VOID
  );

/**
 * Resolves and caches the DebugLib protocol interface.
 *
 * Uses a pool alloc/free canary to validate that UEFI boot services
 * are functional before calling LocateProtocol. The cached protocol
 * pointer is stored in a static global.
 *
 * @return Pointer to the DebugLib protocol interface, or NULL.
 */
DEBUG_LIB_PROTOCOL *
GetDebugProtocol(
  VOID
  );

/**
 * Debug print function with CMOS-level filtering.
 *
 * Reads the CMOS debug level from register 0x4B to determine whether
 * the message at the given ErrorLevel should be printed. Falls back
 * to MMIO 0xFDAF0490 if the CMOS level is 0.
 *
 * @param[in] ErrorLevel  Debug message error level mask.
 * @param[in] Format      printf-style format string.
 * @param[in] ...         Variable arguments for format string.
 * @return Non-zero if message was printed, 0 if filtered or no protocol.
 */
UINT8
DebugPrint(
  IN UINT64        ErrorLevel,
  IN CONST CHAR8   *Format,
  ...
  );

/**
 * Debug assertion handler.
 *
 * Calls the DebugLib protocol's assertion function with the file name,
 * line number, and assertion description.
 *
 * @param[in] FileName     Source file name of the assertion.
 * @param[in] LineNumber   Line number of the assertion.
 * @param[in] Description  Assertion description string.
 */
VOID
DebugAssert(
  IN CONST CHAR8  *FileName,
  IN UINT64        LineNumber,
  IN CONST CHAR8  *Description
  );

/**
 * Locates and caches the HOB (Hand-Off Block) list pointer.
 *
 * Scans the SystemTable->ConfigurationTable[] array for an entry
 * matching EFI_HOB_LIST_GUID. On success, stores and returns the
 * HOB list pointer. On failure, triggers an assertion.
 *
 * @param[in] SystemTable  Pointer to EFI_SYSTEM_TABLE (unused, uses global).
 * @return Pointer to the HOB list, or NULL if not found.
 */
VOID *
GetHobList(
  IN EFI_SYSTEM_TABLE *SystemTable
  );

/**
 * Compares two GUIDs by checking both 8-byte halves.
 *
 * Optimized GUID comparison using ReadUnaligned64 to avoid the
 * overhead of a full CompareGuid() call.
 *
 * @param[in] Guid1  First GUID to compare.
 * @param[in] Guid2  Second GUID (entry from config table).
 * @return TRUE if GUIDs match, FALSE otherwise.
 */
BOOLEAN
IsGuidEqual(
  IN EFI_GUID  *Guid1,
  IN EFI_GUID  *Guid2
  );

/**
 * Reads a UINT64 from memory with NULL pointer assertion.
 *
 * Simple wrapper around pointer dereference that asserts on NULL
 * input. Used by IsGuidEqual for unaligned GUID field reading.
 *
 * @param[in] Buffer  Pointer to read from.
 * @return The UINT64 value at Buffer.
 */
UINT64
ReadUnaligned64(
  IN CONST UINT64  *Buffer
  );

#endif /* __IIO_CFG_UPDATE_DXE_NEON_CITY_FPGA_H__ */