Newer
Older
AMI-Aptio-BIOS-Reversed / PurleySktPkg / Me / Sps / Pei / SpsPei / SpsPei.c
@Ajax Dong Ajax Dong 2 days ago 49 KB Restructure the repo
/**
 * @file SpsPei.c
 * @brief SpsPei PEIM - Server Platform Services PEI Module
 *
 * Source: e:\hs\PurleySktPkg\Me\Sps\Pei\SpsPei.c
 * Platform: Intel Purley (PurleySktPkg, Lewisburg PCH), IA32
 * Compiler: VS2015 DEBUG
 *
 * ImageBase: 0xFFDA3630  ImageSize: 0x3460  MD5: 38dec5b1...
 *
 * SpsPei initializes and manages the ME (Management Engine) during the
 * PEI phase. It determines the boot path (S3 vs. non-S3), waits for ME
 * firmware initialization, establishes the ME-BIOS interface version,
 * manages Node Manager (NM) power policies, sends END_OF_POST during S3
 * resume, configures ICC (Integrated Clock Control) clock settings,
 * and performs pre-DID resets when required.
 *
 * GUIDs (in .rdata):
 *   0xFFDA6860: gMeFwHobGuid       ({52885E62-...})
 *   0xFFDA6880: gSpsInfoHobGuid    ({489D2A71-...})
 *   0xFFDA6888: gSpsPolicyHobGuid  ({D14319E2-...})
 *   0xFFDA6898: gSpsPolicyPpiGuid  ({6B30CE48-...})
 *   0xFFDA68A8: gHeci1PpiGuid      ({12AA57CB-...})
 *
 * PPI Notify Descriptors (in .data):
 *   0xFFDA68B0: S3 path      -> SpsS3Path (0xFFDA3CC4)
 *   0xFFDA68BC: Non-S3 path  -> PpiNotifyHeciReady (0xFFDA4580)
 *
 * Major flows:
 *   1. ModuleEntryPoint -> SpsPeiEntryPoint
 *   2. SpsPeiEntryPoint detects ME is SPS firmware, reads boot mode
 *   3. Branches to SpsS3Path (S3 resume) or SpsNonS3Path (normal boot)
 *   4. Each path waits for ME init via HECI, negotiates protocol version
 *   5. Publishes SPS info HOB for DXE consumption
 */

#include <Uefi.h>
#include <Pi/PiPeiCis.h>
#include <Library/DebugLib.h>
#include <Library/HobLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/IoLib.h>
#include <Library/PcdLib.h>
#include <Library/TimerLib.h>
#include <Library/PeiServicesTablePointerLib.h>

#include "SpsPei.h"

//
// External GUIDs defined in the .data section
//
extern EFI_GUID gHeci1PpiGuid;
extern EFI_GUID gSpsPolicyPpiGuid;
extern EFI_GUID gMeFwHobGuid;
extern EFI_GUID gSpsInfoHobGuid;
extern EFI_GUID gSpsPolicyHobGuid;

//
// Notify descriptors for PPI registration
//
extern EFI_PEI_NOTIFY_DESCRIPTOR mS3NotifyDesc;
extern EFI_PEI_NOTIFY_DESCRIPTOR mNonS3NotifyDesc;

// ---------------------------------------------------------------------------
// Library Wrappers / Internal Helpers
// ---------------------------------------------------------------------------

/**
 * Zero-fill a memory buffer. Wrapper around memset.
 */
VOID *
InternalZeroMem (
  VOID   *Buffer,
  UINTN  Size
  )
{
  return ZeroMem (Buffer, Size);
}

/**
 * Copy a memory buffer. Overlapping-safe backward copy if src < dst.
 */
VOID *
InternalCopyMem (
  VOID        *Destination,
  CONST VOID  *Source,
  UINTN       Length
  )
{
  return CopyMem (Destination, Source, Length);
}

/**
 * Set a memory buffer to a byte value.
 */
VOID *
InternalSetMem (
  VOID   *Buffer,
  UINTN  Count,
  UINT8  Value
  )
{
  return SetMem (Buffer, Count, Value);
}

/**
 * Set a block of 8-byte pairs (non-standard, used for structure init).
 */
VOID
InternalSetMem32_Block (
  OUT UINT32  *Buffer,
  INT32       Count,
  UINT32      ValueLow,
  UINT32      ValueHigh
  )
{
  while (Count > 0) {
    Buffer[0] = ValueLow;
    Buffer[1] = ValueHigh;
    Buffer += 2;
    Count--;
  }
}

/**
 * Fill memory with 32-bit values.
 */
VOID *
InternalSetMem32 (
  OUT VOID    *Buffer,
  IN  UINTN   Count,
  IN  UINT32  Value
  )
{
  return SetMem32 (Buffer, Count, Value);
}

/**
 * Truncate a 64-bit value to lower 32 bits.
 */
UINT32
TruncateTo32 (
  UINT64  Value
  )
{
  return (UINT32)Value;
}

/**
 * Read the Interrupt Descriptor Table Register.
 */
VOID
ReadIdtr (
  OUT IA32_DESCRIPTOR  *Idtr
  )
{
  ASSERT (Idtr != NULL);
  AsmReadIdtr (Idtr);
}

/**
 * Read an unaligned 64-bit value.
 */
UINT64
ReadUnaligned64 (
  IN CONST VOID  *Buffer
  )
{
  ASSERT (Buffer != NULL);
  return *(volatile UINT64 *)Buffer;
}

/**
 * Write an unaligned 64-bit value.
 */
VOID
WriteUnaligned64 (
  OUT VOID    *Buffer,
  IN  UINT64  Value
  )
{
  ASSERT (Buffer != NULL);
  *(volatile UINT64 *)Buffer = Value;
}

/**
 * Get timestamp counter frequency (3.579545 MHz for this platform).
 */
UINT64
GetTimestampFrequency (
  VOID
  )
{
  return TIMER_FREQUENCY;
}

// ---------------------------------------------------------------------------
// I/O Port Access
// ---------------------------------------------------------------------------

/**
 * Read a 16-bit I/O port (aligned).
 */
UINT16
IoRead16 (
  IN UINT16  Port
  )
{
  ASSERT ((Port & 1) == 0);
  return __inword (Port);
}

/**
 * Write a 16-bit I/O port (aligned).
 */
UINT16
IoWrite16 (
  IN UINT16  Port,
  IN UINT16  Value
  )
{
  ASSERT ((Port & 1) == 0);
  return __outword (Port, Value);
}

/**
 * Read a 32-bit I/O port (4-byte aligned).
 */
UINT32
IoRead32 (
  IN UINT16  Port
  )
{
  ASSERT ((Port & 3) == 0);
  return __indword (Port);
}

// ---------------------------------------------------------------------------
// Debug and Assert
// ---------------------------------------------------------------------------

/**
 * Locate the Debug Library protocol via PEI services LocatePpi.
 */
EFI_PEI_PROTOCOL_ENTRY *
GetDebugLibProtocol (
  VOID
  )
{
  EFI_PEI_PROTOCOL_ENTRY  *Protocol;
  EFI_STATUS              Status;

  Status = PeiServicesLocatePpi (NULL, (VOID **)&Protocol);
  if (!EFI_ERROR (Status)) {
    return Protocol;
  }
  return NULL;
}

/**
 * Debug print wrapper. Checks debug level and forwards to protocol.
 *
 * @param ErrorLevel  Debug error level
 * @param Format      Format string
 */
VOID
SpsDebugPrint (
  IN UINTN       ErrorLevel,
  IN CONST CHAR8 *Format,
  ...
  )
{
  EFI_PEI_PROTOCOL_ENTRY  *Protocol;
  UINT32                  DebugLevel;

  Protocol = GetDebugLibProtocol ();
  if (Protocol == NULL) {
    return;
  }

  DebugLevel = GetDebugLevel ();
  if ((DebugLevel & ErrorLevel) != 0) {
    VA_LIST  Marker;
    VA_START (Marker, Format);
    Protocol->DebugPrint (ErrorLevel, Format, Marker);
    VA_END (Marker);
  }
}

/**
 * Assert handler.
 */
VOID
DebugAssert (
  IN CONST CHAR8  *FileName,
  IN UINTN        LineNumber,
  IN CONST CHAR8  *Description
  )
{
  EFI_PEI_PROTOCOL_ENTRY  *Protocol;

  Protocol = GetDebugLibProtocol ();
  if (Protocol != NULL) {
    Protocol->DebugAssert (FileName, LineNumber, Description);
  }
}

