/**
 * @file IioCfgUpdateDxeLightningRidgeEXECB1.h
 *
 * @brief IioCfgUpdateDxeLightningRidgeEXECB1 - UEFI DXE driver for registering
 *        IIO (Integrated IO) configuration data for the LightningRidgeEXECB1
 *        platform via the UBA (Unified Board Architecture) framework.
 *
 * MODULE TYPE: DXE Driver
 * UEFI PHASE:  DXE (Driver Execution Environment)
 *
 * PURPOSE:
 *   This driver is part of Lenovo's UBA (Unified Board Architecture) framework.
 *   It performs the following at entry:
 *     1. Initializes UEFI global variables (gImageHandle, gST, gBS, gRT)
 *        via the UefiBootServicesTableLib and UefiRuntimeServicesTableLib.
 *     2. Locates the HOB (Hand-Off Block) list from the UEFI System Table's
 *        configuration table array by matching the EFI_HOB_LIST_GUID.
 *     3. Locates a UBA board-type protocol using gBS->LocateProtocol()
 *        (same protocol GUID E03E0D46-... used by RomLayoutDxe and other
 *        UBA platform modules).
 *     4. Registers up to 4 IIO configuration protocol instances by calling
 *        the board-type protocol's registration function, passing a
 *        UBA_IIO_CFG_UPDATE_PROTOCOL structure (signature "PIIO") and a
 *        board-config GUID for each IIO (CPU socket) instance.
 *     5. Provides debug output via the DebugLib protocol accessed through
 *        gBS (RaiseTPL/RestoreTPL for critical sections).
 *
 * DEPENDENCIES (Protocols consumed):
 *   - UBA Board-Type Protocol (GUID: e03e0d46-5263-4845-b0a4-58d57b3177e2)
 *     Same protocol used by RomLayoutDxe, SlotDataUpdateDxe*, etc.
 *     Located via gBS->LocateProtocol(). Provides a registration function
 *     at interface offset 0x10.
 *   - EFI_HOB_LIST_GUID (7739f24c-93d7-11d4-9a3a-0090273fc14d)
 *     Used to locate the HOB list from the system configuration table.
 *   - UEFI Debug Library Protocol (implicit via gBS)
 *
 * DEPENDENCIES (Protocols produced):
 *   - UBA IIO Config Update Protocol (GUIDs vary per IIO instance):
 *     * 6FE6C559-4F35-4111-98E1-332A251512F3
 *     * 0F722F2A-650F-448A-ABB7-04EECD75BB30
 *     * EBD11A00-8C5C-4F71-BB9E-5394032B01F4
 *     * 123BD082-3201-465C-B139-0CB8C77208F8
 *     These represent IIO configuration instances for up to 4 CPU sockets
 *     on the LightningRidgeEXECB1 platform.
 *
 * HARDWARE ACCESS:
 *   - CMOS ports 0x70/0x71: Read debug level setting mask from CMOS register 0x4B
 *   - MMIO 0xFDAF0490: On boards where CMOS byte is 0, reads a board config
 *                       register to determine board type.
 *
 * LIBRARY DEPENDENCIES:
 *   - UefiBootServicesTableLib (gImageHandle, gST, gBS)
 *   - UefiRuntimeServicesTableLib (gRT)
 *   - DxeHobLib (HOB list parsing)
 *   - BaseLib (unaligned read: ReadUnaligned64)
 *   - DebugLib (DEBUG macro via CmosDebugLevelProvider)
 *
 * @note This module is specific to the LightningRidgeEXECB1 platform type.
 *       Similar modules exist for other platforms (e.g., LightningRidgeEXECB2,
 *       LightningRidgeEXRP, NeonCityFPGA) with different IIO config tables.
 */

#ifndef _IIO_CFG_UPDATE_DXE_LIGHTNINGRIDGE_EXECB1_H_
#define _IIO_CFG_UPDATE_DXE_LIGHTNINGRIDGE_EXECB1_H_

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

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

