/** @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