/**
 * Determine the current debug level using CMOS/NVRAM.
 *
 * Reads CMOS index 0x4A (bit 7 preserved from original index register value).
 * Returns debug level mask:
 *   0 = EFI_D_ERROR | EFI_D_WARN
 *  -1 = all disabled
 *   1 = EFI_D_ERROR only
 *  -2147483578 = EFI_D_INFO only
 *  -2147483644 = EFI_D_WARN only
 */
UINT32
GetDebugLevel (
  VOID
  )
{
  UINT8   Original;
  UINT8   NvramIndex;
  UINT8   Value;
  UINT32  Result;

  Original = __inbyte (0x70);
  __outbyte (0x70, (Original & 0x80) | 0x4A);
  Value = __inbyte (0x71);

  if (Value <= 3) {
    //
    // Level 0-3: directly interpret
    //
    if (Value == 0) {
      return 0;
    }
  } else {
    //
    // Value > 3: check if n3_0 is zero (backup from memory)
    //
    if (n3_0 == 0) {
      //
      // Read fallback from memory-mapped register
      //
      Value = (*(volatile UINT8 *)0xFDAF0490 & 2) | 1;
      if (Value == 0) {
        return 0;
      }
    }
  }

  if (Value == (UINT8)-1) {
    return 0;
  }

  if (Value == 1) {
    return (UINT32)-2147483644;   // EFI_D_WARN only
  }

  return (UINT32)-2147483578;     // EFI_D_INFO? (0x80000046)
}

// ---------------------------------------------------------------------------
// PCD Access via PEI PCD Protocol
// ---------------------------------------------------------------------------

/**
 * Locate the PEI PCD protocol.
 */
VOID *
GetPcdProtocol (
  VOID  *This
  )
{
  EFI_STATUS  Status;
  VOID        *PcdProtocol = This;

  Status = PeiServicesLocatePpi (NULL, &PcdProtocol);
  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "ASSERT_EFI_ERROR (Status = %r)\n", Status));
    ASSERT_EFI_ERROR (Status);
  }
  return PcdProtocol;
}

/**
 * Get a 32-bit PCD value.
 */
UINT32
PcdGet32 (
  UINTN  Token
  )
{
  EFI_PEI_PCD_PROTOCOL  *PcdProtocol;

  PcdProtocol = (EFI_PEI_PCD_PROTOCOL *)GetPcdProtocol ((VOID *)Token);
  return PcdProtocol->Get32 (Token);
}

/**
 * Get a PCD pointer.
 */
VOID *
PcdGetPtr (
  UINTN  Token
  )
{
  EFI_PEI_PCD_PROTOCOL  *PcdProtocol;

  PcdProtocol = (EFI_PEI_PCD_PROTOCOL *)GetPcdProtocol ((VOID *)Token);
  return PcdProtocol->GetPtr (Token);
}

//
// PCD call-back data structures (used for lazy initialization)
//
STATIC UINT32  mPcdTable[] = { 0 };
STATIC UINT32  mPcdCache[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };

/**
 * Initialize PCD call-back structures (first-call lazy init).
 */
EFI_STATUS
PcdCallbackInit (
  OUT VOID   *EntryData,
  IN  UINTN  EntryCount
  )
{
  EFI_PEI_PCD_PROTOCOL  *PcdProtocol;
  UINT32                TableSize;

  TableSize = 16 * EntryCount + 16;
  PcdProtocol = (EFI_PEI_PCD_PROTOCOL *)PcdGetPtr (PCD_TOKEN_PLATFORM_TYPE);

  if (mPcdCache[0] == 0 && mPcdCache[1] == 0) {
    mPcdCache[2] = PcdGet32 (PCD_TOKEN_PLATFORM_TYPE + 1);
    mPcdCache[3] = 0;
  }
  return EFI_SUCCESS;
}

/**
 * Resolve a PCD value via the protocol (with table/cache lookups).
 *
 * @param[in]  PcdEntry  Pointer to PCD entry descriptor
 * @return     Resolved PCD value (or default if not found)
 */
UINT32
PcdGetFromProtocol (
  IN VOID  *PcdEntry
  )
{
  EFI_PEI_PCD_PROTOCOL  *PcdProtocol;
  UINT32                LocalData;
  UINT32                PcdPtr;
  UINT32                Size;
  UINT16                TokenNum;

  TokenNum = *(UINT16 *)((UINTN)PcdEntry + 4);
  PcdProtocol = (EFI_PEI_PCD_PROTOCOL *)PcdGetPtr (PCD_TOKEN_PLATFORM_TYPE);

  if (*(UINT32 *)((UINTN)PcdEntry + 12) != 0) {
    //
    // External table path
    //
    PcdPtr = *(UINT32 *)(*(UINT32 *)((UINTN)PcdEntry + 12) +
              4 * TokenNum + 255544);
    Size   = *(UINT32 *)(*(UINT32 *)((UINTN)PcdEntry + 12) +
              4 * TokenNum + 255560);
  } else {
    //
    // Local protocol path
    //
    if (PcdProtocol->GetSize (PcdGetPtr) != 0) {
      PcdPtr = *(UINT32 *)((UINTN)PcdProtocol + 16 * TokenNum + 20);
      Size   = *(UINT32 *)((UINTN)PcdProtocol + 16 * TokenNum + 16);
    } else {
      PcdCallbackInit (mPcdTable, 8);
      PcdPtr = mPcdCache[4 * TokenNum];
      Size   = mPcdCache[4 * TokenNum + 1];
      if (Size == 0 && PcdPtr == 0) {
        Size   = PcdGet32 (PCD_TOKEN_PLATFORM_TYPE + 1);
        PcdPtr = 0;
      }
    }
  }

  if (Size == 0 && PcdPtr == 0) {
    return PcdGet32 (PCD_TOKEN_PLATFORM_TYPE + 1);
  }
  return Size;
}

/**
 * Perform a PCI config read using a Direct Address (ECAM) mechanism.
 */
INT32 *
PciCfgRead (
  IN  UINT32  *Address,
  OUT UINT32  *Value
  )
{
  UINT32  SegmentNum;
  UINT32  PhysAddress;

  PhysAddress = PcdGetFromProtocol (Address);
  PhysAddress += (*Address & 0xFFFFFFF);
  *Value = PhysAddress;
  return Value;
}

// ---------------------------------------------------------------------------
// PCH / Platform Helpers
// ---------------------------------------------------------------------------

/**
 * Read a PCH register for LPC device ID, then get the PWRM base address.
 *
 * @param[out] PwrmBase  Pointer to receive PWRM base address
 * @retval EFI_SUCCESS   PWRM base read successfully
 * @retval EFI_DEVICE_ERROR  LPC device not found (LpcDeviceId = 0xFFFF)
 */
EFI_STATUS
PchPwrmBaseGet (
  OUT UINT32  *PwrmBase
  )
{
  UINT16  LpcDeviceId;

  if (PwrmBase == NULL) {
    DEBUG ((EFI_D_ERROR, "PchPwrmBaseGet Error. Invalid pointer.\n"));
    ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
    return EFI_INVALID_PARAMETER;
  }

  //
  // Read LPC device ID from PCH config space at Bus 0, Dev 1F, Func 0
  //
  LpcDeviceId = IoRead16 (GetMeFwHob (31, 2));
  if (LpcDeviceId == 0xFFFF) {
    ASSERT_EFI_ERROR (EFI_DEVICE_ERROR);
    return EFI_DEVICE_ERROR;
  }

  //
  // Extract PWRM base from the same config space
  //
  *PwrmBase = *(volatile UINT32 *)(GetMeFwHob (31, 2) + 72) & 0xFFFF0000;
  return EFI_SUCCESS;
}

/**
 * Get the PCH SKU type by reading LPC Device ID.
 *
 * Returns:
 *   1 = PCH-LP (low power)
 *   2 = PCH-H (regular)
 *   3 = unknown (default)
 */
UINT32
GetPchSkuType (
  VOID
  )
{
  STATIC UINT32  mPchSkuType = 3;
  UINT16         LpcDeviceId;

  if (mPchSkuType != 3) {
    return mPchSkuType;
  }

  LpcDeviceId = IoRead16 ((UINT16 *)(GetMeFwHob (31, 0) + 2));

  if ((LpcDeviceId >= 0xA1C0 && LpcDeviceId <= 0xA1CF) ||
       LpcDeviceId == 0xA243 ||
      (LpcDeviceId >= 0xA240 && LpcDeviceId <= 0xA24F)) {
    //
    // PCH-LP (Low Power)
    //
    mPchSkuType = 1;
  } else if (LpcDeviceId == 0x9D40 || LpcDeviceId == 0x9D41 ||
             LpcDeviceId == 0x9D42 || LpcDeviceId == 0x9D43 ||
             LpcDeviceId == 0x9D46 || LpcDeviceId == 0x9D48) {
    //
    // PCH-H (Regular)
    //
    mPchSkuType = 2;
  } else {
    DEBUG ((EFI_D_ERROR, "Unsupported PCH SKU, LpcDeviceId: 0x%04x!\n", LpcDeviceId));
    ASSERT (FALSE);
  }

  return mPchSkuType;
}