///
/// EFI_HOB_LIST_GUID - GUID used to locate the HOB list in the system
/// configuration table.
/// {7739F24C-93D7-11D4-9A3A-0090273FC14D}
///
#define EFI_HOB_LIST_GUID \
  { 0x7739F24C, 0x93D7, 0x11D4, { 0x9A, 0x3A, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D } }

///
/// UBA_BOARD_TYPE_PROTOCOL_GUID
/// Protocol GUID used with gBS->LocateProtocol() to obtain the UBA board-type
/// protocol interface. This is the same protocol GUID used across all UBA
/// platform modules (RomLayoutDxe, SlotDataUpdateDxe*, etc.).
/// The protocol's interface has a function at offset 0x10 that registers
/// platform-specific configuration data.
/// {E03E0D46-5263-4845-B0A4-58D57B3177E2}
///
#define UBA_BOARD_TYPE_PROTOCOL_GUID \
  { 0xE03E0D46, 0x5263, 0x4845, { 0xB0, 0xA4, 0x58, 0xD5, 0x7B, 0x31, 0x77, 0xE2 } }

///
/// UBA_IIO_CFG_UPDATE_PROTOCOL_GUID_0
/// IIO configuration protocol for CPU socket 0 on LightningRidgeEXECB1.
/// {6FE6C559-4F35-4111-98E1-332A251512F3}
///
#define UBA_IIO_CFG_UPDATE_PROTOCOL_GUID_0 \
  { 0x6FE6C559, 0x4F35, 0x4111, { 0x98, 0xE1, 0x33, 0x2A, 0x25, 0x15, 0x12, 0xF3 } }

///
/// UBA_IIO_CFG_UPDATE_PROTOCOL_GUID_1
/// IIO configuration protocol for CPU socket 1 on LightningRidgeEXECB1.
/// {0F722F2A-650F-448A-ABB7-04EECD75BB30}
///
#define UBA_IIO_CFG_UPDATE_PROTOCOL_GUID_1 \
  { 0x0F722F2A, 0x650F, 0x448A, { 0xAB, 0xB7, 0x04, 0xEE, 0xCD, 0x75, 0xBB, 0x30 } }

///
/// UBA_IIO_CFG_UPDATE_PROTOCOL_GUID_2
/// IIO configuration protocol for CPU socket 2 on LightningRidgeEXECB1.
/// {EBD11A00-8C5C-4F71-BB9E-5394032B01F4}
///
#define UBA_IIO_CFG_UPDATE_PROTOCOL_GUID_2 \
  { 0xEBD11A00, 0x8C5C, 0x4F71, { 0xBB, 0x9E, 0x53, 0x94, 0x03, 0x2B, 0x01, 0xF4 } }

///
/// UBA_IIO_CFG_UPDATE_PROTOCOL_GUID_3
/// IIO configuration protocol for CPU socket 3 on LightningRidgeEXECB1.
/// {123BD082-3201-465C-B139-0CB8C77208F8}
///
#define UBA_IIO_CFG_UPDATE_PROTOCOL_GUID_3 \
  { 0x123BD082, 0x3201, 0x465C, { 0xB1, 0x39, 0x0C, 0xB8, 0xC7, 0x72, 0x08, 0xF8 } }

///
/// UBA_DEBUG_PROTOCOL_GUID
/// Protocol GUID for the UBA Debug Library protocol, cached by GetDebugProtocol().
/// This protocol provides debug output and assertion handling.
/// {36232936-0E76-31C8-A13A-3AF2FC1C3932}
///
#define UBA_DEBUG_PROTOCOL_GUID \
  { 0x36232936, 0x0E76, 0x31C8, { 0xA1, 0x3A, 0x3A, 0xF2, 0xFC, 0x1C, 0x39, 0x32 } }

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

