Newer
Older
AMI-Aptio-BIOS-Reversed / IioInit / IioInit.c
@Ajax Dong Ajax Dong 2 days ago 31 KB Init
/** @file
  IioInit.c -- Integrated IO (IIO) Initialization DXE driver

  This DXE driver initializes the IIO (Integrated IO) subsystem on the Purley
  platform. It performs PCIe link initialization, IIO stack setup, IO fabric
  configuration, S3 boot script management, IOAT initialization, and late
  platform security (TXT) setup. It also manages ReadyToBoot and
  ExitBootServices events for the IIO hardware.

  Source tree path: PurleySktPkg/Dxe/IioInit/IioInit.c
  Build path: Build/HR6N0XMLK/DEBUG_VS2015/X64/PurleySktPkg/Dxe/IioInit/IioInit/DEBUG/AutoGen.c
  MD5: 123a999d39d274b161482592b152ec76
  SHA256: 27b9ba6c6a83f26893d071ec93d110c9490fe7b06ea0eaa86e2040d5abfb6086

  Copyright (C) 2025 Intel Corporation
  SPDX-License-Identifier: Intel
**/

#include "IioInit.h"

//
// Global EFI protocol pointers
//
EFI_HANDLE            ImageHandle     = NULL;
EFI_SYSTEM_TABLE      *SystemTable    = NULL;
EFI_BOOT_SERVICES     *BootServices   = NULL;
EFI_RUNTIME_SERVICES  *RuntimeServices = NULL;
VOID                  *mPciUsra       = NULL;
VOID                  *gDS            = NULL;
VOID                  *mPcd           = NULL;

//
// Global IIO data
//
UINT8   byte_DD59  = 0;          // S3 boot script flag
UINT64  qword_DD20 = 0;          // PCD token for PcdIioRevision
UINT64  qword_DE18 = 0;          // PCD token for PcdIioPostInitDone
UINT64  qword_DE20 = 0;          // Boot script label pointer
UINT64  qword_DE28 = 0;          // Boot script label entry
UINT32  dword_DCA8 = 0;          // MCFG table

//
// Access width/stride table: byte pairs of (element_size, stride_size) for
// access widths 0..3, plus two more entries at +16 for the receive stride.
//
UINT8   byte_A7C0[32] = { 0 };

//
// GUID definitions for IIO protocols
//
EFI_GUID gIioStackProtocolGuid  = { 0x0 };  // unk_AA70 - IIO Stack Protocol
EFI_GUID gMmPciBaseProtocolGuid = { 0x0 };  // unk_AAB0 - MM PCIe Base Protocol
EFI_GUID gPcdProtocolGuid       = { 0x0 };  // unk_AAE0 - PCD Protocol

//
// Forward declarations of static helper functions
//
STATIC
VOID
IioInitAssert (
  IN UINT64   ErrorLevel,
  IN CHAR8    *Message,
  ...
  );

STATIC
EFI_STATUS
IioInitGetMmPciBaseProtocol (
  VOID
  );

STATIC
EFI_STATUS
IioInitGetStackProtocol (
  OUT IIO_STACK_PROTOCOL  **StackProtocol
  );

STATIC
IIO_SOCKET_DATA*
IioInitGetSocketData (
  OUT IIO_STACK_PROTOCOL  **StackProtocol  OPTIONAL
  );

//
// ---------------------------------------------------------------------------
// Low-level utility functions (from BaseLib / IoLib)
// ---------------------------------------------------------------------------

/**
  Generates a breakpoint trap (INT 3).
**/
VOID
EFIAPI
IioInitBreakpoint (
  VOID
  )
{
  __debugbreak ();
}

/**
  No-op wait loop (PAUSE / HLT hint).
**/
VOID
EFIAPI
IioInitHalt (
  VOID
  )
{
  __halt ();
}

/**
  Call stack back trace (TRAP).

  Generates a stack backtrace via debug register.
**/
VOID
EFIAPI
IioInitStackTrace (
  VOID
  )
{
  // Implementation: stack capture primitive
}

/**
  Enable interrupts (STI).
**/
VOID
EFIAPI
IioInitEnableInterrupts (
  VOID
  )
{
  __enable_interrupts ();
}

/**
  Disable interrupts (CLI).
**/
VOID
EFIAPI
IioInitDisableInterrupts (
  VOID
  )
{
  __disable_interrupts ();
}

/**
  Read the RFLAGS register.
**/
UINT16
EFIAPI
IioInitReadEflags (
  VOID
  )
{
  return __readeflags ();
}

/**
  Zero-fill a memory buffer.

  @param[in] Buffer  Pointer to buffer to zero.
  @param[in] Length  Number of bytes to zero.
**/
VOID *
EFIAPI
IioInitZeroMem (
  IN VOID   *Buffer,
  IN UINTN  Length
  )
{
  return memset (Buffer, 0, Length);
}

