Newer
Older
AMI-Aptio-BIOS-Reversed / TxtDxe / TxtDxe.c
@Ajax Dong Ajax Dong 2 days ago 57 KB Init
/** @file
  TxtDxe -- Intel Trusted Execution Technology (TXT) DXE driver.

  This module is responsible for initializing Intel TXT (Trusted Execution
  Technology) on Purley/CoffeeLake Xeon platforms. It performs the following:

   1. UEFI driver initialization (entry point, image/ST/BS/RT/DS setup).
   2. Locates platform TXT device memory and TXT policy HOBs to obtain
      the BIOS ACM address, SINIT memory base/size, DMA protection region,
      LCP policy data, and TXT scratch space.
   3. If the CPU supports LT (LaGrande Technology, i.e. TXT), launches the
      BIOS ACM (Authenticated Code Module) to configure the system for
      measured launch.
   4. Handles ACM errors by either ignoring them (per BIOS setup policy),
      clearing LT/TPM state in CMOS, or triggering a power-good reset.
   5. Installs the TXT DXE Protocol so other DXE drivers (e.g. SMM, boot
      script) can interact with TXT.

  File:   TxtDxe.c
  Module: TxtDxe (ServerCommonPkg\\Universal\\GetSec\\Dxe\\TxtDxe)
  Compiler: VS2015 (DEBUG) for X64
  Base:  ServerCommonPkg\\Universal\\GetSec\\Dxe

  References:
    - Intel TXT (Trusted Execution Technology) Software Development Guide
    - Intel TXT MLE Developer Manual
    - TCG PC Client Platform TPM Profile (PTP) Specification

  Copyright (C) Intel Corporation. All rights reserved.
**/

#include "TxtDxe.h"

//
// =============================================================================
// Global Variables
// =============================================================================
//

//
// UEFI core handles -- populated by DriverInit (sub_47C)
//
EFI_HANDLE            gImageHandle       = NULL;
EFI_SYSTEM_TABLE     *gSystemTable        = NULL;
EFI_BOOT_SERVICES    *gBootServices       = NULL;
EFI_RUNTIME_SERVICES *gRuntimeServices    = NULL;
EFI_DXE_SERVICES     *gDxeServicesTable   = NULL;
VOID                 *mPciUsra            = NULL;  // MM PCI User Access (DxeMmPciBaseLib)

//
// Protocol and database pointers
//
VOID  *mPcdProtocol              = NULL;  // PCD Protocol
VOID  *mHobList                  = NULL;  // HOB list (DxeHobLib)
VOID  *mDebugPrintProtocol       = NULL;  // Debug print protocol (gEfiDebugPortProtocolGuid)
VOID  *mSmmCommunicationProtocol = NULL;  // SMM Communication protocol
VOID  *mSmmBase2Protocol         = NULL;  // SMM Base2 protocol
VOID  *mSmmLockBoxProtocol       = NULL;  // SMM LockBox protocol
VOID  *mPiSmmCommunicationProtocol = NULL; // PI SMM Communication protocol

//
// TXT policy data pointers -- populated from platform HOBs
//
TXT_DEVICE_MEMORY_POLICY  *mTxtDeviceMemoryPolicy  = NULL;  // gEfiPlatformTxtDeviceMemoryGuid
TXT_PLATFORM_POLICY       *mTxtPlatformPolicy       = NULL;  // gEfiPlatformTxtPolicyDataGuid

//
// AP / wake-up state
//
UINT16  mApCount        = 0;       // Number of enabled APs (from MP services)
UINT8   mApWakeUpVector = 0;       // SIPI vector for AP wake-up
UINT32  mApicIdTable[MAX_CPUS];    // APIC ID table populated from MP services

//
// ACM state tracking
//
BOOLEAN mBiosAcmCalled      = FALSE;
UINT8   mBiosAcmErrorCount  = 0;

//
// TXT DXE Protocol instance
//
TXT_DXE_PROTOCOL  gTxtDxeProtocol;
EFI_HANDLE        gTxtDxeProtocolHandle = NULL;

//
// =============================================================================
// Forward declarations of local functions
// =============================================================================
//

EFI_STATUS
EFIAPI
TxtDxeLaunchBiosAcm (
  IN  UINT64  BiosAcmAddress,
  IN  UINT32  Flags
  );

//
// Library helper prototypes that are linked from other compilation units:
//   - TxtDxeLib.c   (ServerCommonPkg)
//   - LtDxeLib.c    (PurleyPlatPkg)
//

//
// =============================================================================
// Debug Print and Assert Helpers
// =============================================================================
//

/**
  Locate the debug print protocol (gEfiDebugPortProtocolGuid).

  This function looks up the debug port protocol and caches it in
  mDebugPrintProtocol. It raises the TPL to TPL_NOTIFY before querying
  to avoid re-entrancy.

  @return  Pointer to the debug print protocol, or NULL if unavailable.
**/
VOID *
GetDebugPrintProtocol (
  VOID
  )
{
  VOID   *Protocol;
  UINT64  Tpl;

  Protocol = mDebugPrintProtocol;
  if (Protocol == NULL) {
    //
    // Raise TPL to avoid re-entrancy during protocol lookup
    //
    Tpl = gBootServices->RaiseTPL (TPL_NOTIFY);
    gBootServices->RestoreTPL (Tpl);

    if (Tpl <= TPL_NOTIFY) {
      if (gBootServices->LocateProtocol (
            &gEfiDebugPortProtocolGuid,
            NULL,
            &Protocol
            ) < 0) {
        Protocol = NULL;
      }
      mDebugPrintProtocol = Protocol;
    }
  }
  return Protocol;
}

/**
  Debug print wrapper (DEBUG macro equivalent).

  Writes a formatted debug message through the debug port protocol if the
  error level matches and the print protocol is available.

  @param[in]  ErrorLevel  Debug error level mask.
  @param[in]  Format      Format string (like printf).
  @param[in]  ...         Variable arguments for the format string.
**/
VOID
DebugPrint (
  IN  UINTN       ErrorLevel,
  IN  CONST CHAR8 *Format,
  ...
  )
{
  EFI_DEBUG_PORT_PROTOCOL *DebugPort;
  UINT64                   Tpl;

  DebugPort = (EFI_DEBUG_PORT_PROTOCOL *)GetDebugPrintProtocol ();
  if (DebugPort != NULL) {
    //
    // Check CMOS byte 0x4B for the platform debug level.
    // If debug level indicates this message should be printed, do so.
    //
    UINT8  DebugLevel;
    UINT64 Filter;

    //
    // Check if this error level should be displayed
    // Simplified: use EFI_D_* constants to filter
    //
    Filter = 0;
    if (DebugLevel == 1) {
      Filter = DEBUG_ERROR;
    } else if (DebugLevel > 1) {
      Filter = (UINT64)(INT64)0x80000000;  // DEBUG_ERROR
    }

    if ((Filter & ErrorLevel) != 0) {
      VA_LIST  Args;
      VA_START (Args, Format);
      DebugPort->Write (DebugPort, ErrorLevel, Format, Args);
      VA_END (Args);
    }
  }
}

/**
  ASSERT macro backend.

  Called when an assertion fails. Prints the file, line number, and
  assertion expression via the debug port protocol.

  @param[in]  FileName  Source file name string.
  @param[in]  LineNumber  Line number of the assertion.
  @param[in]  Assertion  The assertion expression string.
**/
VOID
AssertBreak (
  IN  CONST CHAR8  *FileName,
  IN  UINTN         LineNumber,
  IN  CONST CHAR8  *Assertion
  )
{
  EFI_DEBUG_PORT_PROTOCOL *DebugPort;

  DebugPort = (EFI_DEBUG_PORT_PROTOCOL *)GetDebugPrintProtocol ();
  if (DebugPort != NULL) {
    DebugPort->Write (
                 DebugPort,
                 DEBUG_ERROR,
                 "ASSERT [%a:%u] %a\n",
                 FileName,
                 LineNumber,
                 Assertion
                 );
  }
}

//
// =============================================================================
// UEFI Library Protocol Locators
// =============================================================================
//

/**
  Locate and cache the PCD protocol.

  @return  Pointer to the PCD protocol interface.
**/
VOID *
GetPcdProtocol (
  VOID
  )
{
  if (mPcdProtocol == NULL) {
    if (gBootServices->LocateProtocol (
          &gPcdProtocolGuid,
          NULL,
          &mPcdProtocol
          ) < 0) {
      mPcdProtocol = NULL;
    }
    if (mPcdProtocol == NULL) {
      AssertBreak (
        __FILE__,
        __LINE__,
        "mPcd != NULL"
        );
    }
  }
  return mPcdProtocol;
}

