Newer
Older
AMI-Aptio-BIOS-Reversed / AmiTcgPlatformDxe / AmiTcgPlatformDxe.c
@Ajax Dong Ajax Dong 2 days ago 66 KB Init
/** @file
  AmiTcgPlatformDxe - AMI TCG Platform DXE Driver

  This is the AMI TCG (Trusted Computing Group) Platform DXE driver for the
  HR650X BIOS.  It provides TPM/TCG platform initialization during the DXE
  phase, including:

  - TPM 1.2 and TPM 2.0 protocol detection and dispatch
  - Physical Presence Interface (PPI) request processing
  - TPM PER BIOS flag management
  - Measurement of boot variables (SecureBoot, PK, KEK, db, dbx)
  - Option ROM measurement
  - Ready-to-Boot notification callback
  - TPM state synchronization with UEFI setup variables

  Build source path: e:\hs\AmiModulePkg\TCG2\Common\AmiTcgPlatformDxe\
  Source file: AmiTcgPlatformDxe.c

  Copyright (C) 2025 American Megatrends Inc. (AMI)
  SPDX-License-Identifier: BSD-2-Clause-Patent
**/

#include <Uefi.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/UefiHiiServicesLib.h>
#include <Library/DxeHobLib.h>
#include <Library/HiiLib.h>
#include <Library/PrintLib.h>
#include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Protocol/TcgService.h>
#include <Protocol/Tcg2Protocol.h>
#include <Protocol/TrEEProtocol.h>
#include <Protocol/HiiFont.h>
#include <Protocol/HiiDatabase.h>
#include <Protocol/HiiConfigRouting.h>
#include <Protocol/HiiConfigAccess.h>
#include <Protocol/HiiPackageList.h>
#include <Guid/EventGroup.h>

#include "AmiTcgPlatformDxe.h"

// ===========================================================================
// Global Variable Definitions
// ===========================================================================

//
// Standard UEFI global variables from library constructors
//
EFI_HANDLE            ImageHandle      = NULL;
EFI_SYSTEM_TABLE      *SystemTable     = NULL;
EFI_BOOT_SERVICES     *BootServices    = NULL;
EFI_RUNTIME_SERVICES  *RuntimeServices = NULL;

//
// Module-specific globals
//
UINT8   byte_8D18;                    // SecureBoot status shadow
UINT8   byte_8D19;                    // TPM platform type shadow
UINT64  qword_8D08;                   // Saved protocol handle
UINT64  qword_8D10;                   // Ready-to-boot invocation counter
UINT64  qword_8D60;                   // Cached HOB list pointer
UINT64  qword_8D68;                   // Image handle cache
UINT64  qword_8D70;                   // HII Database Protocol
UINT64  qword_8D78;                   // Protocol instance slots
UINT64  qword_8D80;
UINT64  qword_8D88;
UINT64  qword_8D90;
UINT64  qword_9420;                   // HII Handle
UINT64  qword_9428;                   // Registered ready-to-boot event
UINT32  dword_8DDC;                   // Reset type parameter
UINT8   byte_8DA8;                    // TPM presence flag (non-zero = 2.0)

// ===========================================================================
// GUID Definitions
// ===========================================================================

EFI_GUID  unk_8A20;
EFI_GUID  unk_8A30;
EFI_GUID  unk_8A50;
EFI_GUID  unk_8A80;
EFI_GUID  unk_8AB0;
EFI_GUID  unk_8AD0;
EFI_GUID  unk_8AE0;
EFI_GUID  unk_8B00;
EFI_GUID  unk_8B20;
EFI_GUID  unk_8B30;
EFI_GUID  unk_8B40;
EFI_GUID  unk_8B50;
EFI_GUID  unk_8B60;
EFI_GUID  unk_8B80;
EFI_GUID  unk_8B90;
EFI_GUID  unk_8BC0;
EFI_GUID  unk_8BD0;
EFI_GUID  unk_8BE0;
EFI_GUID  unk_8C10;
EFI_GUID  unk_8C40;
EFI_GUID  unk_8C50;
EFI_GUID  unk_8C60;
EFI_GUID  unk_8C70;

//
// Protocol notify registrations
//
VOID  *off_8CB0;
VOID  *unk_8DC0;
VOID  *unk_8DE0;
VOID  *unk_8DE8;
UINT8  unk_8DF0[512];
UINT8  unk_8DFE;

//
// GUID constants for known algorithm identifiers
//
CONST UINT64  xmmword_6B40[2] = { 0, 0 };  // SHA-1 algorithm GUID
CONST UINT64  xmmword_8A50[2] = { 0, 0 };  // Default algorithm GUID

// ===========================================================================
// Local Helper Functions
// ===========================================================================

/**
  Debug print wrapper.  Formats and prints a debug message at the given
  error level.

  @param[in] ErrorLevel  Debug error severity level.
  @param[in] Format      Format string.
  @param[in] ...          Variable arguments.
**/
VOID
DebugPrint (
  IN UINTN   ErrorLevel,
  IN CHAR8   *Format,
  ...
  )
{
  VA_LIST  Marker;

  VA_START (Marker, Format);
 DEBUG ((ErrorLevel, Format, Marker));
  VA_END (Marker);
}

/**
  Assertion failure handler.  Called when an ASSERT condition evaluates
  to FALSE.

  @param[in] FileName     Source file name.
  @param[in] LineNumber   Line number.
  @param[in] Description  Assertion text.
**/
VOID
AssertFailure (
  IN CHAR8   *FileName,
  IN UINTN   LineNumber,
  IN CHAR8   *Description
  )
{
  DEBUG ((EFI_D_ERROR, "ASSERT [%a](%lu): %a\n", FileName, LineNumber, Description));
  CpuDeadLoop ();
}

/**
  Returns the length of a UCS-2 string (number of characters).

  @param[in] String  Null-terminated UCS-2 string.

  @return Number of characters excluding the null terminator.
**/
UINTN
StrLen (
  IN UINT16  *String
  )
{
  UINTN  Length;

  ASSERT (String != NULL);
  ASSERT (((UINTN)String & 1) == 0);

  for (Length = 0; String[Length] != 0; Length++) {
    ;
  }

  return Length;
}

/**
  Returns the byte-size of a UCS-2 string including the null terminator.

  @param[in] String  Null-terminated UCS-2 string.

  @return Size in bytes, or 0 if String is NULL or empty.
**/
UINTN
StrSize (
  IN UINT16  *String
  )
{
  return (StrLen (String) + 1) * sizeof (UINT16);
}

/**
  Copies a UCS-2 string with overlap-safe handling.  Equivalent to
  StrCpyS with overlap checking.

  @param[out] Destination  Destination buffer.
  @param[in]  Source       Source string.

  @return Destination.
**/
UINT16 *
StrCatOverlap (
  OUT UINT16  *Destination,
  IN  UINT16  *Source
  )
{
  UINT16  *Ptr;
  INTN    Offset;
  UINT16  Char;

  Ptr    = Destination + StrLen (Destination);
  ASSERT (Ptr != NULL);
  ASSERT (((UINTN)Ptr & 1) == 0);
  ASSERT ((Ptr - Source) >> 1 <= StrLen (Source));
  ASSERT ((Source - Ptr) >> 1 <= StrLen (Source));

  Char = *Source;
  if (Char != 0) {
    Offset = Source - Ptr;
    do {
      *Ptr = Char;
      Ptr++;
      Char = *(UINT16 *)((UINT8 *)Ptr + Offset);
    } while (Char != 0);
  }

  *Ptr = 0;
  ASSERT (StrSize (Destination) != 0);

  return Destination;
}

// ===========================================================================
// EFI Module Entry Point
// ===========================================================================

/**
  The UEFI module entry point.

  Initializes the driver by saving UEFI table pointers, locating HII
  services, installing the TCG platform protocol, measuring secure boot
  variables, and registering the ready-to-boot notification.

  @param[in] ImageHandle  The firmware allocated handle for the EFI image.
  @param[in] SystemTable  A pointer to the EFI System Table.

  @retval EFI_SUCCESS           The entry point executed successfully.
  @retval EFI_INVALID_PARAMETER ImageHandle or SystemTable is NULL.
  @retval EFI_UNSUPPORTED       A required protocol could not be located.
**/
EFI_STATUS
EFIAPI
ModuleEntryPoint (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  //
  // Save UEFI table pointers and locate HII protocols.
  //
  DriverInit (ImageHandle, SystemTable);

  //
  // Register HII package list, measure secure variables, and register
  // the reset notification callback.
  //
  return RegisterAndMeasure (ImageHandle);
}

// ===========================================================================
// Driver Initialization
// ===========================================================================