/**
  Copy a memory buffer.

  @param[in] Destination  Pointer to destination buffer.
  @param[in] Source       Pointer to source buffer.
  @param[in] Length       Number of bytes to copy.
**/
VOID *
EFIAPI
IioInitCopyMem (
  IN VOID       *Destination,
  IN CONST VOID *Source,
  IN UINTN      Length
  )
{
  return memcpy (Destination, Source, Length);
}

//
// ---------------------------------------------------------------------------
// ASSERT / Debug helper
// ---------------------------------------------------------------------------

/**
  Conditional assertion failure handler.

  Logs a debug message to the UEFI console and triggers a breakpoint.

  @param[in] ErrorLevel  Debug error level.
  @param[in] Message     Format string.
  @param[in] ...         Variable arguments.
**/
STATIC
VOID
EFIAPI
IioInitDebugAssert (
  IN UINT64  ErrorLevel,
  IN CHAR8   *Message,
  ...
  )
{
  VA_LIST  Args;

  VA_START (Args, Message);
  DebugPrint (ErrorLevel, Message, Args);
  VA_END (Args);

  if ((ErrorLevel & DEBUG_ERROR) != 0) {
    __debugbreak ();
  }
}

/**
  Dead-loop assertion handler.

  Prints the assertion expression and source location, then enters an
  infinite breakpoint loop.

  @param[in] FileName     Source file name.
  @param[in] LineNumber   Source line number.
  @param[in] Description  Assertion expression.
**/
STATIC
VOID
EFIAPI
IioInitAssertDeadLoop (
  IN CHAR8  *FileName,
  IN UINTN  LineNumber,
  IN CHAR8  *Description
  )
{
  DebugPrint (DEBUG_ERROR,
    "ASSERT [%s(%d)]: %s\n",
    FileName, LineNumber, Description);
  while (TRUE) {
    __debugbreak ();
  }
}

//
// ---------------------------------------------------------------------------
// IIO initialization core (entry logic)
// ---------------------------------------------------------------------------

/**
  IIO Driver initialization routine.

  Initializes global protocol pointers, locates the IIO Stack Protocol and
  MM PCIe Base Protocol, sets up the IO fabric, configures PCIe hot-plug
  and IOAT, and registers ReadyToBoot and ExitBootServices callbacks.

  @param[in] ImageHandle  Handle for this image.
  @param[in] SystemTable  Pointer to EFI system table.

  @return EFI_SUCCESS           Initialization successful.
  @return EFI_UNSUPPORTED       Platform not supported.
  @return EFI_NOT_FOUND         Required protocol not found.
**/
STATIC
EFI_STATUS
EFIAPI
IioInitCore (
  IN EFI_HANDLE        ImageHandleParam,
  IN EFI_SYSTEM_TABLE  *SystemTableParam
  )
{
  EFI_STATUS           Status;
  UINT16               Flags;
  BOOLEAN              InterruptsEnabled;
  UINT32               Timestamp;
  UINT64               PcdInterface;
  UINT8                *IioRevision;
  IIO_STACK_PROTOCOL   *StackProtocol;

  //
  // Save image handle and system table globally
  //
  ImageHandle = ImageHandleParam;
  ASSERT (ImageHandle != NULL);
  SystemTable = (EFI_SYSTEM_TABLE *)SystemTableParam;
  ASSERT (SystemTable != NULL);

  //
  // Get boot services and runtime services tables
  //
  BootServices = SystemTable->BootServices;
  ASSERT (BootServices != NULL);
  RuntimeServices = SystemTable->RuntimeServices;
  ASSERT (RuntimeServices != NULL);

  //
  // Locate the DxeServicesTable (gDS)
  //
  Status = gBS->LocateProtocol (&gDxeServicesTableGuid,
                  NULL, (VOID **)&gDS);
  if (EFI_ERROR (Status)) {
    ASSERT_EFI_ERROR (Status);
  }
  ASSERT (gDS != NULL);

  //
  // AutoGen initialization
  //
  if (EFI_ERROR (Status)) {
    ASSERT_EFI_ERROR (Status);
  }

  //
  // Locate the MM PCIe Base protocol
  //
  if (mPciUsra == NULL) {
    Status = gBS->LocateProtocol (&gMmPciBaseProtocolGuid,
                    NULL, &mPciUsra);
    if (EFI_ERROR (Status)) {
      ASSERT_EFI_ERROR (Status);
    }
    ASSERT (mPciUsra != NULL);
  }

  //
  // Platform-specific early init
  //
  IioPlatformEarlyInit ();

  //
  // Get PCD interface and read IIO revision token
  //
  PcdInterface = (UINT64)GetPcdProtocol ();
  qword_DD20 = ((PCD_PROTOCOL *)PcdInterface)->Get64 (PcdIioRevision);

  //
  // Check IIO revision and optionally fix up IioRevision
  //
  IioRevision = (UINT8 *)PcdGetPtr (PcdIioRevision);
  if ((INT8)*IioRevision >= 0) {
    IioRevision = PcdGetPtr (PcdIioRevision);
    ZeroMem (IioRevision, 1280);
    IioRevision = PcdGetPtr (PcdIioRevision);
    *IioRevision |= 0x80;
  }

  //
  // Save interrupt state then call initialization routines
  //
  Flags = SaveAndDisableInterrupts ();
  DisableInterrupts ();
  InterruptsEnabled = (Flags & 0x200) != 0;

  Timestamp = IoRead32 (PCH_LPC_DEFAULT_BASE + R_PCH_LPC_RTC_INDEX) & 0x00FFFFFF;
  ReadTimestamp ();

  //
  // Wait loop for timestamp to advance (small delay)
  //
  while (((Timestamp + 357 - (UINT32)ReadTimestamp ()) & 0x800000) == 0) {
    CpuPause ();
  }

  ReadTimestamp ();

  //
  // Restore interrupt state
  //
  if (InterruptsEnabled) {
    EnableInterrupts ();
  }

  //
  // Register protocols / call main IIO initialization chain
  //
  Status = IioInitEntry ();
  if (EFI_ERROR (Status)) {
    ASSERT_EFI_ERROR (Status);
  }

  //
  // Signal that IIO post-init is done
  //
  PcdInterface = (UINT64)GetPcdProtocol ();
  qword_DE18 = ((PCD_PROTOCOL *)PcdInterface)->Get64 (PcdIioPostInitDone);

  return EFI_SUCCESS;
}