/**
 * Set the PCH MMIO range register (for S3 path).
 *
 * Writes the restored MMIO value to the platform register, after
 * resolving the PCH SKU type.
 */
VOID
SetPchMmioRange (
  IN UINT32  NewMmioValue
  )
{
  GetPchSkuType ();
  *(volatile UINT32 *)PCH_MMIO_RANGE_REGISTER = NewMmioValue;
}

// ---------------------------------------------------------------------------
// HECI (Host Embedded Controller Interface) Access
// ---------------------------------------------------------------------------

/**
 * Retrieve the HECI protocol interface pointer from PEI services.
 *
 * Uses the Interrupt Descriptor Table Register (IDTR) to locate the
 * PEI Services Table, then extracts the HECI protocol entry.
 */
EFI_PEI_HECI_PROTOCOL *
HeciGetProtocol (
  VOID
  )
{
  IA32_DESCRIPTOR  Idtr;
  UINT32           *PeiServiceTable;

  ReadIdtr (&Idtr);
  PeiServiceTable = *(UINT32 **)(*(UINT32 *)&Idtr[2] - 4);

  ASSERT (PeiServiceTable != NULL);
  return (EFI_PEI_HECI_PROTOCOL *)PeiServiceTable;
}

/**
 * Locate a PEI PPI protocol by GUID.
 *
 * Thin wrapper around PeiServices->LocatePpi.
 */
EFI_STATUS
PeiServicesLocatePpi (
  IN  EFI_GUID  *Guid OPTIONAL,
  OUT VOID      **PpiInterface
  )
{
  EFI_PEI_SERVICES  **PeiServices;
  EFI_PEI_HECI_PROTOCOL *HeciProtocol;

  HeciProtocol = HeciGetProtocol ();
  return HeciProtocol->LocatePpi (
           PeiServices,
           Guid,
           0,
           NULL,
           PpiInterface
           );
}

// ---------------------------------------------------------------------------
// ME Firmware HOB Access
// ---------------------------------------------------------------------------

/**
 * Get the ME Firmware HOB (Hand-Off Block) with config space offset.
 *
 * Constructs a PCI config space address from the function/device
 * encoding and reads the result into the output parameter.
 *
 * @param[in]  Flags  Configuration flags (device/func encoding)
 * @param[in]  Value  Additional address bits (used for lower bits)
 * @return     Pointer to the HOB config data
 */
UINT32 *
GetMeFwHob (
  IN UINT8   Flags,
  IN UINT32  Value
  )
{
  UINT32  Address[5];

  Address[2] = 512;
  Address[0] = ((Value & 7 | (8 * (Flags & 0x1F))) << 12);
  Address[3] = 0;
  Address[1] = 0;

  PciCfgRead (Address, (UINT32 *)&Value);
  return (UINT32 *)Value;
}

/**
 * Get the HOB list pointer via PEI services.
 */
VOID *
GetHobList (
  VOID
  )
{
  EFI_PEI_SERVICES  **PeiServices;
  VOID              *HobList;
  EFI_STATUS        Status;

  PeiServices = (EFI_PEI_SERVICES **)HeciGetProtocol ();
  Status = (*PeiServices)->GetHobList (PeiServices, &HobList);

  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status));
    ASSERT_EFI_ERROR (Status);
  }

  ASSERT (HobList != NULL);
  return HobList;
}

/**
 * Get the next HOB in the chain with GUID type.
 */
EFI_HOB_GUID_TYPE *
HobGetNextGuid (
  IN VOID  *HobStart
  )
{
  EFI_HOB_GUID_TYPE  *HobGuid;

  ASSERT (HobStart != NULL);

  for (HobGuid = (EFI_HOB_GUID_TYPE *)HobStart;
       HobGuid->Header.HobType != EFI_HOB_TYPE_END_OF_HOB_LIST;
       HobGuid = NEXT_HOB (HobGuid))
  {
    if (HobGuid->Header.HobType == EFI_HOB_TYPE_GUID_EXTENSION) {
      return HobGuid;
    }
  }
  return NULL;
}

/**
 * Find a GUID extension HOB matching a given GUID.
 *
 * @param[in] Guid  Pointer to the GUID to match
 * @return    Pointer to the GUID HOB, or NULL if not found
 */
VOID *
HobGetGuid (
  IN CONST EFI_GUID  *Guid
  )
{
  EFI_HOB_GUID_TYPE  *HobGuid;

  HobGuid = (EFI_HOB_GUID_TYPE *)GetHobList ();

  while (HobGuid != NULL) {
    if (HobIsMatchingGuid ((VOID *)Guid, (VOID *)((UINTN)HobGuid + 8))) {
      return HobGuid;
    }
    HobGuid = HobGetNextGuid ((UINTN)HobGuid + HobGuid->Header.HobLength);
  }

  return NULL;
}

/**
 * Compare a Name GUID with a HOB GUID (both 16-byte EFI_GUID).
 *
 * @param[in]  NameGuid  Known GUID to match
 * @param[in]  HobGuid   HOB GUID from the HOB
 * @retval TRUE  GUIDs match
 * @retval FALSE GUIDs do not match
 */
BOOLEAN
HobIsMatchingGuid (
  IN CONST EFI_GUID  *NameGuid,
  IN CONST VOID      *HobGuid
  )
{
  UINT64  NameLow;
  UINT64  NameHigh;
  UINT64  HobLow;
  UINT64  HobHigh;

  NameLow  = ReadUnaligned64 (NameGuid);
  NameHigh = ReadUnaligned64 ((UINTN)NameGuid + 8);
  HobLow   = ReadUnaligned64 (HobGuid);
  HobHigh  = ReadUnaligned64 ((UINTN)HobGuid + 8);

  return (NameLow == HobLow) && (NameHigh == HobHigh);
}

/**
 * Get ME FStatus1 from the MeFwHob.
 *
 * Reads the ME FW HOB GUID entry and extracts MEFS1 value.
 * Returns -1 on failure.
 */
UINT32
GetMeFs1FromHob (
  VOID
  )
{
  EFI_HOB_GUID_TYPE  *Hob;
  UINT32             MeFs1;

  MeFs1 = (UINT32)-1;
  Hob = (EFI_HOB_GUID_TYPE *)HobGetGuid (&gMeFwHobGuid);

  if (Hob == NULL) {
    DEBUG ((EFI_D_ERROR, "HECI: GetMeFs1FromHob() Can't read correctly MeFwHob info\n"));
    return (UINT32)-1;
  }

  if (*(UINT32 *)((UINTN)Hob + 28) != 0) {
    //
    // Error path: assert MeFwHob->Group[0].FunNumber == HECI1_DEVICE
    //
    DEBUG ((EFI_D_ERROR, "HECI: GetMeFs1FromHob() Can't read correctly MeFwHob info\n"));
    ASSERT (FALSE);
  } else {
    MeFs1 = *(UINT32 *)((UINTN)Hob + 32);
  }

  if (MeFs1 == (UINT32)-1) {
    DEBUG ((EFI_D_ERROR, "HECI: GetMeFs1FromHob() Can't read correctly MeFwHob info\n"));
    return (UINT32)(-1);
  }

  DEBUG ((EFI_D_INFO, "HECI: GetMeFs1FromHob() returns MEFS1 = %d\n", MeFs1));
  return MeFs1;
}

/**
 * Determine if the running ME firmware is SPS firmware.
 *
 * Reads MEFS1, MEFS2 from HOB, checks operation mode.
 *
 * @retval 1  ME is SPS firmware
 * @retval 2  ME is DFX
 * @retval 15 ME is Other/Not-SPS
 * @retval 255 ME is TAP
 * @retval 0  ME type not recognized
 */
