/**
 * @file OpromUpdateDxeLightningRidgeEXECB2.h
 * @brief UBA OpromUpdate DXE driver for LightningRidge (C621/C622) EXEC B2 board.
 *
 * This is an Intel UBA (Unified BIOS Architecture) OpromUpdate-type driver that
 * registers board-specific PCIe slot configuration callbacks for the LightningRidge
 * PCH (Lewisburg/C620 series) EXEC B2 board variant.
 *
 * The driver registers callbacks via UbaConfigProtocol to provide:
 *   1. PCIe slot populated-function detection (by reading PCI Express Capability registers)
 *   2. Board-specific PCIe slot/port mapping data
 *   3. Two PCIe slot NVRAM configuration tables (slot-to-BDF mapping)
 *
 * Key GUID definitions:
 *   gEfiPciIoProtocolGuid           - EFI_PCI_IO_PROTOCOL (2f707ebb-4a1a-11d4-...)
 *   gUbaDebugProtocolGuid           - UBA debug protocol (36232936-0e76-31c8-...)
 *   gUbaConfigProtocolGuid          - UBA config protocol (e03e0d46-5263-4845-...)
 *   gOpromUpdateBoardGuid           - Board registration GUID (371bd79c-de79-4c5f-...)
 *   gEfiGuidedSectionExtractionProtocolGuid - (7739f24c-93d7-11d4-...)
 */

#ifndef OPROM_UPDATE_DXE_LIGHTNINGRIDGE_EXEC_B2_H_
#define OPROM_UPDATE_DXE_LIGHTNINGRIDGE_EXEC_B2_H_

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

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

///
/// {2f707ebb-4a1a-11d4-9a38-0090273fc14d}
/// Standard UEFI PCI I/O Protocol GUID. Used to read PCI config space
/// for slot-population detection.
///
#define EFI_PCI_IO_PROTOCOL_GUID \
  { 0x2f707ebb, 0x4a1a, 0x11d4, { 0x9a, 0x38, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } }

///
/// {36232936-0e76-31c8-a13a-3af2fc1c3932}
/// UBA Debug Protocol GUID (used for debug message output).
/// The debug protocol interface has a Report function at offset +8
/// and a ReportAssert function at offset +0 (assert handler).
///
#define UBA_DEBUG_PROTOCOL_GUID \
  { 0x36232936, 0x0e76, 0x31c8, { 0xa1, 0x3a, 0x3a, 0xf2, 0xfc, 0x1c, 0x39, 0x32 } }

///
/// {e03e0d46-5263-4845-b0a4-58d57b3177e2}
/// UBA Config Protocol GUID. This is the main protocol interface used
/// to register board-specific configuration data and callbacks.
///
#define UBA_CONFIG_PROTOCOL_GUID \
  { 0xe03e0d46, 0x5263, 0x4845, { 0xb0, 0xa4, 0x58, 0xd5, 0x7b, 0x31, 0x77, 0xe2 } }

///
/// {371bd79c-de79-4c5f-aa2b-bc9ebefa988f}
/// OpromUpdate LightningRidge EXEC B2 Board GUID.
/// Used as registration key when registering the PBDS callback table
/// with the UBA Config Protocol.
///
#define OPROM_UPDATE_BOARD_GUID \
  { 0x371bd79c, 0xde79, 0x4c5f, { 0xaa, 0x2b, 0xbc, 0x9e, 0xbe, 0xfa, 0x98, 0x8f } }

///
/// {7739f24c-93d7-11d4-9a3a-0090273fc14d}
/// EFI Guided Section Extraction Protocol GUID.
/// Stored at 0xD10 but not used in this driver (may be used by UBA framework).
///
#define EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID \
  { 0x7739f24c, 0x93d7, 0x11d4, { 0x9a, 0x3a, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } }

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

///
/// PBDS_CONFIG_SIGNATURE
/// Signature string for the board config callback table.
/// "PBDS" = Platform Board Data Structure (Intel UBA naming convention).
///
#define PBDS_CONFIG_SIGNATURE  SIGNATURE_32('P', 'B', 'D', 'S')