/**
  Locate and cache the HOB list pointer via DXE services.

  @return  Pointer to the HOB list.
**/
VOID *
GetHobList (
  VOID
  )
{
  if (mHobList == NULL) {
    if (gDxeServicesTable->GetHobList ((VOID **)&mHobList) < 0) {
      AssertBreak (
        "e:\\hs\\MdePkg\\Library\\DxeHobLib\\HobLib.c",
        54,
        "!EFI_ERROR (Status)"
        );
    }
    if (mHobList == NULL) {
      AssertBreak (
        "e:\\hs\\MdePkg\\Library\\DxeHobLib\\HobLib.c",
        55,
        "mHobList != NULL"
        );
    }
  }
  return mHobList;
}

/**
  Walk the HOB list to find a specific HOB by GUID.

  @param[in]  Guid  Pointer to the GUID to search for.

  @return  Pointer to the HOB structure if found, NULL otherwise.
**/
VOID *
FindHobByGuid (
  IN  EFI_GUID  *Guid
  )
{
  EFI_HOB_GUID_TYPE *Hob;
  VOID              *HobList;

  HobList = GetHobList ();
  for (Hob = (EFI_HOB_GUID_TYPE *)HobList;
       Hob != NULL;
       Hob = (EFI_HOB_GUID_TYPE *)((UINT8 *)Hob + Hob->Header.HobLength))
  {
    if (Hob->Header.HobType == EFI_HOB_TYPE_GUID_EXT) {
      if (CompareGuid (&Hob->Name, Guid)) {
        return (VOID *)Hob;
      }
    }
    if (Hob->Header.HobLength == 0) {
      break;
    }
  }
  return NULL;
}

//
// =============================================================================
// CopyMem wrapper
// =============================================================================
//

/**
  Copies a block of memory from source to destination with overflow checks.

  @param[in]  Destination  Pointer to the destination buffer.
  @param[in]  Source       Pointer to the source buffer.
  @param[in]  Length       Number of bytes to copy.

  @return  Pointer to the destination buffer.
**/
VOID *
CopyMemS (
  OUT VOID       *Destination,
  IN  CONST VOID *Source,
  IN  UINTN       Length
  )
{
  if (Length > 0) {
    //
    // Validate that the copy range does not overflow UINTN
    //
    if ((Length - 1) > (UINTN)(-1) - (UINTN)Destination) {
      AssertBreak (
        "e:\\hs\\MdePkg\\Library\\BaseMemoryLibRepStr\\CopyMemWrapper.c",
        56,
        "(Length - 1) <= (MAX_UINTN - (UINTN)Destination)"
        );
    }
    if ((Length - 1) > (UINTN)(-1) - (UINTN)Source) {
      AssertBreak (
        "e:\\hs\\MdePkg\\Library\\BaseMemoryLibRepStr\\CopyMemWrapper.c",
        57,
        "(Length - 1) <= (MAX_UINTN - (UINTN)Source)"
        );
    }
    if (Destination != Source) {
      return CopyMem (Destination, Source, Length);
    }
  }
  return Destination;
}

//
// =============================================================================
// Platform Configuration / UEFI Variable Helpers
// =============================================================================
//

/**
  Read a UEFI variable (the "SocketProcessorCoreConfig" or a named var)
  into a caller-allocated buffer.

  @param[in]      VariableName  Wide-string name of the variable.
  @param[in]      VendorGuid    Vendor GUID for the variable.
  @param[out]     Buffer        Output buffer for variable data.
  @param[in,out]  BufferSize    On input, size of Buffer. On output, actual
                                size of the variable data.

  @return  EFI_STATUS.
**/
EFI_STATUS
GetPlatformConfigVariable (
  IN     CONST UINT16   *VariableName,
  IN     EFI_GUID       *VendorGuid,
  OUT    VOID           *Buffer,
  IN OUT UINTN          *BufferSize
  )
{
  return gRuntimeServices->GetVariable (
                             (UINT16 *)VariableName,
                             VendorGuid,
                             NULL,
                             BufferSize,
                             Buffer
                             );
}

/**
  Set a UEFI variable.

  @param[in]  VariableName  Wide-string name of the variable.
  @param[in]  VendorGuid    Vendor GUID for the variable.
  @param[in]  Attributes    Variable attributes.
  @param[in]  DataSize      Size of the data buffer.
  @param[in]  Buffer        Pointer to the data.

  @return  EFI_STATUS.
**/
EFI_STATUS
SetPlatformConfigVariable (
  IN  CONST UINT16   *VariableName,
  IN  EFI_GUID       *VendorGuid,
  IN  UINT32          Attributes,
  IN  UINTN           DataSize,
  IN  VOID           *Buffer
  )
{
  return gRuntimeServices->SetVariable (
                             (UINT16 *)VariableName,
                             VendorGuid,
                             Attributes,
                             DataSize,
                             Buffer
                             );
}

//
// =============================================================================
// LT (LaGrande Technology / TXT) Feature Checks
// =============================================================================
//

/**
  Check if the current processor supports LT (TXT) by reading the LT bit
  in CPUID leaf 1, ECX bit 29.

  @retval TRUE   CPU supports LT/TXT.
  @retval FALSE  CPU does NOT support LT/TXT.
**/
BOOLEAN
IsLtProcessor (
  VOID
  )
{
  UINT32  Ecx;

  AsmCpuid (CPUID_LT_SUPPORT, NULL, NULL, &Ecx, NULL);
  return (Ecx & CPUID_LT_BIT) != 0;
}

/**
  Read the LT SPAD (ScratchPad) HIGH register to check ACM status.

  The LT.SPAD.HIGH register at 0xFED300A4 contains the status from the
  BIOS ACM execution. Bit 31 indicates ACM success/failure.

  @retval TRUE   BIOS ACM completed successfully.
  @retval FALSE  BIOS ACM failed or not yet run.
**/
BOOLEAN
IsBiosAcmSuccessful (
  VOID
  )
{
  UINT32  SpadHigh;

  SpadHigh = *(volatile UINT32 *)TXT_SPAD_HIGH_REG;
  return (SpadHigh & 0x80000000) == 0;
}

/**
  Check whether TXT is enabled on this platform by reading MSR 0x3A
  (IA32_FEATURE_CONTROL or similar platform MSR).

  Returns TRUE if bits [15:8] == 0xFF and bit 1 (LOCK) is set,
  indicating TXT has been configured by the platform init code.

  @retval TRUE   TXT is enabled and locked.
  @retval FALSE  TXT is not enabled.
**/
BOOLEAN
IsTxtEnabled (
  VOID
  )
{
  UINT64  MsrValue;

  MsrValue = AsmReadMsr64 (0x3A);  // Platform feature MSR
  if ((MsrValue & 0xFF00) == 0xFF00 && (MsrValue & 0x2) != 0) {
    return TRUE;
  }
  return FALSE;
}

//
// =============================================================================
// Platform TXT Policy HOB Access
// =============================================================================
//

/**
  Locates the TXT device memory policy HOB and caches the pointer.

  On success, mTxtDeviceMemoryPolicy points to the HOB data, containing:
    - No-DMA table address/size
    - SINIT memory address/size
    - TXT heap memory address/size
    - DMA protection memory region address/size

  @retval EFI_SUCCESS       Policy data found and cached.
  @retval EFI_NOT_FOUND     Policy HOB not present.
**/
EFI_STATUS
LocateTxtDeviceMemoryPolicy (
  VOID
  )
{
  EFI_HOB_GUID_TYPE  *Hob;

  Hob = (EFI_HOB_GUID_TYPE *)FindHobByGuid (&gEfiPlatformTxtDeviceMemoryGuid);
  if (Hob == NULL) {
    DebugPrint (DEBUG_ERROR, "gEfiPlatformTxtDeviceMemoryGuid not found! TxtDxe return error!\n");
    return EFI_NOT_FOUND;
  }

  //
  // The HOB data starts after the GUID extension header
  //
  mTxtDeviceMemoryPolicy = (TXT_DEVICE_MEMORY_POLICY *)((UINT8 *)Hob + sizeof (EFI_HOB_GUID_TYPE));

  DebugPrint (DEBUG_INFO, "PlatformTxtDeviceMemory:\n");
  DebugPrint (DEBUG_INFO, "  NoDMATableAddress                - 0x%08x\n", mTxtDeviceMemoryPolicy->NoDMATableAddress);
  DebugPrint (DEBUG_INFO, "  NoDMATableSize                   - 0x%08x\n", mTxtDeviceMemoryPolicy->NoDMATableSize);
  DebugPrint (DEBUG_INFO, "  SINITMemoryAddress               - 0x%08x\n", mTxtDeviceMemoryPolicy->SINITMemoryAddress);
  DebugPrint (DEBUG_INFO, "  SINITMemorySize                  - 0x%08x\n", mTxtDeviceMemoryPolicy->SINITMemorySize);
  DebugPrint (DEBUG_INFO, "  TXTHeapMemoryAddress             - 0x%08x\n", mTxtDeviceMemoryPolicy->TXTHeapMemoryAddress);
  DebugPrint (DEBUG_INFO, "  TXTHeapMemorySize                - 0x%08x\n", mTxtDeviceMemoryPolicy->TXTHeapMemorySize);
  DebugPrint (DEBUG_INFO, "  DMAProtectionMemoryRegionAddress - 0x%08x\n", mTxtDeviceMemoryPolicy->DMAProtectionMemoryRegionAddress);
  DebugPrint (DEBUG_INFO, "  DMAProtectionMemoryRegionSize    - 0x%08x\n", mTxtDeviceMemoryPolicy->DMAProtectionMemoryRegionSize);

  return EFI_SUCCESS;
}

