/*++

StaticSkuDataDxeLightningRidgeEXECB1.h

UEFI DXE driver for Intel Purley platform static SKU data management.
Provides ACPI (_SB_.CCT0-CCT8, _SB_.CFH0) and SKU configuration data
to the UBA (Universal BIOS Agent) protocol infrastructure.

Module Path:
  PurleyRpPkg/Uba/UbaMain/Dxe/TypeLightningRidgeEXECB1/StaticSkuDataDxe/

Build Info:
  DEBUG_VS2015 X64, HR6N0XMLK platform

PDB: StaticSkuDataDxeLightningRidgeEXECB1.pdb

--*/

#ifndef __STATIC_SKU_DATA_DXE_LIGHTNING_RIDGE_EXEC_B1_H__
#define __STATIC_SKU_DATA_DXE_LIGHTNING_RIDGE_EXEC_B1_H__

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

//
// GUID Definitions
//

// GUID for the SKU data protocol (installed by this module).
// {36232936-0E76-31C8-A13A-3AF2FC1C3932}
#define SKU_DATA_PROTOCOL_GUID \
  { 0x36232936, 0x0E76, 0x31C8, \
    { 0xA1, 0x3A, 0x3A, 0xF2, 0xFC, 0x1C, 0x39, 0x32 } }

// GUID for the UBA (Universal BIOS Agent) protocol -- located via
// BootServices->LocateProtocol to obtain the UBA interface used for
// registering SKU data producers.
// {E03E0D46-5263-4845-B0A4-58D57B3177E2}
#define UBA_PROTOCOL_GUID \
  { 0xE03E0D46, 0x5263, 0x4845, \
    { 0xB0, 0xA4, 0x58, 0xD5, 0x7B, 0x31, 0x77, 0xE2 } }

// HOB GUID for finding the HOB-format configuration data in the
// UEFI HOB list. This is the GUID_EXTENSION-type HOB that contains
// the SKU/platform configuration table.
// {7739F24C-93D7-11D4-9A3A-0090273FC14D}
#define SKU_HOB_GUID \
  { 0x7739F24C, 0x93D7, 0x11D4, \
    { 0x9A, 0x3A, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D } }

// Protocol GUID for UMPT (Unified Memory/Platform Topology?) data.
// {0FF8A1CF-A0AB-4AC0-BFC9-34A78F68DD8A}
#define UMPT_PROTOCOL_GUID \
  { 0x0FF8A1CF, 0xA0AB, 0x4AC0, \
    { 0xBF, 0xC9, 0x34, 0xA7, 0x8F, 0x68, 0xDD, 0x8A } }

// Protocol GUID for PIRQ (Platform IRQ?) data.
// {4C1F48A5-C976-4D90-9F03-8E9B1C327FCF}
#define PIRQ_PROTOCOL_GUID \
  { 0x4C1F48A5, 0xC976, 0x4D90, \
    { 0x9F, 0x03, 0x8E, 0x9B, 0x1C, 0x32, 0x7F, 0xCF } }