//
// ---------------------------------------------------------------------------
// IIO Stack access helpers
// ---------------------------------------------------------------------------

/**
  Locate the IIO Stack Protocol.

  @param[out] StackProtocol  Returns the IIO stack protocol instance.

  @return EFI_SUCCESS  Protocol located.
**/
STATIC
EFI_STATUS
EFIAPI
IioInitGetStackProtocol (
  OUT IIO_STACK_PROTOCOL **StackProtocol
  )
{
  EFI_STATUS  Status;

  *StackProtocol = NULL;

  Status = gBS->LocateProtocol (&gIioStackProtocolGuid,
                  NULL, (VOID **)StackProtocol);
  if (EFI_ERROR (Status)) {
    ASSERT_EFI_ERROR (Status);
  }

  return Status;
}

/**
  Get the IIO socket data block and optionally the stack protocol.

  @param[out] StackProtocol  Optional pointer to receive the stack protocol.

  @return Pointer to the IIO socket data structure.
**/
STATIC
IIO_SOCKET_DATA*
EFIAPI
IioInitGetSocketData (
  OUT IIO_STACK_PROTOCOL **StackProtocol OPTIONAL
  )
{
  EFI_STATUS         Status;
  IIO_STACK_PROTOCOL *Protocol;
  IIO_SOCKET_DATA    *SocketData;

  Status = IioInitGetStackProtocol (&Protocol);
  if (EFI_ERROR (Status)) {
    return NULL;
  }

  SocketData = (IIO_SOCKET_DATA *)Protocol;

  if (StackProtocol != NULL) {
    *StackProtocol = Protocol;
  }

  return SocketData;
}

//
// ---------------------------------------------------------------------------
// PCD Protocol helper
// ---------------------------------------------------------------------------

/**
  Locate and cache the PCD Protocol.

  @return Pointer to the PCD protocol interface.
**/
STATIC
PCD_PROTOCOL*
EFIAPI
IioInitGetPcdProtocol (
  VOID
  )
{
  EFI_STATUS  Status;

  if (mPcd == NULL) {
    Status = gBS->LocateProtocol (&gPcdProtocolGuid,
                    NULL, &mPcd);
    if (EFI_ERROR (Status)) {
      ASSERT_EFI_ERROR (Status);
    }
    ASSERT (mPcd != NULL);
  }

  return (PCD_PROTOCOL *)mPcd;
}

//
// ---------------------------------------------------------------------------
// Boot script S3 support
// ---------------------------------------------------------------------------

/**
  Save S3 boot script label entries.

  Manages a circular buffer of boot script label entries for S3 resume.

  @return 0 on success.
**/
UINTN
EFIAPI
IioInitS3BootScriptLabel (
  VOID
  )
{
  if (qword_DE20 != qword_DE28) {
    S3BootScriptLabel (0, 0);
    if (*(UINT64 *)qword_DE28 == 0) {
      CopyMem ((VOID *)qword_DE28, (VOID *)qword_DE20, 32);
      *(UINT8 *)(qword_DE28 + 14) = 1;
    }
    qword_DE20 = qword_DE28;
  }

  return 0;
}

