/**
 * @file SlotDataUpdateDxeLightningRidgeEXECB1.h
 *
 * @brief UEFI DXE driver header for LightningRidge EXEC B1 slot data update.
 *
 * This driver is part of the AMI UBA (Universal BIOS Architecture) framework.
 * It locates the UBA_CONFIG protocol specific to the LightningRidge EXEC B1
 * platform and reads PSLT (Platform Slot Table) configuration data via the
 * protocol's GetData interface. The data defines PCIe slot layout for the
 * platform and is consumed by slot initialization and SMBIOS slot type
 * reporting subsystems.
 *
 * Build source path: PurleyRpPkg/Uba/UbaMain/Dxe/TypeLightningRidgeEXECB1/
 *                    SlotDataUpdateDxe/SlotDataUpdateDxe/
 * PDB: SlotDataUpdateDxeLightningRidgeEXECB1.pdb
 * Build: VS2015, DEBUG, X64
 */

#ifndef SLOT_DATA_UPDATE_DXE_LIGHTNING_RIDGE_EXEC_B1_H
#define SLOT_DATA_UPDATE_DXE_LIGHTNING_RIDGE_EXEC_B1_H

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

// =============================================================================
// Platform Constants
// =============================================================================

/** CMOS I/O port for selecting CMOS register index. */
#define CMOS_INDEX_PORT                         0x70

/** CMOS I/O port for reading/writing CMOS register data. */
#define CMOS_DATA_PORT                          0x71

/** CMOS register index for platform type / debug verbosity. */
#define CMOS_PLATFORM_TYPE_REG                  0x4B

/** MMIO address for hardware platform strap in PCH. */
#define PLATFORM_STRAP_MMIO_ADDR                0xFDAF0490

// =============================================================================
// Debug Level Masks (UEFI standard)
// =============================================================================

/** Debug error severity. Always enabled by this module's mask logic. */
#define DEBUG_ERROR                             ((UINT64)0x8000000000000001)

/** Debug info severity. */
#define DEBUG_INFO_MASK                         ((UINT64)0x80000004)

/** Debug verbose severity. */
#define DEBUG_VERBOSE_MASK                      ((UINT64)0x80000006)

// =============================================================================
// Function Pointer Type Declarations for UBA Protocol vtable
// =============================================================================

/**
 * DebugPrint function type as implemented by the UBA protocol (vtable +0x00).
 *
 * @param[in] Severity  Debug level mask.
 * @param[in] Format    Format string.
 * @param[in] VaList    Pointer to variable argument list (UINT64*).
 */
typedef
VOID
(EFIAPI *DEBUG_PRINT_FUNC)(
    UINT64       Severity,
    CHAR8        *Format,
    UINT64       *VaList
    );

/**
 * DebugAssert function type as implemented by the UBA protocol (vtable +0x08).
 *
 * @param[in] FileName     Source file name.
 * @param[in] LineNumber   Line number.
 * @param[in] Expression   Assertion expression.
 */
typedef
VOID
(EFIAPI *DEBUG_ASSERT_FUNC)(
    CHAR8        *FileName,
    UINTN         LineNumber,
    CHAR8        *Expression
    );

/**
 * GetData function type as implemented by the UBA protocol (vtable +0x10).
 *
 * @param[in]  This       The UBA protocol interface.
 * @param[in]  Guid       GUID identifying the data to retrieve.
 * @param[out] Data       Output buffer.
 * @param[in]  DataSize   Size of the output buffer.
 * @return EFI_STATUS     EFI_SUCCESS on success, error code otherwise.
 */
typedef
EFI_STATUS
(EFIAPI *UBA_GET_DATA_FUNC)(
    VOID        *This,
    EFI_GUID    *Guid,
    VOID        *Data,
    UINTN        DataSize
    );

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