///
/// Maximum number of PCIe root ports / slot entries in the BDF lookup table.
///
#define MAX_PCIE_ROOT_PORTS  8

///
/// Maximum number of slots in the first slot config table (returned by GetSlotConfig1).
///
#define MAX_SLOT_CONFIG1_ENTRIES  6

///
/// Maximum number of slots in the second slot config table (returned by GetSlotConfig2).
///
#define MAX_SLOT_CONFIG2_ENTRIES  10

///
/// Structure of one entry in the PCIe root port BDF lookup table at 0xED1.
/// Each entry encodes:
///   @v8   Register offset within the root port's config space
///   @v9   [2:0] = Function number, [7:3] = Device number
///   @v10  Bus number
///
/// When combined into a 32-bit value:
///   bits [7:0]   = Register offset
///   bits [15:8]  = (v9 & 7) = Function
///   bits [20:16] = (v9 >> 3) = Device
///   bits [31:24] = v10 = Bus
///
typedef struct {
  UINT8   RegisterOffset;  ///< Config space register offset base
  UINT8   DevFunc;         ///< [2:0]=Function, [7:3]=Device
  UINT8   Bus;             ///< PCI bus number
  UINT8   Reserved;        ///< Padding to 4-byte aligned entry
} PCIE_ROOT_PORT_BDF_ENTRY;

///
/// The PCIe Root Port BDF lookup table.
/// Contains 8 entries mapping root port indices to PCI bus:device:function.
///
typedef struct {
  PCIE_ROOT_PORT_BDF_ENTRY  Entries[MAX_PCIE_ROOT_PORTS];
} PCIE_ROOT_PORT_BDF_TABLE;

///
/// Board callback function table ("PBDS" format).
/// This structure is registered with the UBA Config Protocol.
///
typedef struct {
  UINT32    Signature;  ///< "PBDS" signature
  UINT32    Version;    ///< Structure version (currently 1)
  UINT64    BoardCallbacks[4];  ///< Relocatable RVAs to callback functions:
                                ///<   0: IsFunctionInPopulatedSlot
                                ///<   1: GetBoardInfo
                                ///<   2: GetSlotConfig1
                                ///<   3: GetSlotConfig2
} PBDS_BOARD_CONFIG;

///
/// PCIe Slot NVRAM configuration entry structure.
/// Format used in the slot config tables at 0xD60 and 0xE60.
///
typedef struct {
  UINT32  SlotInfo;   ///< Slot identification / port register
  UINT32  Flags;      ///< Slot capability flags
  UINT32  PciAddress; ///< PCI address: [31:24]=Bus, [23:16]=Reserved, [15:11]=Device, [10:8]=Func
} PCIE_SLOT_CONFIG_ENTRY;

///
/// UEFI System Table global (cached pointer).
///
extern EFI_SYSTEM_TABLE  *gST;
extern EFI_BOOT_SERVICES *gBS;
extern EFI_HANDLE         gImageHandle;

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

///
/// @var gSystemTable
/// Pointer to the UEFI System Table (cached at module entry).
///
extern EFI_SYSTEM_TABLE  *gSystemTable;

///
/// @var gBootServices
/// Pointer to the UEFI Boot Services Table (cached at module entry).
///
extern EFI_BOOT_SERVICES *gBootServices;

///
/// @var gRuntimeServices
/// Pointer to the UEFI Runtime Services Table (cached at module entry).
///
extern EFI_RUNTIME_SERVICES *gRuntimeServices;

///
/// @var gDebugProtocol
/// Cached pointer to the UBA Debug Protocol interface.
/// Lazily initialized by LocateDebugProtocol().
/// NULL if protocol is not found or initialization fails.
///
extern VOID *gDebugProtocol;

///
/// @var gHobList
/// Cached pointer to the HOB (Hand-Off Block) list.
/// Populated by GetHobList() from the SystemTable's configuration table.
///
extern VOID *gHobList;