/**
  Save UEFI boot/runtime service table pointers and locate HII protocols.

  Initializes the module's global table pointers (BootServices,
  RuntimeServices), then locates the HII Font, Database, ConfigRouting,
  and ConfigAccess protocols.

  @param[in] ImageHandle  The module's image handle.
  @param[in] SystemTable  The UEFI system table.
**/
EFI_STATUS
DriverInit (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  EFI_STATUS  Status;

  //
  // Save the image handle and system table.
  //
  ::ImageHandle = ImageHandle;
  ASSERT (::ImageHandle != NULL);

  ::SystemTable = SystemTable;
  ASSERT (::SystemTable != NULL);

  //
  // Save the boot services and runtime services pointers.
  //
  BootServices     = SystemTable->BootServices;
  ASSERT (BootServices != NULL);

  RuntimeServices  = SystemTable->RuntimeServices;
  ASSERT (RuntimeServices != NULL);

  //
  // Initialize the HOB list pointer.
  //
  InternalGetHobList ();

  //
  // Save the image handle for protocol lookups.
  //
  qword_8D68 = sub_4BC4 ();

  //
  // Detect TPM type (enable TPM 2.0 path if applicable).
  //
  if (*(CHAR8 *)sub_6000 (1024068) >= 0) {
    sub_6740 (sub_6000 (1024064));
    *(UINT8 *)sub_6000 (1024068) |= 0x80;
  }

  //
  // Wait for TPM interface to become ready.
  //
  {
    UINT16  TpmStatus;
    UINT64  Ticks;
    BOOLEAN TpmPresent;

    TpmStatus   = sub_410 ();
    sub_400 ();
    TpmPresent  = (TpmStatus & 0x200) != 0;
    Ticks       = sub_6774 (1288) & 0xFFFFFF;

    sub_3E0 ();
    while (((Ticks + 357 - (UINT32)sub_6774 (1288)) & 0x800000) == 0) {
      sub_3D0 ();
    }
    sub_3E0 ();

    if (TpmPresent) {
      sub_3F0 ();
    } else {
      sub_400 ();
    }
  }

  //
  // Locate HII protocols.
  //
  Status = BootServices->LocateProtocol (&unk_8BE0, NULL, &qword_8D70);
  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "ASSERT_EFI_ERROR (Status = %r)\n", Status));
    ASSERT_EFI_ERROR (Status);
  }

  Status = BootServices->LocateProtocol (&unk_8BD0, NULL, &unk_8D90);
  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "ASSERT_EFI_ERROR (Status = %r)\n", Status));
    ASSERT_EFI_ERROR (Status);
  }

  Status = BootServices->LocateProtocol (&unk_8B80, NULL, &unk_8D80);
  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "ASSERT_EFI_ERROR (Status = %r)\n", Status));
    ASSERT_EFI_ERROR (Status);
  }

  BootServices->LocateProtocol (&unk_8CA0, NULL, &unk_8D78);
  BootServices->LocateProtocol (&unk_8BC0, NULL, &unk_8D88);

  return EFI_SUCCESS;
}

// ===========================================================================
// HII Package List and Measurement Registration
// ===========================================================================

/**
  Opens the HII Package List protocol, registers the HII package list,
  measures secure boot variables, and registers the DoResetNow callback.

  @param[in] ImageHandle  The module's image handle.

  @retval EFI_SUCCESS           All operations succeeded.
  @retval EFI_OUT_OF_RESOURCES  Memory allocation failed.
**/
EFI_STATUS
RegisterAndMeasure (
  IN EFI_HANDLE  ImageHandle
  )
{
  EFI_STATUS                   Status;
  EFI_HANDLE                   Handle;
  EFI_HII_DATABASE_PROTOCOL    *HiiDatabase;
  EFI_HII_HANDLE               HiiHandle;

  Handle = ImageHandle;

  //
  // Install the HII Package List protocol on our image handle.
  //
  BootServices->InstallMultipleProtocolInterfaces (
                  &Handle,
                  &unk_8A20,
                  off_8CB0,
                  NULL
                  );

  //
  // Locate the HII Database protocol and register the package list.
  //
  Status = sub_5E18 ();
  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "ASSERT_EFI_ERROR (Status = %r)\n", Status));
    ASSERT_EFI_ERROR (Status);
  }

  Status = BootServices->OpenProtocol (
                           Handle,
                           &unk_8AE0,
                           &HiiHandle,
                           Handle,
                           0,
                           EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
                           );
  if (!EFI_ERROR (Status)) {
    //
    // Locate HII Database protocol and register the new package list.
    //
    Status = BootServices->LocateProtocol (&unk_8BD0, NULL, &HiiDatabase);
    if (!EFI_ERROR (Status)) {
      Status = HiiDatabase->NewPackageList (
                              HiiDatabase,
                              HiiHandle,
                              NULL,
                              &qword_9420
                              );
      DEBUG ((EFI_D_INFO, "NewPackageList status: %r\n", Status));
    } else {
      DEBUG ((EFI_D_INFO,
        "gEfiHiiDatabaseProtocolGuid protocol is not found\n"));
    }
  } else {
    DEBUG ((EFI_D_INFO,
      "gEfiHiiPackageListProtocolGuid protocol is not found\n"));
  }

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

  //
  // Measure secure boot variables (PK, KEK, db, dbx).
  //
  if (EFI_ERROR (MeasureSecureBootVariables ())) {
    DEBUG ((EFI_D_ERROR, "Error Measuring Secure Vars\n"));
  }

  //
  // Write a TCG reset-short event and return.
  //
  TcgWriteResetShortEvent (7);

  return EFI_SUCCESS;
}

// ===========================================================================
// TCG Hash/Extend Event Functions
// ===========================================================================

/**
  TPM 1.2 hash-and-extend event.

  Locates the TCG protocol (EFI_TCG_PROTOCOL) and performs a
  HashLogExtendEvent with the provided buffer and metadata.

  @param[in] a1  Event type (TPM_PCR_EVENT event type).
  @param[in] a2  PCR index (event metadata).
  @param[in] a3  Buffer to hash.
  @param[in] a4  Algorithm GUID.
  @param[in] a5  Additional metadata buffer.
  @param[in] a6  Size of additional data.

  @return Status from TcgHashLogExtendEvent.
**/
EFI_STATUS
Tpm12HashLogExtendEvent (
  IN INT32   a1,
  IN INT32   a2,
  IN VOID    *a3,
  IN VOID    *a4,
  IN VOID    *a5,
  IN UINT64  a6
  )
{
  EFI_STATUS             Status;
  EFI_TCG_PROTOCOL       *TcgProtocol;
  UINT32                 EventSize;
  EFI_PHYSICAL_ADDRESS   TcgEventData;
  TPML_DIGEST_VALUES     DigestList;
  TCG_PCR_EVENT          *TcgEvent;

  TcgProtocol = NULL;
  TcgEvent    = NULL;
  TcgEventData = 0;

  //
  // Locate the TCG protocol.
  //
  Status = BootServices->LocateProtocol (
                  &unk_8C50,
                  NULL,
                  (VOID **)&TcgProtocol
                  );
  if (EFI_ERROR (Status)) {
    ASSERT (!EFI_ERROR (Status));
  }

  EventSize = a6 + 32 + 2 * StrLen (a3);

  //
  // Allocate the TCG event descriptor buffer.
  //
  Status = BootServices->AllocatePages (
                  AllocateAnyPages,
                  EfiBootServicesData,
                  EFI_SIZE_TO_PAGES (EventSize + 32),
                  &TcgEventData
                  );
  if (!EFI_ERROR (Status) && (VOID *)TcgEventData != NULL) {
    TcgEvent = (TCG_PCR_EVENT *)(UINTN)TcgEventData;
    TcgEvent->PCRIndex  = a1;
    TcgEvent->EventType = a2;
    TcgEvent->EventSize = EventSize;

    //
    // Allocate the event log data buffer.
    //
    Status = BootServices->AllocatePages (
                    AllocateAnyPages,
                    EfiBootServicesData,
                    EFI_SIZE_TO_PAGES (EventSize),
                    &TcgEventData
                    );
    if (!EFI_ERROR (Status) && (VOID *)TcgEventData != NULL) {
      TPML_DIGEST_VALUES  *Digest;
      UINT8               *EventLog;

      Digest   = (TPML_DIGEST_VALUES *)(UINTN)TcgEventData;
      EventLog = (UINT8 *)(UINTN)TcgEventData;

      CopyMem (Digest, a4, sizeof (TPML_DIGEST_VALUES));
      Digest->count = StrLen (a3);
      *(UINT64 *)&Digest->digests[0] = a6;

      CopyMem (EventLog + 32, a3, 2 * StrLen (a3));
      CopyMem (EventLog + 32 + 2 * StrLen (a3), a5, a6);

      CopyMem (TcgEvent + 1, EventLog, (UINTN)TcgEvent->EventSize);

      //
      // Call TcgHashLogExtendEvent.
      //
      Status = TcgProtocol->HashLogExtendEvent (
                              TcgProtocol,
                              EventLog,
                              (UINT32)TcgEvent->EventSize,
                              TPM_ALG_SHA,
                              TcgEvent,
                              Digest,
                              (TCG_PCR_EVENT **)&Digest
                              );

      if ((VOID *)TcgEvent != NULL) {
        BootServices->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)TcgEvent, 1);
      }

      if (EFI_ERROR (Status)) {
        ASSERT (!EFI_ERROR (Status));
      }

      if ((VOID *)TcgEventData != NULL) {
        BootServices->FreePages (TcgEventData, 1);
      }

      return Status;
    } else {
      BootServices->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)TcgEvent, 1);
      return EFI_OUT_OF_RESOURCES;
    }
  }

  return Status;
}