///
/// UBA_IIO_CFG_UPDATE_PROTOCOL
/// Structure passed to the UBA board-type protocol to register IIO
/// configuration data for a specific CPU socket.
///
/// The signature is "PIIO" (little-endian: 'P','I','I','O'), which encodes
/// "OIIP" in memory, representing "IIO Protocol".
///
typedef struct {
  ///
  /// Signature = "PIIO" (0x4F494950 in little-endian).
  ///
  UINT32    Signature;
  ///
  /// Board ID value. On LightningRidgeEXECB1, this is 0x0D60.
  ///
  UINT16    BoardId;
  ///
  /// Padding/Reserved.
  ///
  UINT16    Reserved0;
  ///
  /// Slot number (CPU socket index). This is 0x3C (60) on the
  /// LightningRidgeEXECB1 platform.
  ///
  UINT64    SlotNumber;
  ///
  /// Size of the IIO configuration table in bytes. Value = 0x50C (1292).
  ///
  UINT64    IioCfgTableSize;
  ///
  /// Pointer (relative offset from image base) to the IIO configuration table.
  /// On LightningRidgeEXECB1, this points to offset 0xC60 in the image.
  ///
  UINT64    IioCfgTable;
  ///
  /// Reserved padding field. Value = 0xFC (252).
  ///
  UINT64    Reserved1;
} UBA_IIO_CFG_UPDATE_PROTOCOL;

///
/// UBA_IIO_CFG_UPDATE_TABLE_ENTRY
/// An entry in the IIO configuration table at IioCfgTable.
/// Each entry is 12 bytes and encodes configuration for a specific IIO
/// register or port on a CPU socket.
///
typedef struct {
  ///
  /// Byte 0: Configuration type/register index.
  ///
  UINT8     Type;
  ///
  /// Byte 1: Sub-type or function selector.
  ///
  UINT8     SubType;
  ///
  /// Bytes 2-3: Reserved/padding (typically 0xFFFF = unchecked).
  ///
  UINT16    Reserved0;
  ///
  /// Bytes 4-7: Reserved/padding (typically 0xFFFF0000...).
  ///
  UINT32    Reserved1;
  ///
  /// Byte 8: Target value or device selector.
  ///
  UINT8     Value;
  ///
  /// Byte 9: Port/address.
  ///
  UINT8     Port;
  ///
  /// Bytes 10-11: Reserved/padding.
  ///
  UINT16    Reserved2;
} UBA_IIO_CFG_UPDATE_TABLE_ENTRY;

///
/// UBA_IIO_CFG_UPDATE_TABLE_ENTRY_SIZE
/// Size of each entry in the IIO configuration table (12 bytes).
///
#define UBA_IIO_CFG_UPDATE_TABLE_ENTRY_SIZE  12

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

///
/// IIO protocol signature ("PIIO" in little-endian).
///
#define UBA_IIO_CFG_UPDATE_SIGNATURE         SIGNATURE_32('P', 'I', 'I', 'O')

///
/// Board ID value for LightningRidgeEXECB1.
///
#define LIGHTNINGRIDGE_EXECB1_BOARD_ID       0x0D60

///
/// Slot number on this platform.
///
#define LIGHTNINGRIDGE_EXECB1_SLOT_NUMBER    0x3C

///
/// IIO configuration table size (1292 bytes = 0x50C).
///
#define LIGHTNINGRIDGE_EXECB1_IIO_CFG_SIZE   0x50C

///
/// Number of IIO configuration protocols registered (4 sockets max).
///
#define IIO_CFG_UPDATE_PROTOCOL_COUNT        4

///
/// CMOS debug level register. Port 0x70 selects the CMOS register;
/// port 0x71 reads/writes the value.
/// Register 0x4B is used for board type / debug level control.
///
#define CMOS_DEBUG_LEVEL_REGISTER            0x4B

///
/// CMOS index port
///
#define RTC_INDEX_PORT                       0x70

///
/// CMOS data port
///
#define RTC_DATA_PORT                        0x71

///
/// Board configuration MMIO register address (used for debug level fallback
/// when CMOS byte is 0).
///
#define BOARD_CONFIG_MMIO_ADDR               0xFDAF0490ULL

///
/// Debug message severity mask. Used with the DebugLib protocol.
///
#define DEBUG_INFO                           0x80000000

///
/// Board type CMOS byte value indicating "read from MMIO".
///
#define BOARD_TYPE_CMOS_NEEDS_MMIO           0

///
/// Board type threshold: values 1, 2, 3 are "standard" board types.
///
#define BOARD_TYPE_STANDARD_MAX              3