/**
  Locates the TXT platform policy HOB and caches the pointer.

  On success, mTxtPlatformPolicy points to the HOB data, containing:
    - BiosAcmAddress:       Physical address of the BIOS ACM
    - StartupAcmAddressInFit: Startup ACM address in FIT
    - BiosOsDataRegionRevision
    - LcpPolicyDataBase / LcpPolicyDataSize
    - TxtScratchAddress
    - BiosAcmPolicy

  @retval EFI_SUCCESS       Policy data found and cached.
  @retval EFI_NOT_FOUND     Policy HOB not present.
**/
EFI_STATUS
LocateTxtPlatformPolicy (
  VOID
  )
{
  EFI_HOB_GUID_TYPE  *Hob;

  Hob = (EFI_HOB_GUID_TYPE *)FindHobByGuid (&gEfiPlatformTxtPolicyDataGuid);
  if (Hob == NULL) {
    DebugPrint (DEBUG_ERROR, "gEfiPlatformTxtPolicyDataGuid not found! TxtDxe return error!\n");
    return EFI_NOT_FOUND;
  }

  mTxtPlatformPolicy = (TXT_PLATFORM_POLICY *)((UINT8 *)Hob + sizeof (EFI_HOB_GUID_TYPE));

  DebugPrint (DEBUG_INFO, "PlatformTxtPolicy:\n");
  DebugPrint (DEBUG_INFO, "  BiosAcmAddress             - 0x%08x\n", mTxtPlatformPolicy->BiosAcmAddress);
  DebugPrint (DEBUG_INFO, "  StartupAcmAddressInFit     - 0x%08x\n", mTxtPlatformPolicy->StartupAcmAddressInFit);
  DebugPrint (DEBUG_INFO, "  BiosOsDataRegionRevision   - 0x%08x\n", mTxtPlatformPolicy->BiosOsDataRegionRevision);
  DebugPrint (DEBUG_INFO, "  LcpPolicyDataBase          - 0x%08x\n", mTxtPlatformPolicy->LcpPolicyDataBase);
  DebugPrint (DEBUG_INFO, "  LcpPolicyDataSize          - 0x%08x\n", mTxtPlatformPolicy->LcpPolicyDataSize);
  DebugPrint (DEBUG_INFO, "  TxtScratchAddress          - 0x%08x\n", mTxtPlatformPolicy->TxtScratchAddress);
  DebugPrint (DEBUG_INFO, "  BiosAcmPolicy              - 0x%08x\n", mTxtPlatformPolicy->BiosAcmPolicy);

  return EFI_SUCCESS;
}

//
// =============================================================================
// AP Wake-up Vector and APIC Setup
// =============================================================================
//

/**
  Locate the MP floating pointer structure in the EBDA or BIOS ROM area
  (0xE0000-0xFFFFF) to discover APIC IDs of all processors.

  @param[out]  ApCount     Number of application processors found.
  @param[out]  ApicIdTable Buffer to receive the APIC ID list (must hold
                            at least MAX_CPUS entries).

  @retval EFI_SUCCESS       APIC information populated.
  @retval EFI_NOT_FOUND     MP table not found.
**/
EFI_STATUS
GetMpTableApicIds (
  OUT UINT16  *ApCount,
  OUT UINT32  *ApicIdTable
  )
{
  UINT64       Address;
  UINT32       MpFloatSig;
  UINT16       Count;
  UINT16       Index;

  //
  // Search for the MP floating pointer structure in the BIOS ROM area
  // (0xE0000 to 0xFFFFF, i.e. 917504 to 1048576).
  //
  *ApCount = 0;
  for (Address = 0xE0000; Address < 0x100000; Address += 16) {
    if (*(UINT32 *)Address == MP_FLOAT_SIGNATURE) {
      break;
    }
  }
  if (Address >= 0x100000) {
    //
    // MP table not found; fall back to allocating a wake-up buffer
    // at a fixed address.
    //
    Address = 0;
  }

  if (Address == 0) {
    //
    // No MP table found; allocate a 0xFFFFF-sized page-aligned buffer
    // for the wake-up vector.
    //
    EFI_PHYSICAL_ADDRESS  WakeUpBuffer;

    WakeUpBuffer = 0xFFFFF;
    if (gBootServices->AllocatePages (
          AllocateMaxAddress,
          EfiBootServicesData,
          1,
          &WakeUpBuffer
          ) < 0) {
      AssertBreak (
        "e:\\hs\\ServerCommonPkg\\Universal\\GetSec\\Dxe\\TxtDxeLib.c",
        982,
        "!EFI_ERROR (Status)"
        );
    }
    Count = (UINT16)((WakeUpBuffer + 0xFFF) >> 12);
  } else {
    //
    // MP table found; configure the wake-up vector from the MP config table
    //
    EFI_MP_SERVICES_PROTOCOL *MpServices;
    EFI_STATUS                Status;

    Status = gBootServices->LocateProtocol (
                              &gEfiMpServiceProtocolGuid,
                              NULL,
                              (VOID **)&MpServices
                              );
    if (Status < 0) {
      goto FallbackAllocate;
    }

    MpServices->GetNumberOfProcessors (MpServices, &Count, NULL);

    //
    // Use MP services to get APIC IDs
    //
    Count = 0;
    for (Index = 0; Index < mApCount; Index++) {
      UINTN  ProcessorNumber;
      UINTN  Health;
      UINTN  ApicId;

      if (MpServices->GetProcessorInfo (
            MpServices,
            Index,
            &ProcessorNumber,
            &ApicId,
            &Health
            ) >= 0) {
        ApicIdTable[Count++] = (UINT32)ApicId;
      }
    }

    Count = mApCount;
  }

  if (*ApCount > 0) {
    //
    // Set up the wake-up buffer: write the magic value.
    // The WakeUpBuffer address is stored in mApWakeUpVector.
    //
    UINT32  *WakeUpBuffer;

    WakeUpBuffer = (UINT32 *)((UINTN)(Count + 4099) & 0xFFFFF000);
    *WakeUpBuffer = WAKEUP_BUFFER_MAGIC;   // -51645190 as signed
    mApWakeUpVector = (UINT8)((UINTN)WakeUpBuffer >> 12);  // Page number for SIPI
  }

  return EFI_SUCCESS;
}

//
// =============================================================================
// ACM Launch Support
// =============================================================================
//