/**
  TPM 2.0 hash-and-extend event.

  Locates the TCG2 protocol (EFI_TCG2_PROTOCOL) and performs a
  HashLogExtendEvent with larger event descriptor (44 byte header
  vs 32 for TPM 1.2).  Used when sub_60B0() returns TRUE.

  @param[in] a1  Event type.
  @param[in] a2  PCR index / event metadata.
  @param[in] a3  Buffer to hash.
  @param[in] a4  Algorithm GUID / TCG_PCR_EVENT2 header.
  @param[in] a5  Additional metadata.
  @param[in] a6  Size of additional data.

  @return Status from Tcg2HashLogExtendEvent.
**/
EFI_STATUS
Tcg2HashLogExtendEvent (
  IN INT32   a1,
  IN INT32   a2,
  IN VOID    *a3,
  IN VOID    *a4,
  IN VOID    *a5,
  IN UINT64  a6
  )
{
  EFI_STATUS              Status;
  EFI_TCG2_PROTOCOL       *Tcg2Protocol;
  UINT32                  EventSize;
  EFI_PHYSICAL_ADDRESS    TcgEventData;
  TPML_DIGEST_VALUES      DigestList;
  TCG_PCR_EVENT2          *TcgEvent;
  UINTN                   DigestListCount;

  Tcg2Protocol = NULL;
  TcgEvent     = NULL;
  TcgEventData = 0;

  //
  // Locate the TCG2 protocol.
  //
  Status = BootServices->LocateProtocol (
                  &unk_8C50,
                  NULL,
                  (VOID **)&Tcg2Protocol
                  );
  if (EFI_ERROR (Status)) {
    ASSERT (!EFI_ERROR (Status));
  }

  DigestListCount = StrLen (a3);
  EventSize       = a6 + 32 + 2 * (UINT32)DigestListCount;

  //
  // Allocate the TCG2 event descriptor (44 extra bytes).
  //
  Status = BootServices->AllocatePages (
                  AllocateAnyPages,
                  EfiBootServicesData,
                  EFI_SIZE_TO_PAGES (EventSize + 44),
                  &TcgEventData
                  );
  if (!EFI_ERROR (Status) && (VOID *)TcgEventData != NULL) {
    TcgEvent = (TCG_PCR_EVENT2 *)(UINTN)TcgEventData;
    TcgEvent->PCRIndex  = a1;
    TcgEvent->EventType = a2;
    TcgEvent->EventSize = EventSize;

    //
    // Allocate the event log data buffer.
    //
    Status = BootServices->AllocatePages (
                    AllocateAnyPages,
                    EfiBootServicesData,
                    EFI_SIZE_TO_PAGES (EventSize),
                    &TcgEventData
                    );
    if (!EFI_ERROR (Status) && (VOID *)TcgEventData != NULL) {
      TPML_DIGEST_VALUES  *Digest;
      UINT8               *EventLog;

      Digest   = (TPML_DIGEST_VALUES *)(UINTN)TcgEventData;
      EventLog = (UINT8 *)(UINTN)TcgEventData;

      CopyMem (Digest, a4, sizeof (TPML_DIGEST_VALUES));
      Digest->count = DigestListCount;
      *(UINT64 *)&Digest->digests[0] = a6;

      CopyMem (EventLog + 32, a3, 2 * DigestListCount);
      CopyMem (EventLog + 32 + 2 * DigestListCount, a5, a6);

      CopyMem (TcgEvent + 11, EventLog, (UINTN)TcgEvent->EventSize);

      //
      // Call Tcg2HashLogExtendEvent.
      //
      Status = Tcg2Protocol->HashLogExtendEvent (
                               Tcg2Protocol,
                               EventLog,
                               (UINT32)TcgEvent->EventSize,
                               TPM_ALG_SHA256,
                               TcgEvent,
                               Digest,
                               (TCG_PCR_EVENT2 **)&Digest
                               );

      if ((VOID *)TcgEvent != NULL) {
        BootServices->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)TcgEvent, 1);
      }

      if (EFI_ERROR (Status)) {
        ASSERT (!EFI_ERROR (Status));
      }

      if ((VOID *)TcgEventData != NULL) {
        BootServices->FreePages (TcgEventData, 1);
      }

      return Status;
    } else {
      BootServices->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)TcgEvent, 1);
      return EFI_OUT_OF_RESOURCES;
    }
  }

  return Status;
}

// ===========================================================================
// Ready-to-Boot Notification
// ===========================================================================

/**
  Ready-to-Boot notification callback.

  Invoked when the UEFI Boot Manager signals the ReadyToBoot event.
  Measures boot option variables, calls the OpRom Start/End protocol,
  processes PER BIOS flags, and handles PPI state transitions.

  This function is a major integration point for the TCG platform
  initialization sequence.
**/
VOID
TcgReadyToBoot (
  VOID
  )
{
  EFI_STATUS            Status;
  EFI_TCG2_PROTOCOL     *Tcg2Protocol;
  BOOLEAN               IsTpm20;
  VOID                  *TcgProtocol;
  EFI_EVENT             ResetEvent;
  UINT16                ResetData;
  VOID                  *PpiProtocol;
  UINT64                TpmStatus;
  INT32                 Result;

  DEBUG ((EFI_D_INFO, "TcgReady to boot entry\n"));

  //
  // Locate TCG2 protocol.
  //
  BootServices->LocateProtocol (&unk_8C50, NULL, &TcgProtocol);

  IsTpm20 = sub_60B0 ();

  //
  // Locate TCG1.2 protocol for measuring during boot.
  //
  Status = BootServices->LocateProtocol (
                  &unk_8C40,
                  NULL,
                  (VOID **)&Tcg2Protocol
                  );
  if (EFI_ERROR (Status)) {
    return;
  }

  //
  // Check if we have already entered this callback.
  //
  if (qword_8D10 != 0) {
    if (IsTpm20) {
      Status = Tcg2MeasureStringEvent ("Returning from EFI Application from Boot Option");
    } else {
      Status = Tpm12MeasureStringEvent ("Returning from EFI Application from Boot Option");
    }
    if (EFI_ERROR (Status)) {
      return;
    }
    goto Done;
  }

  //
  // First invocation: measure boot variables and call OpRomStartEnd.
  //
  sub_1E74 ();

  if (!EFI_ERROR (BootServices->LocateProtocol (
                        &unk_8AB0,
                        NULL,
                        &PpiProtocol
                        ))) {
    ((VOID (*)(VOID))PpiProtocol) ();
  }

  //
  // Measure "Calling EFI Application from Boot Option" event.
  //
  if (IsTpm20) {
    Status = Tcg2MeasureStringEvent ("Calling EFI Application from Boot Option");
  } else {
    Status = Tpm12MeasureStringEvent ("Calling EFI Application from Boot Option");
  }

  if (!EFI_ERROR (Status)) {
    //
    // Measure boot variables.
    //
    if (EFI_ERROR (sub_1BCC ())) {
      DEBUG ((EFI_D_INFO, "Boot Variables not Measured. Error!\n"));
    }

    sub_1F20 ();

    //
    // Signal that we are done with boot measurements.
    //
    BootServices->SignalEvent (qword_9428);

Done:
    //
    // Check for TPM physical presence request.
    //
    if (qword_8D10 == 0) {
      //
      // Try to locate the physical presence protocol first.
      //
      if (EFI_ERROR (BootServices->LocateProtocol (
                            &unk_8B90,
                            NULL,
                            &PpiProtocol
                            ))) {
        TpmStatus = sub_60B0 ();
        if (!TpmStatus) {
          //
          // No PPI protocol: issue TPM reset command directly.
          //
          ResetData = 1024;
          TpmStatus = TpmSubmitCommand (
                        (UINT64)TcgProtocol,
                        1073741834,
                        2,
                        &ResetData
                        );
          if (byte_8DA8) {
            sub_6A4C (1, 50694662);
          }
          if (TpmStatus) {
            if (byte_8DA8) {
              sub_6A4C (2147483650LL, 50694659);
            }
          }
        }
      } else {
        ((VOID (*)(VOID))PpiProtocol) ();
      }
    }

    qword_8D10++;
  }
}

// ===========================================================================
// Physical Presence Interface (PPI) Functions
// ===========================================================================