/**
 * UBA Debug Protocol GUID for LightningRidge EXEC B1.
 * GUID: 36232936-0E76-31C8-A13A-3AF2FC1C3932
 *
 * Located by UbaGetProtocolInterface(). Provides DebugPrint (+0x00) and
 * DebugAssert (+0x08) services. This is the debug channel portion of the
 * UBA framework and is separate from the UBA Config protocol that provides
 * GetData.
 */
#define UBA_DEBUG_PROTOCOL_GUID \
    { 0x36232936, 0x0E76, 0x31C8, \
      { 0xA1, 0x3A, 0x3A, 0xF2, 0xFC, 0x1C, 0x39, 0x32 } }

/** Pointer to UBA_DEBUG_PROTOCOL_GUID as EFI_GUID */
extern EFI_GUID gUbaDebugProtocolGuid;

/**
 * UBA Config Protocol GUID for LightningRidge EXEC B1.
 * GUID: E03E0D46-5263-4845-B0A4-58D57B3177E2
 *
 * Located directly in _ModuleEntryPoint via gBS->LocateProtocol().
 * Provides GetData (+0x10) for reading PSLT configuration entries.
 * This protocol is separate from the debug protocol and represents
 * the platform-specific UBA configuration data store.
 */
#define UBA_CONFIG_PROTOCOL_GUID \
    { 0xE03E0D46, 0x5263, 0x4845, \
      { 0xB0, 0xA4, 0x58, 0xD5, 0x7B, 0x31, 0x77, 0xE2 } }

/** Pointer to UBA_CONFIG_PROTOCOL_GUID as EFI_GUID */
extern EFI_GUID gUbaConfigProtocolGuid;

/**
 * UBA Slot Data PSLT Entry 1 GUID.
 *
 * GUID: B93613E1-48F0-4B32-B3A8-4FEDFC7C1365
 *
 * Used with UbaProtocol->GetData to retrieve the primary PSLT (Platform Slot
 * Table) structure containing slot count and slot-specific data.
 * Output buffer at mSlotDataBuffer1 (0xBB0), size 32 bytes.
 */
#define UBA_SLOT_DATA_PSLT1_GUID \
    { 0xB93613E1, 0x48F0, 0x4B32, \
      { 0xB3, 0xA8, 0x4F, 0xED, 0xFC, 0x7C, 0x13, 0x65 } }

extern EFI_GUID gUbaSlotDataPsl1Guid;

/**
 * UBA Slot Config PSLT Entry 2 GUID.
 *
 * GUID: 226763AE-972C-4E3C-80D1-73B25E8CBBA3
 *
 * Used with UbaProtocol->GetData to retrieve the secondary slot configuration
 * structure. Output buffer at mSlotDataBuffer2 (0xBE0), size 40 bytes.
 * Contains PSLT header plus 8 bytes of extended config data.
 */
#define UBA_SLOT_CONFIG_GUID \
    { 0x226763AE, 0x972C, 0x4E3C, \
      { 0x80, 0xD1, 0x73, 0xB2, 0x5E, 0x8C, 0xBB, 0xA3 } }

extern EFI_GUID gUbaSlotConfigGuid;

/**
 * DXE Services Table GUID (gEfiDxeServicesTableGuid).
 *
 * GUID: 7739F24C-93D7-11D4-9A3A-0090273FC14D
 *
 * Standard UEFI GUID used to locate the HOB (Hand-Off Block) list from the
 * EFI System Table's ConfigurationTable. The driver scans the config table
 * for this GUID to find the HOB list pointer.
 */
#define DXE_SERVICES_TABLE_GUID \
    { 0x7739F24C, 0x93D7, 0x11D4, \
      { 0x9A, 0x3A, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D } }

extern EFI_GUID gEfiDxeServicesTableGuid;

// =============================================================================
// Data Structure Definitions
// =============================================================================