UINT32
IsSpsFw (
  VOID
  )
{
  UINT32  PwrmBase;
  UINT32  MeFs1;

  PwrmBase = 0;
  PchPwrmBaseGet (&PwrmBase);

  if (PwrmBase != 0) {
    //
    // Check DWR flow
    //
    if ((*(volatile UINT32 *)(PwrmBase + 300) & 0x8000) != 0) {
      DEBUG ((EFI_D_INFO, "HECI: GetOnBoardMeType() for DWR flow return Dfx type\n"));
      return 15;
    }
  } else {
    ASSERT_EFI_ERROR (EFI_DEVICE_ERROR);
  }

  MeFs1 = *(volatile UINT32 *)(GetMeFwHob (0) + 64);

  if (MeFs1 == (UINT32)-1) {
    //
    // HOB not yet available; read from HOB directly
    //
    MeFs1 = GetMeFs1FromHob ();
    DEBUG ((EFI_D_INFO, "HECI: GetOnBoardMeType() reads Hfs info from HOB = %d\n", MeFs1));
  }

  if ((MeFs1 & MEFS1_ME_STATE_MASK) != 0xF) {
    //
    // Valid FSM state
    //
    if ((MeFs1 & MEFS1_ME_STATE_MASK) == 4) {
      return 255;   // TAP
    }

    DEBUG ((EFI_D_INFO, "HECI: MeOperationMode = %d\n",
      (MeFs1 & MEFS1_OPERATION_MODE_MASK) >> 16));

    switch ((MeFs1 >> 16) & 0xF) {
    case 0:   // Normal
    case 1:   // Debug
      return 2;
    case 2:   // Manufacturing
      return 255;
    case 3: case 4: case 5:
      return 2;
    case 7:   // Secure
      return 255;
    case 15:  // SPS
      return 1;
    default:
      DEBUG ((EFI_D_ERROR,
        "HECI: ME type not recognized (MEFS1: 0x%08X)\n", MeFs1));
      DEBUG ((EFI_D_ERROR,
        "                             (MEFS2: 0x%08X)\n",
        *(volatile UINT32 *)(GetMeFwHob (0) + 72)));
      return 0;
    }
  }

  return 15;   // No ME firmware state
}

/**
 * Check if ME is in SPS normal mode and the boot is S3 resume.
 *
 * @retval TRUE   S3 resume path for SPS ME
 * @retval FALSE  Not S3 or not SPS
 */
BOOLEAN
IsSpsNormalModeS3 (
  VOID
  )
{
  if (IsSpsFw () != 1) {
    return FALSE;
  }
  return ((*(volatile UINT32 *)(GetMeFwHob (22, 0) + 64) & MEFS1_ME_STATE_MASK)
          == MEFS1_ME_STATE_RECOVERY);
}

// ---------------------------------------------------------------------------
// HOB Building
// ---------------------------------------------------------------------------

/**
 * Build SPS Policy HOB (builds HobGuid for gSpsPolicyHobGuid + gSpsInfoHobGuid).
 */
VOID *
HobBuildSpsPolicy (
  IN VOID  *Data
  )
{
  UINT64  Temp;
  UINT64  Temp2;

  Temp  = ReadUnaligned64 (&gSpsInfoHobGuid);
  Temp2 = ReadUnaligned64 (&gSpsPolicyHobGuid);
  WriteUnaligned64 ((UINT64 *)Data + 0, Temp);
  WriteUnaligned64 ((UINT64 *)Data + 1, Temp2);

  return Data;
}

/**
 * Create SPS Info HOB from Heci (PEI Services BuildHob).
 *
 * @param[in]  HobGuidPtr  GUID for the HOB
 * @return     Pointer to the created HOB, or NULL
 */
VOID *
HobCreateSpsInfo (
  IN CONST EFI_GUID  *HobGuidPtr
  )
{
  VOID        *Hob;
  EFI_STATUS  Status;

  Hob = HeciGetProtocol ();
  Status = ((EFI_PEI_SERVICES **)Hob)->CreateHob (
             (EFI_PEI_SERVICES **)Hob,
             sizeof (EFI_HOB_GUID_TYPE) + (UINTN)HobGuidPtr,
             &Hob
             );

  if (EFI_ERROR (Status)) {
    Hob = NULL;
  }

  if (Hob == NULL) {
    ASSERT_EFI_ERROR (EFI_OUT_OF_RESOURCES);
  }

  return Hob;
}

// ---------------------------------------------------------------------------
// Timer / Delay
// ---------------------------------------------------------------------------

/**
 * Spin-loop microsecond delay using timestamp counter.
 *
 * @param[in]  MicroSeconds  Number of microseconds to delay
 */
VOID
MicroSecondDelaySpin (
  IN UINT32  MicroSeconds
  )
{
  UINT64  Ticks;
  UINT64  TargetTsc;

  Ticks = MicroSeconds * (TIMER_FREQUENCY / 1000000);
  TargetTsc = (AsmReadTsc () & 0xFFFFFF) + Ticks;

  while (((AsmReadTsc () - TargetTsc) & 0x800000) == 0) {
    _mm_pause ();
  }

  MicroSeconds = (UINT32)(Ticks >> 22);
  while (MicroSeconds-- > 0) {
    _mm_pause ();
  }
}

/**
 * Microsecond delay (1000us = 1ms).
 *
 * @param[in]  This  Ignored
 * @return     1000 (always)
 */
UINTN
MicroSecondDelay (
  VOID  *This
  )
{
  UINT64  Ticks;

  Ticks = (UINT64)GetTimestampFrequency ();
  MicroSecondDelaySpin ((UINT32)(Ticks / 1000000));
  return 1000;
}

// ---------------------------------------------------------------------------
// ME Message Functions
// ---------------------------------------------------------------------------

/**
 * Wait for the ME to reach Normal (0x02) or Recovery (0x05) state
 * within a timeout loop.
 *
 * @param[in] PollCount  Timeout in loop iterations (default 2000 if NULL)
 * @retval EFI_SUCCESS   ME in Normal or Recovery state
 * @retval EFI_TIMEOUT   ME state transition timed out
 * @retval EFI_UNSUPPORTED  ME in unexpected state
 */
EFI_STATUS
WaitForMeNormalOrRecovery (
  IN UINT32  *PollCount OPTIONAL
  )
{
  UINT32   Count;
  UINT32   MeState;

  Count = TIMEOUT_2000_MS;
  if (PollCount != NULL) {
    Count = 1000 * *PollCount;
  }

  DEBUG ((EFI_D_INFO, "[SPS] Wait for ME Normal or Recovery state\n"));

  while (Count > 0) {
    MeState = *(volatile UINT32 *)(GetMeFwHob (0) + 64) & MEFS1_ME_STATE_MASK;

    if (MeState == MEFS1_ME_STATE_RECOVERY ||
        MeState == MEFS1_ME_STATE_NORMAL) {
      DEBUG ((EFI_D_INFO, "[SPS] Wait for ME state reaches ME State = %d\n", MeState));
      return EFI_SUCCESS;
    }

    MicroSecondDelay (NULL);
    Count--;
  }

  DEBUG ((EFI_D_ERROR, "[SPS] ERROR: Timeout when waiting for ME meaningful state\n"));
  return EFI_TIMEOUT;
}

/**
 * Wait for the ME firmware init complete flag (MEFS1 BIT9).
 *
 * @param[in]  SpsPolicy  Pointer to SPS policy PPI (optional)
 * @retval EFI_SUCCESS     ME init completed
 * @retval EFI_TIMEOUT     Timeout waiting for init complete
 * @retval EFI_UNSUPPORTED ME not in valid state
 */
EFI_STATUS
WaitForMeFwInitComplete (
  IN VOID  *SpsPolicy OPTIONAL
  )
{
  UINT32  WaitCount;
  UINT32  MeStatus;
  UINT32  BootMode;

  WaitCount = TIMEOUT_2000_MS;
  if (SpsPolicy != NULL) {
    WaitCount = 1000 * *(UINT32 *)((UINTN)SpsPolicy + 20);
  }

  DEBUG ((EFI_D_INFO, "[SPS] Waiting for ME firmware init complete\n"));

  while (TRUE) {
    MeStatus = *(volatile UINT32 *)(GetMeFwHob (0) + 64);

    if ((MeStatus & MEFS1_FW_INIT_COMPLETE) != 0) {
      break;
    }

    if (WaitCount == 0) {
      DEBUG ((EFI_D_ERROR, "[SPS] ERROR: Timeout when waiting for ME init complete\n"));
      return EFI_DEVICE_ERROR;
    }

    MicroSecondDelay (NULL);
    WaitCount--;
  }

  //
  // Read boot mode for context
  //
  BootMode = 4;
  if (HeciGetProtocol ()->GetBootMode (&BootMode) < 0) {
    DEBUG ((EFI_D_ERROR, "[SPS] ERROR: Cannot read boot mode (%r)\n"));
    BootMode = 4;
  }

  //
  // Validate ME state
  //
  switch ((MeStatus & MEFS1_ME_STATE_MASK) - 2) {
  case 0:   // Recovery
    GetMeFwHob (0);
    DEBUG ((EFI_D_WARN, "[SPS] WARNING: ME is in recovery mode (cause: %d)\n"));
    return EFI_SUCCESS;

  case 3:   // Normal (5 - 2 = 3)
    return EFI_SUCCESS;

  default:
    return EFI_DEVICE_ERROR;
  }
}