///
/// @var gDebugFlags
/// Debug output control flags (used by DebugPrint).
///
extern UINTN gDebugFlags;

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

/**
 * UEFI Driver Entry Point.
 *
 * Initializes UEFI globals, locates the HOB list, and registers the
 * LightningRidge EXEC B2 board-specific callback table with the
 * UBA Config Protocol.
 *
 * The registration includes four callbacks:
 *   - IsFunctionInPopulatedSlot() - detects populated PCIe slots
 *   - GetBoardInfo()              - returns board identification data
 *   - GetSlotConfig1()            - returns first PCIe slot config table
 *   - GetSlotConfig2()            - returns second PCIe slot config table
 *
 * Registration GUID: OPROM_UPDATE_BOARD_GUID (371bd79c-...)
 * Protocol:          gUbaConfigProtocolGuid (e03e0d46-...)
 * Registration data: PBDS_BOARD_CONFIG with Signature="PBDS", Version=1
 *
 * @param[in] ImageHandle  UEFI image handle
 * @param[in] SystemTable  UEFI system table
 * @return EFI_STATUS      EFI_SUCCESS if registered, error otherwise
 */
EFI_STATUS
EFIAPI
_ModuleEntryPoint (
  IN EFI_IMAGE_HANDLE   ImageHandle,
  IN EFI_SYSTEM_TABLE   *SystemTable
  );

/**
 * Checks if a PCI function belongs to a populated PCIe slot.
 *
 * Iterates through 8 PCIe root port table entries. For each root port
 * where the corresponding bit in @p SlotBitmask is clear (slot is
 * populated), reads the root port's PCIe Device Capabilities registers
 * at config offsets (BDF_Base | 0x19) and (BDF_Base | 0x1A) to determine
 * the supported function number range.
 *
 * The root port BDF entries are in a lookup table that encodes
 * Bus/Device/Function for each of the 8 possible root ports.
 *
 * Access to PCI config space uses EFI_PCI_IO_PROTOCOL.Pci.Read
 * through the protocol located via LocateProtocol.

 * @param[in] FuncNum       The PCI function number to check
 * @param[in] SlotBitmask   8-bit bitmask: bit n=0 means slot n is populated and should
 *                          be checked; bit n=1 means slot n is unpopulated (skip)
 * @retval TRUE             The function belongs to at least one populated slot
 * @retval FALSE            The function does NOT belong to any populated slot
 */
BOOLEAN
EFIAPI
IsFunctionInPopulatedSlot (
  IN UINT64   FuncNum,
  IN UINT32   SlotBitmask
  );

/**
 * Returns the board-specific PCIe structure pointer.
 *
 * LightningRidge EXEC B2 does not have additional board info;
 * returns a pointer to an empty/zeroed structure.
 *
 * @param[out] BoardInfo   Pointer to set to the board info structure
 * @return EFI_SUCCESS     Always returns EFI_SUCCESS
 */
EFI_STATUS
EFIAPI
GetBoardInfo (
  OUT VOID   **BoardInfo
  );

/**
 * Returns the first PCIe slot configuration table.
 *
 * The table at memory offset 0xD60 contains @ 6 entries describing
 * PCIe slot-to-BDF mappings for the board.

 * @param[out] SlotConfig   Pointer to set to the slot configuration table
 * @param[out] EntryCount   Set to 6 (number of entries in the table)
 * @return EFI_SUCCESS      Always returns EFI_SUCCESS
*/
EFI_STATUS
EFIAPI
GetSlotConfig1 (
  OUT VOID   **SlotConfig,
  OUT UINTN  *EntryCount
  );

/**
 * Returns the second PCIe slot configuration table.
 *
 * The table at memory offset 0xE60 contains 10 entries describing
 * additional PCIe slot-to-BDF mappings for the board.
 *
 * @param[out] SlotConfig   Pointer to set to the slot configuration table
 * @param[out] EntryCount   Set to 10 (number of entries in the table)
 * @return EFI_SUCCESS      Always returns EFI_SUCCESS
 */