// Protocol GUID for ACPF (ACPI Platform?) data.
// {46504341-0001-0000-0041-000000000000}
#define ACPF_PROTOCOL_GUID \
  { 0x46504341, 0x0001, 0x0000, \
    { 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }


//
// Type Definitions
//

// Forward declaration for the UBA protocol interface.
// This is obtained via LocateProtocol(UBA_PROTOCOL_GUID).
// Method at offset 0x10 (relative to the protocol base) is used
// to register SKU data sub-protocols with their data interfaces.
typedef struct _UBA_PROTOCOL UBA_PROTOCOL;

// UBA protocol method table (partial, only what this driver uses).
// Offset 0x00: QueryVersion?
// Offset 0x08: Some other method.
// Offset 0x10 (method index 2): RegisterProtocol(
//     IN EFI_GUID       *ProtocolGuid,
//     IN VOID           *Interface,
//     IN UINTN          InterfaceSize
//   ) -> EFI_STATUS
#pragma pack(push, 1)
typedef struct {
  UINT64  Field0;
  UINT64  Field8;
  //
  // RegisterProtocol(GUID, Interface, Size)
  // Used to register sub-protocols on the UBA handle.
  //
  EFI_STATUS (EFIAPI *RegisterProtocol)(
    IN EFI_GUID  *ProtocolGuid,
    IN VOID      *Interface,
    IN UINTN     InterfaceSize
    );
} UBA_PROTOCOL;
#pragma pack(pop)


// SKU data interface header (16 bytes).
// Each registered SKU data producer uses this structure as its
// "interface" argument to UBA_PROTOCOL.RegisterProtocol().
// The 'Tag' field is a 4-byte ASCII identifier, the 'Version'
// identifies the data format version, and 'Data' is a type-specific
// value (often a pointer to a larger configuration table).
#pragma pack(push, 1)
typedef struct {
  UINT32  Tag;        // ASCII tag, e.g. 'UMPT', 'PIRQ', 'ACPF'
  UINT32  Version;    // Data format version (typically 1)
  UINT64  Data;       // Type-specific value or pointer
} SKU_DATA_INTERFACE;
#pragma pack(pop)

// Extended SKU data interface (24 bytes).
// Used by the UMPT sub-protocol registration.
// Contains two data fields (a pointer and an offset/pointer).
#pragma pack(push, 1)
typedef struct {
  UINT32  Tag;        // ASCII tag, e.g. 'UMPT'
  UINT32  Version;    // Data format version (typically 1)
  UINT64  Data1;      // First data value/pointer
  UINT64  Data2;      // Second data value/pointer
} SKU_DATA_INTERFACE_EXTENDED;
#pragma pack(pop)


// SKU table entry (32 bytes).
// Each entry describes one ACPI method output or configuration value
// for a specific SKU type.
//
// Field mappings (observed patterns):
//   Field0:  ACPI path string offset or method selector
//   Field2:  Size of data payload (0x08 or 0x5B80 for large blocks)
//   Field3:  Offset to data payload (relative to image base)
//   Field4:  Data type (0x0A = ASCII, 0x0C = method name, 0x0E = numeric)
//   Field5:  Offset to method name / payload descriptor
//   Field6-7: Name (8 bytes), e.g. 'FIX0', 'FIXX', 'FIXV', 'FIXY', 'FIXW'
#pragma pack(push, 1)
typedef struct {
  UINT64  Field0;
  UINT64  Field2;     // Data size
  UINT64  Field3;     // Data offset (image-relative)
  UINT8   Field4;     // Data type
  UINT8   Reserved1[3];
  UINT32  Field5;     // Name offset or auxiliary
  CHAR8   Name[8];    // ACPI method name / entry identifier
} SKU_TABLE_ENTRY;
#pragma pack(pop)

// Full SKU configuration table header.
// At 0x40F0 in the binary there is a GUID-like 16-byte header,
// followed by an array of SKU_TABLE_ENTRY (32 bytes each).
#pragma pack(push, 1)
typedef struct {
  EFI_GUID          TableGuid;   // SKU table identifier GUID
  SKU_TABLE_ENTRY   Entries[1]; // Variable-length array
} SKU_CONFIG_TABLE;
#pragma pack(pop)


//
// Global Variable Declarations
//

extern EFI_HANDLE             gImageHandle;
extern EFI_SYSTEM_TABLE       *gST;
extern EFI_BOOT_SERVICES      *gBS;
extern EFI_RUNTIME_SERVICES   *gRT;


//
// Function Declarations
//

// Entry point for the StaticSkuDataDxe driver.
// Initializes UEFI boot/runtime services pointers, locates the UBA
// protocol handle via BootServices->LocateProtocol, and registers
// three SKU data sub-protocols:
//   - UMPT_PROTOCOL_GUID (data at 0x40B0, 24 bytes)
//   - PIRQ_PROTOCOL_GUID (data at 0x40D8, 16 bytes)
//   - ACPF_PROTOCOL_GUID (data at 0x9020, 16 bytes)
EFI_STATUS
EFIAPI
StaticSkuDataDxeEntryPoint (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  );


// Retrieve the UBA protocol interface pointer.
// Uses BootServices->AllocatePool (type=EfiBootServicesData) and
// BootServices->LocateProtocol to find the UBA protocol.
// Returns 0 if the UBA protocol is not found.
//
// CMOS register 0x4B (CMOS 75 decimal) is read by ASSERT
// via UBA protocol -- the value indicates system config.
//
UBA_PROTOCOL *
GetUbaProtocol (
  VOID
  );


// UBA assertion/debug helper.
// If the UBA protocol is available, calls its method at offset 0x08
// which is a debug print/assert function taking (file, line, expression).
//
VOID
UbaAssert (
  IN CHAR8   *FileName,
  IN UINTN   LineNumber,
  IN CHAR8   *Expression
  );


// Read CMOS register and apply SKU-specific checks.
// This function queries the UBA protocol to determine if a given
// configuration flag (a1) is set, by reading CMOS register 0x4B
// (index 0x4B in RTC/CMOS port 0x70/0x71).
//
// The CMOS byte at index 0x4B encodes the board SKU variant:
//   0x00 -> Memory-mapped I/O at 0xFDAF0490 determines SKU
//   0x01 -> Board revision specific (flags = 0x80000004)
//   0x02-0x03 -> Another board variant (flags = 0x80000006)
//   default -> Returns 4 (no assertion needed)
//
// Returns 0 if the assertion flag (a1) is not set, non-zero to
// indicate that the caller should assert.
//
UINT8
UbaCheckCmosSku (
  IN UINT64   AssertFlag
  );


// Initialize the HOB list pointer.
// Scans the UEFI SystemTable(104)->NumberOfTableEntries for a HOB
// (Hand-Off Block) entry.  The HOB list is used to locate platform
// configuration data passed from the PEI phase.
//
// Returns the HOB list base address, or 0 if not found.
//
VOID *
GetHobList (
  VOID
  );


// Compare two GUIDs/HOB entry identifiers (by first two QWORDs).
// Used to find a matching HOB entry in the HOB list.
//
// @param[in]  Guid1  First GUID pointer
// @param[in]  Guid2  Second GUID pointer (e.g., a HOB entry GUID)
// @retval TRUE  if the two GUIDs match
// @retval FALSE otherwise
//
BOOLEAN
EFIAPI
CompareGuidQwords (
  IN EFI_GUID  *Guid1,
  IN EFI_GUID  *Guid2
  );


// Read a UINT32 from an unaligned pointer.
//
UINT32
EFIAPI
ReadUnaligned32 (
  IN UINT32  *Buffer
  );


// Read a UINT64 from an unaligned pointer.
//
UINT64
EFIAPI
ReadUnaligned64 (
  IN VOID  *Buffer
  );


// Convert a UCS-2 (CHAR16*) string to an ASCII (CHAR8*) string.
// The destination buffer must be at least 'DestMax' bytes.
//
EFI_STATUS
EFIAPI
UnicodeStrToAsciiStr (
  IN  CHAR16  *Source,
  OUT CHAR8   *Destination
  );


#endif // __STATIC_SKU_DATA_DXE_LIGHTNING_RIDGE_EXEC_B1_H__