/**
 * Wait for the ME Reset Counter to change.
 *
 * @param[in]  OldResetCounter  Previous reset counter value to compare
 * @param[in]  pTimeout         Pointer to timeout counter
 * @retval EFI_SUCCESS          Reset counter changed
 * @retval EFI_TIMEOUT          Timed out waiting
 */
EFI_STATUS
WaitForMeResetCounterChange (
  IN UINT32  OldResetCounter,
  IN UINT32  *pTimeout OPTIONAL
  )
{
  UINT32  Timeout = TIMEOUT_2000_MS;
  UINT32  CurrentReset;

  if (pTimeout == NULL) {
    pTimeout = &Timeout;
  }

  while (TRUE) {
    CurrentReset = (*(volatile UINT32 *)(GetMeFwHob (0) + 64) >> 20) & 0xF;

    if (OldResetCounter != CurrentReset) {
      return EFI_SUCCESS;
    }

    if (*pTimeout == 0) {
      break;
    }

    MicroSecondDelay (NULL);
    (*pTimeout)--;
  }

  DEBUG ((EFI_D_ERROR, "[SPS] ERROR: Timeout when waiting for ME Reset Counter Change\n"));
  return EFI_TIMEOUT;
}

/**
 * Set the NM (Node Manager) Boot Mode via MSR.
 *
 * @param[in] PerformanceOptimized  TRUE = Performance, FALSE = Power Optimized
 */
VOID
SetNmBootMode (
  IN BOOLEAN  PerformanceOptimized
  )
{
  UINT64  PlatformId;
  UINT64  MiscEnables;
  UINT64  NewMisc;

  PlatformId  = AsmReadMsr64 (MSR_IA32_PLATFORM_ID);
  MiscEnables = AsmReadMsr64 (MSR_IA32_MISC_ENABLES);
  MiscEnables &= 0xFFFF80FF;

  if (PerformanceOptimized) {
    NewMisc = (PlatformId & 0x7F00) | MiscEnables;
    DEBUG ((EFI_D_INFO, "[SPS] NM Boot Mode: Performance Optimized\n"));
  } else {
    NewMisc = (TruncateTo32 (AsmReadTsc ()) & 0x7F00) | MiscEnables;
    DEBUG ((EFI_D_INFO, "[SPS] NM Boot Mode: Power Optimized\n"));
  }

  AsmWriteMsr64 (MSR_IA32_MISC_ENABLES, NewMisc);
}

/**
 * Send END_OF_POST message to the ME via HECI.
 * Used during S3 resume path.
 */
EFI_STATUS
SpsS3Path (
  VOID
  )
{
  UINT32  MmioRange;
  UINT32  MeFlags1, MeFlags2;
  UINT8   MeState;
  UINT8   MeExtendedState;
  HECI_PROTOCOL  *HeciPpi;
  UINT32          MkhiMsg;
  UINT32          ResponseSize;
  EFI_STATUS      Status;

  DEBUG ((EFI_D_INFO, "[SPS] SpsS3Path called.\n"));

  //
  // Wait for ME firmware init
  //
  Status = WaitForMeFwInitComplete (GetSpsPolicyPpi ());
  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "[SPS] ERROR: ME not initialized correctly (%r)\n", Status));
    FinalizeSpsInit (0, 0, 0, 0, 0);
    return Status;
  }

  //
  // Locate HECI PPI
  //
  Status = PeiServicesLocatePpi (&gHeci1PpiGuid, (VOID **)&HeciPpi);
  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "[SPS] ERROR: Cannot locate HECI PPI (%r)\n", Status));
    return Status;
  }

  //
  // Save and adjust MMIO range
  //
  MmioRange = *(volatile UINT32 *)PCH_MMIO_RANGE_REGISTER;
  SetPchMmioRange (MmioRange & 0xFFFFFEFF);

  MeFlags1 = *(volatile UINT32 *)(GetMeFwHob (0) + 16);
  MeFlags2 = *(volatile UINT32 *)(GetMeFwHob (0) + 20);
  MeState  = *(volatile UINT8 *)(GetMeFwHob (0) + 4);
  MeExtendedState  = *(volatile UINT8 *)(GetMeFwHob (0) + 60);

  if (MeFlags2 != 0 && (MeFlags1 & 4) != 0) {
    *(volatile UINT32 *)(GetMeFwHob (0) + 16) = 0;
  }

  //
  // Re-initialize HECI
  //
  HeciPpi->ReInit (0);

  //
  // Check if END_OF_POST should be sent
  //
  if (GetHeciPpi (NULL) != NULL &&
      (*(volatile UINT8 *)((UINTN)GetHeciPpi (NULL) + 12) & 3) == 0) {
    DEBUG ((EFI_D_INFO, "[SPS] Sending END_OF_POST to ME\n"));

    MkhiMsg       = HECI_MSG_END_OF_POST;
    ResponseSize  = HECI_MSG_EOP_LENGTH;

    Status = HeciPpi->SendMessage (
                      0, &MkhiMsg, 4, &ResponseSize,
                      0, 7
                      );

    if (!EFI_ERROR (Status)) {
      if (MkhiMsg != HECI_MSG_EOP_RESPONSE_MKHI) {
        DEBUG ((EFI_D_ERROR, "[SPS] ERROR: Invalid END_OF_POST response (MKHI: 0x%X)\n", MkhiMsg));
      }
    } else {
      DEBUG ((EFI_D_ERROR, "[SPS] ERROR: Cannot send END_OF_POST (%r)\n", Status));
    }
  }

  //
  // Restore flags
  //
  *(volatile UINT32 *)(GetMeFwHob (0) + 20) = MeFlags2;
  *(volatile UINT32 *)(GetMeFwHob (0) + 16) = MeFlags1;
  *(volatile UINT8 *)(GetMeFwHob (0) + 4)  = MeExtendedState;

  SetPchMmioRange (MmioRange);

  return EFI_SUCCESS;
}

/**
 * Normal (non-S3) boot path for SPS.
 *
 * Negotiates ME-BIOS interface version, configures Node Manager (NM),
 * sets ICC clock settings if required.
 */
