/** @file
  StaticSkuDataDxeLightningRidgeEXECB2.h -- Header for the StaticSkuData DXE driver.

  This UEFI DXE driver publishes three platform-specific configuration protocols
  (NUMPT, PIRQ, ACPF) used by the ACPI subsystem to describe static SKU
  configuration data. It is part of the Lenovo UBA (Universal BIOS Architecture)
  framework, targeting the LightningRidge EXECB2 platform.

  The driver:
    1. Caches UEFI boot services, runtime services, and system table pointers.
    2. Locates a platform protocol that provides debug output and configuration
       table installation services.
    3. Walks the UEFI Configuration Table array for a predefined GUID to locate
       platform SKU data.
    4. Installs three protocol instances (NUMPT, PIRQ, ACPF) using the platform
       protocol's InstallConfigurationTable function.

  GUID Definitions:
    - NUMPT_PROTOCOL_GUID  {0FF8A1CF-A0AB-4AC0-BFC9-34A78F68DD8A}
      Installed as protocol 1 with a 24-byte NUMPT_PROTOCOL interface.

    - PIRQ_PROTOCOL_GUID   {4C1F48A5-C976-4D90-9F03-8E9B1C327FCF}
      Installed as protocol 2 with a 16-byte PIRQ_PROTOCOL interface.

    - ACPF_PROTOCOL_GUID   {81129EF8-391D-4F63-AE99-58517EC077E3}
      Installed as protocol 3 with a 16-byte ACPF_PROTOCOL interface.

    - SKU_CONFIG_TABLE_GUID {7739F24C-93D7-11D4-9A3A-0090273FC14D}
      GUID used to locate the platform SKU data in the UEFI Configuration Table.

    - PLATFORM_PROTOCOL_GUID {36232936-0E76-31C8-A13A-3AF2FC1C3932}
      GUID of the protocol providing debug print and table install services.

  Copyright (c) Lenovo. All rights reserved.
  SPDX-License-Identifier: BSD-2-Clause-Patent
**/

#ifndef STATIC_SKU_DATA_DXE_LIGHTNINGRIDGE_EXECB2_H_
#define STATIC_SKU_DATA_DXE_LIGHTNINGRIDGE_EXECB2_H_

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

//
// GUID Definitions
//

/// {36232936-0E76-31C8-A13A-3AF2FC1C3932}
#define PLATFORM_PROTOCOL_GUID \
  { 0x36232936, 0x0E76, 0x31C8, { 0xA1, 0x3A, 0x3A, 0xF2, 0xFC, 0x1C, 0x39, 0x32 } }

/// {7739F24C-93D7-11D4-9A3A-0090273FC14D}
#define SKU_CONFIG_TABLE_GUID \
  { 0x7739F24C, 0x93D7, 0x11D4, { 0x9A, 0x3A, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D } }

/// {0FF8A1CF-A0AB-4AC0-BFC9-34A78F68DD8A}
#define NUMPT_PROTOCOL_GUID \
  { 0x0FF8A1CF, 0xA0AB, 0x4AC0, { 0xBF, 0xC9, 0x34, 0xA7, 0x8F, 0x68, 0xDD, 0x8A } }

/// {4C1F48A5-C976-4D90-9F03-8E9B1C327FCF}
#define PIRQ_PROTOCOL_GUID \
  { 0x4C1F48A5, 0xC976, 0x4D90, { 0x9F, 0x03, 0x8E, 0x9B, 0x1C, 0x32, 0x7F, 0xCF } }

/// {81129EF8-391D-4F63-AE99-58517EC077E3}
#define ACPF_PROTOCOL_GUID \
  { 0x81129EF8, 0x391D, 0x4F63, { 0xAE, 0x99, 0x58, 0x51, 0x7E, 0xC0, 0x77, 0xE3 } }

//
// Protocol Interface Structures
//

/// NUMPT table entry: (SkuDataPtr, Count) pair, terminated by NULL ptr.
typedef struct {
  UINT64  SkuDataPtr;   ///< Pointer to per-SKU data in .data section
  UINT64  Count;        ///< Number of entries
} NUMPT_SKU_TABLE_ENTRY;

/// NUMPT protocol interface (24 bytes).
typedef struct {
  UINT32                  Signature;  ///< "NUMPT"
  UINT32                  Version;    ///< 1
  NUMPT_SKU_TABLE_ENTRY   *SkuTable;  ///< SkuTable array
  NUMPT_SKU_TABLE_ENTRY   *SkuCountTable;  ///< SkuCountTable array
} NUMPT_PROTOCOL;