/**
  Saves/restores machine check banks (MC9-MC11) during ACM launch.
  ACM execution may generate corrected machine check events, so we
  disable the applicable MCi_CTL MSRs before ACM launch and restore them
  afterward, clearing any pending status.

  @param[in]  Flags  If non-zero, save original values and disable MC banks.
                     If zero, restore original values.
**/
VOID
ConfigureMachineCheckBanks (
  IN  UINT32  Flags
  )
{
  static UINT32  Mc9CtlOrig  = 0;
  static UINT32  Mc10CtlOrig = 0;
  static UINT32  Mc11CtlOrig = 0;
  static UINT32  McgContainOrig = 0;
  static BOOLEAN McgContainValid = FALSE;

  if (Flags != 0) {
    //
    // Save original MC9-MC11 control values and mask out bit 7 (EN)
    //
    Mc9CtlOrig  = (UINT32)AsmReadMsr64 (MSR_IA32_MC9_CTL);
    Mc10CtlOrig = (UINT32)AsmReadMsr64 (MSR_IA32_MC10_CTL);
    Mc11CtlOrig = (UINT32)AsmReadMsr64 (MSR_IA32_MC11_CTL);

    DebugPrint (DEBUG_INFO, "Ia32_Mc9_Ctl_Org  = 0x%08x\n", Mc9CtlOrig);
    DebugPrint (DEBUG_INFO, "Ia32_Mc10_Ctl_Org = 0x%08x\n", Mc10CtlOrig);
    DebugPrint (DEBUG_INFO, "Ia32_Mc11_Ctl_Org = 0x%08x\n", Mc11CtlOrig);

    //
    // Optionally save IA32_MCG_CONTAIN if MCG_CMCP (bit 24) is set
    //
    if ((AsmReadMsr64 (MSR_IA32_MCG_CAP) & 0x1000000) != 0) {
      McgContainOrig = (UINT32)AsmReadMsr64 (MSR_IA32_MCG_CONTAIN);
      McgContainValid = TRUE;
      DebugPrint (DEBUG_INFO, "Ia32_Mcg_Contain_Org = 0x%08x\n", McgContainOrig);
      AsmWriteMsr64 (MSR_IA32_MCG_CONTAIN, 0);
    }

    //
    // Write new values with EN bit cleared
    //
    DebugPrint (DEBUG_INFO, "Ia32_Mc9_Ctl_New  = 0x%08x\n", Mc9CtlOrig & ~0x80);
    DebugPrint (DEBUG_INFO, "Ia32_Mc10_Ctl_New = 0x%08x\n", Mc10CtlOrig & ~0x80);
    DebugPrint (DEBUG_INFO, "Ia32_Mc11_Ctl_New = 0x%08x\n", Mc11CtlOrig & ~0x80);

    AsmWriteMsr64 (MSR_IA32_MC9_CTL,  Mc9CtlOrig & ~0x80);
    AsmWriteMsr64 (MSR_IA32_MC10_CTL, Mc10CtlOrig & ~0x80);
    AsmWriteMsr64 (MSR_IA32_MC11_CTL, Mc11CtlOrig & ~0x80);
  } else {
    //
    // Restore: clear status first, then restore control
    //
    DebugPrint (DEBUG_INFO, "Write Ia32_Mc9_Ctl_Org  = 0x%08x\n", Mc9CtlOrig);
    DebugPrint (DEBUG_INFO, "Write Ia32_Mc10_Ctl_Org = 0x%08x\n", Mc10CtlOrig);
    DebugPrint (DEBUG_INFO, "Write Ia32_Mc11_Ctl_Org = 0x%08x\n", Mc11CtlOrig);

    AsmWriteMsr64 (MSR_IA32_MC9_STATUS,  0);
    AsmWriteMsr64 (MSR_IA32_MC10_STATUS, 0);
    AsmWriteMsr64 (MSR_IA32_MC11_STATUS, 0);

    AsmWriteMsr64 (MSR_IA32_MC9_CTL,  Mc9CtlOrig);
    AsmWriteMsr64 (MSR_IA32_MC10_CTL, Mc10CtlOrig);
    AsmWriteMsr64 (MSR_IA32_MC11_CTL, Mc11CtlOrig);

    //
    // Restore IA32_MCG_CONTAIN if saved
    //
    if (McgContainValid) {
      DebugPrint (DEBUG_INFO, "Ia32_Mcg_Contain_Org = 0x%16x\n", McgContainOrig);
      AsmWriteMsr64 (MSR_IA32_MCG_CONTAIN, McgContainOrig);
      McgContainValid = FALSE;
    }
  }
}

/**
  Launch the BIOS ACM (Authenticated Code Module).

  This function performs the following:
    1. Saves and disables machine check banks MC9-MC11 (to avoid false
       CMCI from ACM execution).
    2. If APs are present, sends a startup IPI (SIPI) to bring them online.
    3. Raises TPL to TPL_HIGH_LEVEL to serialize ACM execution.
    4. Calls into the platform-specific LaunchBiosAcm () routine
       (implemented in LtDxeLib or similar).
    5. Restores TPL and machine check bank settings.
    6. Sends SIPI again for AP wake-up after ACM.

  @param[in]  BiosAcmAddress  Physical address of the BIOS ACM module.
  @param[in]  Flags           Additional flags (reserved, should be 0).

  @retval EFI_SUCCESS  ACM launched successfully.
**/
EFI_STATUS
EFIAPI
TxtDxeLaunchBiosAcm (
  IN  UINT64  BiosAcmAddress,
  IN  UINT32  Flags
  )
{
  UINTN   OldTpl;
  UINT16  Index;

  //
  // Step 1: Disable MC9-MC11 machine check banks
  //
  ConfigureMachineCheckBanks (1);

  //
  // Step 2: If APs exist, send SIPI to start them (required for SINIT)
  //
  if (mApCount > 0) {
    EFI_STATUS  Status;

    Status = MpServicesProtocol->StartupAllAPs (
                                   MpServicesProtocol,
                                   0,       // Single-threaded
                                   NULL,
                                   NULL,
                                   &mApCount
                                   );
    if (Status < 0) {
      AssertBreak (
        "e:\\hs\\ServerCommonPkg\\Universal\\GetSec\\Dxe\\TxtDxeLib.c",
        1082,
        "!EFI_ERROR (Status)"
        );
    }
    //
    // Send INIT IPI to all (including self)
    //
    SendInitIpi ();
  }

  //
  // Step 3: Debug log and raise TPL
  //
  DebugPrint (DEBUG_INFO, "LtDxeLibLaunchBiosAcm: BiosAcmAddress = 0x%08x\n", BiosAcmAddress);
  DebugPrint (DEBUG_INFO, "LtDxeLibLaunchBiosAcm: Raising TPL\n");
  OldTpl = gBootServices->RaiseTPL (TPL_HIGH_LEVEL);

  //
  // Step 4: Call the platform-specific BIOS ACM launch routine.
  //         This is a raw assembly routine (sub_4700) that:
  //           - Saves GDT/IDT
  //           - Sets up MTRR page tables for ACM
  //           - Clears caches (WBINVD or INVD)
  //           - Enables MCE and OSFXSR
  //           - Writes MTRR physbase/physmask for ACM memory range
  //           - Clears all machine check banks
  //           - Performs a far return to the ACM entry point
  //         The ACM then executes in a special environment and returns
  //         control via the LT.SPAD.HIGH register.
  //
  DebugPrint (DEBUG_INFO, "LtDxeLibLaunchBiosAcm: Calling LaunchBiosAcm()\n");
  PlatformLaunchBiosAcm (BiosAcmAddress, Flags);

  //
  // Step 5: Restore TPL and machine check banks
  //
  DebugPrint (DEBUG_INFO, "LtDxeLibLaunchBiosAcm: Restoring TPL\n");
  gBootServices->RestoreTPL (OldTpl);

  DebugPrint (DEBUG_INFO, "LtDxeLibLaunchBiosAcm: Sending SIPI\n");

  //
  // Step 6: Send SIPI to wake APs after ACM
  //
  SendInitIpi ();
  MicroSecondDelay (10);
  SendSipi ((UINT32)((mApWakeUpVector << 12) | SIPI_BASE) >> 12);
  MicroSecondDelay (200);
  SendSipi ((UINT32)((mApWakeUpVector << 12) | SIPI_BASE) >> 12);

  //
  // Restore MC banks to original state
  //
  ConfigureMachineCheckBanks (0);

  return EFI_SUCCESS;
}

//
// =============================================================================
// ACM Error Handling
// =============================================================================
//

/**
  Checks if the BIOS setup option for "LtDxe Lib" functions is installed.

  @param[out]  SetupValue  Pointer to receive the setup option value.

  @retval EFI_SUCCESS       Setup value retrieved.
  @retval other             Failed to read the variable.
**/
EFI_STATUS
GetLtDxeLibSetupOption (
  OUT UINT8  *SetupValue
  )
{
  UINTN       BufferSize;
  UINT8       Buffer[311];
  EFI_STATUS  Status;

  BufferSize = sizeof (Buffer);
  Status = GetPlatformConfigVariable (
             L"SocketProcessorCoreConfig",
             &gSetupGuid,
             Buffer,
             &BufferSize
             );
  if (!EFI_ERROR (Status)) {
    *SetupValue = Buffer[36];   // LtDxe lib enable/disable option
  }
  return Status;
}

/**
  Checks if the BIOS setup option for ACM error type is configured.

  @param[out]  AcmType  Pointer to receive the ACM error type.

  @retval EFI_SUCCESS       ACM type retrieved.
  @retval other             Failed to read the variable.
**/
EFI_STATUS
GetAcmErrorType (
  OUT UINT8  *AcmType
  )
{
  UINTN       BufferSize;
  UINT8       Buffer[311];
  EFI_STATUS  Status;

  BufferSize = sizeof (Buffer);
  Status = GetPlatformConfigVariable (
             L"SocketProcessorCoreConfig",
             &gSetupGuid,
             Buffer,
             &BufferSize
             );
  if (!EFI_ERROR (Status)) {
    *AcmType = Buffer[37];    // ACM error handling type
  }
  return Status;
}