EFI_STATUS
SpsNonS3Path (
  VOID
  )
{
  SPS_POLICY_PPI    *SpsPolicy;
  HECI_PROTOCOL     *HeciPpi;
  UINT8              Msg[HECI_MSG_GET_MEBIOS_LENGTH];
  UINT32             MsgSize;
  UINT32             RetryCount;
  EFI_STATUS         Status;
  UINT32             FeatureSet;
  UINT8              NmfsValue;
  ICC_PROTOCOL       *IccPpi;
  BOOLEAN            PowerOptimized;
  UINT32             CoresToDisable;
  BOOLEAN            NodeManagerEnabled;

  DEBUG ((EFI_D_INFO, "[SPS] SpsNonS3Path called.\n"));

  //
  // Get SPS policy
  //
  SpsPolicy = (SPS_POLICY_PPI *)GetSpsPolicyPpi ();
  if (SpsPolicy == NULL) {
    DEBUG ((EFI_D_ERROR, "[SPS] ERROR: Cannot locate SPS Policy PPI, defaults will be used\n"));
  }

  //
  // Wait for ME firmware init
  //
  Status = WaitForMeFwInitComplete (SpsPolicy);
  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "[SPS] ERROR: ME not initialized correctly.\n"));
    FinalizeSpsInit (0, 0, 0, 0, 0);
    return Status;
  }

  //
  // Locate the HECI PPI
  //
  GetMeFwHob (0);
  Status = PeiServicesLocatePpi (&gHeci1PpiGuid, (VOID **)&HeciPpi);
  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "[SPS] ERROR: Cannot locate HECI PPI\n"));
    return Status;
  }

  //
  // Reset HECI and send ME-BIOS Interface Version request
  //
  HeciPpi->ReInit (0);
  ZeroMem (Msg, HECI_MSG_GET_MEBIOS_LENGTH);

  DEBUG ((EFI_D_INFO, "[SPS] Sending ME-BIOS Interface Version request\n"));

  //
  // Retry loop for interface version negotiation
  //
  for (RetryCount = 0; RetryCount < HECI_MSG_GET_MEBIOS_RETRY; RetryCount++) {
    Msg[0] = HECI_MSG_GET_MEBIOS_INTERFACE;
    MsgSize = 1;

    Status = HeciPpi->SendMessage (0, Msg, 1, 0, 32);
    if (EFI_ERROR (Status)) {
      DEBUG ((EFI_D_WARN, "[SPS] WARNING: Cannot send SPS_GET_MEBIOS_INTERFACE (status %r)\n", Status));
      continue;
    }

    MsgSize = HECI_MSG_GET_MEBIOS_LENGTH;
    Status = HeciPpi->ReadMessage (0, 1, Msg, &MsgSize);
    if (EFI_ERROR (Status)) {
      DEBUG ((EFI_D_WARN,
        "[SPS] WARNING: Cannot get SPS_GET_MEBIOS_INTERFACE response (status: %r)\n",
        Status));
      continue;
    }

    if (Msg[0] != HECI_MSG_GET_MEBIOS_RESPONSE || MsgSize != HECI_MSG_GET_MEBIOS_LENGTH) {
      DEBUG ((EFI_D_ERROR,
        "[SPS] ERROR: Invalid GET_MEBIOS_INTERFACE response (cmd: 0x%X, len %d)\n",
        Msg[0], MsgSize));
      Status = EFI_PROTOCOL_ERROR;
      continue;
    }

    //
    // Success - interface version negotiated
    //
    break;
  }

  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "[SPS] ERROR: Error sending SPS_GET_MEBIOS_INTERFACE message (Status = %r)\n", Status));
    FinalizeSpsInit (0, 0, 0, 0, 0);
    return EFI_PROTOCOL_ERROR;
  }

  DEBUG ((EFI_D_INFO, "[SPS] SPS ME-BIOS interface version is %d.%d\n", Msg[1], Msg[2]));
  DEBUG ((EFI_D_INFO, "      Feature set is   0x%08X\n", *(UINT32 *)&Msg[3]));
  DEBUG ((EFI_D_INFO, "      Feature set 2 is 0x%08X\n", *(UINT32 *)&Msg[7]));

  FeatureSet = *(UINT32 *)&Msg[3];

  //
  // Configure Node Manager (NM) if enabled
  //
  if ((FeatureSet & FEATURE_NODE_MANAGER) != 0) {
    DEBUG ((EFI_D_INFO, "[SPS] Node Manager enabled\n"));

    NmfsValue = *(volatile UINT8 *)(GetMeFwHob (1) + 64);

    if ((NmfsValue & 0x80) != 0) {
      //
      // NMFS configured
      //
      if (SpsPolicy != NULL) {
        if ((SpsPolicy->Flags & ME_POLICY_INVERT_NMFS) != 0) {
          NmfsValue ^= (UINT8)((UINT32)(NmfsValue ^ ~(UINT8)SpsPolicy->NmVariant) & 1);
        }
        if ((SpsPolicy->Flags & ME_POLICY_SET_NMFS) != 0) {
          NmfsValue ^= (UINT8)((UINT32)(NmfsValue ^ SpsPolicy->NmVariant) & 0xFE);
        }
      }

      SetNmBootMode ((BOOLEAN)(NmfsValue & 1));
    } else {
      DEBUG ((EFI_D_ERROR, "[SPS] ERROR: NMFS not configured while NM enabled \n"));
      DEBUG ((EFI_D_ERROR,
        "(feature set: 0x%08X, feature set 2: 0x%08X, NMFS: 0x%08X)\n",
        FeatureSet, *(UINT32 *)&Msg[7], NmfsValue));

      SetNmBootMode ((BOOLEAN)(FeatureSet & 1));
    }

    //
    // Initialize HECI-2
    //
    if (EFI_ERROR (PeiServicesLocatePpi (&gHeci1PpiGuid, (VOID **)&IccPpi)) ||
        IccPpi->Initialize () < 0) {
      DEBUG ((EFI_D_ERROR, "[SPS] ERROR: Cannot initialize HECI-2 (%r)\n"));
    }

    //
    // Apply ICC clock settings
    //
    if (IccSetGetCurrentClockingMode (NULL) >= 0) {
      Status = PeiHeciSetSscAlternate (FALSE);
      ASSERT_EFI_ERROR (Status);
    } else {
      DEBUG ((EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status));
      ASSERT_EFI_ERROR (Status);
    }

    NodeManagerEnabled = TRUE;
  } else {
    NodeManagerEnabled = FALSE;
    PowerOptimized = TRUE;
  }

  //
  // Apply ICC clock settings if feature enabled
  //
  if ((FeatureSet & FEATURE_ICC_CLOCK_SETTINGS) != 0 &&
      SpsPolicy != NULL &&
      (SpsPolicy->Flags & ME_POLICY_ICC_SETTINGS) != 0) {
    DEBUG ((EFI_D_INFO, "[SPS][ICC] Sending IccSetClockSettings request \n"));

    if (PeiHeciSetSscAlternate (
          (BOOLEAN)((SpsPolicy->Flags >> 14) & 1)) >= 0) {
      DEBUG ((EFI_D_INFO, "[SPS][ICC] IccSetClockSettings: status: Success\n"));
    } else {
      DEBUG ((EFI_D_ERROR, "[SPS] ERROR: Unable to set clock settings (%r)\n"));
    }
  }

  //
  // Finalize SPS init with HOB publishing
  //
  FinalizeSpsInit (
    (UINT8)NodeManagerEnabled,
    (UINT8)(NodeManagerEnabled ? !PowerOptimized : 0),
    (UINT8)(NodeManagerEnabled ? (PowerOptimized ? 1 : 0) : 0),
    PowerOptimized,
    NodeManagerEnabled
    );

  return EFI_SUCCESS;
}

/**
 * Finalize SPS initialization by creating the SPS info HOB, building the
 * SPS policy HOB, and registering the HOB.
 *
 * @param[in] FlowType           ME flow type (1=normal, 0=non-functional)
 * @param[in] FeatureSet          Feature set value (from ME-BIOS interface)
 * @param[in] FeatureSet2         Feature set 2 value
 * @param[in] PowerOptimizedBoot  Power optimized boot indicator
 * @param[in] CoresToDisable      Number of cores to disable
 */
VOID
FinalizeSpsInit (
  IN UINT8    FlowType,
  IN UINT32   FeatureSet,
  IN UINT32   FeatureSet2,
  IN BOOLEAN  PowerOptimizedBoot,
  IN UINT8    CoresToDisable
  )
{
  //
  // Data buffer published in the HOB (16 bytes)
  //
  struct {
    UINT32  FeatureSet;
    UINT32  FeatureSet2;
    UINT8   PowerOptimizedBoot;
    UINT8   CoresToDisable;
    UINT8   FlowType;
    UINT8   Reserved;
    UINT32  Zero;
  } SpsData;

  SPS_INFO_HOB  *SpsInfoHob;

  ZeroMem (&SpsData, sizeof (SpsData));

  SpsData.FeatureSet         = FeatureSet;
  SpsData.FeatureSet2        = FeatureSet2;
  SpsData.PowerOptimizedBoot = (UINT8)PowerOptimizedBoot;
  SpsData.CoresToDisable     = CoresToDisable;
  SpsData.FlowType           = FlowType;

  //
  // Build the SPS info HOB via PEI services
  //
  SpsInfoHob = (SPS_INFO_HOB *)HobCreateSpsInfo (
                  sizeof (SPS_INFO_HOB)
                  );

  if (SpsInfoHob != NULL) {
    HobBuildSpsPolicy ((VOID *)SpsInfoHob);
    SafeCopyMem ((CHAR8 *)SpsInfoHob, (CHAR8 *)&SpsData);
  }

  DEBUG ((EFI_D_INFO,
    "[SPS] HOB: flow %d, feature set 0x%08X, features 2 0x%08x, "
    "pwr opt boot %d, cores2disable %d\n",
    FlowType, FeatureSet, FeatureSet2, PowerOptimizedBoot, CoresToDisable));

  if (FlowType != 1) {
    DEBUG ((EFI_D_ERROR, "[SPS] ERROR: ME is non functional (flow %d)\n", FlowType));
  }

  //
  // Verify SPS info HOB was registered
  //
  if (HobGetGuid (&gSpsInfoHobGuid) == NULL) {
    DEBUG ((EFI_D_ERROR, "[SPS] ERROR: SPS info HOB has not been registered\n"));
  }
}