/**
  Write S3 boot script entries for PCIe configuration.

  Writes a PCIe register into the boot script table for S3 restore.

  @return EFI_SUCCESS on success.
**/
EFI_STATUS
EFIAPI
IioInitS3BootScriptPciCfg (
  VOID
  )
{
  IIO_SOCKET_DATA *SocketData;
  UINT32          DataSize;
  EFI_STATUS      Status;

  SocketData = IioInitGetSocketData (NULL);
  if (SocketData == NULL) {
    return EFI_UNSUPPORTED;
  }

  if (!*(UINT8 *)((UINT8 *)SocketData + 15)) {
    *(UINT32 *)((UINT8 *)SocketData + 16) = *(UINT32 *)((UINT8 *)SocketData + 8) + 3;

    Status = S3BootScriptSavePciCfg (S3BootScriptWidthUint32,
               (UINT64)SocketData, 0);
    if (EFI_ERROR (Status)) {
      ASSERT_EFI_ERROR (Status);
    }

    Status = S3BootScriptLabel (S3BootScriptWidthUint32,
               *(UINT64 *)SocketData,
               *(UINT32 *)((UINT8 *)SocketData + 16));
    if (EFI_ERROR (Status)) {
      ASSERT_EFI_ERROR (Status);
    }

    *(UINT8 *)((UINT8 *)SocketData + 15) = 1;
    S3BootScriptDone ();
  }

  return 0;
}

//
// ---------------------------------------------------------------------------
// IOAT / VT-d initialization
// ---------------------------------------------------------------------------

/**
  Initialize IOAT (I/O Acceleration Technology) for all IIO sockets.

  Checks the socket state and enables IOAT features based on platform
  configuration.

  @return EFI_SUCCESS on success.
**/
EFI_STATUS
EFIAPI
IioInitIoatInit (
  VOID
  )
{
  EFI_STATUS         Status;
  IIO_STACK_PROTOCOL *StackProtocol;
  IIO_SOCKET_DATA    *SocketData;

  StackProtocol = NULL;
  Status = IioInitGetStackProtocol (&StackProtocol);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  if (!byte_DD59) {
    SocketData = (IIO_SOCKET_DATA *)StackProtocol;
    if (*(UINT8 *)((UINT8 *)SocketData + 4855)) {
      IioIoatInit ();
      byte_DD59 = TRUE;
    }
  }

  return EFI_SUCCESS;
}

//
// ---------------------------------------------------------------------------
// PCIe port configuration
// ---------------------------------------------------------------------------

/**
  Enable/disable PCIe hot-plug and link configuration for active IIO ports.

  Iterates over all 4 IIO sockets and configures the active PCIe ports,
  setting up hot-plug support and link training parameters.

  @return EFI_SUCCESS on success.
**/
EFI_STATUS
EFIAPI
IioInitPciePortConfig (
  VOID
  )
{
  EFI_STATUS         Status;
  IIO_STACK_PROTOCOL *StackProtocol;
  IIO_SOCKET_DATA    *SocketData;
  UINT8              SocketIndex;
  UINT8              PortIndex;
  UINT16             HotPlugReg;
  UINT16             LinkStatusReg;
  UINT16             LinkCtrl2Reg;
  UINT16             NewHotPlugReg;
  UINT16             NewLinkStatusReg;

  Status = IioInitGetStackProtocol (&StackProtocol);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  SocketData = (IIO_SOCKET_DATA *)StackProtocol;

  for (SocketIndex = 0; SocketIndex < 4; SocketIndex++) {
    if (*(UINT8 *)((UINT8 *)&SocketData->SocketIndexArray[SocketIndex])) {
      //
      // Read current hot-plug and link status registers
      //
      HotPlugReg = StackProtocol->Read (SocketIndex, 0, PCIE_HP_REG);
      LinkStatusReg = StackProtocol->Read (SocketIndex, 0, PCIE_LINK_STATUS_REG);

      if (SocketData->PlatformLateInit && !SocketData->S3DataActive) {
        //
        // Enable hot-plug detect on this port
        //
        NewHotPlugReg = HotPlugReg | 1;

        for (PortIndex = 0; PortIndex < 6; PortIndex++) {
          if ((1 << PortIndex) & SocketData->PortActive[SocketIndex]) {
            //
            // Enable slot capability
            //
            StackProtocol->Write (SocketIndex, PortIndex, PCIE_SLOT_CAP_REG,
              StackProtocol->Read (SocketIndex, PortIndex, PCIE_SLOT_CAP_REG) | 1);
          }
        }
      }

      //
      // Write back link control registers
      //
      NewLinkStatusReg = LinkStatusReg;
      IioPcieWriteConfig (2, (UINT64)StackProtocol->Read (SocketIndex, 0, PCIE_LINK_STATUS_REG),
        NULL, &NewLinkStatusReg);
      IioPcieWriteConfig (2, (UINT64)StackProtocol->Read (SocketIndex, 0, PCIE_HP_REG),
        NULL, &NewHotPlugReg);
    }
  }

  return EFI_SUCCESS;
}