/**
  Handle BIOS ACM failure by checking the BIOS setup policy.

  Three possible outcomes:
    1. If "LtDxe Lib" function is not installed (SetupValue == 0) and
       the "ignore" flag is set, log a warning and continue.
    2. If the setup policy says to ignore the ACM error for the detected
       ACM type, log and continue.
    3. Otherwise, clear LT/TPM state in CMOS and trigger a power-good
       reset (cold reboot).

  @param[in]  SpadHigh  The value read from LT.SPAD.HIGH register.
**/
VOID
HandleAcmError (
  IN  UINT32  SpadHigh
  )
{
  UINT8   LtDxeLibInstalled;
  UINT8   AcmType;
  BOOLEAN IgnoreError;

  IgnoreError = FALSE;

  //
  // Check if LtDxeLib functions are installed
  //
  if (!GetLtDxeLibSetupOption (&LtDxeLibInstalled) && LtDxeLibInstalled) {
    IgnoreError = TRUE;
  }

  if (IgnoreError) {
    //
    // BIOS setup is configured to ignore ACM errors -- just log
    //
    if (GetAcmErrorType (&AcmType)) {
      DebugPrint (DEBUG_ERROR,
        "ERROR: No LtDxe Lib functions installed  - BIOS setup option is set to ignore ACM error\n");
    } else {
      DebugPrint (DEBUG_ERROR,
        "ERROR: IGNORING ACM ERROR - ACM Type %x detected  - BIOS setup option is set to ignore ACM error\n",
        AcmType);
    }
  } else {
    //
    // ACM failure is fatal: clear LT/TPM state and reset
    //
    DebugPrint (DEBUG_ERROR, "Bios Acm Failed. Reboot in non-ltsx mode\n");
    ClearLtTpmCmosState ();
    DebugPrint (DEBUG_ERROR, "Acm Fails : do powergood reset!\n");

    //
    // Trigger a system reset via runtime services
    //
    gRuntimeServices->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
  }
}

/**
  Clear the LT/TPM state in CMOS and platform configuration variables.

  This writes a "1" to the "AcmError" UEFI variable and clears the
  LT/TPM enable bits in the SocketProcessorCoreConfig variable so that
  the next boot will not attempt ACM launch.
**/
VOID
ClearLtTpmCmosState (
  VOID
  )
{
  UINT8       Buffer[303];
  UINTN       BufferSize;
  UINT32      Attributes;
  UINT8       AcmErrorValue;
  UINTN       VarSize;

  //
  // Write "AcmError" variable to record the failure
  //
  AcmErrorValue = 1;
  SetPlatformConfigVariable (
    L"AcmError",
    &gAcmErrorGuid,
    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
    sizeof (AcmErrorValue),
    &AcmErrorValue
    );

  //
  // Clear LT enable bits in SocketProcessorCoreConfig
  //
  BufferSize = sizeof (Buffer);
  Attributes = 3;  // Variable storage size
  if (GetPlatformConfigVariable (
        L"SocketProcessorCoreConfig",
        &gSetupGuid,
        Buffer,
        &BufferSize
        ) >= 0) {
    Buffer[6] = 0;  // Clear LT/TPM enable field
    Buffer[8] = 0;  // Clear related field

    SetPlatformConfigVariable (
      L"SocketProcessorCoreConfig",
      &gSetupGuid,
      Attributes,
      BufferSize,
      Buffer
      );
  }
}

/**
  Apply the TXT platform policy to the "SocketProcessorCoreConfig" UEFI
  variable. Specifically, this sets byte offset 15 (TXT enable) to the
  value from the platform policy HOB (mTxtPlatformPolicy).

  @param[in]  PolicyByte  The TXT policy byte to write.
**/
VOID
ApplyTxtPolicyToPlatformConfig (
  IN  UINT8  PolicyByte
  )
{
  UINTN       BufferSize;
  UINT8       Buffer[311];
  UINT32      VarSize;
  EFI_STATUS  Status;

  VarSize = 3;
  BufferSize = sizeof (Buffer);

  Status = GetPlatformConfigVariable (
             L"SocketProcessorCoreConfig",
             &gSetupGuid,
             Buffer,
             &BufferSize
             );
  if (!EFI_ERROR (Status)) {
    Buffer[37] = PolicyByte;    // TXT policy byte in platform config

    SetPlatformConfigVariable (
      L"SocketProcessorCoreConfig",
      &gSetupGuid,
      VarSize,
      BufferSize,
      Buffer
      );
  }
}

//
// =============================================================================
// SMM / S3 Boot Script Support
// =============================================================================
//

/**
  Register callback for Scheck/LockConfig using SMM communication protocol.

  This function is called during initialization to allow the SMM core to
  lock down certain TXT configuration registers on S3 resume.
**/
EFI_STATUS
RegisterForScheckLockConfigCallback (
  VOID
  )
{
  EFI_STATUS  Status;
  UINTN       CommSize;

  //
  // Send a SMM communication command for Scheck/LockConfig registration
  //
  DebugPrint (DEBUG_INFO, "Register for Scheck/LockConfig Callback\n");
  return EFI_SUCCESS;
}

//
// =============================================================================
// S3 Boot Script Save
// =============================================================================
//

/**
  Driver unload / S3 boot script close handler.

  This function is called when the driver is being unloaded (or on error path
  from entry point). It closes all S3 boot script resources that were opened
  during initialization. References are from PiDxeS3BootScriptLib.

  The order is:
    1. Close boot script table write if open.
    2. Close SMM communication protocol references.
    3. Close SMM LockBox protocol references.
    4. Clear SMM ready-to-lock flag.
    5. Close SMM Base2 protocol.
**/
EFI_STATUS
CloseS3BootScriptResources (
  VOID
  )
{
  DebugPrint (DEBUG_INFO, "%a() in %a module\n", __FUNCTION__, "TxtDxe");

  //
  // Close Boot Script Table Write if opened
  //
  if (mSmmCommunicationProtocol != NULL) {
    if (gBootServices->CloseEvent (
          ((EFI_SMM_COMMUNICATION_PROTOCOL *)mSmmCommunicationProtocol)->SmmBootScriptDone
          ) < 0) {
      AssertBreak (
        "e:\\hs\\MdeModulePkg\\Library\\PiDxeS3BootScriptLib\\BootScriptSave.c",
        707,
        "!EFI_ERROR (Status)"
        );
    }
  }

  //
  // Close SMM Communication protocol
  //
  if (mSmmBase2Protocol != NULL) {
    if (mSmmCommunicationProtocol != NULL) {
      if (((EFI_SMM_BASE2_PROTOCOL *)mSmmBase2Protocol)->InSmm (
            mSmmBase2Protocol,
            NULL
            ) == EFI_SUCCESS) {
        //
        // Inside SMM; close SMM communication protocol
        //
        if (((EFI_SMM_BASE2_PROTOCOL *)mSmmBase2Protocol)->Communicate (
              mSmmBase2Protocol,
              NULL,
              NULL
              ) < 0) {
          AssertBreak (
            "e:\\hs\\MdeModulePkg\\Library\\PiDxeS3BootScriptLib\\BootScriptSave.c",
            720,
            "!EFI_ERROR (Status)"
            );
        }
      }
    }

    if (mPiSmmCommunicationProtocol != NULL) {
      if (((EFI_SMM_BASE2_PROTOCOL *)mSmmBase2Protocol)->Communicate (
            mSmmBase2Protocol,
            NULL,
            NULL
            ) < 0) {
        AssertBreak (
          "e:\\hs\\MdeModulePkg\\Library\\PiDxeS3BootScriptLib\\BootScriptSave.c",
          731,
          "!EFI_ERROR (Status)"
          );
      }
    }

    if (mSmmLockBoxProtocol != NULL) {
      if (((EFI_SMM_BASE2_PROTOCOL *)mSmmBase2Protocol)->Communicate (
            mSmmBase2Protocol,
            NULL,
            NULL
            ) < 0) {
        AssertBreak (
          "e:\\hs\\MdeModulePkg\\Library\\PiDxeS3BootScriptLib\\BootScriptSave.c",
          742,
          "!EFI_ERROR (Status)"
          );
      }
    }
  }

  //
  // Clear SMM ready-to-lock flag and close SMM Base2
  //
  if (mSmmReadyToLockEvent != NULL) {
    if (gBootServices->CloseEvent (mSmmReadyToLockEvent) < 0) {
      AssertBreak (
        "e:\\hs\\MdeModulePkg\\Library\\PiDxeS3BootScriptLib\\BootScriptSave.c",
        751,
        "!EFI_ERROR (Status)"
        );
    }

    GetPcdProtocol ();
    if (((EFI_PCD_PROTOCOL *)mPcdProtocol)->SetBool (137, FALSE) < 0) {
      AssertBreak (
        "e:\\hs\\MdeModulePkg\\Library\\PiDxeS3BootScriptLib\\BootScriptSave.c",
        753,
        "!EFI_ERROR (Status)"
        );
    }
  }

  if (mSmmBase2Protocol != NULL && mSmmBase2ProtocolReadyToLock != FALSE) {
    if (((EFI_SMM_BASE2_PROTOCOL *)mSmmBase2Protocol)->InSmm (
          mSmmBase2Protocol,
          NULL
          ) >= 0) {
      if (((EFI_SMM_BASE2_PROTOCOL *)mSmmBase2Protocol)->Communicate (
            mSmmBase2Protocol,
            NULL,
            NULL
            ) < 0) {
        AssertBreak (
          "e:\\hs\\MdeModulePkg\\Library\\PiDxeS3BootScriptLib\\BootScriptSave.c",
          757,
          "!EFI_ERROR (Status)"
          );
      }

      GetPcdProtocol ();
      if (((EFI_PCD_PROTOCOL *)mPcdProtocol)->SetBool (138, FALSE) < 0) {
        AssertBreak (
          "e:\\hs\\MdeModulePkg\\Library\\PiDxeS3BootScriptLib\\BootScriptSave.c",
          759,
          "!EFI_ERROR (Status)"
          );
      }
    }
  }

  return EFI_SUCCESS;
}