/**
  TCG2 PPI handler.

  Reads the AMITCGPPIVAR and TcgINTPPI variables, processes PPI
  operations (TPM enable/disable/clear), dispatches TPM commands,
  and manages TPM PER BIOS flag and TPM state transitions.

  Handles PPI request codes:
  - 168 (0xA8): TPM Enable + Activate
  - 341 (0x155): TPM Disable + Deactivate
  - 358 (0x166): TPM Clear
**/
EFI_STATUS
PpiHandler (
  VOID
  )
{
  EFI_STATUS            Status;
  EFI_TCG2_PROTOCOL     *Tcg2Protocol;
  UINT64                TcgProtocol;
  VOID                  *TcgPpProtocol;
  VOID                  *TcgProtocolInterface;
  EFI_GUID              *PpiProtocolGuid;
  VOID                  *PpiEventData;
  VOID                  *PpiNotifyRegistration;
  UINTN                 DataSize;
  UINT64                AmiTcgPpiVar[2];
  INT32                 PpiFlags;
  UINTN                 PpiFlagsSize;
  INT32                 TcgFlags;
  INT32                 TcgFlagsSize;
  UINT16                PerBiosFlags;
  UINT8                 PerBiosFlagsByte;
  UINT16                Tpm20Response;
  UINT8                 SetupValue;
  UINT32                PpiRequestNewValue;
  UINT32                CommandResult;
  UINT64                TpmStatus;
  INT32                 PpiRequest;
  UINT8                 EnableFlag;
  UINT32                StatusCode;
  BOOLEAN               IsTpm20;

  PpiRequest = 0;
  SetupValue = 1;
  DataSize   = 4;

  //
  // Try to locate an existing PPI protocol handler.
  //
  if (!EFI_ERROR (BootServices->LocateProtocol (
                        &unk_8C70, NULL, &PpiProtocolGuid
                        ))) {
    return ((EFI_STATUS (*)(VOID))PpiProtocolGuid) ();
  }

  //
  // Locate the TPM Platform Protocol.
  //
  Status = BootServices->LocateProtocol (
                  &unk_8C10,
                  NULL,
                  &TcgProtocolInterface
                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Read TPM PER BIOS flags via TCG Platform Protocol.
  //
  PerBiosFlags = 0;
  Status = BootServices->LocateProtocol (
                  &unk_8B50,
                  NULL,
                  &TcgPpProtocol
                  );
  if (!EFI_ERROR (Status)) {
    Status = ((EFI_STATUS (*)(UINT16 *))TcgPpProtocol) (&PerBiosFlags);
    if (EFI_ERROR (Status)) {
      PerBiosFlags = 0;
    }
  }

  if (!EFI_ERROR (Status)) {
    PerBiosFlags = 0;
  }

  //
  // Read TPMPERBIOSFLAGS variable.
  //
  sub_60EC (
    L"TPMPERBIOSFLAGS",
    &unk_8B30,
    7,
    6,
    &PerBiosFlags
    );

  DataSize = 24;

  //
  // Read or initialize the AMITCGPPIVAR variable.
  //
  Status = RuntimeServices->GetVariable (
                  L"AMITCGPPIVAR",
                  &unk_8B20,
                  NULL,
                  &DataSize,
                  AmiTcgPpiVar
                  );
  if (Status == EFI_NOT_FOUND) {
    AmiTcgPpiVar[0] = 0;
    AmiTcgPpiVar[1] = 0;
    *((UINT32 *)&AmiTcgPpiVar[2]) = 0;
    sub_60EC (
      L"AMITCGPPIVAR",
      &unk_8B20,
      7,
      DataSize,
      AmiTcgPpiVar
      );
  }

  PpiRequestNewValue = (UINT32)AmiTcgPpiVar[0];

  //
  // Read the TcgINTPPI variable (PPI request code from OS).
  //
  TcgFlagsSize = 7;
  PpiFlagsSize = 4;
  PpiFlags     = 0;
  Status = RuntimeServices->GetVariable (
                  L"TcgINTPPI",
                  &unk_8C60,
                  &TcgFlagsSize,
                  &PpiFlagsSize,
                  &PpiFlags
                  );
  if (EFI_ERROR (Status)) {
    PpiFlags = 0;
  }

  DEBUG ((EFI_D_INFO, "\n PPI_request is:  %x \n", PpiRequestNewValue));

  //
  // Process PPI request if one is pending.
  //
  if (PpiFlags != 0) {
    EFI_TCG_PROTOCOL  *TcgProtocolInstance;
    EFI_EVENT         *TcgEvent;
    BOOLEAN           IsTpm20Local;

    //
    // Initialize TPM platform type context.
    //
    CopyMem (
      TpmPlatformContext,
      TcgProtocolInterface + 1,
      27
      );
    TpmPlatformContext[14] = 1;

    ((VOID (*)(VOID *, UINT8))(
      *(VOID **)((UINT8 *)TcgProtocolInterface + 32)
      )) (TpmPlatformContext, 1);

    //
    // Locate the TCG protocol.
    //
    Status = BootServices->LocateProtocol (
                    &unk_8C40,
                    NULL,
                    &TcgProtocolInstance
                    );
    if (EFI_ERROR (Status)) {
      return Status;
    }

    Status = BootServices->LocateProtocol (
                    &unk_8C50,
                    NULL,
                    &TcgProtocol
                    );
    if (EFI_ERROR (Status)) {
      return Status;
    }

    IsTpm20Local = sub_60B0 ();
    if (IsTpm20Local) {
      //
      // TPM 2.0 path
      //
      if (PpiFlags == 168) {
        //
        // TPM Enable + Activate
        //
        CommandResult = TpmSubmitCommand (TcgProtocol, 113, 1, &SetupValue);
        Tpm20Response = (UINT16)((CommandResult >> 8) |
                          HIWORD (CommandResult) & 0xFF00);
        sub_61C0 (TcgProtocol, Tpm20Response);
        if (!sub_60B0 ()) {
          TcgProtocolInstance->ExitBootServices (TcgProtocolInstance);
        }
        PpiFlags = 0;
        sub_60EC (L"TcgINTPPI", &unk_8C60, 3, 4, &PpiFlags);
        TpmResetSystem ();
      }

      if (PpiFlags == 341) {
        //
        // TPM Disable + Deactivate
        //
        TpmSubmitCommand (TcgProtocol, 93, 0, NULL);
        if (!sub_60B0 ()) {
          TcgProtocolInstance->ExitBootServices (TcgProtocolInstance);
        }
        PpiFlags = 0;
        sub_60EC (L"TcgINTPPI", &unk_8C60, 3, 4, &PpiFlags);
        TpmResetSystem ();
      }

      if (PpiFlags == 358) {
        //
        // TPM Clear (owner clear + clear control)
        //
        CommandResult = TpmSubmitCommand (TcgProtocol, 32879, 0, NULL);
        if (!CommandResult) {
          CommandResult = TpmSubmitCommand (TcgProtocol, 32882, 1, &SetupValue);
          if (!byte_8DA8) {
            goto PpiUpdateDone;
          }
          sub_6A4C (1, 50694667);
        } else {
          if (!byte_8DA8) {
            goto PpiUpdateDone;
          }
          sub_6A4C (2147483650LL, 50694676);
        }

PpiUpdateDone:
        Tpm20Response = (UINT16)((CommandResult >> 8) |
                          HIWORD (CommandResult) & 0xFF00);
        sub_61C0 (TcgProtocol, Tpm20Response);
        if (!sub_60B0 ()) {
          TcgProtocolInstance->ExitBootServices (TcgProtocolInstance);
        }
        PpiFlags = 0;
        sub_60EC (L"TcgINTPPI", &unk_8C60, 3, 4, &PpiFlags);
        TpmResetSystem ();
      }
    } else {
      //
      // TPM 1.2 path
      //
      TcgProtocolInstance->ExitBootServices (TcgProtocolInstance);

      if (PpiFlags == 168) {
        //
        // TPM Enable + Activate
        //
        CommandResult = TpmSubmitCommand (TcgProtocol, 113, 1, &SetupValue);
        Tpm20Response = (UINT16)((CommandResult >> 8) |
                          HIWORD (CommandResult) & 0xFF00);
        sub_61C0 (TcgProtocol, Tpm20Response);
        if (!sub_60B0 ()) {
          TcgProtocolInstance->ExitBootServices (TcgProtocolInstance);
        }
        PpiFlags = 0;
        sub_60EC (L"TcgINTPPI", &unk_8C60, 3, 4, &PpiFlags);
        TpmResetSystem ();
      }

      if (PpiFlags == 341) {
        //
        // TPM Disable + Deactivate
        //
        TpmSubmitCommand (TcgProtocol, 93, 0, NULL);
        if (!sub_60B0 ()) {
          TcgProtocolInstance->ExitBootServices (TcgProtocolInstance);
        }
        PpiFlags = 0;
        sub_60EC (L"TcgINTPPI", &unk_8C60, 3, 4, &PpiFlags);
        TpmResetSystem ();
      }

      if (PpiFlags == 358) {
        //
        // TPM Clear
        //
        CommandResult = TpmSubmitCommand (TcgProtocol, 111, 0, NULL);
        if (byte_8DA8) {
          sub_6A4C (1, 50694666);
        }
        if (!CommandResult) {
          CommandResult = TpmSubmitCommand (TcgProtocol, 114, 1, &SetupValue);
          goto UpdateResponse;
        }
        if (!byte_8DA8) {
          goto PpiUpdateDone;
        }
        sub_6A4C (2147483650LL, 50694676);
        goto UpdateResponse;
      }
    }
  }

  //
  // After PPI processing, check for pending AMI PPI VAR and install
  // the appropriate protocol notify handler.
  //
  if (PpiRequestNewValue == 13) {
    //
    // PPI setup value "PPI request sync" - install the PPI member protocol.
    //
    if (!EFI_ERROR (BootServices->AllocatePool (
                          EfiBootServicesData,
                          512,
                          (VOID **)&PpiNotifyRegistration
                          ))) {
      BootServices->InstallProtocolInterface (
                      &unk_8B00,
                      &unk_8C70,
                      EFI_NATIVE_INTERFACE,
                      unk_8DC0
                      );
    }
    return EFI_SUCCESS;
  }

  if ((PpiRequestNewValue - 1) <= 0x15) {
    //
    // PPI request in range 1-22: install PPI protocol with the
    // appropriate handler (PpiSetupFlowStub for user confirmation flows).
    //
    return BootServices->InstallProtocolInterface (
                    &unk_8B60,
                    &unk_8C70,
                    EFI_NATIVE_INTERFACE,
                    unk_8DE8
                    );
  }

  //
  // Default: install PPI protocol with PpiDispatchStub handler.
  //
  return BootServices->InstallProtocolInterface (
                  &unk_8B00,
                  &unk_8C70,
                  EFI_NATIVE_INTERFACE,
                  unk_8DC0
                  );
}

/**
  TPM state machine and PER BIOS flag synchronization.

  Reads the current TPM state from the TCG GetCapability, then
  synchronizes with the "TpmOldvar" runtime variable and setup
  values.  If the TPM state differs from setup, triggers a TPM
  enable/disable transition.

  @return EFI_STATUS from the TCG protocol operations.
**/
EFI_STATUS
TpmStateSync (
  VOID
  )
{
  EFI_STATUS            Status;
  EFI_TCG2_PROTOCOL     *Tcg2Protocol;
  UINT64                TcgProtocol;
  VOID                  *TcgPpProtocol;
  VOID                  *TcgPlatformProtocol;
  UINTN                 DataSize;
  UINT32                PpiFlags;
  UINT64                PpiFlagsBuffer;
  UINT16                PerBiosStatus;
  UINT8                 TpmEnabled;
  UINT8                 TpmOldVar;
  UINT8                 TpmOldVarNew;
  UINT8                 PlatformTypeContext[27];
  UINT8                 TpmCapData[512];
  UINT8                 TpmCapResult;
  UINT64                VarSize;
  UINT8                 TpmActive;
  UINT8                 TpmEnable;
  UINT8                 SyncRequired;
  UINT32                ResetValue;
  UINT8                 EnablePending;
  INT32                 SetupValue;
  UINT8                 OldVarMatch;
  UINT16                CapTag;
  UINT32                CapRetCode;
  UINT32                CapSize;

  PpiFlagsBuffer = 0;
  ResetValue     = 3;
  DataSize       = 64;
  SyncRequired   = 0;
  EnablePending  = 0;
  OldVarMatch    = 1;

  //
  // Try PPI protocol first (already installed).
  //
  if (!EFI_ERROR (BootServices->LocateProtocol (
                        &unk_8A80, NULL, &TcgPpProtocol
                        ))) {
    return ((EFI_STATUS (*)(VOID))TcgPpProtocol) ();
  }

  //
  // Locate TCG1.2 protocol and TCG2 protocol.
  //
  Status = BootServices->LocateProtocol (
                  &unk_8C40, NULL, (VOID **)&Tcg2Protocol
                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  Status = BootServices->LocateProtocol (
                  &unk_8C50, NULL, &TcgProtocol
                  );
  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR,
      "Error: failed to locate TCG protocol: %r\n", Status));
    return Status;
  }

  //
  // Locate the TPM Platform Protocol.
  //
  Status = BootServices->LocateProtocol (
                  &unk_8C10, NULL, &TcgPlatformProtocol
                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Get TPM capability information.
  //
  TcgGetCapability (TcgProtocol, TpmCapData);

  //
  // Read "TpmOldvar" UEFI variable (tracks previous TPM state).
  //
  VarSize = 3;
  TpmOldVar = 0;

  Status = RuntimeServices->GetVariable (
                  L"TpmOldvar",
                  &unk_8C60,
                  &VarSize,
                  &PpiFlagsBuffer,
                  &TpmOldVar
                  );

  if (Status == EFI_NOT_FOUND) {
    //
    // Variable does not exist yet - create it.
    //
    TpmOldVar         = TpmPlatformInfo.Enable;
    Status = RuntimeServices->SetVariable (
                    L"TpmOldvar",
                    &unk_8C60,
                    VarSize,
                    PpiFlagsBuffer,
                    &TpmOldVar
                    );
    if (EFI_ERROR (Status)) {
      DEBUG ((EFI_D_INFO,
        "\n Set Old TpmOldvar Status = %r \n", Status));
    }
  } else {
    TpmOldVarNew = TpmOldVar;
  }

  //
  // Compare old TPM state with current state from setup.
  //
  if (Status == EFI_SUCCESS) {
    TpmActive = ((TpmCapData[0] | TpmCapData[1]) & 1) == 0;
    if (TpmOldVar != TpmActive) {
      //
      // TPM state changed: sync required.
      //
      TpmOldVarNew   = TpmActive;
      SyncRequired   = 1;
      TpmOldVar      = TpmActive;
      EnablePending  = 0;

      Status = RuntimeServices->SetVariable (
                      L"TpmOldvar",
                      &unk_8C60,
                      VarSize,
                      PpiFlagsBuffer,
                      &TpmOldVar
                      );
      if (EFI_ERROR (Status)) {
        DEBUG ((EFI_D_INFO,
          "\n Set Old TpmOldvar Status = %r \n", Status));
      }
    }
  }

  //
  // Save the platform type context.
  //
  byte_8D19 = PlatformTypeContext[0];

  //
  // Process TPM PER BIOS flags and setup synchronisation.
  //
  Status = sub_647C (&SyncRequired);
  if (EFI_ERROR (Status)) {
    //
    // Register a periodic timer callback to retry PER BIOS processing.
    //
    Status = BootServices->SetTimer (
                    &ResetValue,
                    TimerPeriodic,
                    EFI_TIMER_PERIOD_SECONDS (1)
                    );
    if (EFI_ERROR (Status)) {
      return Status;
    }
    Status = BootServices->RegisterProtocolNotify (
                    &unk_8B00,
                    ResetValue,
                    (VOID **)&PpiFlagsBuffer
                    );
    if (EFI_ERROR (Status)) {
      return Status;
    }
  }

  //
  // Update the TPM platform type.
  //
  ((VOID (*)(VOID *, UINT64))(
    *(VOID **)((UINT8 *)TcgPlatformProtocol + 32)
    )) (PlatformTypeContext, 0);

  //
  // Check if TPM state needs to change.
  //
  if (TpmOldVarNew == TpmActive) {
    if (EnablePending) {
      //
      // Enable was requested.
      //
      DEBUG ((EFI_D_INFO, "\n ENABLE == Setup in setup \n"));
      sub_24D8 (EnablePending);
      EnablePending = 0;
    }
    return Status;
  }

  //
  // TPM state mismatch: trigger a TPM enable/disable request.
  //
  DEBUG ((EFI_D_INFO, "\n TMP_ENABLE != Setup in setup \n"));
  sub_24D8 (7 - (TpmOldVarNew != 0));

  //
  // Refresh the platform type context.
  //
  ((VOID (*)(VOID *, UINT8))(
    *(VOID **)((UINT8 *)TcgPlatformProtocol + 32)
    )) (PlatformTypeContext, 0);

  //
  // Apply the new TPM state.
  //
  ((VOID (*)(VOID *, UINT8))(
    *(VOID **)((UINT8 *)TcgPlatformProtocol + 32)
    )) (PlatformTypeContext, 1);

  TpmResetSystem ();

  return Status;
}