///
/// Mask for board type extraction from MMIO register.
///
#define BOARD_TYPE_MMIO_MASK                 2

///
/// Flag bit for MMIO-based board type.
///
#define BOARD_TYPE_MMIO_FLAG_BIT             BIT0

// ============================================================================
// Global Variable Declarations
// ============================================================================

//
// UEFI Boot Services Table pointer (cached by UefiBootServicesTableLib).
//
extern EFI_SYSTEM_TABLE     *gST;
extern EFI_BOOT_SERVICES    *gBS;
extern EFI_RUNTIME_SERVICES *gRT;
extern EFI_HANDLE           gImageHandle;

///
/// Pointer to the HOB list, obtained from the system configuration table
/// by searching for the EFI_HOB_LIST_GUID entry.
///
extern VOID                 *gHobList;

///
/// Cached debug protocol interface obtained by GetDebugProtocol().
///
extern VOID                 *gDebugProtocol;

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

/**
 * Module entry point for IioCfgUpdateDxeLightningRidgeEXECB1.
 *
 * Initializes UEFI global variables (gImageHandle, gST, gBS, gRT), locates the
 * HOB list via GetHobList(), prints a debug banner via DebugPrint(), locates the
 * UBA board-type protocol, and registers up to 4 IIO configuration protocol
 * instances by calling the protocol's registration function.
 *
 * @param[in] ImageHandle  The firmware-allocated handle for this driver image.
 * @param[in] SystemTable  A pointer to the EFI System Table.
 *
 * @return EFI_SUCCESS     At least one IIO configuration protocol was registered.
 * @return Other           The board-type protocol could not be located.
 */
EFI_STATUS
EFIAPI
_ModuleEntryPoint (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  );

/**
 * Registers all IIO configuration protocol instances for this platform.
 *
 * Locates the UBA board-type protocol, then registers up to 4 IIO configuration
 * protocol instances (one per CPU socket) by calling the protocol's registration
 * function. Each registration call passes a different board-config GUID and the
 * same UBA_IIO_CFG_UPDATE_PROTOCOL structure (48 bytes).
 *
 * @return EFI_SUCCESS     All configurations were registered successfully.
 * @return Other           The board-type protocol could not be located, or
 *                         one or more registration calls failed.
 */
EFI_STATUS
RegisterIioConfig (
  VOID
  );

/**
 * Resolves and caches the UBA DebugLib protocol interface.
 *
 * Raises the task priority level to TPL_HIGH_LEVEL, then calls
 * gBS->LocateProtocol() with the UBA_DEBUG_PROTOCOL_GUID to obtain the
 * DebugLib protocol interface. Results are cached in the global variable
 * gDebugProtocol to avoid repeated Lookups.
 *
 * @return Pointer to the UBA DebugLib protocol interface.
 *         Returns 0 if the platform only has 1 CPU package (HOB allocation
 *         size <= 0x10) or if the protocol cannot be located.
 */
VOID *
GetDebugProtocol (
  VOID
  );

/**
 * Debug print function (wraps the UEFI DebugLib protocol).
 *
 * Resolves the DebugLib protocol interface via GetDebugProtocol(), then
 * reads the debug level from CMOS register 0x4B to determine if the
 * requested severity mask is enabled. If so, calls the DebugLib protocol's
 * output function.
 *
 * @param[in] ErrorLevel  The debug error level mask (e.g., DEBUG_INFO = 0x80000000).
 * @param[in] Format      A format string for the debug message.
 * @param[in] ...         Variable arguments for the format string.
 *
 * @return The return value from the DebugLib protocol's output function,
 *         or 0 if the protocol is not available.
 */
UINTN
EFIAPI
DebugPrint (
  IN UINTN       ErrorLevel,
  IN CONST CHAR8 *Format,
  ...
  );

/**
 * ASSERT assertion failure handler.
 *
 * Called when a runtime assertion fails. Resolves the DebugLib protocol
 * via GetDebugProtocol() and calls its assertion failure handler.
 *
 * @param[in] FileName     Source file name where the assertion occurred.
 * @param[in] LineNumber   Line number of the assertion.
 * @param[in] Description  Description of the failed assertion.
 *
 * @return 0 if the DebugLib protocol is not available.
 */