//
// =============================================================================
// TXT DXE Protocol Installation
// =============================================================================
//

/**
  Install the TXT DXE Protocol.

  Locates the protocol GUID, and if it is not already installed, installs
  a new protocol instance with the TXT DXE service functions.

  @param[in]  ImageHandle   Handle of the driver image.
  @param[in]  SystemTable   Pointer to the UEFI system table.

  @retval EFI_SUCCESS  Protocol installed successfully or already present.
  @retval other        Protocol installation failed.
**/
EFI_STATUS
InstallTxtDxeProtocol (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE *SystemTable
  )
{
  EFI_STATUS  Status;
  VOID       *Interface;

  //
  // Check if protocol is already installed
  //
  Status = gBootServices->LocateProtocol (
                            &gTxtDxeProtocolGuid,
                            NULL,
                            &Interface
                            );
  if (!EFI_ERROR (Status)) {
    if (Interface != NULL) {
      return EFI_ALREADY_STARTED;
    }
  }

  //
  // Set up the protocol instance
  //
  gTxtDxeProtocol.LaunchBiosAcm    = TxtDxeLaunchBiosAcm;
  gTxtDxeProtocolHandle             = ImageHandle;

  //
  // Install the protocol
  //
  Status = gBootServices->InstallProtocolInterface (
                            &gTxtDxeProtocolHandle,
                            &gTxtDxeProtocolGuid,
                            EFI_NATIVE_INTERFACE,
                            &gTxtDxeProtocol
                            );
  if (!EFI_ERROR (Status)) {
    //
    // Verify the protocol was installed correctly by locating it again
    //
    Interface = NULL;
    Status = gBootServices->LocateProtocol (
                              &gTxtDxeProtocolGuid,
                              NULL,
                              &Interface
                              );
    if (!EFI_ERROR (Status) && Interface != &gTxtDxeProtocol) {
      return EFI_ALREADY_STARTED;
    }
  }

  return Status;
}

//
// =============================================================================
// Platform ACM Launch (Assembly Wrapper) -- sub_4700
// =============================================================================
//

/**
  Platform-specific BIOS ACM launch routine.

  This function performs the low-level CPU configuration required before
  transferring control to the BIOS ACM. It is typically implemented in
  assembly and handles:

    1. Save GDT, IDT, CR0, CR3, CR4.
    2. If Flags indicates "with APs", save GDTR/IDTR and MTRRs.
    3. Disable caches: WBINVD (if APs present) or INVD (if not).
    4. Disable MTRRs (MSR 0x2FF = 0).
    5. Clear all MTRR physbase/physmask pairs.
    6. Set up MTRR ranges for the ACM:
       - For each 2M page in the ACM range, compute the page order,
         write MTRR_PHYSBASE (with MEM_TYPE_WB = 6) and MTRR_PHYSMASK
         (with valid bit and ~(size-1)).
    7. Enable MCE (CR4.MCE), OSFXSR (CR4.OSFXSR), and OSXMMEXCPT
       (CR4.OSXMMEXCPT).
    8. Set EM (emulation) and MP (monitor coprocessor) bits in CR0.
    9. Zero all machine check banks (MCi_STATUS) from bank 0 to bank
       count.
   10. Perform far return (retf) to the ACM entry point.

  @param[in]  BiosAcmAddress  Physical address of the ACM.
  @param[in]  Flags           0 = BSP only, non-zero = with APs.
**/
VOID
PlatformLaunchBiosAcm (
  IN  UINT64   BiosAcmAddress,
  IN  UINT64   Flags
  )
{
  //
  // This function is implemented in assembly (sub_4700). The equivalent C
  // logic is documented here for reference:
  //
  //   UINT64  GdtBackup[2];   // GDT limit + base
  //   UINT64  IdtBackup[2];   // IDT limit + base
  //   UINTN   Cr0, Cr3, Cr4;
  //
  //   if (Flags != 0) {
  //     Sgdt (&GdtBackup);
  //     Sidt (&IdtBackup);
  //     // Save MCG_CAP MTRR state
  //   }
  //
  //   Cr4 = AsmReadCr4 ();
  //   AsmWriteCr4 (Cr4 | 0x4208);  // Enable MCE, OSFXSR, OSXMMEXCPT
  //
  //   Cr0 = AsmReadCr0 ();
  //   AsmWriteCr0 ((Cr0 & 0x9FFFFFDF) | 0x40000020);  // Set EM, MP; clear NE, TS, EM?
  //
  //   if (Flags != 0)  Wbinvd ();
  //   else              Invd ();
  //
  //   AsmWriteMsr64 (0x2FF, 0);  // Disable MTRRs
  //
  //   // Clear all MTRR pairs
  //   for (Index = 0; Index < N; Index++) {
  //     AsmWriteMsr64 (0x200 + Index*2,     0);  // MTRR_PHYSBASE
  //     AsmWriteMsr64 (0x200 + Index*2 + 1, 0);  // MTRR_PHYSMASK
  //   }
  //
  //   // Set up MTRRs for ACM memory range
  //   for (Remaining = AcmSize; Remaining > 0; ) {
  //     // Find largest power-of-two aligned region
  //     Reg = MtrrIndex++;
  //     AsmWriteMsr64 (0x200 + Reg*2,     AcmBase | 6);  // WB
  //     AsmWriteMsr64 (0x200 + Reg*2 + 1, ~(Size-1) | 0xF00000800);
  //     AcmBase += Size;
  //     Remaining -= Size;
  //   }
  //
  //   AsmWriteMsr64 (0x2FF, 0x800);  // Enable MTRRs
  //   AsmWriteMsr64 (0x17B, 0);       // Clear MCG_CTL
  //
  //   // Zero all machine check banks
  //   for (Bank = 0; Bank < McgBankCount; Bank++) {
  //     AsmWriteMsr64 (0x400 + Bank*4 + 1, 0);  // MCi_STATUS
  //   }
  //
  //   // Far return to ACM entry point
  //   AsmFarReturn (BiosAcmAddress, 0x08);  // Code segment selector
  //
}

//
// =============================================================================
// InitializeLtDxeLib -- sub_DD0
// =============================================================================
//