// ===========================================================================
// TPM Reset Functions
// ===========================================================================

/**
  Perform a TPM / system reset.

  Issues ResetSystem via the UEFI Runtime Services.  If the reset call
  returns (which it should not normally), logs the failure and registers
  a callback to retry once the Reset Architectural Protocol is available.
**/
VOID
TpmResetSystem (
  VOID
  )
{
  EFI_STATUS  Status;

  dword_8DDC = 0;

  DEBUG ((EFI_D_INFO, "TCG: Resets the system: type(%d)\n", 0));
  DEBUG ((EFI_D_INFO, "TCG: Resets the system: typeaddress(%x)\n",
    (UINTN)&dword_8DDC));

  //
  // Attempt to clear the "LastBootFailed" flag.
  //
  {
    UINTN   VarSize;
    UINT8   BootFailedFlag;

    VarSize = 4;

    if (!EFI_ERROR (RuntimeServices->GetVariable (
                          L"LastBootFailed",
                          &unk_8B40,
                          NULL,
                          &VarSize,
                          &BootFailedFlag
                          ))) {
      Status = RuntimeServices->SetVariable (
                      L"LastBootFailed",
                      &unk_8B40,
                      1,
                      0,
                      &BootFailedFlag
                      );
      DEBUG ((EFI_D_INFO, "Status : = %r\n", Status));
    }
  }

  //
  // Issue the system reset.
  //
  RuntimeServices->ResetSystem (
                    dword_8DDC,
                    EFI_SUCCESS,
                    0,
                    NULL
                    );

  DEBUG ((EFI_D_ERROR, "\tError: Reset failed???\n"));

  //
  // Register a DoResetNow callback in case ResetSystem failed.
  //
  Status = BootServices->CreateEvent (
                  EVT_TIMER | EVT_NOTIFY_SIGNAL,
                  TPL_CALLBACK,
                  DoResetNow,
                  &dword_8DDC,
                  &qword_8DC8
                  );
  if (!EFI_ERROR (Status)) {
    BootServices->SetTimer (
                    qword_8DC8,
                    TimerPeriodic,
                    EFI_TIMER_PERIOD_SECONDS (1)
                    );
    DEBUG ((EFI_D_INFO,
      "\tRegister DoResetNow after Reset Architecture driver\n"));
  }
}

/**
  DoResetNow callback.

  Called (via timer or event) to retry the system reset after the
  Reset Architectural Protocol becomes available.

  @param[in] a1  Context / reset type value.
  @param[in] a2  Reset data (unused).
**/
VOID
DoResetNow (
  IN UINT32  *a1,
  IN UINT32  *a2
  )
{
  DEBUG ((EFI_D_INFO, "TCG: DoResetNow resets the system: type(%d)\n",
    *a1));
  DEBUG ((EFI_D_INFO, "TCG: DoResetNow resets the system: type(%x)\n",
    (UINTN)a1));

  RuntimeServices->ResetSystem (*a1, EFI_SUCCESS, 0, NULL);

  DEBUG ((EFI_D_ERROR, "\tError: Reset failed???\n"));
}

// ===========================================================================
// TCG GetCapability
// ===========================================================================