/**
 * PPI notify callback: called when HECI PPI is ready during non-S3 path.
 *
 * Locates the SPS info HOB and updates it with the HECI readiness
 * indication.
 *
 * @param[in] PeiServices   Pointer to PEI services table
 * @param[in] NotifyDesc    Pointer to notify descriptor
 * @param[in] Ppi           Pointer to the HECI PPI
 * @retval EFI_SUCCESS      HOB updated
 * @retval EFI_UNSUPPORTED  SPS info HOB not found or not flagged ready
 */
EFI_STATUS
EFIAPI
PpiNotifyHeciReady (
  IN EFI_PEI_SERVICES           **PeiServices,
  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDesc,
  IN VOID                       *Ppi
  )
{
  SPS_INFO_HOB  *SpsInfoHob;

  //
  // Locate existing SPS info HOB
  //
  SpsInfoHob = (SPS_INFO_HOB *)HobGetGuid (&gSpsInfoHobGuid);
  if (SpsInfoHob == NULL || (SpsInfoHob->Flags & 1) == 0) {
    return EFI_UNSUPPORTED;
  }

  //
  // Store notify descriptor and PPI pointer in the HOB at known offsets
  //   Offset +35: low byte of NotifyDesc
  //   Offset +36: low byte of Ppi
  //
  *(volatile UINT8 *)((UINTN)SpsInfoHob + 35) = (UINT8)(UINTN)NotifyDesc;
  *(volatile UINT8 *)((UINTN)SpsInfoHob + 36) = (UINT8)(UINTN)Ppi;

  return EFI_SUCCESS;
}

// ---------------------------------------------------------------------------
// Pre-DID Reset
// ---------------------------------------------------------------------------

/**
 * Execute the Pre-DID (Device ID) reset sequence.
 *
 * Sends a pre-DID reset message to ME, waits for reset counter change,
 * then waits for ME to return to Normal or Recovery state.
 *
 * @retval EFI_SUCCESS           Pre-DID reset successful
 * @retval EFI_TIMEOUT           Timed out waiting for ME
 * @retval EFI_DEVICE_ERROR      HECI PPI not available
 * @retval EFI_PROTOCOL_ERROR    Pre-DID reset not accepted by ME
 */
EFI_STATUS
ExecutePreDidReset (
  VOID
  )
{
  HECI_PROTOCOL  *HeciPpi;
  UINT32          MeFs1Pre;
  UINT32          Timeout;
  UINT32          MkhiMsgBuf[3];
  UINT32          ResponseSize;
  UINT8           ResetAck;
  EFI_STATUS      Status;

  Timeout = TIMEOUT_5000_MS;

  DEBUG ((EFI_D_WARN, "[SPS] WARNING: Execute ME pre-DID reset\n"));

  //
  // Locate HECI PPI
  //
  Status = PeiServicesLocatePpi (&gHeci1PpiGuid, (VOID **)&HeciPpi);
  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "[SPS] ERROR: Cannot locate HECI PPI (%r)\n", Status));
    ASSERT_EFI_ERROR (Status);
    return EFI_NOT_STARTED;
  }

  //
  // Capture pre-reset ME state
  //
  MeFs1Pre = *(volatile UINT32 *)(GetMeFwHob (0) + 64);

  //
  // Build and send Pre-DID reset MKHI message
  //
  MkhiMsgBuf[0] = HECI_MSG_PRE_DID_RESET;
  MkhiMsgBuf[1] = 0;
  MkhiMsgBuf[2] = 0;
  ResponseSize  = HECI_MSG_PRE_DID_RESET_LENGTH;

  Status = HeciPpi->SendMessage (
                      0, MkhiMsgBuf, HECI_MSG_PRE_DID_RESET_LENGTH,
                      &ResponseSize, 0, 7
                      );

  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "[SPS] Pre-DID reset, no ACK. Continue without reset (%r)\n", Status));
    return EFI_SUCCESS;
  }

  //
  // Check reset response
  //
  if ((MkhiMsgBuf[0] & 0x7F00) != 0 ||
      (UINT8)MkhiMsgBuf[0] != 5 ||
      (MkhiMsgBuf[0] & 0x8000) == 0 ||
      (UINT8)MkhiMsgBuf[1] != 0) {
    DEBUG ((EFI_D_ERROR,
      "[SPS] Pre-DID reset is not accepted by ME. Continue without reset (%r)\n"));
    return Status;
  }

  //
  // Wait for reset counter to change
  //
  Status = WaitForMeResetCounterChange (
             (MeFs1Pre >> 20) & 0xF,
             &Timeout
             );

  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "[SPS] ERROR: Pre-DID reset, ME Reset Counter not changed (%r)\n", Status));
    return Status;
  }

  //
  // Wait for ME to return to Normal or Recovery state
  //
  Status = WaitForMeNormalOrRecovery (&Timeout);
  if (EFI_ERROR (Status)) {
    return EFI_TIMEOUT;
  }

  DEBUG ((EFI_D_INFO, "[SPS] Pre-DID reset has been executed successfully\n"));
  return EFI_SUCCESS;
}

// ---------------------------------------------------------------------------
// ICC (Integrated Clock Control)
// ---------------------------------------------------------------------------

/**
 * Set/Get current clocking mode via HECI ICC command.
 *
 * @param[in,out] Buffer  ICC message buffer (48 bytes)
 * @retval EFI_SUCCESS           Clock settings applied
 * @retval EFI_UNSUPPORTED       Not SPS firmware
 * @retval EFI_NOT_STARTED       HECI protocol unavailable
 * @retval EFI_PROTOCOL_ERROR    Invalid response from ME
 */