EFI_STATUS
EFIAPI
GetSlotConfig2 (
  OUT VOID   **SlotConfig,
  OUT UINTN  *EntryCount
  );

/**
 * Debug callback invoked when UBA sets a PCIe slot number.
 *
 * LightningRidge EXEC B2 does not override PCIe slot numbers
 * (returns 0, indicating use the hardware default).
 *
 * @param[out] SlotNumber  Set to 0 (no override)
 * @return EFI_SUCCESS     Always returns EFI_SUCCESS
 */
EFI_STATUS
EFIAPI
SetPcieSlotNumber (
  OUT UINT8  *SlotNumber
  );

//
// Internal library functions
//

/**
 * Lazily locates and caches the UBA Debug Protocol.
 *
 * Allocates a page of BootServicesData memory (for the protocol
 * interface buffer), checks if TPL was <= TPL_NOTIFY (0x10),
 * then calls LocateProtocol(gUbaDebugProtocolGuid, NULL, &gDebugProtocol).
 *
 * Cached in @p gDebugProtocol (at 0xF50).
 *
 * @return Pointer to UBA Debug Protocol interface, or NULL on failure
 */
VOID *
LocateDebugProtocol (
  VOID
  );

/**
 * Outputs a debug message via the UBA Debug Protocol.
 *
 * If the debug protocol is available, calls its Report function
 * (at interface+8) with the given severity, format string, and args.
 *
 * Also performs a CMOS check: reads CMOS index 0x4B (via I/O ports 0x70/0x71)
 * to determine debug verbosity level. Only prints if the requested
 * severity level matches the CMOS-configured bitmask.
 *
 * @param[in] ErrorLevel  Debug severity level
 * @param[in] Format      Printf-style format string
 * @param[in] ...         Variable arguments for format string
 *
 * @return Non-zero if message was printed, 0 if suppressed or protocol unavailable
 */
UINT8
EFIAPI
DebugPrint (
  IN UINTN       ErrorLevel,
  IN CONST CHAR8 *Format,
  ...
  );

/**
 * Reports an assertion failure via the UBA Debug Protocol.
 *
 * If the debug protocol is available, forwards the assert
 * to the protocol's ReportAssert function (at interface+0).
 *
 * @param[in] FileName     Source file name where assertion failed
 * @param[in] LineNumber   Line number of the failed assertion
 * @param[in] Description  Assert condition description string
 *
 * @retval 0               Assert handled (by protocol)
 * @retval negative        Protocol not available
 */
EFI_STATUS
EFIAPI
ReportAssert (
  IN CONST CHAR8  *FileName,
  IN UINTN        LineNumber,
  IN CONST CHAR8  *Description
  );

/**
 * Locates and caches the HOB (Hand-Off Block) list.
 *
 * Iterates through the SystemTable's configuration table entries
 * looking for one with the HOB list GUID (gHobListGuid).
 * If found, caches the HOB list pointer in @p gHobList.
 * Uses CompareGuid() for GUID matching.
 *
 * @return Pointer to HOB list, or NULL if not found
 */
VOID *
GetHobList (
  VOID
  );

/**
 * Compares two GUIDs for equality.
 *
 * Simple byte-by-byte comparison of two 16-byte GUIDs.
 * Used by GetHobList() to match GUID entries in the
 * configuration table.
 *
 * @param[in] Guid1  First GUID to compare
 * @param[in] Guid2  Second GUID to compare
 * @retval TRUE      GUIDs are equal
 * @retval FALSE     GUIDs differ
 */
BOOLEAN
EFIAPI
CompareGuid (
  IN EFI_GUID  *Guid1,
  IN EFI_GUID  *Guid2
  );

/**
 * Reads a 64-bit value from an unaligned memory address.
 *
 * If the address is NULL, triggers an assertion.
 *
 * @param[in] Buffer  Memory address to read from
 * @return UINT64     The value read from the address
 */
UINT64
EFIAPI
ReadUnaligned64 (
  IN CONST VOID  *Buffer
  );

#endif // OPRON_UPDATE_DXE_LIGHTNINGRIDGE_EXEC_B2_H_