/**
  Initialize the LT (LaGrande Technology / TXT) DXE library.

  This function:
    1. Disables the NMI in CMOS and disables the NMI enable bit on port 0x70.
    2. Locates and caches the SMM Communication protocol (qword_6C50).
    3. Locates and caches the MP Services protocol (qword_6C58).
    4. Checks if the current platform supports TXT (via PCD).
    5. Locates the TXT Device Memory HOB and TXT Platform Policy HOB.
    6. Validates that a BIOS ACM address is provided.
    7. Gets the number of APs and their APIC IDs via MP Services.
    8. Sets up the AP wake-up vector.

  @param[in]  ImageHandle  Handle of the driver image.
  @param[in]  SystemTable  Pointer to the UEFI system table.

  @retval EFI_SUCCESS           Initialization succeeded.
  @retval EFI_UNSUPPORTED       Platform does not support TXT.
  @retval EFI_NOT_FOUND         Required HOB or protocol not found.
  @retval EFI_INVALID_PARAMETER BIOS ACM address not configured.
**/
EFI_STATUS
InitializeLtDxeLib (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE *SystemTable
  )
{
  EFI_STATUS                 Status;
  EFI_MP_SERVICES_PROTOCOL  *MpServices;
  EFI_SMM_COMMUNICATION_PROTOCOL *SmmComm;
  UINTN                      BufferSize;
  UINTN                      Index;

  //
  // Save ImageHandle and SystemTable globally (also set in DriverInit)
  //
  gImageHandle = ImageHandle;
  gSystemTable = SystemTable;

  //
  // Enable access to CMOS: clear NMI disable bit on port 0x70
  //
  IoWrite8 (0x70, IoRead8 (0x530) & 0xBF);
  IoWrite8 (0x530, IoRead8 (0x530) & 0xBF);

  //
  // Locate the SMM Communication protocol for S3 boot script support
  //
  Status = gBootServices->LocateProtocol (
                            &gEfiSmmCommunicationProtocolGuid,
                            NULL,
                            (VOID **)&SmmComm
                            );
  if (Status < 0) {
    AssertBreak (
      "e:\\hs\\ServerCommonPkg\\Universal\\GetSec\\Dxe\\TxtDxeLib.c",
      227,
      "!EFI_ERROR (Status)"
      );
  }

  //
  // Locate the MP Services protocol for AP management
  //
  Status = gBootServices->LocateProtocol (
                            &gEfiMpServiceProtocolGuid,
                            NULL,
                            (VOID **)&MpServices
                            );
  if (Status < 0) {
    AssertBreak (
      "e:\\hs\\ServerCommonPkg\\Universal\\GetSec\\Dxe\\TxtDxeLib.c",
      237,
      "!EFI_ERROR (Status)"
      );
    return Status;
  }

  //
  // Check if TXT is supported on this platform via PCD
  //
  GetPcdProtocol ();
  if (!((EFI_PCD_PROTOCOL *)mPcdProtocol)->GetBool (26)) {
    return EFI_UNSUPPORTED;
  }

  //
  // Locate TXT device memory policy from HOB
  //
  Status = LocateTxtDeviceMemoryPolicy ();
  if (EFI_ERROR (Status)) {
    DebugPrint (DEBUG_ERROR,
      "gEfiPlatformTxtDeviceMemoryGuid not found! TxtDxe return error!\n");
    return Status;
  }

  //
  // Locate TXT platform policy from HOB
  //
  Status = LocateTxtPlatformPolicy ();
  if (EFI_ERROR (Status)) {
    DebugPrint (DEBUG_ERROR,
      "gEfiPlatformTxtPolicyDataGuid not found! TxtDxe return error!\n");
    return Status;
  }

  //
  // Validate that the BIOS ACM address is configured
  //
  if (mTxtPlatformPolicy->BiosAcmAddress == 0) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // Get MP services info: number of processors
  //
  Status = MpServices->GetNumberOfProcessors (MpServices, &mApCount, NULL);
  if (Status < 0) {
    AssertBreak (
      "e:\\hs\\ServerCommonPkg\\Universal\\GetSec\\Dxe\\TxtDxeLib.c",
      300,
      "!EFI_ERROR (Status)"
      );
  }

  //
  // mApCount includes the BSP; subtract 1 to get AP count
  //
  mApCount--;
  DebugPrint (DEBUG_INFO, "ApCount - 0x%08x\n", mApCount);

  //
  // If there are APs, get their APIC IDs and set up the wake-up vector
  //
  if (mApCount > 0) {
    EFI_STATUS  ApStatus;
    UINT32      ApicIds[MAX_CPUS];

    //
    // Query each AP for its APIC ID via GetProcessorInfo
    //
    ApStatus = GetMpTableApicIds (&mApCount, ApicIds);
    if (ApStatus < 0) {
      AssertBreak (
        "e:\\hs\\ServerCommonPkg\\Universal\\GetSec\\Dxe\\TxtDxeLib.c",
        306,
        "!EFI_ERROR (Status)"
        );
    }

    DebugPrint (DEBUG_INFO, "ApVector - 0x%08x\n", mApWakeUpVector);

    //
    // Iterate and log each APIC ID
    //
    for (Index = 0; Index < mApCount; Index++) {
      DebugPrint (DEBUG_INFO, "TXT-LIB APIC[%d] = 0x%08x\n", Index, ApicIds[Index]);
    }
  }

  return EFI_SUCCESS;
}

//
// =============================================================================
// Entry Point and Driver Init
// =============================================================================
//

/**
  Driver initialization -- sub_47C.

  Called by _ModuleEntryPoint to set up the global protocol pointers
  (BS, RT, DS), enable SMM, initialize the HOB list, enable MTRR for
  SINIT, and perform a brief delay.

  This function corresponds to the auto-generated DXE driver init sequence
  plus TxtDxe-specific setup.

  @param[in]  ImageHandle  Handle of the loaded driver image.
  @param[in]  SystemTable  Pointer to the UEFI system table.
**/
EFI_STATUS
DriverInit (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE *SystemTable
  )
{
  EFI_STATUS           Status;
  UINT16               LtCheck;
  BOOLEAN              LtEnabled;
  UINT32               Delay;
  UINT32               CmosVal;

  //
  // Save protocol pointers
  //
  gImageHandle    = ImageHandle;
  gSystemTable    = SystemTable;
  gBootServices   = SystemTable->BootServices;
  gRuntimeServices = SystemTable->RuntimeServices;

  AssertBreak_NotNull (gBootServices,   "gBS != NULL");
  AssertBreak_NotNull (gRuntimeServices, "gRT != NULL");

  //
  // Locate the DXE Services Table via the protocol database
  //
  Status = SystemTable->BootServices->LocateProtocol (
                                        &gEfiDxeServicesTableGuid,
                                        NULL,
                                        &gDxeServicesTable
                                        );
  if (Status < 0) {
    AssertBreak (
      "e:\\hs\\MdePkg\\Library\\DxeServicesTableLib\\DxeServicesTableLib.c",
      64,
      "!EFI_ERROR (Status)"
      );
  }
  AssertBreak_NotNull (gDxeServicesTable, "gDS != NULL");

  //
  // Locate the MM PCI User Access protocol (DxeMmPciBaseLib)
  //
  if (mPciUsra == NULL) {
    Status = gBootServices->LocateProtocol (
                              &gEfiMmPciBaseProtocolGuid,
                              NULL,
                              &mPciUsra
                              );
    if (Status < 0) {
      AssertBreak (
        "e:\\hs\\CpRcPkg\\Library\\DxeMmPciBaseLib\\DxeMmPciBaseLib.c",
        52,
        "!EFI_ERROR (Status)"
        );
    }
    if (mPciUsra == NULL) {
      AssertBreak (
        "e:\\hs\\CpRcPkg\\Library\\DxeMmPciBaseLib\\DxeMmPciBaseLib.c",
        53,
        "mPciUsra != NULL"
        );
    }
  }

  //
  // Initialize HOB list
  //
  GetHobList ();

  //
  // Get PCD protocol and enable MTRR for SINIT if not already enabled
  //
  GetPcdProtocol ();
  if (((EFI_PCD_PROTOCOL *)mPcdProtocol)->GetBool (PCD_SINIT_MTRR_ENABLE) >= 0) {
    EFI_PHYSICAL_ADDRESS  SinitMemoryBase;

    SinitMemoryBase = ((EFI_PCD_PROTOCOL *)mPcdProtocol)->Get64 (PCD_SINIT_MTRR_BASE);
    EnableSinitMtrr (SinitMemoryBase);
    ((EFI_PCD_PROTOCOL *)mPcdProtocol)->SetBool (PCD_SINIT_MTRR_ENABLE, TRUE);
  }

  //
  // Check if LT (TXT) is supported on this CPU
  //
  LtCheck = IsLtProcessor ();
  LtEnabled = (LtCheck & CPUID_LT_BIT) != 0;

  //
  // Delay loop: read/write timer counter to wait for hardware stabilization
  //
  CmosVal = IoRead8 (0x70) & 0x80 | 0x4B;  // CMOS offset 0x4B, NMI preserved
  Delay = 1288;  // ~1ms delay based on platform timer
  {
    UINT32  Start;
    UINT32  Current;

    Start = IoRead32 (0x44);  // Timer value
    do {
      Current = IoRead32 (0x44);
    } while (((Start + Delay - Current) & 0x800000) == 0);  // Spin until delta >= 357
  }

  //
  // Restore LT configuration if it was modified during the delay
  //
  if (LtEnabled) {
    RestoreLtConfig ();
  } else {
    DisableLtConfig ();
  }

  //
  // Final initialization step (AutoGen.c line 495)
  //
  Status = FinalInitStep ();
  if (Status < 0) {
    AssertBreak (
      "e:\\hs\\Build\\HR6N0XMLK\\DEBUG_VS2015\\X64\\ServerCommonPkg\\Universal\\GetSec\\Dxe\\TxtDxe\\DEBUG\\AutoGen.c",
      495,
      "!EFI_ERROR (Status)"
      );
  }

  return Status;
}

//
// =============================================================================
// Main Driver Entry Dispatch -- original sub_AA8
// =============================================================================
//