/**
 * PSLT_HEADER - Platform Slot Table Header.
 *
 * This structure defines the layout of a PSLT entry. The driver reads PSLT
 * entries from the UBA protocol using GetData with specific GUIDs.
 *
 * Template instances:
 *   - mSlotDataBuffer1 (0xBB0): GetData writes 32 bytes (PSLT_HEADER)
 *   - mSlotDataBuffer2 (0xBE0): GetData writes 40 bytes (SLOT_CONFIG)
 *
 * At runtime, the UBA protocol fills in these structures with platform-
 * specific slot configuration data for the LightningRidge EXEC B1 platform.
 */
#pragma pack(push, 1)
typedef struct {
    UINT32  Signature;      ///< "PSLT" (0x544C5350) -- Platform Slot Table signature
    UINT32  Version;        ///< PSLT format version (1 for this generation)
    UINT64  Length;         ///< Total length of PSLT data block (3024 = 0xBD0)
    UINT64  StructSize;     ///< Size of each per-slot structure (1200 = 0x4B0)
    UINT64  NumberOfSlots;  ///< Number of PCIe slots defined for this platform (1)
} PSLT_HEADER;

/**
 * SLOT_CONFIG - Extended slot configuration structure (40 bytes).
 *
 * Used for the second GetData call. Contains a PSLT_HEADER followed by
 * 8 bytes of platform-specific extended configuration (initialized to
 * 0x04B4 in the template, which equals StructSize + 4).
 */
typedef struct {
    PSLT_HEADER Header;     ///< PSLT header (32 bytes)
    UINT64      ConfigData; ///< Extended slot configuration data (8 bytes)
} SLOT_CONFIG;
#pragma pack(pop)

/** Compile-time assertion macro for struct size validation. */
#define ASSERT_STRUCT_SIZE(type, expected) \
    typedef char ASSERT_##type##_SIZE[(sizeof(type) == (expected)) ? 1 : -1]

/** Verify PSLT_HEADER is exactly 32 bytes. */
ASSERT_STRUCT_SIZE(PSLT_HEADER, 32);
/** Verify SLOT_CONFIG is exactly 40 bytes. */
ASSERT_STRUCT_SIZE(SLOT_CONFIG, 40);

// =============================================================================
// UBA Protocol Interface Structure
// =============================================================================

/**
 * UBA Debug Protocol interface structure.
 *
 * Located by UbaGetProtocolInterface() with GUID
 * {36232936-0E76-31C8-A13A-3AF2FC1C3932} (at 0xB60).
 *
 * Provides DebugPrint and DebugAssert only. The GetData slot (+0x10)
 * may be a stub or null in this protocol instance.
 */
typedef struct {
    DEBUG_PRINT_FUNC    DebugPrint;      ///< +0x00: DebugPrint function
    DEBUG_ASSERT_FUNC   DebugAssert;     ///< +0x08: DebugAssert function
    VOID               *Reserved3;       ///< +0x10: Reserved/GetData (unused)
} UBA_DEBUG_PROTOCOL_INTERFACE;

/**
 * UBA Config Protocol interface structure.
 *
 * Located directly in _ModuleEntryPoint with GUID
 * {E03E0D46-5263-4845-B0A4-58D57B3177E2} (at 0xB70).
 *
 * Provides GetData at +0x10 for reading PSLT configuration entries.
 * The +0x00 and +0x08 slots may be reserved or different from the
 * debug protocol.
 */
typedef struct {
    VOID               *Reserved1;       ///< +0x00: Possibly DebugPrint (unused)
    VOID               *Reserved2;       ///< +0x08: Possibly DebugAssert (unused)
    UBA_GET_DATA_FUNC   GetData;         ///< +0x10: GetData for PSLT reads
} UBA_CONFIG_PROTOCOL_INTERFACE;

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

/** Saved ImageHandle from entry point parameter. Address: 0xC18. */
extern EFI_HANDLE   gImageHandle;

/** Saved SystemTable pointer from entry point parameter. Address: 0xC08. */
extern EFI_SYSTEM_TABLE *gSystemTable;

