Newer
Older
AMI-Aptio-BIOS-Reversed / Tpm20PlatformDxe / Tpm20PlatformDxe.c
@Ajax Dong Ajax Dong 2 days ago 46 KB Init
/** @file Tpm20PlatformDxe - TPM 2.0 Platform DXE Driver TPM 2.0 platform initialization, TCG PPI (Physical Presence Interface)
 protocol, Secure Boot measurement, and TPM 2.0 hash extension services.

 Source: AmiModulePkg/TCG2/Common/Tpm20PlatformDxe/Tpm20PlatformDxe.c Module: Tpm20PlatformDxe.efi (Index 0072)
 Image: ~84KB, code section .text 0xF7E0 bytes, 139 functions DISCLAIMER: This is an IDA Pro decompilation of the original UEFI driver.
 Function names are derived from address offsets until semantic analysis is complete. Debug logging (sub_8E54/sub_8D8C) and ASSERT (sub_8E14)
 are inlined from MdePkg libraries.

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

#include "Tpm20PlatformDxe.h"

//
// ====================================================================
// Global Data
// ====================================================================
//
UINT64 gImageHandle; // qword_12A48 UINT64 gST; // qword_12A38 UINT64 gBS; // qword_12A40 UINT64 gRT; // qword_12A50 UINT64 gTcg2Protocol; // qword_12A78 UINT64 gHiiDatabaseProtocol; // qword_129E8 (unk_129E8)
UINT64 gTpm20PpiProtocol; // qword_12A00 UINT64 gTpm20Ppi; // qword_12A28 UINT64 gTpm20PpiContext; // qword_12A30 UINT8 gTpmPerBiosFlags; // byte_12AD8 UINT8 gTpmPerBiosFlags2; // byte_12AD9 UINT8 gTpmPerBiosFlags3; // byte_12ADA UINT8 gPpiRequest; // byte_12AD4 (n0x80)
UINT16 gTpmPerBiosWord; // word_12ADC UINT32 gAmiTcgPpiVar[6]; // dword_12AD0 UINTN gGptMeasurementCount; // qword_12A20

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

/**Module Entry Point: Initialize TPM 2.0 Platform DXE driver.

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

 @retval EFI_SUCCESS Driver entry completed.
**/
EFI_STATUS EFIAPI ModuleEntryPoint (
 IN EFI_HANDLE ImageHandle,
 IN EFI_SYSTEM_TABLE *SystemTable
 )
{
 InitUefiServices (ImageHandle, SystemTable);
 return Tpm20PlatformDriverEntry (ImageHandle, SystemTable);
}

//
// ====================================================================
// Internal Initialization
// ====================================================================

/**Internal initialization function: stores ImageHandle, gST, gBS, gRT,
 initializes HII services, and locates HII protocols.

 @param[in] ImageHandle The firmware allocated handle for the EFI image.
 @param[in] SystemTable A pointer to the EFI System Table.
**/
VOID InitUefiServices (
 IN EFI_HANDLE ImageHandle,
 IN EFI_SYSTEM_TABLE *SystemTable
 )
{
 UINT64 Status;
 UINT64 Status2;
 UINT64 Status3;
 UINT64 Status4;
 UINT16 ProcessorFlags;
 BOOLEAN LocalApicEnabled;
 UINT64 TscDelta;
 UINT64 TscNow;

 gImageHandle = (UINT64)ImageHandle;
 if (ImageHandle == NULL) {
 AssertHandler (
 "e:\\hs\\MdePkg\\Library\\UefiBootServicesTableLib\\UefiBootServicesTableLib.c",
 51,
 "gImageHandle != ((void *) 0)"
 );
 }

 gST = (UINT64)SystemTable;
 if (SystemTable == NULL) {
 AssertHandler (
 "e:\\hs\\MdePkg\\Library\\UefiBootServicesTableLib\\UefiBootServicesTableLib.c",
 57,
 "gST != ((void *) 0)"
 );
 }

 gBS = *(UINT64 *)(SystemTable + 96); // SystemTable->BootServices if (gBS == 0) {
 AssertHandler (
 "e:\\hs\\MdePkg\\Library\\UefiBootServicesTableLib\\UefiBootServicesTableLib.c",
 63,
 "gBS != ((void *) 0)"
 );
 }

 gRT = *(UINT64 *)(SystemTable + 88); // SystemTable->RuntimeServices if (gRT == 0) {
 AssertHandler (
 "e:\\hs\\MdePkg\\Library\\UefiRuntimeServicesTableLib\\UefiRuntimeServicesTableLib.c",
 47,
 "gRT != ((void *) 0)"
 );
 }

 // Initialize global data structures InitializeAmiTcgPpiVar ();

 // Locate and initialize TCG platform protocol Status = LocateTcgPlatformProtocol ();
 gTpm20PpiContext = ((UINT64 (**)(UINT64))Status)(5);

 // Enable write protection if not already enabled if (*(INT8 *)GetMemoryConfig (1024068) >= 0) {
 Status2 = GetMemoryConfig (1024064);
 EnableWriteProtection (Status2);
 *((UINT8 *)GetMemoryConfig (1024068)) |= 0x80;
 }

 // Check if Local APIC is enabled for delay calibration ProcessorFlags = ReadControlRegister ();
 ClearInterruptFlag ();
 LocalApicEnabled = (ProcessorFlags & 0x200) != 0;
 TscDelta = ReadTimeStampCounter (1288) & 0xFFFFFF;
 EnableInterruptFlag ();
 while ((((UINT32)TscDelta + 357 - (UINT32)ReadTimeStampCounter (1288)) & 0x800000) == 0) {
 CpuPause ();
 }
 EnableInterruptFlag ();
 if (LocalApicEnabled) {
 SetInterruptFlag ();
 } else {
 ClearInterruptFlag ();
 }

 // Locate HII Database protocol Status = (*(UINT64 ( **)(VOID *, UINT64, UINT64 *))(gBS + 320))(
 &gEfiHiiDatabaseProtocolGuid, 0, &gTcg2Protocol);
 if (Status < 0) {
 DebugPrint (0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
 AssertHandler (
 "e:\\hs\\MdeModulePkg\\Library\\UefiHiiServicesLib\\UefiHiiServicesLib.c",
 88,
 "!EFI_ERROR (Status)"
 );
 }

 Status2 = (*(UINT64 ( **)(VOID *, UINT64, VOID *))(gBS + 320))(
 &gEfiHiiPackageListProtocolGuid, 0, &gEfiHiiDatabaseProtocolGuid);
 if (Status2 < 0) {
 DebugPrint (0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status2);
 AssertHandler (
 "e:\\hs\\MdeModulePkg\\Library\\UefiHiiServicesLib\\UefiHiiServicesLib.c",
 94,
 "!EFI_ERROR (Status)"
 );
 }

 Status3 = (*(UINT64 ( **)(VOID *, UINT64, VOID *))(gBS + 320))(
 &gEfiVariableLockProtocolGuid, 0, &gEfiTpm20PlatformProtocolGuid);
 if (Status3 < 0) {
 DebugPrint (0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status3);
 AssertHandler (
 "e:\\hs\\MdeModulePkg\\Library\\UefiHiiServicesLib\\UefiHiiServicesLib.c",
 100,
 "!EFI_ERROR (Status)"
 );
 }

 (*(VOID ( **)(VOID *, UINT64, VOID *))(gBS + 320))(
 &gEfiTcg2ProtocolGuid, 0, &gHiiDatabaseProtocol);
 Status4 = (*(UINT64 ( **)(VOID *, UINT64, VOID *))(gBS + 320))(
 &gEfiHiiDatabaseProtocolGuid, 0, &gTcg2Protocol);
}

//
// ====================================================================
// Main Driver Entry
// ====================================================================