/**
  TCG GetCapability wrapper with debug logging.

  Sends a TPM2_GetCapability command via the TCG2 protocol and logs
  the response (capability data, return code, tag, and data bytes)
  for diagnostic purposes.

  @param[in] a1  TCG2/TCG protocol instance.
  @param[in] a2  Output buffer (minimum 36 bytes for capability response).

  @return EFI_STATUS from GetCapability.
**/
EFI_STATUS
TcgGetCapability (
  IN VOID   *a1,
  OUT VOID  *a2
  )
{
  EFI_STATUS  Status;
  UINT32      CapSize;
  UINT32      CapRetCode;
  UINT16      CapTag;
  UINT32      CapDataBytes;
  UINT16      TcgCapCmd;
  UINT32      ResponseSize;
  UINT8       ResponseBuffer[256];

  //
  // Build the TPM GetCapability command buffer.
  //
  TcgCapCmd = TPM_ST_NO_SESSIONS;
  *(UINT32 *)((UINT8 *)&TcgCapCmd + 2) = 369098752;  // TPM_CC_GetCapability
  *(UINT32 *)((UINT8 *)&TcgCapCmd + 6) = 0x4000000;
  *(UINT32 *)((UINT8 *)&TcgCapCmd + 10) = 134283264;
  *(UINT32 *)((UINT8 *)&TcgCapCmd + 14) = 1702887424;

  if (!sub_60B0 ()) {
    *(UINT32 *)((UINT8 *)&TcgCapCmd + 14) = 1694498816;
  }

  *(UINT32 *)((UINT8 *)&TcgCapCmd + 18) = 0x4000000;

  //
  // TPM2_GetCapability via the TCG2 protocol.
  //
  Status = ((EFI_STATUS (*)(VOID *, UINT32, VOID *, UINT32, VOID *))(
    *(VOID **)((UINT8 *)a1 + 24)
    )) (a1, 22, &TcgCapCmd, 256, ResponseBuffer);

  if (!EFI_ERROR (Status)) {
    //
    // Copy capability response to the caller's buffer.
    //
    CopyMem (a2, ResponseBuffer, 36);

    //
    // Decode and log capability response fields (byte-order swap).
    //
    CapDataBytes = ((*(UINT32 *)((UINT8 *)a2 + 16) & 0xFF00 |
                    (*(UINT32 *)((UINT8 *)a2 + 16) << 16)) << 8) |
                   ((HIWORD(*(UINT32 *)((UINT8 *)a2 + 16)) |
                    *(UINT32 *)((UINT8 *)a2 + 16) & 0xFF0000u) >> 8);
    CapTag = HIBYTE(*(UINT16 *)((UINT8 *)a2 + 14)) |
             (*(UINT16 *)((UINT8 *)a2 + 14) << 8);
    CapRetCode = ((*(UINT32 *)((UINT8 *)a2 + 6) & 0xFF00 |
                  (*(UINT32 *)((UINT8 *)a2 + 6) << 16)) << 8) |
                 ((HIWORD(*(UINT32 *)((UINT8 *)a2 + 6)) |
                  *(UINT32 *)((UINT8 *)a2 + 6) & 0xFF0000u) >> 8);
    CapSize = ((*(UINT32 *)((UINT8 *)a2 + 2) & 0xFF00 |
               (*(UINT32 *)((UINT8 *)a2 + 2) << 16)) << 8) |
              ((HIWORD(*(UINT32 *)((UINT8 *)a2 + 2)) |
               *(UINT32 *)((UINT8 *)a2 + 2) & 0xFF0000u) >> 8);

    DEBUG ((EFI_D_INFO,
      "GetCapability: %r; size: %x; retCode:%x; tag:%x; bytes %08x\n",
      Status, CapSize, CapRetCode, CapTag, CapDataBytes));
  }

  return Status;
}

// ===========================================================================
// TCG Measurement Event Helpers
// ===========================================================================

/**
  TPM 1.2 measurement of an event with a string description.

  Allocates a TCG_PCR_EVENT buffer, populates it with the string,
  and calls TcgHashLogExtendEvent to measure the data.

  @param[in] String  Null-terminated ASCII string describing the event.

  @return EFI_STATUS from the TCG protocol HashLogExtendEvent.
**/
EFI_STATUS
Tpm12MeasureStringEvent (
  IN CHAR8  *String
  )
{
  EFI_STATUS        Status;
  EFI_TCG_PROTOCOL  *TcgProtocol;
  UINT32            EventSize;
  TCG_PCR_EVENT     *TcgEvent;
  UINT32            ReturnSize;
  UINT8             Digest[16];

  TcgEvent = NULL;

  //
  // Locate TCG protocol.
  //
  Status = BootServices->LocateProtocol (
                  &unk_8C50,
                  NULL,
                  (VOID **)&TcgProtocol
                  );
  if (EFI_ERROR (Status)) {
    ASSERT (!EFI_ERROR (Status));
  }

  //
  // Calculate event size and allocate buffer.
  //
  EventSize = StrSize (String);
  Status = BootServices->AllocatePool (
                  EfiBootServicesData,
                  EventSize + 32,
                  (VOID **)&TcgEvent
                  );
  if (!EFI_ERROR (Status) && TcgEvent != NULL) {
    TcgEvent->PCRIndex  = 5;
    TcgEvent->EventType = (UINT32)(INT32)0x80010007;
    TcgEvent->EventSize = EventSize;

    //
    // Copy event data into the buffer.
    //
    CopyMem (TcgEvent + 1, String, EventSize);

    //
    // Submit the measurement.
    //
    Status = TcgProtocol->HashLogExtendEvent (
                            TcgProtocol,
                            String,
                            EventSize,
                            TPM_ALG_SHA,
                            TcgEvent,
                            Digest,
                            &ReturnSize
                            );

    if (TcgEvent != NULL) {
      BootServices->FreePool (TcgEvent);
    }

    return Status;
  }

  return Status;
}

/**
  TPM 2.0 measurement of an event with a string description.

  Uses the larger TCG2_PCR_EVENT2 structure with 44-byte header
  (vs 32 for TPM 1.2).  Supports multiple algorithm digests.

  @param[in] String  Null-terminated ASCII string describing the event.

  @return EFI_STATUS from the TCG2 protocol HashLogExtendEvent.
**/
EFI_STATUS
Tcg2MeasureStringEvent (
  IN CHAR8  *String
  )
{
  EFI_STATUS           Status;
  EFI_TCG2_PROTOCOL    *Tcg2Protocol;
  UINT32               EventSize;
  TCG_PCR_EVENT2       *TcgEvent;
  UINT32               ReturnSize;
  UINT8                Digest[16];

  TcgEvent = NULL;

  //
  // Locate TCG2 protocol.
  //
  Status = BootServices->LocateProtocol (
                  &unk_8C50,
                  NULL,
                  (VOID **)&Tcg2Protocol
                  );
  if (EFI_ERROR (Status)) {
    ASSERT (!EFI_ERROR (Status));
  }

  //
  // Calculate event size and allocate buffer (44 extra bytes for TCG2 header).
  //
  EventSize = StrSize (String);
  Status = BootServices->AllocatePool (
                  EfiBootServicesData,
                  EventSize + 44,
                  (VOID **)&TcgEvent
                  );
  if (!EFI_ERROR (Status) && TcgEvent != NULL) {
    TcgEvent->PCRIndex  = 5;
    TcgEvent->EventType = (UINT32)(INT32)0x80010007;
    TcgEvent->EventSize = EventSize;

    //
    // Copy event data after the header (offset 44 for TCG2).
    //
    CopyMem ((UINT8 *)TcgEvent + 44, String, EventSize);

    //
    // Submit the measurement.
    //
    Status = Tcg2Protocol->HashLogExtendEvent (
                             Tcg2Protocol,
                             String,
                             EventSize,
                             TPM_ALG_SHA256,
                             TcgEvent,
                             Digest,
                             &ReturnSize
                             );

    if (TcgEvent != NULL) {
      BootServices->FreePool (TcgEvent);
    }

    return Status;
  }

  return Status;
}

// ===========================================================================
// Secure Boot Variable Measurement
// ===========================================================================

/**
  Measures Secure Boot related UEFI variables into PCR[7].

  Iterates over SecureBoot, PK, KEK, db, dbx (and ImageExecTable)
  UEFI variables and measures each via the TCG/TCG2 protocol.

  @return EFI_STATUS from the last measurement operation.
**/
EFI_STATUS
MeasureSecureBootVariables (
  VOID
  )
{
  EFI_STATUS        Status;
  UINT64            TcgProtocol;
  UINTN             Index;
  EFI_GUID          *AlgoGuid;
  UINT16            *VariableNames[6];
  INT32             EventTypes[6];

  //
  // Initialize variable name and event type tables.
  //
  VariableNames[0] = L"SecureBoot";
  VariableNames[1] = L"PK";
  VariableNames[2] = L"KEK";
  VariableNames[3] = L"db";
  VariableNames[4] = L"dbx";
  VariableNames[5] = L"ImageExecTable";

  EventTypes[0] = (INT32)0x80010007;
  EventTypes[1] = (INT32)0x80010007;
  EventTypes[2] = (INT32)0x80010007;
  EventTypes[3] = (INT32)0x80010007;
  EventTypes[4] = (INT32)0x80010007;

  //
  // Locate TCG2 protocol.
  //
  Status = BootServices->LocateProtocol (
                  &unk_8C50,
                  NULL,
                  &TcgProtocol
                  );
  if (EFI_ERROR (Status)) {
    ASSERT (!EFI_ERROR (Status));
  }

  for (Index = 0; Index < 5; Index++) {
    EFI_GUID  Guid;
    VOID      *VariableData;
    UINTN     VariableSize;

    //
    // Select the algorithm GUID.
    //
    if ((Index >= 3) && (Index <= 4)) {
      Guid = *(EFI_GUID *)xmmword_6B40;
    } else {
      Guid = *(EFI_GUID *)xmmword_8A50;
    }

    //
    // Read the UEFI variable.
    //
    Status = sub_18E8 (VariableNames[Index], &Guid, &VariableSize);
    if (Status == EFI_SUCCESS && VariableSize > 0) {
      //
      // Check if this is the SecureBoot variable.
      //
      if (Index == 0) {
        byte_8D18 = (*(UINT8 *)VariableData != 0) ? 1 : byte_8D18;
      }

      if (byte_8D18 != 1) {
        BOOLEAN  IsTpm20;

        IsTpm20 = sub_60B0 ();
        if (IsTpm20) {
          Status = Tcg2HashLogExtendEvent (
                     7,
                     EventTypes[Index],
                     VariableNames[Index],
                     &Guid,
                     VariableData,
                     VariableSize
                     );
        } else {
          Status = Tpm12HashLogExtendEvent (
                     7,
                     EventTypes[Index],
                     VariableNames[Index],
                     &Guid,
                     VariableData,
                     VariableSize
                     );
        }

        if (byte_8DA8) {
          sub_6A4C (1, 50694677);
        }

        BootServices->FreePool (VariableData);
      }
    }
  }

  return Status;
}