UINTN
DebugAssert (
  IN CONST CHAR8  *FileName,
  IN UINTN        LineNumber,
  IN CONST CHAR8  *Description
  );

/**
 * Locates the HOB (Hand-Off Block) list from the UEFI System Table's
 * configuration table array.
 *
 * Iterates through SystemTable->ConfigurationTable[] looking for an entry
 * whose VendorGuid matches EFI_HOB_LIST_GUID (7739f24c-93d7-11d4-9a3a-0090273fc14d).
 * The comparison is done by matching the first 8 bytes and second 8 bytes of
 * the GUID separately.
 *
 * Results are cached in the global variable gHobList.
 *
 * @param[in] ImageHandle  The driver image handle (passed through from entry,
 *                         may be unused).
 *
 * @return Pointer to the HOB list, or NULL if not found.
 */
VOID *
GetHobList (
  IN EFI_HANDLE  ImageHandle
  );

/**
 * Compares a GUID against the EFI_HOB_LIST_GUID by comparing its first 8 bytes
 * and second 8 bytes independently.
 *
 * Uses ReadUnaligned64() to perform the comparison.
 *
 * @param[in] ImageHandle  Unused parameter.
 * @param[in] GuidPtr      Pointer to the GUID to compare.
 *
 * @retval TRUE   The GUID matches EFI_HOB_LIST_GUID.
 * @retval FALSE  The GUID does not match.
 */
BOOLEAN
IsHobListGuid (
  IN EFI_HANDLE  ImageHandle,
  IN EFI_GUID    *GuidPtr
  );

/**
 * Returns the UEFI status code for "Not Found".
 *
 * This is a trivial leaf function that returns 0x800000000000000E (EFI_NOT_FOUND).
 *
 * @return EFI_NOT_FOUND (0x800000000000000E).
 */
EFI_STATUS
ReturnNotFound (
  VOID
  );

/**
 * Reads an unaligned 64-bit value from memory.
 *
 * Wraps the BaseLib ReadUnaligned64() function with a NULL pointer check.
 *
 * @param[in] Buffer  Pointer to the memory to read. Must not be NULL.
 *
 * @return The 64-bit value read from the given address.
 */
UINT64
ReadUnaligned64 (
  IN CONST VOID  *Buffer
  );

// ============================================================================
// UBA Board-Type Protocol Interface
// ============================================================================

///
/// UBA_BOARD_TYPE_PROTOCOL
///
/// The protocol interface obtained via gBS->LocateProtocol() using the GUID
/// UBA_BOARD_TYPE_PROTOCOL_GUID.
///
/// This protocol is used to register platform-specific configuration data
/// (IIO config, setup config, slot data, SMBIOS data, etc.). The registration
/// function is at offset 0x10 within the interface structure.
///
typedef struct {
  ///
  /// Unknown fields at offsets 0x00-0x0F (may contain protocol revision,
  /// header, or other methods).
  ///
  UINT64   Reserved0;
  UINT64   Reserved1;
  ///
  /// Function at offset 0x10. Registers a platform-specific configuration
  /// protocol instance.
  ///
  /// @param[in] This              Pointer to the UBA board-type protocol interface.
  /// @param[in] ProtocolGuid      GUID of the protocol to register
  ///                              (e.g., UBA_IIO_CFG_UPDATE_PROTOCOL_GUID_x).
  /// @param[in] ConfigData        Pointer to the UBA_IIO_CFG_UPDATE_PROTOCOL structure.
  /// @param[in] ConfigDataSize    Size of the configuration data structure in bytes.
  ///
  /// @return EFI_STATUS.
  ///
  EFI_STATUS
  (EFIAPI *RegisterConfig) (
    IN VOID                    *This,
    IN EFI_GUID                *ProtocolGuid,
    IN UBA_IIO_CFG_UPDATE_PROTOCOL *ConfigData,
    IN UINT64                  ConfigDataSize
    );
} UBA_BOARD_TYPE_PROTOCOL;

#endif /* _IIO_CFG_UPDATE_DXE_LIGHTNINGRIDGE_EXECB1_H_ */