/**
  ExitBootServices notification callback.

  Called when the OS loader is about to take control. Performs late secure
  platform actions (TXT) and disables IIO stacks.

  @return EFI_SUCCESS on success.
**/
EFI_STATUS
EFIAPI
IioInitExitBootServices (
  VOID
  )
{
  EFI_STATUS         Status;
  IIO_STACK_PROTOCOL *StackProtocol;
  IIO_SOCKET_DATA    *SocketData;
  UINT8              SocketIndex;

  Status = IioInitGetStackProtocol (&StackProtocol);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  DEBUG ((DEBUG_INFO, "\nOnExitBootServices..\n"));

  SocketData = (IIO_SOCKET_DATA *)StackProtocol;

  if (SocketData->PlatformLateInit) {
    if (!SocketData->S3DataActive) {
      DEBUG ((DEBUG_INFO, "IioInit Late Secure the Platform (TXT)..\n"));

      for (SocketIndex = 0; SocketIndex < 4; SocketIndex++) {
        if (SocketData->SocketIndexArray[SocketIndex]) {
          LinkStatusReg = StackProtocol->Read (SocketIndex, 0, PCIE_LINK_STATUS_REG);
          StackProtocol->Write (SocketIndex, 0, PCIE_LINK_STATUS_REG,
            LinkStatusReg | 1);
        }
      }
    }
  }

  return EFI_SUCCESS;
}

/**
  Check if VGA is present on a given IIO socket and port.

  @param[in]  SocketIndex  IIO socket index.
  @param[out] VendorId     Buffer for 16-bit vendor ID.
  @param[out] DeviceId     Buffer for 16-bit device ID.
  @param[out] RevisionId   Buffer for 8-bit revision ID.
  @param[out] IsVga        Boolean indicating if a VGA device was found.

  @return EFI_SUCCESS  Port state determined.
**/
EFI_STATUS
EFIAPI
IioInitCheckVgaPresent (
  IN  UINT8    SocketIndex,
  OUT UINT16   *VendorId,
  OUT BOOLEAN  *IsVga,
  OUT UINT8    *RevisionInfo
  )
{
  EFI_STATUS         Status;
  IIO_STACK_PROTOCOL *StackProtocol;
  IIO_SOCKET_DATA    *SocketData;
  UINT8              StackId;
  UINT16             VendorReg;
  UINT16             ClassReg;
  UINT16             SubClassReg;

  Status = IioInitGetStackProtocol (&StackProtocol);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  SocketData = (IIO_SOCKET_DATA *)StackProtocol;

  IioPcieGetStackInfo (SocketData, SocketIndex, &StackId, VendorId,
    (UINT8 *)VendorId + 2, (UINT8 *)VendorId + 3);

  if (SocketIndex == (UINT8)-1 && StackId == 0xFF) {
    return EFI_NOT_FOUND;
  }

  if (StackId >= 0x15) {
    return EFI_INVALID_PARAMETER;
  }

  *VendorId = StackProtocol->Read (SocketIndex, StackId, PCIE_VENDOR_ID_REG);
  VendorId[1] = StackProtocol->Read (SocketIndex, StackId, PCIE_DEVICE_ID_REG);
  *RevisionInfo = (UINT8)(StackProtocol->Read (SocketIndex, StackId, PCIE_REVISION_REG) >> 8);

  //
  // Extract sub-class from class code register
  //
  ClassReg = StackProtocol->Read (SocketIndex, StackId, PCIE_CLASS_REG);
  SubClassReg = StackProtocol->Read (SocketIndex, StackId, PCIE_SUBCLASS_REG);

  *IsVga = ((ClassReg & 0xFF) == PCI_CLASS_DISPLAY &&
            (SubClassReg & 0xFF) == PCI_SUBCLASS_VGA);

  return EFI_SUCCESS;
}

/**
  ReadyToBoot notification callback.

  Called before invoking the boot option. Programs IOAPIC, initializes IOAT
  engines, and performs NTB late initialization for all active IIO sockets.

  @param[in] Event   The ReadyToBoot event.
  @param[in] Context Not used.

  @return EFI_SUCCESS on success.
**/
EFI_STATUS
EFIAPI
IioInitReadyToBoot (
  IN EFI_EVENT  Event,
  IN VOID       *Context
  )
{
  EFI_STATUS         Status;
  IIO_STACK_PROTOCOL *StackProtocol;
  IIO_SOCKET_DATA    *SocketData;
  UINT8              SocketIndex;
  UINT8              PortIndex;
  UINT16             IoApicReg;

  Status = IioInitGetStackProtocol (&StackProtocol);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  SocketData = (IIO_SOCKET_DATA *)StackProtocol;
  Status = gBS->CloseEvent (Event);

  for (SocketIndex = 0; SocketIndex < 4; SocketIndex++) {
    if (SocketData->SocketIndexArray[SocketIndex]) {
      DEBUG ((DEBUG_INFO,
        "Calling IioIoatReadyToBootEvent IioIndex: %d\n",
        SocketIndex));

      //
      // Configure IOAPIC redirection for all 8 ports
      //
      for (PortIndex = 0; PortIndex < 8; PortIndex++) {
        IoApicReg = StackProtocol->Read (SocketIndex, 0,
                      IOAPIC_REDIR_TABLE | (PortIndex << 16));

        if (*(UINT8 *)(PortIndex + 8 * SocketIndex + (UINT8 *)SocketData + 4188) ||
            SocketData->IoatCapable) {
          IoApicReg |= 4;
        } else {
          IoApicReg &= ~4;
        }

        StackProtocol->Write (SocketIndex, 0,
          IOAPIC_REDIR_TABLE | (PortIndex << 16), IoApicReg);
      }

      DEBUG ((DEBUG_INFO,
        "Calling IioIoApicInitBootEvent IioReadyToBoot IioIndex: %d\n",
        SocketIndex));

      IioIoApicInitBootEvent (SocketData, SocketIndex, 11);

      DEBUG ((DEBUG_INFO,
        "Calling NtbLateInit IioReadyToBoot IioIndex: %d\n",
        SocketIndex));

      IioNtbLateInit (SocketData, SocketIndex, 11);
    }
  }

  return EFI_SUCCESS;
}