// ===========================================================================
// Option ROM Measurement
// ===========================================================================

/**
  Measures an option ROM or legacy image into the TPM.

  Locates the TCG/TCG2 protocol and builds a TCG_PCR_EVENT or
  TCG_PCR_EVENT2 structure to measure the image.

  @param[in] ImageBase  Pointer to the image to measure.
  @param[in] ImageSize  Size of the image in bytes.
  @param[in] Pfa        PFA (Processor Family Architecture) identifier.

  @return EFI_STATUS from TcgHashLogExtendEvent.
**/
EFI_STATUS
MeasureOptionRom (
  IN VOID    *ImageBase,
  IN UINT64  ImageSize,
  IN UINT16  Pfa
  )
{
  EFI_STATUS      Status;
  UINT64          TcgProtocol;
  UINT32          HashLen;
  UINT8           *HashPtr;
  UINT32          EventStruct[2];
  UINT32          EventHeader[2];
  UINT32          PcrIndex;
  UINT32          StructSize;
  BOOLEAN         IsTpm20;
  UINT8           *DigestBuf;

  DEBUG ((EFI_D_INFO,
    "Measuring image @ %x, image len = %x, pfa = %x  \n",
    ImageBase, ImageSize, Pfa));

  IsTpm20 = sub_60B0 ();

  if (IsTpm20) {
    //
    // TPM 2.0 measurement path.
    //
    Status = BootServices->LocateProtocol (
                    &unk_8C50,
                    NULL,
                    &TcgProtocol
                    );
    if (EFI_ERROR (Status)) {
      return EFI_SUCCESS;
    }

    EventHeader[1] = Pfa;
    HashPtr        = &DigestBuf;
    EventStruct[0] = 2;
    EventStruct[1] = 6;
    PcrIndex       = 7;
    StructSize     = 44;
    HashLen        = 32;

    Status = ((EFI_STATUS (*)(VOID *, VOID *, UINT64, UINT32,
              UINT32 *, UINT8 **))(
      *(VOID **)((UINT8 *)TcgProtocol + 8)
      )) (TcgProtocol, ImageBase, ImageSize, 4, &HashLen, &HashPtr);

    if (!EFI_ERROR (Status)) {
      Status = ((EFI_STATUS (*)(VOID *, UINT32 *, UINT32, UINT32,
                UINT32 *, UINT8 *, UINT8 *))(
        *(VOID **)((UINT8 *)TcgProtocol + 32)
        )) (TcgProtocol, PcrIndex, StructSize, 4, EventStruct,
            HashPtr, DigestBuf);
    }
  } else {
    //
    // TPM 1.2 measurement path.
    //
    Status = BootServices->LocateProtocol (
                    &unk_8C50,
                    NULL,
                    &TcgProtocol
                    );
    if (EFI_ERROR (Status)) {
      return EFI_SUCCESS;
    }

    EventHeader[1] = Pfa;
    HashPtr        = &DigestBuf;
    EventStruct[0] = 2;
    EventStruct[1] = 6;
    StructSize     = 32;
    HashLen        = 20;

    Status = ((EFI_STATUS (*)(VOID *, VOID *, UINT64, UINT32,
              UINT32 *, UINT8 **))(
      *(VOID **)((UINT8 *)TcgProtocol + 8)
      )) (TcgProtocol, ImageBase, ImageSize, 4, &HashLen, &HashPtr);

    if (!EFI_ERROR (Status)) {
      Status = ((EFI_STATUS (*)(VOID *, UINT32 *, UINT32, UINT32,
                UINT32 *, UINT8 *, UINT8 *))(
        *(VOID **)((UINT8 *)TcgProtocol + 32)
        )) (TcgProtocol, PcrIndex, StructSize, 4, EventStruct,
            HashPtr, DigestBuf);
    }
  }

  return Status;
}

// ===========================================================================
// PCI I/O Protocol Notify and OpROM Measurement
// ===========================================================================

/**
  OnPciIOInstalled protocol callback.

  Triggered when a PCI I/O protocol is installed.  Locates the
  OpRomStartEnd protocol to obtain the PCI I/O instance, then
  retrieves and measures the option ROM image associated with
  the device.

  The function reads RomImage and RomSize from the PCI I/O protocol,
  determines the PFA (Processor Family Architecture) from the device,
  and calls MeasureOptionRom to measure the ROM content.
**/
VOID
OnPciIOInstalled (
  VOID
  )
{
  EFI_STATUS              Status;
  EFI_HANDLE              *HandleBuffer;
  UINTN                   HandleCount;
  UINTN                   Index;
  OPROM_START_END_PROTOCOL  *OpRomStartEnd;
  EFI_PCI_IO_PROTOCOL     *PciIo;
  UINT64                  RomSize;
  VOID                    *RomImage;
  UINT16                  Pfa;
  UINTN                   DataSize;

  HandleBuffer = NULL;
  DataSize     = 8;

  DEBUG ((EFI_D_INFO, "OnPciIOInstalled\n"));

  //
  // Locate all handles that support the OpRomStartEnd protocol.
  //
  Status = BootServices->LocateHandle (
                  ByProtocol,
                  &unk_8AD0,
                  NULL,
                  &DataSize,
                  &HandleBuffer
                  );
  if (Status == EFI_BUFFER_TOO_SMALL) {
    HandleBuffer = AllocatePool (DataSize);
    if (HandleBuffer != NULL) {
      Status = BootServices->LocateHandle (
                      ByProtocol,
                      &unk_8AD0,
                      NULL,
                      &DataSize,
                      HandleBuffer
                      );
    }
  }

  DEBUG ((EFI_D_INFO,
    "OnPciIOInstalled LocateHandle = %r \n", Status));

  //
  // Open the OpRomStartEnd protocol on each handle.
  //
  if (!EFI_ERROR (Status)) {
    HandleCount = DataSize / sizeof (EFI_HANDLE);
  } else {
    HandleCount = 0;
  }

  for (Index = 0; Index < HandleCount; Index++) {
    Status = BootServices->HandleProtocol (
                    HandleBuffer[Index],
                    &unk_8AD0,
                    (VOID **)&OpRomStartEnd
                    );
    DEBUG ((EFI_D_INFO,
      "OnPciIOInstalled HandleProtocol = %r \n", Status));

    if (!EFI_ERROR (Status)) {
      DEBUG ((EFI_D_INFO,
        "OpRomStartEndProtocol located \n"));

      if (OpRomStartEnd != NULL && OpRomStartEnd->PciIo != NULL) {
        RomImage = OpRomStartEnd->PciIo->RomImage;
        RomSize  = OpRomStartEnd->PciIo->RomSize;

        DEBUG ((EFI_D_INFO,
          "OpRomStartEndProtocol->PciIo->RomImage = %x \n",
          RomImage));
        DEBUG ((EFI_D_INFO,
          "OpRomStartEndProtocol->PciIo->RomSize = %x \n",
          RomSize));
        DEBUG ((EFI_D_INFO, "Measuring legacy image \n"));

        //
        // Determine PFA from the PCI I/O protocol.
        //
        Pfa = sub_1234 (OpRomStartEnd);

        //
        // Measure the option ROM image.
        //
        MeasureOptionRom (RomImage, (UINT32)RomSize, Pfa);
      }
    }
  }

  if (HandleBuffer != NULL) {
    FreePool (HandleBuffer);
  }
}

// ===========================================================================
// TPM PER BIOS Flag Processing
// ===========================================================================

/**
  Writes a value into a TPM-peripheral BIOS-storage format block.

  Parses a TPM-formatted data buffer, finds the field matching the
  magic tag "TPM_" (0x5F504D54), and updates the value at the field's
  offset based on the type byte.

  Supported types:
   0x01 (UINT8), 0x0A (UINT8 at offset+5), 0x0B (UINT16 at offset+5),
   0x0C (UINT32 at offset+5), 0x0E (UINT64 at offset+5)

  @param[in] Buffer    TPM-formatted data buffer (type-length-value).
  @param[in] Size      Size of the data buffer.
  @param[in] Data      Input string (used for initial tag calculation).
  @param[in] NewValue  The new value to write at the matched field.

  @retval EFI_SUCCESS        Value updated successfully.
  @retval EFI_NOT_FOUND      "TPM_" tag not found in buffer.
  @retval EFI_UNSUPPORTED    Unrecognized field type.
**/
UINT64
PerBiosWriteValue (
  IN VOID    *Buffer,
  IN UINT64  Size,
  IN VOID    *Data,
  IN UINT64  NewValue
  )
{
  UINT32  TpmTag;
  UINT32  TagValue;
  INT32   FieldOffset;
  UINT32  Index;
  UINT8   *BytePtr;

  //
  // Compute the TPM tag ("TPM_" = 0x5F504D54 as an integer
  // written into the buffer).
  //
  TpmTag = 1600085855;  // Magic constant for tag search
  CopyMem (&TagValue, Data, StrSize (Data));

  //
  // Search for the tag in the buffer.
  //
  FieldOffset = -1;
  for (Index = 0; Index < (UINT32)Size; Index++) {
    if (*(UINT32 *)((UINT8 *)Buffer + Index) == TpmTag) {
      FieldOffset = (INT32)Index;
      break;
    }
  }

  if (FieldOffset < 0) {
    return EFI_NOT_FOUND;
  }

  BytePtr = (UINT8 *)Buffer + FieldOffset;

  //
  // Check if the preceding byte is a valid continuation indicator.
  //
  if (((*(BytePtr - 1) - 92) & 0xFD) == 0) {
    BytePtr--;
  }

  //
  // Determine the value type and update accordingly.
  //
  if (*(BytePtr - 1) == 8) {
    //
    // Found a valid field - examine its type.
    //
    switch (*(BytePtr + 4)) {
    case 0x01:
    case 0x02:
      //
      // UINT8 - only update if the new value fits.
      //
      if (NewValue >= 2) {
        return EFI_UNSUPPORTED;
      }
      *(BytePtr + 4) = (UINT8)NewValue;
      break;

    case 0x0A:
      *(BytePtr + 5) = (UINT8)NewValue;
      break;

    case 0x0B:
      *(UINT16 *)(BytePtr + 5) = (UINT16)NewValue;
      break;

    case 0x0C:
      *(UINT32 *)(BytePtr + 5) = (UINT32)NewValue;
      break;

    case 0x0E:
      *(UINT64 *)(BytePtr + 5) = NewValue;
      return EFI_SUCCESS;

    default:
      return EFI_UNSUPPORTED;
    }
  }

  return EFI_SUCCESS;
}