/**
  Main driver entry dispatch (TxtDxe entry logic proper).

  Called from _ModuleEntryPoint after DriverInit completes. This function
  performs the TXT-specific initialization:
    1. Registers the Scheck/LockConfig callback.
    2. Calls InitializeLtDxeLib to set up TXT library pointers and HOBs.
    3. If InitializeLtDxeLib succeeds:
       a. Applies the TXT policy to platform config.
       b. Checks if the CPU is an LT-capable processor.
       c. If yes:
          i.  Locates the SMM Communication protocol for S3 boot script.
          ii. Checks TXT enable MSR (0x3A) and LT.SPAD.HIGH.
          iii. If LT.SPAD.HIGH indicates ACM success:
               - Install the TXT DXE Protocol.
               - If installation succeeds, return success.
          iv.  If LT.SPAD.HIGH indicates ACM failure:
               - Call HandleAcmError() to check BIOS setup policy.
               - If setup allows ignoring, fall through.
               - If not, trigger reset.
       d. If not LT-capable:
          - Log "Not LT processor", clear state.
    4. On failure to initialize:
       - Log error, clear state.
    5. If TXT protocol not installed because LT not enabled or error,
       attempt to close S3 boot script resources.
       If that fails, continue.
  Returns 0 (EFI_SUCCESS) at end regardless, since the driver should
  not prevent boot even if TXT is unavailable.

  @param[in]  ImageHandle  Handle of the loaded driver image.
  @param[in]  SystemTable  Pointer to the UEFI system table.

  @retval EFI_SUCCESS  Driver initialized (possibly with TXT unavailable).
**/
EFI_STATUS
TxtDxeMain (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE *SystemTable
  )
{
  EFI_STATUS           Status;
  EFI_SMM_COMMUNICATION_PROTOCOL *SmmComm;

  //
  // Step 1: Register for Scheck/LockConfig callback (SMM)
  //
  RegisterForScheckLockConfigCallback ();

  //
  // Step 2: Initialize the TXT DXE library (HOBs, protocols, APIC table)
  //
  Status = InitializeLtDxeLib (ImageHandle, SystemTable);
  if (EFI_ERROR (Status)) {
    DebugPrint (DEBUG_ERROR, "InitializeLtDxeLib Error: %r\n", Status);
    mBiosAcmCalled = FALSE;
    return EFI_SUCCESS;
  }

  //
  // Step 3: Apply TXT policy from HOB to platform configuration
  //
  {
    UINT8  TxtPolicy;

    TxtPolicy = (UINT8)mTxtPlatformPolicy->BiosAcmPolicy;  // Byte 15 of the HOB data
    ApplyTxtPolicyToPlatformConfig (TxtPolicy);
  }

  //
  // Step 4: Check if this is an LT-enabled processor
  //
  {
    UINT32  CpuidEcx;

    AsmCpuid (CPUID_LT_SUPPORT, NULL, NULL, &CpuidEcx, NULL);
    if ((CpuidEcx & CPUID_LT_BIT) == 0) {
      DebugPrint (DEBUG_ERROR, "LtDxe Error: Not LT processor\n");
      mBiosAcmCalled = FALSE;
      return EFI_SUCCESS;
    }
  }

  //
  // Step 5: LT-enabled processor -- proceed with ACM launch
  //

  //
  // 5a: Locate SMM Communication protocol for S3 boot script
  //
  Status = gBootServices->LocateProtocol (
                            &gEfiSmmCommunicationProtocolGuid,
                            NULL,
                            (VOID **)&SmmComm
                            );
  if (Status < 0) {
    AssertBreak (
      "e:\\hs\\ServerCommonPkg\\Universal\\GetSec\\Dxe\\TxtDxeLib.c",
      451,
      "!EFI_ERROR (Status)"
      );
  }

  //
  // 5b: Check TXT enable MSR
  //
  if (!IsTxtEnabled ()) {
    DebugPrint (DEBUG_ERROR, "LT_SPAD_HIGH (0xFED300A4): %r\n",
      *(UINT32 *)TXT_SPAD_HIGH_REG);
    //
    // TXT not enabled, fall through to non-TXT path
    //
    Status = EFI_UNSUPPORTED;
  } else {
    //
    // TXT is enabled -- check ACM result
    //
    DebugPrint (DEBUG_INFO, "LT_SPAD_HIGH (0xFED300A4): %r\n",
      *(UINT32 *)TXT_SPAD_HIGH_REG);

    if (IsBiosAcmSuccessful ()) {
      //
      // ACM completed successfully (or no error) -- install protocol
      //
      DebugPrint (DEBUG_ERROR, "Install TXT_DXE_PROTOCOL...\n");
      Status = InstallTxtDxeProtocol (ImageHandle, SystemTable);
      if (!EFI_ERROR (Status)) {
        DebugPrint (DEBUG_ERROR, "Success\n");
        return EFI_SUCCESS;
      }
      DebugPrint (DEBUG_ERROR, "Error\n");
    } else {
      //
      // ACM failed -- handle according to BIOS setup policy
      //
      HandleAcmError (*(UINT32 *)TXT_SPAD_HIGH_REG);
    }
  }

  //
  // If we get here, LT is not enabled or ACM failed
  //
  DebugPrint (DEBUG_ERROR, "Lt not enabled\n");

  //
  // Attempt to close S3 boot script resources for a clean state
  //
  {
    UINT8  ResetStatus;

    Status = SmmComm->SmmReadyToLock (SmmComm, &ResetStatus);
    if (Status < 0) {
      AssertBreak (
        "e:\\hs\\ServerCommonPkg\\Universal\\GetSec\\Dxe\\TxtDxeLib.c",
        403,
        "!EFI_ERROR (Status)"
        );
    }
    if ((ResetStatus & 1) == 0) {
      //
      // System not resetting -- close S3 boot script resources
      //
      Status = TxtDxeCleanup ();
      if (Status < 0) {
        AssertBreak (
          "e:\\hs\\ServerCommonPkg\\Universal\\GetSec\\Dxe\\TxtDxeLib.c",
          555,
          "!EFI_ERROR (Status)"
          );
      }
    }
  }

  return EFI_SUCCESS;
}

//
// =============================================================================
// Driver Unload Handler -- sub_2FEC / sub_748 equivalent
// =============================================================================
//

/**
  Driver unload / cleanup handler.

  Called from the entry error path (sub_748) or when the driver is being
  unloaded. Closes all S3 boot script resources and SMM protocol handles
  opened during InitializeLtDxeLib and DriverInit.

  @retval EFI_SUCCESS  Cleanup completed successfully.
**/
EFI_STATUS
TxtDxeCleanup (
  VOID
  )
{
  return CloseS3BootScriptResources ();
}

/**
  Unload the TxtDxe driver.

  Called by the UEFI core when the driver needs to be unloaded. Equivalent
  to the AutoGen.c unload handler (sub_748 + sub_2FEC).

  @param[in]  ImageHandle  Handle of the driver image being unloaded.

  @retval EFI_SUCCESS  Driver unloaded successfully.
**/
EFI_STATUS
EFIAPI
TxtDxeUnload (
  IN EFI_HANDLE  ImageHandle
  )
{
  EFI_STATUS  Status;

  Status = TxtDxeCleanup ();
  if (Status < 0) {
    AssertBreak (
      "e:\\hs\\Build\\HR6N0XMLK\\DEBUG_VS2015\\X64\\ServerCommonPkg\\Universal\\GetSec\\Dxe\\TxtDxe\\DEBUG\\AutoGen.c",
      518,
      "!EFI_ERROR (Status)"
      );
  }

  return Status;
}

//
// =============================================================================
// Module Entry Point -- _ModuleEntryPoint
// =============================================================================
//

/**
  UEFI DXE driver entry point for TxtDxe.

  This is the first function called when the DXE core loads this driver.
  It performs:
    1. Initialize UEFI core globals (gImageHandle, gST, gBS, gRT, gDS)
       via DriverInit().
    2. Execute the main TxtDxe initialization logic via TxtDxeMain().
    3. If main initialization fails, attempt unload/cleanup.

  @param[in]  ImageHandle  Handle of the loaded driver image.
  @param[in]  SystemTable  Pointer to the UEFI system table.

  @return  Status code from the initialization sequence.
**/
EFI_STATUS
EFIAPI
_ModuleEntryPoint (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE *SystemTable
  )
{
  EFI_STATUS  Status;

  //
  // Step 1: Initialize UEFI core protocols and driver globals
  //
  Status = DriverInit (ImageHandle, SystemTable);

  //
  // Step 2: Execute TXT-specific initialization
  //
  Status = TxtDxeMain (ImageHandle, SystemTable);

  //
  // Step 3: If initialization failed, perform cleanup via unload handler
  //
  if (EFI_ERROR (Status)) {
    Status = TxtDxeUnload (ImageHandle);
  }

  return Status;
}