/**
  IIO socket initialization - late secure platform (TXT) handler.

  Called during exit boot services to apply late secure platform
  configurations when TXT is enabled.

  @return EFI_SUCCESS on success.
**/
EFI_STATUS
EFIAPI
IioInitLateSecurePlatform (
  VOID
  )
{
  EFI_STATUS         Status;
  IIO_STACK_PROTOCOL *StackProtocol;
  IIO_SOCKET_DATA    *SocketData;

  Status = IioInitGetStackProtocol (&StackProtocol);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  SocketData = (IIO_SOCKET_DATA *)StackProtocol;

  if (SocketData->InitComplete != 1) {
    StackProtocol->WriteWidth ((UINT8)-17, 0, 255);
    IioLateSecurePlatformInit (SocketData);
    SocketData->InitComplete = 1;
  }

  return EFI_SUCCESS;
}

//
// ---------------------------------------------------------------------------
// PCIe MMCFG / Address library routines (from PcieCommonInitLib / PcieAddressLib)
// ---------------------------------------------------------------------------

/**
  IO-port read double-word (32-bit).

  @param[in] Port  IO port to read from (must be 4-byte aligned).

  @return Value read from the port.
**/
UINT32
EFIAPI
IioInitIoPortRead32 (
  IN UINT16  Port
  )
{
  ASSERT ((Port & 3) == 0);
  return IoRead32 (Port);
}

/**
  Read unaligned 64-bit value from buffer.

  @param[in] Buffer  Pointer to possibly-unaligned buffer.

  @return 64-bit value at Buffer.
**/
UINT64
EFIAPI
IioInitReadUnaligned64 (
  IN VOID  *Buffer
  )
{
  ASSERT (Buffer != NULL);
  return *(UINT64 *)Buffer;
}

/**
  64-bit right shift.

  @param[in] Value  Value to shift.
  @param[in] Count  Number of bits (must be < 64).

  @return Value >> Count.
**/
UINT64
EFIAPI
IioInitRShiftU64 (
  IN UINT64  Value,
  IN UINTN   Count
  )
{
  ASSERT (Count < 64);
  return Value >> (UINT8)Count;
}

/**
  64-bit left shift.

  @param[in] Value  Value to shift.
  @param[in] Count  Number of bits (must be < 64).

  @return Value << Count.
**/
UINT64
EFIAPI
IioInitLShiftU64 (
  IN UINT64  Value,
  IN UINTN   Count
  )
{
  ASSERT (Count < 64);
  return Value << (UINT8)Count;
}

/**
  Zero-fill a memory buffer (wrapper with assertion).

  @param[in] Buffer  Pointer to buffer.
  @param[in] Length  Number of bytes.

  @return Pointer to Buffer.
**/
VOID *
EFIAPI
IioInitSafeZeroMem (
  IN VOID   *Buffer,
  IN UINTN  Length
  )
{
  if (Length == 0) {
    return Buffer;
  }

  if (Length - 1 > ~(UINTN)Buffer) {
    ASSERT (
      (Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)Buffer)
      );
  }

  return IioInitZeroMem (Buffer, Length, 0);
}

/**
  Copy memory buffer (wrapper with assertions).

  @param[in] Destination  Destination buffer.
  @param[in] Source       Source buffer.
  @param[in] Length       Number of bytes.

  @return Pointer to Destination.
**/
VOID *
EFIAPI
IioInitSafeCopyMem (
  IN VOID       *Destination,
  IN CONST VOID *Source,
  IN UINTN      Length
  )
{
  if (Length == 0) {
    return Destination;
  }

  ASSERT (
    (Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)Destination)
    );
  ASSERT (
    (Length - 1) <= (0xFFFFFFFFFFFFFFFFULL - (UINTN)Source)
    );

  if (Destination == Source) {
    return Destination;
  }

  return IioInitCopyMem (Destination, Source, Length);
}

//
// ---------------------------------------------------------------------------
// PCIe address translation (from PcieAddressLib / CpRcPkg)
// ---------------------------------------------------------------------------