/** Saved BootServices pointer (SystemTable->BootServices). Address: 0xC10. */
extern EFI_BOOT_SERVICES *gBootServices;

/** Saved RuntimeServices pointer (SystemTable->RuntimeServices). Address: 0xC20. */
extern EFI_RUNTIME_SERVICES *gRuntimeServices;

// =============================================================================
// Internal Module State (STATIC in .c, listed here for documentation only)
// =============================================================================

/**
 * Cached UBA debug protocol interface pointer (mUbaDebugProtocol). Address: 0xC28.
 * Lazily initialized by UbaGetProtocolInterface() using GUID at 0xB60.
 * Provides DebugPrint and DebugAssert. NULL initially.
 */
extern UBA_DEBUG_PROTOCOL_INTERFACE *mUbaDebugProtocol;

/**
 * Cached HOB list pointer from config table (mHobList). Address: 0xC30.
 * Initialized by GetHobList(). NULL initially.
 */
extern VOID *mHobList;

/**
 * Cached platform type from CMOS[0x4B] or hardware strap (mPlatformType).
 * Address: 0xC38. Initial value: 0.
 */
extern UINT8 mPlatformType;

/**
 * PSLT buffer 1 -- slot data output buffer (mSlotDataBuffer1).
 * Address: 0xBB0. 32 bytes. Template filled by GetData.
 */
extern PSLT_HEADER mSlotDataBuffer1;

/**
 * PSLT buffer 2 -- slot config output buffer (mSlotDataBuffer2).
 * Address: 0xBE0. 40 bytes. Template filled by GetData.
 */
extern SLOT_CONFIG mSlotDataBuffer2;

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

/**
 * UEFI DXE driver entry point.
 *
 * Called by the DXE Core during driver dispatch. Performs:
 *   1. Caches ImageHandle, SystemTable, BootServices, RuntimeServices globals.
 *   2. Initializes HOB list from config table.
 *   3. Locates the UBA protocol via LocateProtocol.
 *   4. Reads PSLT entry 1 (slot data) and entry 2 (slot config) via GetData.
 *
 * @param[in] ImageHandle  The firmware-allocated handle for this image.
 * @param[in] SystemTable  A pointer to the EFI System Table.
 * @return EFI_STATUS      EFI_SUCCESS, or EFI_NOT_FOUND from LocateProtocol,
 *                         or error from GetData.
 */
EFI_STATUS
EFIAPI
_ModuleEntryPoint (
    IN EFI_HANDLE        ImageHandle,
    IN EFI_SYSTEM_TABLE  *SystemTable
    );

/**
 * Returns the supported slot count for this platform.
 *
 * Always returns 2 for LightningRidge EXEC B1. Used by the UBA framework
 * for slot enumeration and SMBIOS topology reporting.
 *
 * @return UINT8  Always 2 (number of PCIe slots).
 */
UINT8
EFIAPI
GetSlotCount (
    VOID
    );

/**
 * Identity pass-through for slot data.
 *
 * Returns DefaultData unchanged. Slot data on EXEC B1 is populated by
 * UbaProtocol->GetData directly; no callback customization is needed.
 *
 * @param[in] Slot          Slot index (unused).
 * @param[in] DefaultData   Pointer to default slot data.
 * @return VOID*            The unmodified DefaultData pointer.
 */
VOID *
EFIAPI
GetSlotData (
    IN UINTN  Slot,
    IN VOID   *DefaultData
    );

/**
 * Lazily resolves and caches the UBA DEBUG protocol interface.
 *
 * TPL-safe LocateProtocol wrapper. Uses the debug protocol GUID at 0xB60
 * ({36232936-0E76-31C8-A13A-3AF2FC1C3932}). Raises to TPL_HIGH_LEVEL (31),
 * restores to verify current TPL <= TPL_NOTIFY (0x10), then calls
 * gBS->LocateProtocol(...). Provides DebugPrint and DebugAssert.
 *
 * NOTE: This is SEPARATE from the UBA CONFIG protocol used directly
 * in _ModuleEntryPoint (GUID at 0xB70 = E03E0D46-...).
 *
 * @return UBA_DEBUG_PROTOCOL_INTERFACE*  Cached debug protocol, or NULL.
 */