/**Main driver entry called after initialization.

 Reads TPMPERBIOSFLAGS variable, determines PPI request,
 installs TPM PPI protocol, and registers ready-to-boot callbacks.

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

 @retval EFI_SUCCESS Driver initialized successfully.
 @retval EFI_UNSUPPORTED TPM 2.0 not available.
 @retval EFI_DEVICE_ERROR TPM 2.0 device error.
**/
EFI_STATUS Tpm20PlatformDriverEntry (
 IN EFI_HANDLE ImageHandle,
 IN EFI_SYSTEM_TABLE *SystemTable
 )
{
 EFI_STATUS Status;
 EFI_STATUS StatusVar;
 UINT64 Event1;
 UINT64 Event2;
 UINT64 Event3;
 UINT64 Event4;
 UINT64 DataSize;
 UINT8 ReadyToBootRegistration[16];
 UINT8 PpiRequest;

 //
 // Step 1: Read TPMPERBIOSFLAGS variable
 //
 DataSize = 6;
 if ((*(INT64 ( **)(const UINT16 *, VOID *, UINT64, UINT64 *, UINT8 *))(gRT + 72))(
 L"TPMPERBIOSFLAGS",
 &gEfiTpm20PlatformProtocolGuid,
 0,
 &DataSize,
 &gTpmPerBiosFlags) < 0)
 {
 //
 // Variable not found - set defaults
 //
 gTpmPerBiosFlags = 1;
 gTpmPerBiosWord &= ~1u;
 gTpmPerBiosWord &= ~2u;
 gTpmPerBiosFlags2 = 1;
 gTpmPerBiosWord &= ~4u;
 gTpmPerBiosFlags3 = 0;
 gTpmPerBiosWord |= 8u;
 gTpmPerBiosWord |= 0x10u;
 gTpmPerBiosWord |= 0x20u;
 gTpmPerBiosWord |= 0x40u;

 StatusVar = AmiSetVariable (
 (UINT32)L"TPMPERBIOSFLAGS",
 (UINT32)&gEfiTpm20PlatformProtocolGuid,
 7,
 6,
 (UINT64)&gTpmPerBiosFlags
 );
 if (StatusVar < 0) {
 return StatusVar;
 }
 }

 //
 // Step 2: Determine PPI request from AMI TCG PPI variable
 //
 gPpiRequest = GetTpmPpiRequest (&gAmiTcgPpiVar[0]);

 if (DebugEnabled (0x80000000) && DebugLevelEnabled (0x80000000)) {
 DebugPrint (0x80000000, "PpiRequest = %d \n", gPpiRequest);
 }

 //
 // Step 3: If PPI request is active, install HII + PPI protocol
 //
 if (gPpiRequest && gPpiRequest <= 0x80) {
 InstallTpm20HiiPackage (ImageHandle, &gTpm20PpiProtocol);

 Event1 = (*(UINT64 ( **)(UINT64, UINT64, UINT64 ( *)(), UINT64, UINT64 *))(gBS + 80))(
 512,
 8,
 Tpm20PpiCallback,
 0,
 &Event2);
 if (Event1 < 0) {
 return Event1;
 }

 Status = (*(UINT64 ( **)(VOID *, UINT64, VOID *))(gBS + 168))(
 &gEfiHiiDatabaseProtocolGuid,
 Event2,
 &gEfiTpm20PlatformProtocolGuid);
 if (Status < 0) {
 return Status;
 }
 } else {
 //
 // No PPI request - install variable lock callback
 //
 if ((*(UINT64 ( **)(UINT64, UINT64, UINT64 ( *)(), UINT64, UINT64 *))(gBS + 80))(
 512,
 8,
 Tpm20OnVariableLock,
 0,
 &Event3) >= 0)
 {
 Status = (*(UINT64 ( **)(VOID *, UINT64, VOID *))(gBS + 168))(
 &gEfiVariableLockProtocolGuid,
 Event3,
 &gEfiTpm20PlatformProtocolGuid);
 if (Status < 0) {
 return Status;
 }
 }

 if (CreateReadyToBootEvent (8, SidPpiCallback, 0, ReadyToBootRegistration) < 0) {
 return 0;
 }
 }

 //
 // Step 4: Locate TCG2 protocol for TPM measurements
 //
 Status = (*(UINT64 ( **)(VOID *, UINT64, UINT64 *))(gBS + 320))(
 &gEfiTcg2ProtocolGuid, 0, &gTpm20PpiContext);
 if (Status >= 0) {
 CompleteTpm20PlatformInit (0, 0);
 } else {
 if ((*(UINT64 ( **)(UINT64, UINT64, UINT64 ( *)(UINT64, UINT64), UINT64, UINT64 *))(gBS + 80))(
 512,
 8,
 CompleteTpm20PlatformInit,
 0,
 &Event4) < 0)
 {
 return 0;
 }
 Status = (*(UINT64 ( **)(VOID *, UINT64, VOID *))(gBS + 168))(
 &gEfiTcg2ProtocolGuid,
 Event4,
 &gEfiTpm20PlatformProtocolGuid);
 if (Status < 0) {
 return 0;
 }
 }

 return Status;
}

//
// ====================================================================
// Complete TPM 2.0 Platform Initialization
// ====================================================================

/**Complete TPM 2.0 platform initialization: register ready-to-boot and BDS callbacks, start TPM platform hardware initialization.

 @param[in] Context Not used.
 @param[in] SystemTable Not used.

 @return EFI_SUCCESS always.
**/
EFI_STATUS CompleteTpm20PlatformInit (
 IN UINT64 Context,
 IN UINT64 SystemTable
 )
{
 EFI_STATUS Status;
 EFI_STATUS Status2;
 UINT64 Event;
 UINT64 EventReg;
 UINT8 Registration[16];

 //
 // Step 1: Measure Secure Boot variables
 //
 Status = PrepareSecureBootMeasurement ();
 if (Status >= 0) {
 MeasureSecureBootVariables ();

 if (DebugEnabled (64) && DebugLevelEnabled (64)) {
 DebugPrint (64, "Secure boot state measured.\n");
 }

 //
 // Step 2: Measure SID (Storage ID) via PPI
 //
 MeasureSidPpi (7);

 //
 // Step 3: Register BDS TCG TPM2 ready-to-boostrap callback
 //
 Status = CreateReadyToBootEvent (8, SidPpiCallback2, 0, &Registration);
 if (Status >= 0) {
 //
 // Step 4: Initialize TPM platform hardware
 //
 Status2 = InitializeTpmPlatformHardware ();
 if (DebugEnabled (0x80000000) && Status2 < 0) {
 AssertHandler (
 "e:\\hs\\AmiModulePkg\\TCG2\\Common\\Tpm20PlatformDxe\\Tpm20PlatformDxe.c",
 5247,
 "!(((INTN)(RETURN_STATUS)(Status)) < 0)"
 );
 }

 //
 // Step 5: Register TPM platform hardware init callback
 //
 Status = (*(UINT64 ( **)(UINT64, UINT64, UINT64 ( *)(), UINT64, UINT8 *))(gBS + 80))(
 513, 16, TpmPlatformHardwareInit, 0, Registration);

 if (Status >= 0) {
 if ((*(UINT64 ( **)(UINT64, UINT64, UINT64 ( *)(), UINT64, UINT64 *))(gBS + 80))(
 512, 8, Tpm2BdsCallback, 0, &Event) >= 0)
 {
 if ((*(UINT64 ( **)(VOID *, UINT64, VOID *))(gBS + 168))(
 &gEfiHiiDatabaseProtocolGuid,
 Event,
 &gEfiTpm20PlatformProtocolGuid) < 0
 && DebugEnabled (0x80000000)
 && DebugLevelEnabled (0x80000000))
 {
 DebugPrint (0x80000000, "[%d]: Error for Register BDS TCGTpm20HsTiPrepare(...)\n", 5282);
 }
 } else if (DebugEnabled (0x80000000) && DebugLevelEnabled (0x80000000)) {
 DebugPrint (0x80000000, "[%d]: Error for Create BDS TCGTpm20HsTiPrepare(...)\n", 5270);
 }

 //
 // Step 6: Register TPM platform ready-to-boot callback
 //
 Status2 = RegisterTpmPlatformReadyBoot (16, Tpm20PlatformReadyBoot, 0, &gEfiTpm20PlatformProtocolGuid);
 if (DebugEnabled (0x80000000) && Status2 < 0) {
 if (DebugEnabled (0x80000000) && DebugLevelEnabled (0x80000000)) {
 DebugPrint (0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status2);
 }
 AssertHandler (
 "e:\\hs\\AmiModulePkg\\TCG2\\Common\\Tpm20PlatformDxe\\Tpm20PlatformDxe.c",
 5291,
 "!EFI_ERROR (Status)"
 );
 }

 return FinalizeTpm20PlatformInit ();
 }
 }
 }

 return Status;
}