/**
  Validate parameters for a DMA/PCIe memory access.

  Checks alignment, access width, and size constraints.

  @param[in]  AccessWidth  Encoded access width (0..3) mapped via byte_A7C0.
  @param[in]  Address      Base address.
  @param[in]  Count        Number of elements.
  @param[in]  ElementSize  Element size override (0 = auto).
  @param[in]  Buffer       Destination buffer.

  @return EFI_SUCCESS           Parameters valid.
  @return EFI_INVALID_PARAMETER Invalid width or null buffer.
  @return EFI_BAD_BUFFER_SIZE   Alignment or overflow violation.
**/
EFI_STATUS
EFIAPI
IioInitValidatePcieAccess (
  IN UINT8   AccessWidth,
  IN UINTN   Count,
  IN UINT64  Address,
  IN UINTN   ElementSize,
  IN VOID    *Buffer
  )
{
  UINT8  WidthIndex;
  UINTN  ElementAlignment;
  UINTN  MaxElements;

  if (Buffer == NULL || AccessWidth >= 0xC) {
    return EFI_INVALID_PARAMETER;
  }

  WidthIndex = AccessWidth & 3;

  //
  // Force element size to 1 for access widths 4..7
  //
  if (AccessWidth - 4 <= 3) {
    ElementSize = 1;
  }

  //
  // Check alignment
  //
  ElementAlignment = byte_A7C0[WidthIndex];
  if ((Address & (ElementAlignment - 1)) != 0) {
    return EFI_BAD_BUFFER_SIZE;
  }

  //
  // Check address range
  //
  if (Count > 0) {
    MaxElements = RShiftU64 (0xFFFFFFFFFFFFFFFF, WidthIndex);
    if (Count < ElementSize || Address > LShiftU64 (MaxElements - Count + 1, WidthIndex)) {
      return EFI_BAD_BUFFER_SIZE;
    }
  }

  //
  // Check buffer alignment
  //
  {
    UINTN Stride = byte_A7C0[WidthIndex];
    if (Stride > 8) {
      Stride = 8;
    }
    if ((Buffer & (Stride - 1)) != 0) {
      return EFI_BAD_BUFFER_SIZE;
    }
  }

  return EFI_SUCCESS;
}

/**
  Read memory from MMIO space into a buffer.

  Validates parameters, then reads Count elements of ElementSize from Address
  into Buffer using the appropriate access width.

  @param[in]  BufferDesc  Buffer descriptor (contains info, width, count).
  @param[out] Buffer      Destination buffer.

  @return EFI_SUCCESS  Read successful.
**/
EFI_STATUS
EFIAPI
IioInitMmioRead (
  IN  VOID   *BufferDesc,
  OUT VOID   *Buffer
  )
{
  UINTN   Count;
  UINT64  CurrentAddress;
  EFI_STATUS  Status;
  UINT8   WidthIndex;
  UINTN   ElementStride;
  UINTN   BufferStride;

  Count = *(UINT16 *)((UINT8 *)BufferDesc + 6);
  PcieGetElementInfo (0, 0, BufferDesc, &CurrentAddress);

  WidthIndex = (*(UINT32 *)((UINT8 *)BufferDesc + 8) >> 8) & 0xF;

  Status = IioInitValidatePcieAccess (WidthIndex, CurrentAddress, Count, (UINTN)Buffer);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  if (Count > 0) {
    ElementStride = byte_A7C0[WidthIndex];
    BufferStride = byte_A7C0[WidthIndex + 16];

    do {
      MmioReadBuffer (WidthIndex & 3, CurrentAddress, Buffer);
      CurrentAddress += ElementStride;
      Buffer = (VOID *)((UINT8 *)Buffer + BufferStride);
    } while (--Count);
  }

  return EFI_SUCCESS;
}

/**
  Write memory from a buffer into MMIO space.

  Validates parameters, then writes Count elements of ElementSize from Buffer
  into Address.

  @param[in]  BufferDesc  Buffer descriptor (contains info, width, count).
  @param[in]  Buffer      Source buffer.

  @return EFI_SUCCESS  Write successful.
**/
EFI_STATUS
EFIAPI
IioInitMmioWrite (
  IN VOID  *BufferDesc,
  IN VOID  *Buffer
  )
{
  UINTN   Count;
  UINT64  CurrentAddress;
  EFI_STATUS  Status;
  UINT8   WidthIndex;
  UINTN   ElementStride;
  UINTN   BufferStride;
  UINT32  DescFlags;

  Count = *(UINT16 *)((UINT8 *)BufferDesc + 6);
  PcieGetElementInfo (0, 0, BufferDesc, &CurrentAddress);

  WidthIndex = (*(UINT32 *)((UINT8 *)BufferDesc + 8) >> 8) & 0xF;

  Status = IioInitValidatePcieAccess (WidthIndex, CurrentAddress, Count, (UINTN)Buffer);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  if (Count > 0) {
    ElementStride = byte_A7C0[WidthIndex];
    BufferStride = byte_A7C0[WidthIndex + 16];

    do {
      MmioWriteBuffer (WidthIndex & 3, CurrentAddress, Buffer);

      DescFlags = *(UINT32 *)((UINT8 *)BufferDesc + 8);
      if ((DescFlags & 0x2000) != 0) {
        IioPcieWriteConfig (WidthIndex & 3, CurrentAddress, NULL, Buffer);
      }

      CurrentAddress += ElementStride;
      Buffer = (VOID *)((UINT8 *)Buffer + BufferStride);
    } while (--Count);
  }

  return EFI_SUCCESS;
}