// ===========================================================================
// HOB List Initialization
// ===========================================================================

/**
  Initializes the HOB list pointer by scanning the system table.

  Walks the configuration table entries looking for a HOB list,
  caches the pointer in qword_8D60, and uses ASSERT on failure.

  @param[in] a1  ImageHandle (unused in this implementation).
**/
UINT64
InternalGetHobList (
  IN VOID  *a1
  )
{
  UINTN   Index;

  if (qword_8D60 == 0) {
    qword_8D60 = 0;

    if (SystemTable->NumberOfTableEntries > 0) {
      for (Index = 0; Index < SystemTable->NumberOfTableEntries; Index++) {
        if (sub_6814 (a1,
            SystemTable->ConfigurationTable[Index].VendorTable)) {
          qword_8D60 =
            (UINT64)SystemTable->ConfigurationTable[Index].VendorTable;
          break;
        }
      }

      if (qword_8D60 == 0) {
        DEBUG ((EFI_D_ERROR,
          "ASSERT_EFI_ERROR (Status = %r)\n",
          EFI_NOT_FOUND));
        ASSERT_EFI_ERROR (EFI_NOT_FOUND);
      }
    } else {
      DEBUG ((EFI_D_ERROR,
        "ASSERT_EFI_ERROR (Status = %r)\n",
        EFI_NOT_FOUND));
      ASSERT_EFI_ERROR (EFI_NOT_FOUND);
    }

    if (qword_8D60 == 0) {
      ASSERT (qword_8D60 != 0);
    }
  }

  return qword_8D60;
}

// ===========================================================================
// HII String Retrieval
// ===========================================================================

/**
  Retrieves a string from the HII database by String ID.

  @param[in]  HiiHandle  HII handle of the package list.
  @param[in]  StringId   ID of the string to retrieve.
  @param[in]  Language   Language code string.

  @return Pointer to the retrieved UCS-2 string, or NULL on failure.
**/
UINT16 *
HiiGetString (
  IN EFI_HII_HANDLE  HiiHandle,
  IN UINT16          StringId,
  IN CHAR8           *Language
  )
{
  EFI_HII_DATABASE_PROTOCOL  *HiiDatabase;
  EFI_HII_STRING_PROTOCOL    *StringProtocol;
  UINT16                     *StringBuffer;
  UINT16                     *StringPtr;
  UINTN                      StringSize;
  VOID                       *PackageList;
  VOID                       *PackageListCopy;

  HiiDatabase    = NULL;
  StringBuffer   = NULL;
  StringPtr      = NULL;
  StringSize     = 0;
  PackageList    = NULL;

  //
  // Validate HII handle.
  //
  ASSERT (qword_9420 != NULL);
  ASSERT (StringId != 0);

  //
  // Get the HII package list for the given handle.
  //
  PackageList = sub_63D8 (qword_9420);
  if (PackageList != NULL) {
    sub_5BDC (PackageList, &PackageListCopy);

    if (PackageListCopy != NULL) {
      StringPtr = PackageListCopy;
    } else {
      StringPtr = &unk_84FA;
    }

    StringBuffer = sub_5CD4 (
                     (UINT64)PackageList,
                     0,
                     &unk_84FA,
                     StringPtr,
                     (UINT64)PackageList,
                     0
                     );
    if (StringBuffer != NULL) {
      //
      // Try to get the string via HII String Protocol.
      //
      if (((EFI_STATUS (*)(VOID *, UINT16 *, UINT64, UINT16,
           UINT16 **, UINTN *, UINT32))(
        *(VOID **)((UINT8 *)qword_8D70 + 8)
        )) (qword_8D70, StringBuffer, qword_9420, StringId,
            &StringSize, &StringBuffer, 0) == EFI_BUFFER_TOO_SMALL) {
        //
        // Allocate a temporary buffer for the string.
        //
        StringPtr = sub_69E0 (StringSize);
        if (StringPtr != NULL) {
          if (((EFI_STATUS (*)(VOID *, UINT16 *, UINT64, UINT16,
               UINT16 *, UINTN *, UINT32))(
            *(VOID **)((UINT8 *)qword_8D70 + 8)
            )) (qword_8D70, StringBuffer, qword_9420, StringId,
                StringPtr, &StringSize, 0) < 0) {
            sub_6A08 (StringPtr);
            StringPtr = NULL;
          }
        }
      }
    }

    sub_6A08 (PackageList);
    if (PackageListCopy != NULL) {
      sub_6A08 (PackageListCopy);
    }
    if (StringBuffer != NULL) {
      sub_6A08 (StringBuffer);
    }
  }

  return StringPtr;
}

// ===========================================================================
// Write TCG Reset-Short Event
// ===========================================================================

/**
  Writes a short-form TCG event indicating a TPM reset cycle.

  @param[in] ResetType  Reset type code (typically 7 for TPM reset).

  @return EFI_STATUS from TcgHashLogExtendEvent.
**/
EFI_STATUS
TcgWriteResetShortEvent (
  IN INT32  ResetType
  )
{
  EFI_STATUS        Status;
  UINT64            TcgProtocol;
  UINT32            EventData[8];
  UINT8             DigestBuffer[24];
  INT32             ResetEvent;
  UINT8             EventOut;
  UINT8             EventOut2;

  TcgProtocol = 0;
  ResetEvent  = 0;

  //
  // Locate TCG protocol.
  //
  BootServices->LocateProtocol (
                  &unk_8C50,
                  NULL,
                  &TcgProtocol
                  );

  //
  // Build the TCG_PCR_EVENT structure.
  //
  EventData[0] = ResetType;
  EventData[1] = 4;
  EventData[7] = 4;

  CopyMem (DigestBuffer, &ResetEvent, 4);

  //
  // Call HashLogExtendEvent.
  //
  return ((EFI_STATUS (*)(VOID *, INT32 *, UINT32, UINT32,
          UINT32 *, UINT8 *, UINT8 *))(
    *(VOID **)((UINT8 *)TcgProtocol + 32)
    )) (TcgProtocol, &ResetEvent, 4, 4, EventData, &EventOut, &EventOut2);
}

// ===========================================================================
// TCG Command Submission
// ===========================================================================

/**
  Submits a TPM command via the TCG/TCG2 protocol and returns the response.

  Wraps the TcgSubmitCommand / Tcg2SubmitCommand protocol call with
  a command code and parameters.

  @param[in] TcgProtocol   Pointer to the TCG or TCG2 protocol instance.
  @param[in] CommandCode   TPM command ordinal (e.g. TPM_CC_GetCapability).
  @param[in] Param1        First parameter (varies by command).
  @param[in] Param2        Second parameter (varies by command).

  @return Command response data (platform-specific encoding).
**/
UINT32
TpmSubmitCommand (
  IN VOID    *TcgProtocol,
  IN UINT32  CommandCode,
  IN UINT32  Param1,
  IN UINT32  Param2
  )
{
  //
  // Build the TPM command buffer and call SubmitCommand via
  // the protocol interface (offset +24 from protocol base).
  //
  // The exact buffer format depends on the TPM command type
  // and the TCG/TCG2 protocol version.
  //
  return ((UINT32 (*)(VOID *, UINT32, UINT32, UINT32, UINT32))(
    *(VOID **)((UINT8 *)TcgProtocol + 24)
    )) (TcgProtocol, CommandCode, Param1, Param2, 0);
}

/**
  Debug wrapper: writes 1 to output and returns 0.

  @param[out] a1  Set to 1.

  @return 0 (EFI_SUCCESS).
**/
EFI_STATUS
PpiWriteAndReturnSuccess (
  OUT UINT32  *a1
  )
{
  *a1 = 1;
  return 0;
}

/**
  Stub function for PPI member protocol dispatch.

  @return EFI_SUCCESS.
**/
VOID
PpiDispatchStub (
  VOID
  )
{
  return;
}

/**
  Stub function for PPI protocol dispatch (setup flow).

  @return EFI_SUCCESS.
**/
VOID
PpiSetupFlowStub (
  VOID
  )
{
  return;
}

/**
  Timer notification callback for PER BIOS retry processing.

  @param[in] a1  Event context (unused).
  @param[in] a2  Event context (unused).
**/
VOID
PerBiosRetryTimerNotify (
  UINT64  a1,
  UINT64  a2
  )
{
  return;
}