//
// ====================================================================
// TPM PPI Request Handler
// ====================================================================

/**Get the TPM PPI request from AMI TCG PPI variable storage.

 Reads AMITCGPPIVAR NVRAM variable. If the variable does not exist,
 initializes it to zero. If AMITCGPPIVAR2 exists and contains a
 version 23 structure, migrates it to AMITCGPPIVAR format.

 @param[out] PpiRequest Pointer to receive the current PPI request value.

 @return The PPI request state (0=inactive, 1..23=active).
**/
UINT8 EFIAPI GetTpmPpiRequest (
 OUT UINT32 *PpiRequest
 )
{
 UINT64 DataSize;
 INT32 VarAttr;
 UINT32 PpiVar2[8];
 INT32 VarAttr2;
 UINT64 DataSize2;
 INT32 PpiState;
 INT32 PpiData[6];

 VarAttr = 0;
 VarAttr2 = 0;
 DataSize = 24;
 DataSize2 = 24;
 PpiState = 0;
 PpiData[0] = 0;
 PpiData[1] = 0;
 PpiData[2] = 0;
 PpiData[3] = 0;
 PpiData[4] = 0;
 PpiData[5] = 0;

 //
 // Attempt to read AMITCGPPIVAR
 //
 if ((*(INT64 ( **)(const UINT16 *, VOID *, INT32 *, UINT64 *, INT32 *))(gRT + 72))(
 L"AMITCGPPIVAR",
 &gEfiTpm20PlatformProtocolGuid,
 &VarAttr,
 &DataSize,
 &PpiState) == EFI_NOT_FOUND)
 {
 //
 // Variable not found - initialize to zero
 //
 PpiState = 0;
 PpiData[0] = 0;
 PpiData[1] = 0;
 PpiData[2] = 0;
 PpiData[3] = 0;
 PpiData[4] = 0;
 PpiData[5] = 0;
 AmiSetVariable (
 (UINT32)L"AMITCGPPIVAR",
 (UINT32)&gEfiTpm20PlatformProtocolGuid,
 7,
 DataSize,
 (UINT64)&PpiState
 );
 } else {
 //
 // Variable exists - check if we need to migrate from AMITCGPPIVAR2
 //
 if (!PpiState &&
 (*(INT64 ( **)(const UINT16 *, VOID *, INT32 *, UINT64 *, UINT32 *))(gRT + 72))(
 L"AMITCGPPIVAR2",
 &gEfiTpm20PlatformProtocolGuid,
 &VarAttr2,
 &DataSize2,
 PpiVar2) >= 0 &&
 PpiVar2[0] == 23)
 {
 //
 // Migrate AMITCGPPIVAR2 (version 23) to AMITCGPPIVAR
 //
 PpiData[1] = PpiVar2[1];
 PpiData[5] = PpiVar2[5];
 PpiState = 23;
 AmiSetVariable (
 (UINT32)L"AMITCGPPIVAR",
 (UINT32)&gEfiTpm20PlatformProtocolGuid,
 VarAttr,
 DataSize,
 (UINT64)&PpiState
 );
 PpiVar2[0] = 0;
 AmiSetVariable (
 (UINT32)L"AMITCGPPIVAR2",
 (UINT32)&gEfiTpm20PlatformProtocolGuid,
 VarAttr2,
 DataSize2,
 (UINT64)PpiVar2
 );
 }

 *PpiRequest = PpiData[5];
 }

 return PpiState;
}

//
// ====================================================================
// TPM PPI Handler (called via event notification)
// ====================================================================

/**TPM PPI request callback executed as part of PPI processing.

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

 @retval EFI_SUCCESS PPI callback processed successfully.
**/
EFI_STATUS EFIAPI Tpm20PpiCallback (
 IN EFI_HANDLE ImageHandle,
 IN EFI_SYSTEM_TABLE *SystemTable
 )
{
 //
 // Process TPM PPI request
 // This function handles TPM enable/disable/clear operations
 // based on the gPpiRequest value
 //
 return HandleTpm20PpiRequest ();
}

//
// ====================================================================
// Install HII Package List for TPM PPI
// ====================================================================

/**Install HII package list for TPM PPI.

 @param[in] ImageHandle The firmware allocated handle for the EFI image.
 @param[in] HiiHandle Pointer to receive HII handle.

 @return Status code from HII protocol operations.
**/
EFI_STATUS InstallTpm20HiiPackage (
 IN EFI_HANDLE ImageHandle,
 OUT VOID **HiiHandle
 )
{
 EFI_STATUS Status;
 EFI_STATUS FinalStatus;
 EFI_STATUS LocateStatus;
 UINT64 PackageListHandle;
 UINT64 HiiDatabase;
 UINT64 NewPackageList;

 //
 // Install HII package list protocol on ImageHandle
 //
 Status = (*(INT64 ( **)(EFI_HANDLE, VOID *, UINT64 *, EFI_HANDLE, UINT64, INT32))(gBS + 280))(
 ImageHandle,
 &gEfiHiiPackageListProtocolGuid,
 &PackageListHandle,
 ImageHandle,
 0,
 2);
 if (Status >= 0) {
 //
 // Locate HII Database protocol
 //
 LocateStatus = (*(UINT64 ( **)(VOID *, UINT64, UINT64 *))(gBS + 320))(
 &gEfiHiiDatabaseProtocolGuid,
 0,
 &HiiDatabase);
 if (LocateStatus >= 0) {
 //
 // Call HiiDatabase->NewPackageList to register the HII package
 //
 NewPackageList = (*(UINT64 ( **)(UINT64, UINT64, UINT64, UINT64))HiiDatabase)(
 HiiDatabase,
 PackageListHandle,
 0,
 (UINT64)HiiHandle);

 if (DebugEnabled (64) && DebugLevelEnabled (64)) {
 DebugPrint (64, "NewPackageList status: %r\n", NewPackageList);
 }

 return NewPackageList;
 } else {
 if (DebugEnabled (0x80000000) && DebugLevelEnabled (0x80000000)) {
 DebugPrint (0x80000000, "gEfiHiiDatabaseProtocolGuid protocol is not found\n");
 }
 return LocateStatus;
 }
 } else {
 if (DebugEnabled (0x80000000)) {
 if (DebugLevelEnabled (0x80000000)) {
 DebugPrint (0x80000000, "gEfiHiiPackageListProtocolGuid protocol is not found\n");
 }
 }
 return Status;
 }
}

//
// ====================================================================
// Variable Lock Callback
// ====================================================================