EFI_STATUS
IccSetGetCurrentClockingMode (
  IN OUT ICC_MESSAGE_BUFFER  *Buffer OPTIONAL
  )
{
  HECI_PROTOCOL     *HeciPpi;
  UINT32             ResponseSize;
  EFI_STATUS         Status;

  //
  // ICC header: signature 0x40000, version, response fields
  //
  ICC_MESSAGE_BUFFER LocalBuf;

  DEBUG ((EFI_D_INFO, "[ICC] SpsSetGetCurrenClockingMode\n"));

  Status = EFI_UNSUPPORTED;

  if (IsSpsFw () != 1 || IsSpsNormalModeS3 ()) {
    return EFI_UNSUPPORTED;
  }

  if (Buffer == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // Locate HECI PPI and send ICC command
  //
  Status = PeiServicesLocatePpi (&gHeci1PpiGuid, (VOID **)&HeciPpi);
  if (EFI_ERROR (Status)) {
    return EFI_NOT_STARTED;
  }

  ResponseSize = sizeof (ICC_MESSAGE_BUFFER);

  Buffer->Header.Signature      = ICC_HEADER_SIGNATURE;
  Buffer->Header.Command        = ICC_HEADER_COMMAND_SET_CURRENT;
  Buffer->Header.Reserved       = 0;
  Buffer->Header.Response       = ICC_HEADER_RESPONSE_SUCCESS;
  Buffer->Header.Reserved2      = 0;
  Buffer->Header.Version        = 1;

  Status = HeciPpi->SendMessage (
                     0, Buffer, sizeof (ICC_MESSAGE_BUFFER),
                     &ResponseSize, 0, 8
                     );

  if (!EFI_ERROR (Status)) {
    if (Buffer->Header.Command != ICC_HEADER_COMMAND_SET_CURRENT ||
        Buffer->Header.Response != 0) {
      DEBUG ((EFI_D_ERROR,
        "(ICC) SpsSetGetCurrenClockingMode: Wrong response! "
        "IccHeader.IccResponse = 0x%x\n",
        Buffer->Header.Response));
      Status = EFI_PROTOCOL_ERROR;
    }
  }

  DEBUG ((EFI_D_INFO, "[ICC] SpsSetGetCurrenClockingMode exit status = %r \n", Status));
  return Status;
}

/**
 * Set SSC (Spread Spectrum Clocking) alternate mode via HECI.
 *
 * @param[in] SscAlternate  TRUE to enable SSC alternate
 * @return    Status from IccSetGetCurrentClockingMode
 */
EFI_STATUS
PeiHeciSetSscAlternate (
  IN BOOLEAN  SscAlternate
  )
{
  ICC_MESSAGE_BUFFER  Buffer;

  DEBUG ((EFI_D_INFO, "[ME] PeiHeciSetSSCAlternate(%d)\n", SscAlternate));

  ZeroMem (&Buffer, sizeof (Buffer));
  Buffer.Data[43] = (UINT8)SscAlternate;

  DEBUG ((EFI_D_INFO, "[ME] PeiHeciSetSSCAlternate sets SSC settings to %d\n", SscAlternate));

  return IccSetGetCurrentClockingMode (&Buffer);
}

// ---------------------------------------------------------------------------
// ME Entry Point
// ---------------------------------------------------------------------------

/**
 * Main entry point for SpsPei.
 *
 * Detects ME type, reads boot mode, performs pre-DID reset if needed,
 * then branches to S3 or non-S3 path.
 *
 * @param[in] ImageHandle  PEI image handle
 * @param[in] SystemTable  PEI system table
 * @retval EFI_SUCCESS     Module initialized successfully
 * @retval EFI_UNSUPPORTED Non-SPS firmware detected
 */
EFI_STATUS
EFIAPI
SpsPeiEntryPoint (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  EFI_STATUS           Status;
  UINT32               BootMode;
  SPS_POLICY_PPI       *SpsPolicy;
  UINT32               MeState;
  UINT32               MeFs1;

  DEBUG ((EFI_D_INFO, "[SPS] SpsPeiEntryPoint called.\n"));

  //
  // Step 1: Verify ME firmware is SPS
  //
  if (IsSpsFw () != 1) {
    DEBUG ((EFI_D_INFO, "[SPS] Other ME FW detected.\n"));
    goto NonSpsFwError;
  }

  //
  // Step 2: Read boot mode
  //
  BootMode = 4;
  Status = SystemTable->BootServices->GetBootMode (&BootMode);
  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "[SPS] ERROR: Cannot read boot mode (%r)\n"));
    BootMode = 4;
  }

  //
  // Step 3: Check pre-DID reset policy
  //
  SpsPolicy = (SPS_POLICY_PPI *)GetSpsPolicyPpi ();
  DEBUG ((EFI_D_INFO, "[SPS] Pre-DID reset "));

  if (BootMode != BOOT_MODE_S3_RESUME &&
      SpsPolicy != NULL &&
      (SpsPolicy->Flags & 1) != 0) {
    //
    // Pre-DID reset is enabled for this boot
    //
    DEBUG ((EFI_D_INFO, " execution\n"));

    if (EFI_ERROR (ExecutePreDidReset ())) {
      goto NonSpsFwError;
    }

    MeState = *(volatile UINT32 *)(GetMeFwHob (0) + 64) & MEFS1_ME_STATE_MASK;
    MeFs1   = *(volatile UINT32 *)(GetMeFwHob (0) + 72) & 0x700;

    if (MeState == 2 && MeFs1 == 0x400) {
      //
      // ME in recovery mode: re-initialize
      //
      DEBUG ((EFI_D_WARN,
        "[SPS] WARNING: ME is in recovery mode (cause: %d)\n",
        *(volatile UINT32 *)(GetMeFwHob (0) + 64)));

      Status = WaitForMeFwInitComplete (NULL);

      if (EFI_ERROR (Status)) {
        if (Status == EFI_TIMEOUT) {
          DEBUG ((EFI_D_ERROR,
            "[SPS] ERROR: Pre-DID reset timeout failure causes ME non-functional flow\n"));
          goto NonSpsFwError;
        }
        DEBUG ((EFI_D_ERROR,
          "[SPS] ERROR: Pre-DID reset failure. Continue according to ME state\n"));
      } else if ((MeState & MEFS1_ME_STATE_MASK) == MEFS1_ME_STATE_NORMAL) {
        DEBUG ((EFI_D_INFO,
          "[SPS] Pre-DID reset finished successfully, ME in Normal state\n"));
      }
    }
  } else {
    DEBUG ((EFI_D_INFO, " is disabled\n"));
  }

  //
  // Step 4: Branch to S3 or non-S3 path
  //
  if (BootMode == BOOT_MODE_S3_RESUME) {
    //
    // S3 resume path
    //
    DEBUG ((EFI_D_INFO, "[SPS] S3 resume path\n"));

    Status = PeiServicesLocatePpi (
               &gHeci1PpiGuid,
               &mS3NotifyDesc
               );

  } else {
    //
    // Non-S3 boot path
    //
    DEBUG ((EFI_D_INFO, "[SPS] Non S3 boot path\n"));

    Status = PeiServicesLocatePpi (
               &gHeci1PpiGuid,
               &mNonS3NotifyDesc
               );
  }

  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "[SPS] ERROR: Cannot register PPI notify handler (%r)\n"));
  }

  return EFI_SUCCESS;

NonSpsFwError:
  //
  // Non-SPS firmware detected: publish minimal HOBs and return error
  //
  FinalizeSpsInit (0, 0, 0, 0, 0);
  DEBUG ((EFI_D_ERROR,
    "[SPS] ERROR: Non SPS firmware running in ME\n"
    "             (MEFS1: 0x%08X, MEFS2: 0x%08X)\n",
    *(volatile UINT32 *)(GetMeFwHob (0) + 64),
    *(volatile UINT32 *)(GetMeFwHob (0) + 72)));

  return EFI_UNSUPPORTED;
}

// ---------------------------------------------------------------------------
// Module Entry Point (PEI)
// ---------------------------------------------------------------------------

/**
 * Standard UEFI PEIM entry point.
 *
 * Calls through to SpsPeiEntryPoint but performs a one-time initialization
 * guard: checks if this is the first invocation by testing a global flag,
 * setting the watchdog timer, and then delegating.
 *
 * @param[in] ImageHandle  PEI image handle
 * @param[in] SystemTable  PEI system table
 * @retval Status          Return value from SpsPeiEntryPoint
 */
EFI_STATUS
EFIAPI
ModuleEntryPoint (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  //
  // One-time initialization guard (0xFDA362C + 1024068 = 0xFDA362C + 0xFA000)
  // Check whether bit 7 of the marker byte is set.
  //
  if (*(CHAR8 *)(GetBootMode () + 1024068) >= 0) {
    //
    // First call: set watchdog timer (1280ms)
    //
    SetWatchdogTimer ();
    //
    // Mark as initialized
    //
    *(_BYTE *)(GetBootMode () + 1024068) |= 0x80;
  }

  return SpsPeiEntryPoint (ImageHandle, SystemTable);
}

/**
 * Get the current boot mode from PCD.
 *
 * @return  Boot mode value (BOOT_MODE_S3_RESUME = 0x11, etc.)
 */
UINT32
GetBootMode (
  VOID
  )
{
  return PcdGet32 (PCD_TOKEN_BOOT_MODE);
}

/**
 * Set the watchdog timer count (1280 ticks = approx 357us @ 3.579545 MHz?).
 *
 * Reads current boot mode PCD and writes 1280 to the associated I/O register.
 */
VOID
SetWatchdogTimer (
  VOID
  )
{
  IoWrite16 ((UINT16 *)(GetBootMode () + 1024064), 1280);
}

/**
 * HECI PPI wrapper: returns the HECI protocol PPI.
 */
HECI_PROTOCOL *
GetHeciPpi (
  VOID  *This
  )
{
  EFI_STATUS      Status;
  HECI_PROTOCOL   *HeciPpi = This;

  Status = PeiServicesLocatePpi (&gHeci1PpiGuid, (VOID **)&HeciPpi);
  if (EFI_ERROR (Status)) {
    HeciPpi = NULL;
    DEBUG ((EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status));
    ASSERT_EFI_ERROR (Status);
  }

  return HeciPpi;
}

/**
 * Get SPS Policy PPI.
 */
VOID *
GetSpsPolicyPpi (
  VOID  *This
  )
{
  VOID  *PolicyPpi = This;

  if (EFI_ERROR (PeiServicesLocatePpi (&gSpsPolicyPpiGuid, &PolicyPpi))) {
    PolicyPpi = NULL;
    DEBUG ((EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", Status));
    ASSERT_EFI_ERROR (Status);
  }

  return PolicyPpi;
}

// ---------------------------------------------------------------------------
// PPI Notify Descriptors (in .data section)
// ---------------------------------------------------------------------------

//
// EFI_PEI_NOTIFY_DESCRIPTOR at 0xFFDA68B0 (for S3 path)
//   Notify = SpsS3Path
//
EFI_PEI_NOTIFY_DESCRIPTOR mS3NotifyDesc = {
  EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
  &gHeci1PpiGuid,
  SpsS3Path
};

//
// EFI_PEI_NOTIFY_DESCRIPTOR at 0xFFDA68BC (for Non-S3 path)
//   Notify = PpiNotifyHeciReady
//
EFI_PEI_NOTIFY_DESCRIPTOR mNonS3NotifyDesc = {
  EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
  &gHeci1PpiGuid,
  PpiNotifyHeciReady
};