UBA_DEBUG_PROTOCOL_INTERFACE *
EFIAPI
UbaGetProtocolInterface (
    VOID
    );

/**
 * UBA-aware debug print with CMOS platform-type filtering.
 *
 * Reads CMOS register 0x4B via I/O ports 0x70/0x71 to determine verbosity:
 *   - <= 3: Direct verbosity level (0=DE, 1=DE|DI, 2+=DE|DV)
 *   - > 3: Platform type. If cached type is 0, derives from hardware strap
 *           at MMIO 0xFDAF0490: type = (strap & 2) | 1 (always >= 1)
 *   - All derived types >= 1 produce DE|DV mask (0x80000006).
 *
 * If the resulting mask matches the caller's severity, the message is
 * forwarded to the protocol's DebugPrint function.
 *
 * @param[in] DebugLevel  Debug message severity mask.
 * @param[in] Format      Print format string.
 * @param[in] ...         Variable arguments for the format string.
 */
VOID
EFIAPI
UbaDebugPrint (
    IN UINT64       DebugLevel,
    IN CONST CHAR8  *Format,
    ...
    );

/**
 * UBA-aware ASSERT failure handler.
 *
 * Locates the UBA protocol and calls DebugAssert (+0x08) with the file
 * name, line number, and assertion expression. Silently returns if the
 * UBA protocol is unavailable.
 *
 * @param[in] FileName     Source file where assertion failed.
 * @param[in] LineNumber   Line number of failed assertion.
 * @param[in] Expression   Assertion expression string.
 */
VOID
EFIAPI
UbaDebugAssert (
    IN CONST CHAR8  *FileName,
    IN UINTN         LineNumber,
    IN CONST CHAR8  *Expression
    );

/**
 * Locates and caches the HOB list from SystemTable->ConfigurationTable.
 *
 * Scans for gEfiDxeServicesTableGuid ({7739F24C-93D7-11D4-9A3A-0090273FC14D})
 * using IsHobGuidMatch (64-bit halves comparison).
 * If not found, triggers debug assert with EFI_NOT_FOUND.
 *
 * @return VOID*  Pointer to the HOB list, or NULL.
 */
VOID *
EFIAPI
GetHobList (
    VOID
    );

/**
 * Compares two EFI_GUID values via unaligned 64-bit reads.
 *
 * Reads both halves (bytes 0-7 and 8-15) of each GUID using
 * ReadUnaligned64 and compares them. This is an unaligned-safe
 * comparison following the standard EDK2 pattern.
 *
 * @param[in] Guid1  Pointer to first EFI_GUID.
 * @param[in] Guid2  Pointer to second EFI_GUID.
 * @return BOOLEAN   TRUE if both halves match, FALSE otherwise.
 */
BOOLEAN
EFIAPI
IsHobGuidMatch (
    IN EFI_GUID  *Guid1,
    IN EFI_GUID  *Guid2
    );

/**
 * Reads a UINT64 from a potentially unaligned address with NULL assertion.
 *
 * Asserts via UbaDebugAssert if Buffer is NULL, then performs a direct
 * 64-bit read. On x64 the CPU natively handles unaligned accesses.
 *
 * @param[in] Buffer  Pointer to UINT64 (must not be NULL).
 * @return UINT64     The value at Buffer.
 */
UINT64
EFIAPI
ReadUnaligned64 (
    IN CONST UINT64  *Buffer
    );

#endif // SLOT_DATA_UPDATE_DXE_LIGHTNING_RIDGE_EXEC_B1_H