/// PIRQ routing table entry: (RoutingPtr, Count) pair.
typedef struct {
  UINT64  PirqRoutingPtr;  ///< Pointer to PIRQ routing data
  UINT64  Count;           ///< Number of routing entries
} PIRQ_TABLE_ENTRY;

/// PIRQ protocol interface (16 bytes).
typedef struct {
  UINT32              Signature;  ///< "PIRQ"
  UINT32              Version;    ///< 1
  PIRQ_TABLE_ENTRY    *PirqTable; ///< PIRQ table entries
} PIRQ_PROTOCOL;

/// ACPF protocol interface (16 bytes).
typedef struct {
  UINT32              Signature;  ///< "ACPF"
  UINT32              Version;    ///< 1
  UINT32              BoardType;  ///< Board type
  UINT32              Reserved;   ///< Reserved
} ACPF_PROTOCOL;

//
// SKU Table Entry (32 bytes each in .data)
//
// Layout:
//   0x00: UINT64  Offset in data section
//   0x08: UINT32  GroupId
//   0x0C: UINT32  .rdata offset of ACPI path string
//   0x10: UINT32  EntryType (0x0C,0x0E,0x0A,0x08)
//   0x14: UINT32  Reserved
//   0x18: CHAR8[8] Tag ("FIX0", "FIXX\1\0\0\0\0", etc.)
//

typedef struct {
  UINT64    Offset;       ///< Data section offset
  UINT32    GroupId;      ///< Group ID (e.g. 0x5B80)
  UINT32    StringOffset; ///< ACPI path string offset in .rdata
  UINT32    EntryType;    ///< Entry type
  UINT32    Reserved;     ///< Reserved
  CHAR8     Tag[8];       ///< Entry tag name
} SKU_TABLE_ENTRY;

//
// Platform Protocol Layout (inferred)
//
// +0x00: Unknown header (8 bytes)
// +0x08: DebugAssert (PLATFORM_DEBUG_ASSERT)
// +0x10: InstallConfigurationTable (PLATFORM_INSTALL_PROTOCOL)
//

typedef
VOID
(EFIAPI *PLATFORM_DEBUG_ASSERT)(
  IN CONST CHAR8  *FileName,
  IN UINTN        LineNumber,
  IN CONST CHAR8  *Description
  );

typedef
EFI_STATUS
(EFIAPI *PLATFORM_INSTALL_PROTOCOL)(
  IN VOID       *This,
  IN EFI_GUID   *KeyGuid,
  IN VOID       *Data,
  IN UINTN      DataSize
  );

typedef struct {
  UINT64                      Unknown;          ///< +0x00
  PLATFORM_DEBUG_ASSERT       DebugAssert;      ///< +0x08
  PLATFORM_INSTALL_PROTOCOL   InstallProtocol;  ///< +0x10
} PLATFORM_PROTOCOL;

//
// Globals (declared extern in .c)
//

extern EFI_HANDLE              gImageHandle;
extern EFI_SYSTEM_TABLE        *gSystemTable;
extern EFI_BOOT_SERVICES       *gBootServices;
extern EFI_RUNTIME_SERVICES    *gRuntimeServices;
extern PLATFORM_PROTOCOL       *gPlatformProtocol;
extern VOID                    *gSkuConfigTable;

//
// Function Prototypes
//

EFI_STATUS
EFIAPI
StaticSkuDataDxeEntryPoint (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  );

PLATFORM_PROTOCOL *
GetPlatformProtocol (
  VOID
  );

VOID
EFIAPI
PlatformDebugPrint (
  IN UINTN       Status,
  IN CONST CHAR8 *FormatString,
  ...
  );

VOID
EFIAPI
PlatformAssert (
  IN CONST CHAR8 *FileName,
  IN UINTN       LineNumber,
  IN CONST CHAR8 *Description
  );

VOID *
GetSkuConfigTable (
  IN VOID  *Context
  );

BOOLEAN
IsSkuConfigTableGuid (
  IN VOID  *Context,
  IN VOID  *GuidToCheck
  );

UINT64
EFIAPI
ReadUnaligned64 (
  IN CONST VOID  *Buffer
  );

#endif /* STATIC_SKU_DATA_DXE_LIGHTNINGRIDGE_EXECB2_H_ */