/**
  MMIO read helper with element size decode.

  @param[in]  BufferDesc  Buffer descriptor.
  @param[in]  Address     MMIO address.
  @param[out] Buffer      Destination buffer.
  @param[in]  ElementSize  Logical element size.

  @return 0 on success.
**/
UINTN
EFIAPI
IioInitPcieMmioRead (
  IN  VOID   *BufferDesc,
  IN  UINT64 Address,
  OUT VOID   *Buffer,
  IN  UINT8  ElementSize
  )
{
  UINT8       WidthIndex;
  PCMCI_STATE PciState;
  INT32       AccessWidthEncoded = 0x08040001;

  PciState = PcieGetState (BufferDesc);
  WidthIndex = *((UINT8 *)&AccessWidthEncoded + ((*(UINT32 *)((UINT8 *)BufferDesc + 8) >> 8) & 0xF));

  PcieSetupAccess (PciState, Address, Buffer, (UINT8)WidthIndex);
  PcieCleanupAccess (BufferDesc, PciState);

  return 0;
}

/**
  Initialize the PCIe MMCFG table from given header.

  @param[in]  TableHeader  MCFG table descriptor pointer.
  @param[in]  SegmentCount  Number of PCI segments.

  @return EFI_SUCCESS  Table initialized.
**/
EFI_STATUS
EFIAPI
IioInitInitMmcfgTable (
  IN MCFG_TABLE_HEADER  *TableHeader,
  IN UINT32             SegmentCount
  )
{
  UINT32            TotalSize;
  MMCFG_TABLE_DESCRIPTOR  *MmcfgTable;
  PCD_PROTOCOL      *PcdProtocol;

  TotalSize = 16 * SegmentCount + 16;
  PcdProtocol = (PCD_PROTOCOL *)sub_4500 (6);

  //
  // Validate that MMCFG table fits in PCD-allocated space
  //
  if (sub_CF0 () && TotalSize >= (UINTN)PcdProtocol->GetSize (6)) {
    ASSERT (
      "MmcfgTableSize < LibPcdGetSize(6U)"
      );
  }

  MmcfgTable = (MMCFG_TABLE_DESCRIPTOR *)PcdProtocol->GetSize (6);
  IioInitCopyMem (MmcfgTable, TableHeader, (UINTN)PcdProtocol->GetSize (6));

  MmcfgTable->TableSize = TotalSize;

  //
  // If base address not provided, use PCD default
  //
  if (!TableHeader->OemId && !TableHeader->Reserved) {
    MmcfgTable->BaseAddresses[0] = sub_44E4 (5);
  }

  return EFI_SUCCESS;
}

/**
  Resolve the MMCFG base address for a given PCIe address.

  @param[in]  Address  Pointer to PCIe address structure.

  @return MMCFG base address for the segment.
**/
UINT64
EFIAPI
IioInitGetMmcfgBaseAddress (
  IN PCIE_ADDRESS  *Address
  )
{
  MMCFG_TABLE_DESCRIPTOR  *MmcfgTable;
  UINT64                  TableHandle;

  TableHandle = 0;

  if (Address->Bus != 0) {
    TableHandle = Address->Bus;
  } else {
    TableHandle = (UINT64)sub_4500 (6);
    if (*(UINT32 *)(TableHandle + 4) == 0) {
      IioInitInitMmcfgTable (&dword_DCA8, 8);
    }
  }

  MmcfgTable = (MMCFG_TABLE_DESCRIPTOR *)TableHandle;

  if (sub_CF0 () && Address->Segment >= MmcfgTable->SegmentMax) {
    ASSERT (
      "Address->Pcie.Seg < MmcfgTable->Header.SegMax"
      );
  }

  if (sub_CF0 () && (MmcfgTable->ValidSegMap & (1 << Address->Segment)) == 0) {
    ASSERT (
      "(1<<Address->Pcie.Seg) & MmcfgTable->Header.ValidSegMap"
      );
  }

  return MmcfgTable->BaseAddresses[Address->Segment];
}

//
// ---------------------------------------------------------------------------
// Module Entry Point
// ---------------------------------------------------------------------------

/**
  IIO Initialization driver entry point.

  Calls the main initialization routine and returns its status.

  @param[in] ImageHandle  EFI image handle.
  @param[in] SystemTable  Pointer to EFI system table.

  @return EFI_SUCCESS           IIO initialization completed.
  @return EFI_UNSUPPORTED       Platform or configuration unsupported.
**/
EFI_STATUS
EFIAPI
ModuleEntryPoint (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  EFI_STATUS  Status;

  Status = IioInitCore (ImageHandle, SystemTable);
  if (EFI_ERROR (Status)) {
    IioInitErrorHandler ();
  }

  return Status;
}