/**Notification callback for gEfiVariableLockProtocolGuid.
 Locks TPMPERBIOSFLAGS and AMITCGPPIVAR variables.

 @return EFI_SUCCESS always.
**/
EFI_STATUS EFIAPI Tpm20OnVariableLock (
 VOID
 )
{
 EFI_STATUS Status;
 EFI_STATUS LockStatus;
 UINT64 VariableLockProtocol;
 UINT64 ( **VariableLockRequestToLock)(UINT64, const UINT16 *, VOID *);

 if (DebugEnabled (64) && DebugLevelEnabled (64)) {
 DebugPrint (64, "Tpm20OnVariableLockProtocolGuid callback entry\n");
 }

 Status = (*(UINT64 ( **)(VOID *, UINT64, UINT64))(gBS + 320))(
 &gEfiVariableLockProtocolGuid,
 0,
 &VariableLockProtocol);
 if (Status >= 0) {
 VariableLockRequestToLock = (UINT64 ( **)(UINT64, const UINT16 *, VOID *))VariableLockProtocol;

 LockStatus = (*VariableLockRequestToLock)(
 VariableLockProtocol,
 L"TPMPERBIOSFLAGS",
 &gEfiTpm20PlatformProtocolGuid);
 if (DebugEnabled (0x80000000) && LockStatus < 0) {
 if (DebugEnabled (0x80000000) && DebugLevelEnabled (0x80000000)) {
 DebugPrint (0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", LockStatus);
 }
 AssertHandler (
 "e:\\hs\\AmiModulePkg\\TCG2\\Common\\Tpm20PlatformDxe\\Tpm20PlatformDxe.c",
 4549,
 "!EFI_ERROR (Status)"
 );
 }

 Status = (*VariableLockRequestToLock)(
 VariableLockProtocol,
 L"AMITCGPPIVAR",
 &gEfiTpm20PlatformProtocolGuid);
 }

 if (DebugEnabled (0x80000000) && Status < 0) {
 if (DebugEnabled (0x80000000) && DebugLevelEnabled (0x80000000)) {
 DebugPrint (0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
 }
 AssertHandler (
 "e:\\hs\\AmiModulePkg\\TCG2\\Common\\Tpm20PlatformDxe\\Tpm20PlatformDxe.c",
 4552,
 "!EFI_ERROR (Status)"
 );
 }

 return 0;
}

//
// ====================================================================
// SID PPI Callback
// ====================================================================

/**SID (Storage ID) PPI handler. Checks TcgSIDVariable state and sends EnableBlock SID command if needed.

 @return EFI_SUCCESS SID PPI processed successfully.
**/
EFI_STATUS EFIAPI SidPpiCallback (
 VOID
 )
{
 EFI_STATUS Status;
 INT32 VarAttr;
 UINT64 SidState;
 UINT64 DataSize;
 UINT64 Result;

 SidState = 1;
 VarAttr = 3;
 DataSize = 8;

 //
 // Read TcgSIDVariable
 //
 Status = (*(INT64 ( **)(const UINT16 *, VOID *, INT32 *, UINT64 *, UINT64 *))(gRT + 72))(
 L"TcgSIDVariable",
 &gEfiTpm20PlatformProtocolGuid,
 &VarAttr,
 &DataSize,
 &SidState);

 if (DebugEnabled (64) && DebugLevelEnabled (64)) {
 DebugPrint (64, "SidState = %x ; Status = %r \n", SidState, Status);
 }

 Result = 0;
 if (Status < 0 || SidState == 1) {
 if (DebugEnabled (64) && DebugLevelEnabled (64)) {
 DebugPrint (64, "Sending EnableBlock SID command \n");
 }
 Result = SendEnableBlockSidCommand ();
 }

 if (!SidState) {
 SidState = 1;
 return AmiSetVariable (
 (UINT32)L"TcgSIDVariable",
 (UINT32)&gEfiTpm20PlatformProtocolGuid,
 3,
 8,
 (UINT64)&SidState
 );
 }

 return Result;
}

//
// ====================================================================
// Ready-to-Boot Event Registration
// ====================================================================

/**Create a Ready-to-Boot event and register a callback.

 @param[in] NotifyTpl TPL for notification.
 @param[in] Callback Function to call on ReadyToBoot.
 @param[in] Context Context for callback (not used).
 @param[out] Registration Registration pointer.

 @return EFI_STATUS.
**/
EFI_STATUS CreateReadyToBootEvent (
 IN UINT64 NotifyTpl,
 IN EFI_EVENT_NOTIFY Callback,
 IN UINT64 Context,
 OUT UINT64 Registration
 )
{
 EFI_EVENT_NOTIFY NotifyFunction;

 if (Registration == 0) {
 AssertHandler (
 "e:\\hs\\MdePkg\\Library\\UefiLib\\UefiNotTiano.c",
 181,
 "ReadyToBootEvent != ((void *) 0)"
 );
 }

 //
 // Check UEFI spec version (>= 2.0 supports CreateEventEx)
 //
 if (*(UINT32 *)(gST + 8) >= 0x20000) {
 NotifyFunction = NULL;
 if (Callback) {
 NotifyFunction = Callback;
 }

 return (*(INT64 ( **)(UINT64, UINT64, EFI_EVENT_NOTIFY, UINT64, VOID *, UINT64))(gBS + 368))(
 512, // EventType: EVT_NOTIFY_SIGNAL NotifyTpl,
 NotifyFunction,
 Context,
 &gEfiTcg2ProtocolGuid, // ReadyToBoot GUID Registration
 );
 } else {
 DebugPrint (0x80000000, "EFI1.1 can't support ReadyToBootEvent!");
 AssertHandler (
 "e:\\hs\\MdePkg\\Library\\UefiLib\\UefiNotTiano.c",
 185,
 "((BOOLEAN)(0==1))"
 );
 return EFI_UNSUPPORTED;
 }
}

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

/**Measure Secure Boot variables (SecureBoot, PK, KEK, db, dbx) into TPM.

 @return EFI_SUCCESS Secure Boot state measured successfully.
**/
EFI_STATUS MeasureSecureBootVariables (
 VOID
 )
{
 EFI_STATUS Status;
 UINT64 DataSize;
 UINT8 *DataBuffer;
 UINT64 VarSize;
 CHAR16 *VarName;
 UINT64 VarGuid[2];
 INT32 Attributes;
 INT32 Attributes2;

 DataBuffer = 0;
 Attributes = 23;
 Attributes2 = 7;
 VarGuid[0] = -2147483647; // 0x80000001 (EFI_GLOBAL_VARIABLE)

 //
 // Read SecureBoot variable
 //
 VarSize = 23;
 Status = (*(INT64 ( **)(UINT64, UINT64 *, UINT8 *, UINT8 *))(gRT + 128))(
 23, &DataSize, (UINT8 *)&VarSize, (UINT8 *)&Attributes);
 if (Status < 0) {
 return Status;
 }

 VarSize = DataSize;
 Status = (*(UINT64 ( **)(UINT64, UINT64, UINT8 **))(gBS + 64))(
 4, DataSize, &DataBuffer);
 if (!DataBuffer || Status < 0) {
 return EFI_OUT_OF_RESOURCES;
 }

 //
 // Zero the buffer
 //
 (*(VOID ( **)(UINT8 *, UINT64, UINT64))(gBS + 360))(DataBuffer, VarSize, 0);

 //
 // Read and measure SecureBoot
 //
 VarName = L"SecureBoot";
 VarGuid[0] = (UINT64)VarGuid;
 Status = (*(INT64 ( **)(const UINT16 *, UINT64 *, UINT64, UINT64 *, UINT8 *))(gRT + 72))(
 L"SecureBoot", &gEfiTpm20PlatformProtocolGuid, 0, &VarSize, DataBuffer);
 if (Status < 0) {
 VarSize = 0;
 *DataBuffer = 0;
 }

 Status = MeasureVariable (7, 0x80000001, VarName, (EFI_GUID *)&VarGuid, DataBuffer, VarSize);

 //
 // Read and measure PK
 //
 VarSize = DataSize;
 (*(VOID ( **)(UINT8 *, UINT64, UINT64))(gBS + 360))(DataBuffer, VarSize, 0);
 VarName = L"PK";
 Status = (*(INT64 ( **)(const UINT16 *, UINT64 *, UINT64, UINT64 *, UINT8 *))(gRT + 72))(
 L"PK", &gEfiTpm20PlatformProtocolGuid, 0, &VarSize, DataBuffer);
 if (Status < 0) {
 VarSize = 0;
 *DataBuffer = 0;
 }

 Status = MeasureVariable (7, 0x80000001, VarName, (EFI_GUID *)&VarGuid, DataBuffer, VarSize);

 //
 // Read and measure KEK
 //
 VarSize = DataSize;
 (*(VOID ( **)(UINT8 *, UINT64, UINT64))(gBS + 360))(DataBuffer, VarSize, 0);
 VarName = L"KEK";
 Status = (*(INT64 ( **)(const UINT16 *, UINT64 *, UINT64, UINT64 *, UINT8 *))(gRT + 72))(
 L"KEK", &gEfiTpm20PlatformProtocolGuid, 0, &VarSize, DataBuffer);
 if (Status < 0) {
 VarSize = 0;
 *DataBuffer = 0;
 }

 Status = MeasureVariable (7, 0x80000001, VarName, (EFI_GUID *)&VarGuid, DataBuffer, VarSize);

 if (Status >= 0) {
 //
 // Read and measure db
 //
 VarSize = DataSize;
 (*(VOID ( **)(UINT8 *, UINT64, UINT64))(gBS + 360))(DataBuffer, VarSize, 0);
 VarName = L"db";
 Status = (*(INT64 ( **)(const UINT16 *, UINT64 *, UINT64, UINT64 *, UINT8 *))(gRT + 72))(
 L"db", &gEfiTpm20PlatformProtocolGuid, 0, &VarSize, DataBuffer);
 if (Status < 0) {
 VarSize = 0;
 *DataBuffer = 0;
 }

 Status = MeasureVariable (7, 0x80000001, VarName, (EFI_GUID *)&VarGuid, DataBuffer, VarSize);

 if (Status >= 0) {
 //
 // Read and measure dbx
 //
 VarSize = DataSize;
 (*(VOID ( **)(UINT8 *, UINT64, UINT64))(gBS + 360))(DataBuffer, VarSize, 0);
 VarName = L"dbx";
 Status = (*(INT64 ( **)(const UINT16 *, UINT64 *, UINT64, UINT64 *, UINT8 *))(gRT + 72))(
 L"dbx", &gEfiTpm20PlatformProtocolGuid, 0, &VarSize, DataBuffer);
 if (Status < 0) {
 VarSize = 0;
 *DataBuffer = 0;
 }

 Status = MeasureVariable (7, 0x80000001, VarName, (EFI_GUID *)&VarGuid, DataBuffer, VarSize);
 }
 }

 //
 // Finalize measurement
 //
 Tpm2PcrExtend (1, 50694677);

 //
 // Free allocated buffer
 //
 (*(VOID ( **)(UINT8 *))(gBS + 72))(DataBuffer);

 return 0;
}

//
// ====================================================================
// Measure variable into TPM
// ====================================================================

/**Measure a UEFI variable into the TPM.

 @param[in] PcrIndex PCR index to extend.
 @param[in] EventType Event type for measurement.
 @param[in] VarName Variable name (wide string).
 @param[in] VendorGuid Variable vendor GUID.
 @param[in] Data Variable data buffer.
 @param[in] DataSize Size of variable data.

 @retval EFI_SUCCESS Measurement successful.
 @retval EFI_DEVICE_ERROR TPM device error.
**/
EFI_STATUS MeasureVariable (
 IN UINT32 PcrIndex,
 IN UINT32 EventType,
 IN CHAR16 *VarName,
 IN EFI_GUID *VendorGuid,
 IN VOID *Data,
 IN UINTN DataSize
 )
{
 //
 // TCG PC Client Platform Firmware Profile Specification
 // Measure variable Name + VendorGuid + Data into PCR
 //
 return Tpm2MeasureVariable (PcrIndex, EventType, VarName, VendorGuid, Data, DataSize);
}

//
// ====================================================================
// GPT Measurement
// ====================================================================

/**Measure the GPT (GUID Partition Table) into the TPM.

 @param[in] BlockIoProtocol Block I/O protocol interface.

 @return Status code from GPT measurement.
**/
EFI_STATUS MeasureGpt (
 IN EFI_BLOCK_IO_PROTOCOL *BlockIoProtocol
 )
{
 UINT64 Status;
 UINT8 PpiIndex;
 INT32 EntrySize;
 UINT64 BlockIo;
 UINT64 DiskIo;
 UINT64 PartitionTableHeader;
 UINT64 PartitionEntries;
 UINT64 GptDataBuffer;
 UINT64 GptProtocol;
 UINT64 GptBlockSize;
 UINT64 GptEntryCount;
 UINT64 GptValidEntries;
 UINT32 NumPartitions;
 UINT64 CurrentEntry;
 UINT64 CurrentDestination;
 UINT32 Index;
 UINT32 ValidIndex;
 UINT64 GptHeader;
 UINT64 GptEntries;
 UINT64 GptEntry;
 INT32 ParamBlockSize;
 INT32 ParamEntrySize;
 UINT64 AlignedBuffer;
 UINT32 BufferSize;
 UINT64 TcgProtocol;
 UINT64 ( **TcgPpi)(UINT64, UINT64, UINT64, UINT64, UINT32 *, UINT64 *);
 INT32 Action[100];
 UINT64 GptBlockIo;
 UINT64 GptDiskIo;
 UINT64 Media;
 UINT64 MediaId;

 //
 // Initialize local variables
 //
 GptDataBuffer = 0;
 AlignedBuffer = 0;
 GptProtocol = 0;
 BlockIo = 0;
 DiskIo = 0;
 PartitionTableHeader = 0;
 PartitionEntries = 0;
 GptBlockIo = 0;
 GptDiskIo = 0;

 //
 // Check if GPT already measured
 //
 if (gGptMeasurementCount > 0) {
 return 0;
 }

 //
 // Locate Block I/O protocol and Disk I/O protocol
 //
 if ((*(INT64 ( **)(UINT64, VOID *, UINT64 *))(gBS + 152))(
 (UINT64)BlockIoProtocol, &gEfiTpm20PlatformProtocolGuid, &BlockIo) < 0
 || (*(INT64 ( **)(UINT64, VOID *, UINT64 *))(gBS + 152))(
 (UINT64)BlockIoProtocol, &gEfiTpm20PlatformProtocolGuid, &DiskIo) < 0)
 {
 return EFI_UNSUPPORTED;
 }

 //
 // Allocate buffer for partition table header
 //
 Status = (*(INT64 ( **)(UINT64, UINT64, UINT64 *))(gBS + 64))(
 4,
 *(UINT32 *)(*(UINT64 *)(BlockIo + 8) + 12),
 &PartitionTableHeader);
 if (Status < 0 || !PartitionTableHeader) {
 return EFI_OUT_OF_RESOURCES;
 }

 //
 // Read partition table header
 //
 (*(VOID ( **)(UINT64, UINT64, UINT64, UINT64, UINT64))(DiskIo + 8))(
 DiskIo,
 **(UINT32 **)(BlockIo + 8),
 0,
 *(UINT32 *)(*(UINT64 *)(BlockIo + 8) + 12),
 PartitionTableHeader);

 //
 // Look for GPT protective MBR signature (0xEE)
 //
 PpiIndex = 0;
 while (*(UINT8 *)(PartitionTableHeader + 16 *PpiIndex + 450) != 0xEE) {
 if (++PpiIndex >= 4) {
 goto CHECK_GPT_SIGNATURE;
 }
 }

 EntrySize = *(UINT8 *)(PartitionTableHeader + 16 *PpiIndex + 454);
 if (!EntrySize) {
CHECK_GPT_SIGNATURE:
 Status = EFI_NOT_FOUND;
 goto CLEANUP_PARTITION_HEADER;
 }

 //
 // Read GPT header
 //
 Status = (*(INT64 ( **)(UINT64, UINT64, UINT64 *))(gBS + 64))(
 4,
 *(UINT32 *)(*(UINT64 *)(BlockIo + 8) + 12),
 &GptBlockIo);
 if (Status < 0 || !GptBlockIo) {
 goto CLEANUP_PARTITION_HEADER2;
 }

 Status = (*(INT64 ( **)(UINT64, UINT64, UINT64, UINT64, UINT64))(DiskIo + 8))(
 DiskIo,
 **(UINT32 **)(BlockIo + 8),
 EntrySize * *(_DWORD *)(*(UINT64 *)(BlockIo + 8) + 12),
 *(UINT32 *)(*(UINT64 *)(BlockIo + 8) + 12),
 GptBlockIo);

 if (CompareMemory ("EFI PART", GptBlockIo, 8)) {
 Status = EFI_NOT_FOUND;
 goto CLEANUP_GPT;
 }

 if (Status < 0) {
 DebugPrint (0x80000000, "Failed to Read Partition Table Header!\n");
 Status = EFI_DEVICE_ERROR;
 goto CLEANUP_GPT;
 }

 //
 // Allocate buffer for partition entries
 //
 Status = (*(INT64 ( **)(UINT64, UINT64, UINT64 *))(gBS + 64))(
 4,
 (UINT32)(*(UINT32 *)(GptBlockIo + 80) * *(UINT32 *)(GptBlockIo + 84)),
 &GptDiskIo);
 if (Status < 0 || !GptDiskIo) {
 goto CLEANUP_GPT_ENTRIES;
 }

 //
 // Read partition entries
 //
 Status = (*(INT64 ( **)(UINT64, UINT64, UINT64, UINT64, UINT64))(DiskIo + 8))(
 DiskIo,
 **(UINT32 **)(BlockIo + 8),
 *(UINT64 *)(GptBlockIo + 72) * *(UINT32 *)(*(UINT64 *)(BlockIo + 8) + 12),
 (UINT32)(*(UINT32 *)(GptBlockIo + 80) * *(UINT32 *)(GptBlockIo + 84)),
 GptDiskIo);
 if (Status < 0) {
 Status = EFI_DEVICE_ERROR;
 goto CLEANUP_GPT_ENTRIES;
 }

 //
 // Count valid partition entries
 //
 GptHeader = GptBlockIo;
 GptEntries = GptDiskIo;
 GptValidEntries = 0;
 for (Index = 0; Index < *(UINT32 *)(GptBlockIo + 80); ++Index) {
 if (CompareMemory (GptEntries, &gEfiTpm20PlatformProtocolGuid, 16)) {
 ++GptValidEntries;
 }
 GptHeader = GptBlockIo;
 GptEntries += 128;
 }

 //
 // Allocate buffer for combined GPT data
 //
 BufferSize = GptValidEntries * *(UINT32 *)(GptBlockIo + 84) + 100;
 GptDataBuffer = BufferSize;

 Status = (*(INT64 ( **)(UINT64, UINT64, UINT64 *))(gBS + 64))(
 4, BufferSize, &AlignedBuffer);
 if (Status < 0 || !AlignedBuffer) {
 goto CLEANUP_GPT_ENTRIES;
 }

 //
 // Zero and populate GPT data buffer
 //
 (*(VOID ( **)(UINT64, UINT64, UINT64))(gBS + 360))(AlignedBuffer, BufferSize, 0);

 Action[0] = 5;
 Action[1] = -2147483642; // EV_EFI_GPT_EVENT
 *(UINT32 *)((UINT8 *)Action + 342) = BufferSize;

 //
 // Copy GPT header to buffer
 //
 (*(VOID ( **)(UINT64, UINT64, UINT64))(gBS + 352))(AlignedBuffer, GptBlockIo, 92);
 *(UINT64 *)(AlignedBuffer + 92) = GptValidEntries;

 //
 // Copy valid partition entries
 //
 GptEntry = GptDiskIo;
 ValidIndex = 0;
 CurrentDestination = 0;

 if (*(UINT32 *)(GptBlockIo + 80)) {
 do {
 if (CompareMemory (GptEntry, (VOID *)&gEfiTpm20PlatformProtocolGuid, 16)) {
 (*(VOID ( **)(UINT64, UINT64, UINT64))(gBS + 352))(
 CurrentDestination + AlignedBuffer + 100,
 GptEntry,
 128);
 ++ValidIndex;
 CurrentDestination += 128;
 }
 GptEntry += 128;
 ++Index;
 } while (Index < *(UINT32 *)(GptBlockIo + 80));
 }

 //
 // Extend GPT measurement into TPM
 //
 if (ValidIndex) {
 Status = (*(UINT64 ( **)(VOID *, UINT64, UINT64 ( ***)(UINT64, UINT64, UINT64, UINT64, INT32 *, UINT64 *)))(gBS + 320))(
 &gEfiTcg2ProtocolGuid, 0, &TcgPpi);
 if (Status < 0) {
 return Status;
 }

 (*TcgPpi)(gTpm20PpiContext, AlignedBuffer, 0, BufferSize, Action, (UINT64 *)AlignedBuffer);
 ++gGptMeasurementCount;
 DebugPrint (64, "\n GPT measurement successfull !!!\n");
 }

 //
 // Cleanup
 //
 (*(VOID (**)(VOID))(gBS + 72))();
 (*(VOID ( **)(UINT64))(gBS + 72))(GptBlockIo);
 (*(VOID ( **)(UINT64))(gBS + 72))(AlignedBuffer);
 (*(VOID ( **)(UINT64))(gBS + 72))(PartitionTableHeader);

 return Status;

CLEANUP_GPT:
 Status = EFI_DEVICE_ERROR;
 goto CLEANUP_PARTITION_HEADER2;

CLEANUP_GPT_ENTRIES:
 if (GptDataBuffer) {
 (*(VOID ( **)(UINT64))(gBS + 72))(GptDataBuffer);
 }
 goto CLEANUP_PARTITION_HEADER2;

CLEANUP_PARTITION_HEADER2:
 (*(VOID ( **)(UINT64))(gBS + 72))(PartitionTableHeader);
 return Status;

CLEANUP_PARTITION_HEADER:
 (*(VOID ( **)(UINT64))(gBS + 72))(PartitionTableHeader);
 return Status;
}

//
// ====================================================================
// TPM 2.0 Hash Algorithm Implementations
// ====================================================================

//
// Note: sub_B90C (0xB90C, ~9.6KB) is the SHA-256 hash compression function
// It implements the SHA-256 message schedule and compression loop
// (FIPS 180-4 Section 6.2).
//
// Note: sub_A554 (0xA554, ~4.5KB) is the SHA-512 hash compression function
// It implements the SHA-512 message schedule and compression loop
// (FIPS 180-4 Section 6.4).
//
// Note: sub_4FEC (0x4FEC, ~8KB) is the HandleTpm20Ppi function.
// It processes TPM PPI requests (enable/disable/clear).
//
// Note: sub_8FB8 (0x8FB8, ~3.6KB) is the Unicode SPrint library function
// (BasePrintLib Unicode Sprint wrapper with bounds checking).
//
// Note: sub_E220 (0xE220, ~1.4KB) is the SHA-512 message expansion function.
// It prepares the 80 64-bit words for the SHA-512 compression loop.
//
// Note: sub_4128 (0x4128, ~3.8KB) is the HandleSIDPpi function.
// It handles SID (Storage ID) PPI UI interactions.
//

//
// ====================================================================
// SHA-256: Initialize context
// ====================================================================

VOID Sha256Init (
 OUT VOID *Context
 )
{
 //
 // Initialize SHA-256 context with initial hash values (H0-H7)
 // H0 = 0x6a09e667, H1 = 0xbb67ae85, H2 = 0x3c6ef372, H3 = 0xa54ff53a
 // H4 = 0x510e527f, H5 = 0x9b05688c, H6 = 0x1f83d9ab, H7 = 0x5be0cd19
 //
 sub_B6EC (Context);
}

//
// ====================================================================
// SHA-256: Update with data
// ====================================================================

VOID Sha256Update (
 IN OUT VOID *Context,
 IN VOID *Data,
 IN UINTN DataLen
 )
{
 sub_B718 (Context, Data, DataLen);
}

//
// ====================================================================
// SHA-256: Finalize and produce digest
// ====================================================================

VOID Sha256Final (
 IN OUT VOID *Context,
 OUT UINT8 *HashData
 )
{
 UINT16 AlgId;

 AlgId = 11; /*TPM2_ALG_SHA256 = 0x000B */
 sub_B7E4 (&HashData, Context);
}

//
// ====================================================================
// SM3-256: Hash computation
// ====================================================================

VOID Sm3Hash (
 IN VOID *Data,
 IN UINTN DataLen,
 OUT UINT8 *HashData
 )
{
 VOID *Context;

 sub_DEB8 (Context);
 sub_DEFC (Context, Data, DataLen);
 sub_DFCC (Context, &HashData);
}

//
// ====================================================================
// SHA-512: Initialize context
// ====================================================================

VOID Sha512Init (
 OUT VOID *Context
 )
{
 sub_E154 (Context);
}

//
// ====================================================================
// SHA-512: Update with data
// ====================================================================

VOID Sha512Update (
 IN OUT VOID *Context,
 IN VOID *Data,
 IN UINTN DataLen
 )
{
 sub_E7F8 (Context, Data, DataLen);
}

//
// ====================================================================
// SHA-512: Finalize and produce digest (SHA-384 variant)
// ====================================================================

VOID Sha384Final (
 IN OUT VOID *Context,
 OUT UINT8 *HashData
 )
{
 UINT16 AlgId;

 AlgId = 12; /*TPM2_ALG_SHA384 = 0x000C */
 sub_E1D8 (Context, HashData);
}

//
// ====================================================================
// SHA-512: Finalize and produce digest (SHA-512 variant)
// ====================================================================

VOID Sha512Final (
 IN OUT VOID *Context,
 OUT UINT8 *HashData
 )
{
 UINT16 AlgId;

 AlgId = 13; /*TPM2_ALG_SHA512 = 0x000D */
 sub_E8D0 (Context, HashData);
}

//
// ====================================================================
// Firmware Image Measurement
// ====================================================================

/**Measure a firmware image into the TPM using configured hash algorithms.

 @param[in] ImageBase Base address of the image to measure.
 @param[in] ImageSize Size of the image in bytes.
 @param[in] Algorithm Algorithm index from ActivePcrBanks.

 @return Status code from TPM measurement operations.
**/
EFI_STATUS MeasureFirmwareImage (
 IN UINT64 ImageBase,
 IN UINT64 ImageSize,
 IN UINT16 Algorithm
 )
{
 EFI_STATUS Status;
 EFI_STATUS Status2;
 UINT64 Tcg2Protocol;
 UINT64 TpmHashHandle;
 UINT64 HashHandle;
 UINT64 PcrIndex;
 UINT64 EventData;
 UINT64 DataPtrs[4];
 INT32 PcrAction[3];
 UINT16 AlgCount;
 UINT8 Sha256Context[96];
 UINT8 Sha512Context[208];
 UINT8 Sm3Context[216];
 UINT8 AlignedBuffer[108];
 UINT8 VpIndex;
 UINT64 FinalStatus;
 UINT64 PcrVal;
 UINT64 SequenceResult;
 UINT64 DataSize;
 UINT64 HashValue[8];
 UINT64 ( **TcgProtocol)(UINT64, UINT64, UINT64, UINT64, INT32 *, UINT64 *);
 UINT64 ActivePcrBanks;
 UINT16 NumAlgs;
 UINT16 HashAlg[32];

 //
 // Validate parameters
 //
 if (DebugEnabled (64) && DebugLevelEnabled (64)) {
 DebugPrint (64, "Measuring image @ %x, image len = %x, pfa = %x \n", ImageBase, ImageSize, Algorithm);
 }

 if (!ImageBase || !ImageSize) {
 return 0;
 }

 //
 // Locate TCG2 protocol if not already available
 //
 if (!gTpm20PpiContext) {
 Status = (*(UINT64 ( **)(VOID *, UINT64, UINT64 *))(gBS + 320))(
 &gEfiTcg2ProtocolGuid, 0, &gTpm20PpiContext);
 if (Status < 0) {
 return Status;
 }
 }

 //
 // Locate TPM platform protocol
 //
 Status = (*(UINT64 ( **)(VOID *, UINT64, UINT64 *))(gBS + 320))(
 &gEfiTpm20PlatformProtocolGuid, 0, &Tcg2Protocol);
 if (Status < 0) {
 return Status;
 }

 //
 // Build PPI action structure
 //
 PcrAction[0] = 2; // Number of events PcrAction[1] = -2147483640; // EV_EFI_BOOT_SERVICES_APPLICATION AlgCount = 16;
 DataPtrs[0] = &ImageBase;
 DataPtrs[1] = ImageSize;

 //
 // Determine active PCR banks and iterate
 //
 ActivePcrBanks = *(UINT8 *)(Tcg2Protocol + 6);
 if (ActivePcrBanks == 1) {
 //
 // SHA-1 only
 //
 Sha256Init (Sha256Context);
 } else if (ActivePcrBanks == 2) {
 //
 // SHA-256 only or multi-algorithm
 //
 if ((*(UINT32 *)(Tcg2Protocol + 24) & 1) != 0) {
 Sha256Init (Sha256Context);
 Sha256Update (Sha256Context, (VOID *)ImageBase, (UINT32)ImageSize);
 HashAlg[0] = 11; // TPM2_ALG_SHA256 Sha256Final (Sha256Context, (UINT8 *)&HashAlg);
 }

 if ((*(UINT32 *)(Tcg2Protocol + 24) & 2) != 0) {
 Sm3Hash ((VOID *)ImageBase, (UINT32)ImageSize, Sm3Context);
 HashAlg[33] = 12; // TPM2_ALG_SM3_256 Sm3Hash (Sm3Context, &HashAlg);
 }

 if ((*(UINT32 *)(Tcg2Protocol + 24) & 4) != 0) {
 Sha512Init (Sm3Context);
 Sha512Update (Sm3Context, (VOID *)ImageBase, (UINT32)ImageSize);
 HashAlg[33] = 12; // TPM2_ALG_SHA384 Sha384Final (Sm3Context, &HashAlg);
 }

 if ((*(UINT32 *)(Tcg2Protocol + 24) & 8) != 0) {
 Sha512Init (AlignedBuffer);
 Sha512Update (AlignedBuffer, (VOID *)ImageBase, (UINT32)ImageSize);
 HashAlg[33] = 13; // TPM2_ALG_SHA512 Sha512Final (AlignedBuffer, &HashAlg);
 }

 if ((*(UINT32 *)(Tcg2Protocol + 24) & 0x10) != 0) {
 //
 // TPM2_HMAC session approach for SHA-256 (via TCG protocol)
 //
 TpmHashHandle = 0;
 if (gTpm20PpiContext) {
 TpmHashHandle = (*(UINT64 ( **)(VOID *, UINT64, UINT64 *))(gBS + 320))(
 &gEfiTcg2ProtocolGuid, 0, &HashHandle);
 }

 if (TpmHashHandle >= 0) {
 //
 // Hash sequence start
 //
 DataSize = 4;
 TpmHashHandle = (*(INT64 ( **)(UINT64, UINT64, UINT8 *, UINT64 *))(HashHandle + 8))(
 gTpm20PpiContext, 16, (UINT8 *)&PcrIndex, &DataSize);
 }

 if (TpmHashHandle >= 0) {
 //
 // Hash sequence update
 //
 (*(VOID ( **)(UINT64, UINT64, UINT64, UINT64, UINT8 *))(HashHandle + 16))(
 gTpm20PpiContext, ImageBase, ImageSize, 16, (UINT8 *)&PcrIndex);

 //
 // Hash sequence complete
 //
 SequenceResult = 64;
 FinalStatus = (*(INT64 ( **)(UINT64, UINT8 *, UINT64, UINT8 *, UINT64 *))(HashHandle + 24))(
 gTpm20PpiContext,
 (UINT8 *)&PcrIndex,
 16,
 AlignedBuffer,
 &SequenceResult);

 if (FinalStatus < 0) {
 return EFI_DEVICE_ERROR;
 }

 HashAlg[33] = 18; // TPM2_ALG_SHA256 (HMAC)
 (*(VOID ( **)(UINT16 *, UINT8 *, UINT64))(gBS + 352))(
 &HashAlg[33], AlignedBuffer, SequenceResult);

 if (DebugEnabled (0x400000) && DebugLevelEnabled (0x400000)) {
 DebugPrint (0x400000, "\n Tpm2SequenceComplete Success \n");
 }
 }
 }
 }

 //
 // Finalize: call TCG PPI to extend to PCR
 //
 PcrAction[2] = AlgCount;
 Status = (*(UINT64 ( **)(VOID *, UINT64, UINT64 ( ***)(UINT64, UINT64, UINT64, UINT64, INT32 *, UINT64 *)))(gBS + 320))(
 &gEfiTcg2ProtocolGuid,
 0,
 &TcgProtocol);
 if (Status >= 0) {
 return (*TcgProtocol)(gTpm20PpiContext, 0, 0, 0, PcrAction, DataPtrs);
 } else {
 return Status;
 }
}

//
// ====================================================================
// SHA-256 Hash Sequence and PCR Extend
// ====================================================================

/**Perform SHA-256 based hash sequence and extend to PCR.

 @param[in] Data Data to hash and extend.
 @param[in] DataLen Length of data.
 @param[in] PcrIndex PCR index.
 @param[in] Tcg2Protocol TCG2 protocol instance.

 @return Status code.
**/
EFI_STATUS Tpm2HashSequenceSha256 (
 IN VOID *Data,
 IN UINTN DataLen,
 IN UINT32 PcrIndex,
 IN VOID *Tcg2Protocol
 )
{
 EFI_STATUS Status;
 UINT64 HashHandle;
 UINT64 HashDataSize;
 UINT8 HashBuffer[64];
 UINTN SequenceResult;

 //
 // Open hash sequence
 //
 HashDataSize = 4;
 Status = ((INT64 ( *)(UINT64, UINT64, UINT8 *, UINT64 *))(
 (UINT64)Tcg2Protocol + 8))(
 gTpm20PpiContext,
 16,
 (UINT8 *)&PcrIndex,
 &HashDataSize);
 if (Status < 0) {
 return Status;
 }

 //
 // Hash the data
 //
 ((VOID ( *)(UINT64, UINT64, UINT64, UINT64, UINT64))(
 (UINT64)Tcg2Protocol + 16))(
 gTpm20PpiContext, (UINT64)Data, DataLen, 16, (UINT64)&PcrIndex);

 //
 // Complete hash sequence and get result
 //
 SequenceResult = 64;
 Status = ((INT64 ( *)(UINT64, UINT8 *, UINT64, UINT8 *, UINT64 *))(
 (UINT64)Tcg2Protocol + 24))(
 gTpm20PpiContext,
 (UINT8 *)&PcrIndex,
 16,
 HashBuffer,
 &SequenceResult);

 if (DebugEnabled (0x400000) && DebugLevelEnabled (0x400000)) {
 DebugPrint (0x400000, "\n Tpm2SequenceComplete Success \n");
 }

 return Status;
}

//
// ====================================================================
// UEFI String Print Library (Unicode SPrint wrapper)
// ====================================================================

/**Unicode SPrint function (bounds-checked).

 Implements Unicode string formatting (similar to swprintf) with bounds checking. Calls the BasePrintLib Unicode Sprint engine.

 @param[out] Buffer Output buffer for formatted string.
 @param[in] BufferSize Size of the output buffer in characters.
 @param[in] Format Format string (Unicode).
 @param[in] ... Variable arguments.

 @return Number of characters written, or 0 on error.
**/
UINTN UnicodeSPrint (
 OUT CHAR16 *Buffer,
 IN UINTN BufferSize,
 IN CONST CHAR16 *Format,
 ...
 )
{
 //
 // IDA pseudocode reference: sub_8FB8
 // Implements assertion checks for Buffer, Format, and BufferSize limits.
 // Wraps the internal BasePrintLib SPrint function.
 //
 // Assertions:
 // Buffer != NULL
 // Format != NULL
 // BufferSize <= PcdMaximumUnicodeStringLength
 // StrnLenS(Format, PcdMaximumUnicodeStringLength + 1) <= PcdMaximumUnicodeStringLength
 //
 return 0;
}

//
// ====================================================================
// SHA-512 Hash Initialization Functions
// ====================================================================

/**SHA-512 message expansion (initialization of W[0..79]).
 Used internally by the SHA-512 hash computation.

 @param[in,out] State SHA-512 state to initialize.
 @param[in] Block Input block (128 bytes).

 @return EFI_SUCCESS.
**/
EFI_STATUS Sha512MessageSchedule (
 IN OUT UINT64 *State,
 IN UINT8 *Block
 )
{
 //
 // IDA pseudocode reference: sub_E220
 //
 // This function:
 // 1. Loads the 1024-bit (128-byte) input block as 16 UINT64 words
 // 2. Expands to 80 words using: W[t] = sigma1(W[t-2]) + W[t-7] +
 // sigma0(W[t-15]) + W[t-16]
 // 3. Initializes working variables a-h from state
 // 4. Runs 80 rounds of SHA-512 compression
 // 5. Updates the state with the round output
 //
 // Where:
 // sigma0(x) = ROTR(1,x) ^ ROTR(8,x) ^ SHR(7,x)
 // sigma1(x) = ROTR(19,x) ^ ROTR(61,x) ^ SHR(6,x)
 //
 return 0;
}

//
// ====================================================================
// AMI TCG PPI Variable Initialization
// ====================================================================

/**Initialize the AMI TCG PPI variable structure.
**/
VOID InitializeAmiTcgPpiVar (
 VOID
 )
{
 gAmiTcgPpiVar[0] = 0;
 gAmiTcgPpiVar[1] = 0;
 gAmiTcgPpiVar[2] = 0;
 gAmiTcgPpiVar[3] = 0;
 gAmiTcgPpiVar[4] = 0;
 gAmiTcgPpiVar[5] = 0;
}

//
// ====================================================================
// AMI Set Variable (wrapper for gRT->SetVariable)
// ====================================================================

/**Set a UEFI variable using RT services.

 @param[in] VarName Variable name (as UINT32 encoded address).
 @param[in] VendorGuid Vendor GUID (as UINT32 encoded address).
 @param[in] Attributes Variable attributes.
 @param[in] DataSize Size of variable data.
 @param[in] Data Variable data buffer.

 @return Status code from gRT->SetVariable.
**/
EFI_STATUS AmiSetVariable (
 IN UINT32 VarName,
 IN UINT32 VendorGuid,
 IN UINT32 Attributes,
 IN UINT64 DataSize,
 IN UINT64 Data
 )
{
 return (*(INT64 ( **)(UINT32, UINT32, UINT32, UINT64, UINT64))(gRT + 80))(
 VarName, VendorGuid, Attributes, DataSize, Data);
}

//
// ====================================================================
// Stub Forward Declarations (to be resolved with renamed functions)
// ====================================================================

// sub_17F8 -> PrepareSecureBootMeasurement
// sub_6AC -> MeasureSidPpi
// sub_7A80 -> InitializeTpmPlatformHardware
// sub_7C84 -> FinalizeTpm20PlatformInit
// sub_1EA4 -> SendEnableBlockSidCommand
// sub_2210 -> SidPpiCallback2 (SID callback variant)
// sub_2544 -> Tpm2BdsCallback
// sub_6F14 -> TpmPlatformHardwareInit
// sub_70E8 -> Tpm20PlatformReadyBoot
// sub_7D0C -> HandleTpm20PpiRequest
// sub_8C64 -> LocateTcgPlatformProtocol
// sub_8D8C -> DebugPrint
// sub_8E14 -> AssertHandler
// sub_8E54 -> DebugEnabled
// sub_8E58 -> DebugLevelEnabled
// sub_8A5C -> CompareMemory
// sub_A24C -> RegisterTpmPlatformReadyBoot
// sub_A3EC -> InitializeAmiTcgPpiVar
// sub_A470 -> GetMemoryConfig
// sub_B4C -> Tpm2MeasureVariable
// sub_B6EC -> Sha256InitCore
// sub_B718 -> Sha256UpdateCore
// sub_B7E4 -> Sha256FinalCore
// sub_CCC -> MeasureGpt
// sub_DEB8 -> Sm3Init
// sub_DEFC -> Sm3Update
// sub_DFCC -> Sm3Final
// sub_E154 -> Sha512InitCore
// sub_E1D8 -> Sha384FinalCore
// sub_E774 -> Sha512Sm3Init
// sub_E7F8 -> Sha512Sm3Update
// sub_E8D0 -> Sha512FinalCore
// sub_EEE8 -> AmiSetVariable
// sub_EEC4 -> Tpm2PcrExtend
// sub_F900 -> EnableWriteProtection
// sub_F934 -> ReadTimeStampCounter
// sub_3D0 -> CpuPause
// sub_3E0 -> EnableInterruptFlag
// sub_3F0 -> SetInterruptFlag
// sub_400 -> ClearInterruptFlag
// sub_410 -> ReadControlRegister