/**
* Tcg2Dxe.c -- Clean decompilation of TCG2 (TPM 2.0) DXE driver
*
* Source: Lenovo HR650X BIOS
* Module: 0271_Tcg2Dxe (AMI ModulePkg/TCG2/Common/TcgDxe/Tcg2Dxe.c)
* Build: e:\hs\Build\HR6N0XMLK\DEBUG_VS2015\X64\Build\Tcg2Dxe\DEBUG\AutoGen.c
* SHA256: 20a1dc1fde42e15349d92fb451ae3f9e482594cb4537979c43b6fb3639da64de
* Image: Tcg2Dxe.efi, x64, size 0x14700
*
* This driver implements the EFI_TCG2_PROTOCOL (also referred to as "TrEE"
* -- Trusted Execution Environment) for TPM 2.0 on the Lenovo HR650X platform.
*
* Key source paths from debug strings:
* e:\hs\AmiModulePkg\TCG2\Common\TcgDxe\Tcg2Dxe.c
* e:\hs\AmiModulePkg\TCG2\CRB_lib\Tpm20CRBLib.c
* e:\hs\MdePkg\Library\BaseLib\String.c
* e:\hs\MdePkg\Library\BaseMemoryLibRepStr\CompareMemWrapper.c
* e:\hs\MdePkg\Library\UefiDevicePathLib\DevicePathUtilities.c
* e:\hs\MdePkg\Library\BaseLib\Unaligned.c
*/
#include "Tcg2Dxe.h"
// ===========================================================================
// Globals (data segment at 0x13740-0x13C60)
// ===========================================================================
// Protocol Interfaces
static EFI_BOOT_SERVICES *gBS; // 0x13B18
static EFI_RUNTIME_SERVICES *gRT; // 0x13B28
static EFI_SYSTEM_TABLE *gST; // 0x13B10
static EFI_HANDLE gImageHandle; // 0x13B20
static EFI_SMM_BASE2_PROTOCOL *gDS; // 0x13B48
// ACPI table pointers (found via LibGetDsdt)
static UINT64 mRsdtDsdtAddr; // 0x13B58
static UINT64 mXsdtDsdtAddr; // 0x13B50
// Event log buffers (allocated via BS->AllocatePool)
static UINT8 *mTreeEventLog; // 0x13C00
static UINT8 *mTreeExtraTcpLog; // 0x13C08
static UINT64 *mTcg2FinalEventsTable; // 0x13C38
// Event log tracking
static UINT64 mEventLogLastEntry; // 0x13AD8
static UINT8 mEventLogTruncated; // 0x13AC0
static UINT64 mEventLogBootSize; // 0x13AE8
// TPM capabilities
static UINT32 mActivePcrBankBitMap; // 0x13A90
static UINT32 mSupportedPcrBankBitMap; // 0x13AAC
static UINT32 mTcgFeatureMask; // 0x13AB0
static UINT16 mMaxCapsSize; // 0x139F8
static UINT16 mMaxCapsResponse; // 0x13A10
static UINT32 mTpmPcrCount; // 0x13980
// TPM2 Protocol & CRB handles
static void *mTpm2Protocol; // 0x13B00
static void *mTrEEProtocol; // 0x13AB8
static void *mTpm2Handle; // 0x13C40
static UINT32 mTpmDeviceFlags; // 0x13850
// ACPI update state
static UINT8 *mAcpiBuffer; // 0x13AC8
static void *mAcpiProtocol; // 0x13B58
static void *mVariableLockProtocol; // 0x13BF0
static void *mResetNotification; // 0x13C30
static void *mAcpiEvent; // 0x13C28
// Internal state
static UINT8 mTreeBootHashAlgSha1; // 0x13AA8
static UINT64 mImageContextHandle; // 0x13AE0
static UINT64 mHobList; // 0x13B90
static UINT32 mSecureBootSetup; // 0x19B0
static UINT32 mSecureBootMode; // 0x19B1
static UINT32 mDefaultProvision; // 0x19B2
// ===========================================================================
// Debug Print (sub_9C8C)
// ===========================================================================
// AMD platform debug output via IO port 0x70/0x71 (CMOS).
// Checks CMOS index 0x4B bit for debug level.
static
UINT8
EFIAPI
DebugPrint (
IN UINTN ErrorLevel,
IN CONST CHAR8 *Format,
...
)
{
UINT64 PrintFunc;
UINT64 DebugLevel = 0;
UINT8 CmosValue;
PrintFunc = GetDebugPrintFunction ();
if (PrintFunc) {
IoWrite8 (0x70, (IoRead8 (0x70) & 0x80) | 0x4B);
CmosValue = IoRead8 (0x71);
if (CmosValue > 3) {
if (CmosValue == 0) {
CmosValue = (IoRead8 (0xFDAF0490) & 2) | 1;
}
}
switch (CmosValue) {
case 1:
DebugLevel = 0x80000004;
break;
default:
DebugLevel = 0x80000006;
break;
}
if (DebugLevel & ErrorLevel) {
VA_LIST Marker;
VA_START (Marker, Format);
((UINTN (*)(UINTN, CONST CHAR8 *, VA_LIST))PrintFunc)(ErrorLevel, Format, Marker);
VA_END (Marker);
}
}
return TRUE;
}
// ===========================================================================
// Tcg2GetSpecVersion (sub_9B4)
// ===========================================================================
// Returns byte at offset 6 from TPM2 protocol structure.
static
UINT8
Tcg2GetSpecVersion (
VOID
)
{
UINT64 Handle;
if (gBS->LocateProtocol (&gEfiTpm2DeviceProtocolGuid, NULL, (VOID **)&Handle) >= 0) {
return *(UINT8 *)(Handle + 6);
}
return 0;
}
// ===========================================================================
// MorCheckAndClear (sub_D00)
// ===========================================================================
// Reads MemoryOverwriteRequestControl variable. If MOR bit is set,
// performs memory clear and reports.
static
UINT8
MorCheckAndClear (
VOID
)
{
UINT8 MorValue = 0;
UINTN DataSize = 1;
EFI_STATUS Status;
Status = gRT->GetVariable (
L"MemoryOverwriteRequestControl",
&gMemoryOverwriteRequestControlGuid,
NULL,
&DataSize,
&MorValue
);
if (Status >= 0 && (MorValue & 1)) {
DEBUG ((DEBUG_INFO, "MOR: before Clear memory\n"));
// platform-specific clear
DEBUG ((DEBUG_INFO, "MOR: After Clear memory\n"));
}
return Status;
}
// ===========================================================================
// TreeGetCapability (sub_1928)
// ===========================================================================
// Fills EFI_TCG2_PROTOCOL capabilities structure.
// ===========================================================================
// TreeSetActivePcrs (sub_1820)
// ===========================================================================
// Sets active PCR banks. Validates against supported banks.
// Persists via AMITCGPPIVAR2 UEFI variable.
static
EFI_STATUS
TreeSetActivePcrs (
IN UINT64 This,
IN UINT32 ActivatePcrBanks
)
{
DEBUG ((DEBUG_INFO, "[%d]: Enter EfiTreeSetActivePcrs(...)\n", 1631));
DEBUG ((DEBUG_INFO, "EfiTreeSetActivePcrs ActivatePcrBanks[0x%x]\n", ActivatePcrBanks));
DEBUG ((DEBUG_INFO, "EfiTreeSetActivePcrs ActiveBankBitMap[0x%x]\n", mActivePcrBankBitMap));
DEBUG ((DEBUG_INFO, "EfiTreeSetActivePcrs TcgSupportedBankBitMap[0x%x]\n", mSupportedPcrBankBitMap));
EventLogTimer (1, 50694696);
if (!This || (ActivatePcrBanks & mSupportedPcrBankBitMap) != ActivatePcrBanks || !ActivatePcrBanks) {
return EFI_INVALID_PARAMETER;
}
if (ActivatePcrBanks == mActivePcrBankBitMap) {
return EFI_SUCCESS;
}
EFI_STATUS Status;
Status = gRT->SetVariable (
L"AMITCGPPIVAR2",
&gAmiTcgPpiVarGuid,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
3,
&ActivatePcrBanks
);
DEBUG ((DEBUG_INFO, "EfiTreeSetActivePcrs SetVariable[0x%r]\n", Status));
return Status;
}
// ===========================================================================
// TreeGetResultOfSetActivePcrs (sub_1728)
// ===========================================================================
// Checks result of a prior SetActivePcrs via AMITCGPPIVAR variable.
static
EFI_STATUS
TreeGetResultOfSetActivePcrs (
IN UINT64 This,
OUT UINT32 *OperationResult,
OUT UINT32 *ErrorCode
)
{
UINT8 Buffer[24];
UINTN DataSize = 24;
if (!OperationResult || !ErrorCode) {
return EFI_INVALID_PARAMETER;
}
DEBUG ((DEBUG_INFO, "[%s] [%d]:EfiTreeGetResultOfSetActivePcrs \n",
__FILE__, 1590));
EFI_STATUS Status;
Status = gRT->GetVariable (
L"AMITCGPPIVAR",
&gAmiTcgPpiVarGuid,
NULL,
&DataSize,
Buffer
);
if (Status >= 0) {
if (DataSize == 23) {
*OperationResult = 1;
*ErrorCode = *(UINT32 *)(Buffer + 8);
DEBUG ((DEBUG_INFO, "Temp.ERROR = %x \n", *ErrorCode));
if (*ErrorCode) {
return EFI_UNSUPPORTED;
}
return EFI_SUCCESS;
}
} else {
DEBUG ((DEBUG_INFO, "[%s] [%d]: Status Error(...)\n", __FILE__, 1600));
}
return Status;
}
// ===========================================================================
// TreeGetEventLog (sub_1EEC)
// ===========================================================================
// Returns event log location, last entry pointer, and truncated flag.
// Checks TCG2 spec version and returns appropriate log.
static
EFI_STATUS
TreeGetEventLog (
IN UINT64 This,
IN UINT32 EventLogFormat,
OUT UINT64 *EventLogLocation,
OUT UINT64 *EventLogLastEntry,
OUT UINT8 *EventLogTruncated
)
{
UINT8 Tcg2Version;
Tcg2Version = Tcg2GetSpecVersion ();
DEBUG ((DEBUG_INFO, "Tcg2SpecVersion = %x\n", Tcg2Version));
DEBUG ((DEBUG_INFO, "EventLogFormat = %x\n", EventLogFormat));
if (!This || !EventLogLocation || !EventLogTruncated) {
return EFI_INVALID_PARAMETER;
}
if (Tcg2Version == 1 && EventLogFormat != 1) {
if (Tcg2Version == 2 && EventLogFormat != 2) {
// TC log format
*EventLogLocation = (UINT64)mTreeEventLog;
*EventLogLastEntry = mEventLogLastEntry;
*EventLogTruncated = mEventLogTruncated;
if (!mEventLogBootSize) {
mEventLogBootSize = (UINT64)mTcg2FinalEventsTable + 16;
}
} else {
return EFI_INVALID_PARAMETER;
}
} else {
if ((mActivePcrBankBitMap & BOOT_HASH_ALG_SHA1) != 0) {
// SHA1 log available
UINT64 Entry;
Entry = GetLastEventLogEntry ();
if (!Entry) {
Entry = (UINT64)mTreeExtraTcpLog;
}
*EventLogLocation = (UINT64)mTreeExtraTcpLog;
*EventLogLastEntry = Entry;
*EventLogTruncated = mEventLogTruncated;
} else {
DEBUG ((DEBUG_INFO, "ActiveBankBitMap & TREE_BOOT_HASH_ALG_SHA1) != 0\n"));
return EFI_INVALID_PARAMETER;
}
}
DEBUG ((DEBUG_INFO, "EventLogLocation = %x\n", *EventLogLocation));
DEBUG ((DEBUG_INFO, "EventLogLastEntry = %x\n", *EventLogLastEntry));
DEBUG ((DEBUG_INFO, "EventLogTruncated = %x\n", *EventLogTruncated));
DEBUG ((DEBUG_INFO, "TreeEventLogLocation = %x\n", mTreeEventLog));
DEBUG ((DEBUG_INFO, "TreeExtraTCPASha1LogLoc = %x\n", mTreeExtraTcpLog));
DEBUG ((DEBUG_INFO, "LastEventPtr = %x\n", mEventLogLastEntry));
DEBUG ((DEBUG_INFO, "EventLogTruncated = %x\n", (UINT8)mEventLogTruncated));
DEBUG ((DEBUG_INFO, "EventLogFormat = %x\n", EventLogFormat));
return Status;
}
// ===========================================================================
// Tpm20DxeAcpiUpdate (sub_7DA4)
// ===========================================================================
// Registered as a notification callback.
// Locates DSDT, updates TPM device ASL objects.
static
EFI_STATUS
EFIAPI
Tpm20DxeAcpiUpdate (
IN EFI_EVENT Event,
IN VOID *Context
)
{
UINT64 DsdtAddress;
EFI_STATUS Status;
Status = LibGetDsdt (&DsdtAddress, 0x1E);
if (Status >= 0) {
Status = AcpiUpdateAmlTable (DsdtAddress, "PPIM", (UINT32)mAcpiBuffer);
if (Status >= 0) {
Status = AcpiUpdateAmlTable (DsdtAddress, "PPIL", 28);
ASSERT_EFI_ERROR (Status);
}
}
return Status;
}
// ===========================================================================
// TpmServFlagsLockCallback (sub_7B88)
// ===========================================================================
// Called when gEdkiiVariableLockProtocolGuid is available.
// Locks the TpmServFlags variable.
static
EFI_STATUS
EFIAPI
TpmServFlagsLockCallback (
IN EFI_EVENT Event,
IN VOID *Context
)
{
EFI_LOCK_PROTOCOL *VariableLock;
DEBUG ((DEBUG_INFO, "AcpiOnVariableLockProtocolGuid callback entry\n"));
if (gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLock) >= 0) {
EFI_STATUS Status;
Status = VariableLock->RequestToLock (VariableLock, L"TpmServFlags", &gAmiTpmServFlagsGuid);
ASSERT_EFI_ERROR (Status);
}
return gBS->CloseEvent (Event);
}
// ===========================================================================
// CopyTcgLog (sub_411C)
// ===========================================================================
// Copies the TCG event log from the PEI HOB into the allocated
// DXE event log buffer.
static
EFI_STATUS
CopyTcgLog (
VOID
)
{
VOID *Hob;
DEBUG ((DEBUG_INFO, " CopyTcgLog Entry \n"));
Hob = GetFirstGuidHob (gST->HobList, gST->HobListSize, &gEfiPeiLogHobGuid);
if (!Hob) {
DEBUG ((DEBUG_INFO, " gEfiPeiLogHobGuid Not found \n"));
return EFI_NOT_FOUND;
}
*((UINT32*)Hob) = 0; // Set structure version
gBS->CopyMem (mTreeEventLog, Hob, TREE_EVENT_LOG_HEADER_SIZE);
gBS->CopyMem (mTreeEventLog + TREE_EVENT_LOG_HEADER_SIZE,
Hob + TREE_EVENT_LOG_HEADER_SIZE,
*((UINT32*)(Hob + 4))
);
mEventLogBootSize = (UINT64)mTreeEventLog + *((UINT32*)(Hob + 4));
DEBUG ((DEBUG_INFO, " CopyTcgLog TreeEventLogLocation = %x \n", mTreeEventLog));
DEBUG ((DEBUG_INFO, " CopyTcgLog LastEntry = %x \n", mEventLogBootSize));
return EFI_SUCCESS;
}
// ===========================================================================
// InstallTrEEProtocol (sub_7ED8)
// ===========================================================================
// Allocates event log buffers, installs TCG2 config table,
// and registers the TrEE (TCG2) protocol.
static
EFI_STATUS
InstallTrEEProtocol (
IN EFI_HANDLE ImageHandle
)
{
EFI_STATUS Status;
DEBUG ((DEBUG_INFO, " InstallTrEEProtocol \n"));
Status = gBS->AllocatePool (EfiBootServicesData, 16, (VOID **)&mTreeEventLog);
if (Status < 0) return Status;
Status = gBS->AllocatePool (EfiBootServicesData, 16, (VOID **)&mTreeExtraTcpLog);
if (Status < 0) return Status;
Status = gBS->AllocatePool (EfiBootServicesData, 16, (VOID **)&mTcg2FinalEventsTable);
if (Status < 0) return Status;
DEBUG ((DEBUG_INFO, " TreeExtraTCPASha1LogLoc = %x \n", mTreeEventLog));
DEBUG ((DEBUG_INFO, " TreeEventLogLocation = %x \n", mTreeExtraTcpLog));
DEBUG ((DEBUG_INFO, " pEfiTcg2FinalEventsTbl = %x \n", mTcg2FinalEventsTable));
gBS->SetMem (mTcg2FinalEventsTable, 16, 0);
*(UINT64 *)mTcg2FinalEventsTable = 1;
*(UINT64 *)(mTcg2FinalEventsTable + 8) = 0;
if (gBS->InstallConfigurationTable (&gEfiTcg2FinalEventsGuid, mTcg2FinalEventsTable) < 0) {
DEBUG ((DEBUG_INFO, " TCG2 Finals Configuration table install failed\n"));
}
gBS->SetMem (mTreeEventLog, -1, -1);
gBS->SetMem (mTreeExtraTcpLog, -1, -1);
Status = CopyTcgLog ();
if (Status < 0) return Status;
Status = gBS->InstallMultipleProtocolInterfaces (
&ImageHandle,
&gEfiTcg2ProtocolGuid,
&mTrEEProtocolTemplate,
&gTrEEEventProtocolGuid,
&mTrEEEventProtocolTemplate,
&gTrEEHashProtocolGuid,
&mHashProtocolTemplate,
&gTrEEPeImageProtocolGuid,
&mPeImageProtocolTemplate,
NULL
);
DEBUG ((DEBUG_INFO, " InstallTrEEProtocol Exit Status = %r \n", Status));
return Status;
}
// ===========================================================================
// TrEEUpdateTpmDeviceASL (sub_4324)
// ===========================================================================
// Updates ACPI DSDT with TPM device ASL objects
// (TCMF, TTDP, PPIV, TTPF).
static
EFI_STATUS
TrEEUpdateTpmDeviceASL (
IN VOID *TpmDeviceFlags,
IN EFI_EVENT Event
)
{
UINT32 *DsdtBuffer;
EFI_STATUS Status;
UINT64 DsdtAddress;
UINT32 *Dsdt;
DEBUG ((DEBUG_INFO, "TrEEUpdateTpmDeviceASL Entry \n"));
Status = LibGetDsdt (&DsdtAddress, 0x1E);
if (Status >= 0) {
Dsdt = (UINT32 *)DsdtAddress;
DEBUG ((DEBUG_INFO, "TrEEUpdateTpmDeviceASL::dsdtAddress %x \n", DsdtAddress));
DEBUG ((DEBUG_INFO, "dsdt->Signature = %x \n", *Dsdt));
if (IsAcpiSdtValid (DsdtAddress)) {
DEBUG ((DEBUG_INFO, "TrEEUpdateTpmDeviceASL::Set TCMF Device ID \n"));
Status = AcpiUpdateAmlTable (Dsdt, "TCMF", 1);
if (Status < 0) {
DEBUG ((DEBUG_INFO, "TrEEUpdateTpmDeviceASL::Failed set TCMF Device ID %r \n", Status));
}
}
}
return Status;
}
// ===========================================================================
// LibGetDsdt (sub_FEAC)
// ===========================================================================
// Locate DSDT table in ACPI tables.
// Searches RSDT/XSDT to find DSDT address.
static
EFI_STATUS
LibGetDsdt (
OUT UINT64 *DsdtAddress,
IN UINT8 TableTypeMask
)
{
EFI_ACPI_SUPPORT_PROTOCOL *AcpiSupport;
UINT32 Signature;
EFI_STATUS Status;
UINT32 TableIndex;
Signature = 0x20534444; // "DSDT "
Status = gBS->LocateProtocol (&gEfiAcpiSupportProtocolGuid, 0, (VOID **)&AcpiSupport);
if (Status < 0) {
DEBUG ((DEBUG_INFO, "AcpiResLib: LibGetDsdt(): LocateProtocol(ACPISupport) returned %r \n", Status));
return 0xA000000000000002;
}
// Search through ACPI tables
for (TableIndex = 0; ; TableIndex++) {
VOID *Table;
UINTN TableKey;
UINTN TableSize;
Status = AcpiSupport->GetAcpiTable (TableIndex, &Table, &TableKey, &TableSize);
if (Status < 0) {
break;
}
if (*(UINT32 *)Table == 0x20534444) {
mRsdtDsdtAddr = (UINT64)((UINT32 *)Table)[10];
Status = EFI_SUCCESS;
}
if (mRsdtDsdtAddr && mXsdtDsdtAddr) {
break;
}
}
if ((TableTypeMask & 0x1D) && mXsdtDsdtAddr) {
*DsdtAddress = mXsdtDsdtAddr;
return EFI_SUCCESS;
}
if (mRsdtDsdtAddr && (TableTypeMask & 2 || TableTypeMask & 1)) {
*DsdtAddress = mRsdtDsdtAddr;
return EFI_SUCCESS;
}
return Status;
}
// ===========================================================================
// DriverInit (sub_420)
// ===========================================================================
// Standard UEFI driver init. Saves image handle, system table,
// boot services, runtime services. Calls DxeServicesTableLib init
// and performs delay calibration via PIT.
static
VOID
DriverInit (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
gImageHandle = (UINT64)ImageHandle;
ASSERT (gImageHandle != NULL);
gST = (UINT64)SystemTable;
ASSERT (gST != NULL);
gBS = SystemTable->BootServices;
ASSERT (gBS != NULL);
gRT = SystemTable->RuntimeServices;
ASSERT (gRT != NULL);
// Init DxeServicesTable
DxeServicesTableLibConstructor ();
// Calibrate delay via PIT (8253 timer)
PpiWaitForPitCalibration ();
// Initialize DXE services table pointer
DxeServicesTableLibDestructor ();
}
// ===========================================================================
// TreeDxeEntry (sub_8238) - Main Driver Entry
// ===========================================================================
// Flow:
// 1. Locate TPM2 Device Protocol (gEfiTpm2DeviceProtocolGuid)
// 2. Check Tcg2SpecVersion[6] for TPM presence
// 3. Allocate ACPI buffer (28 bytes)
// 4. Register ACPI update notification event
// 5. Read TpmServFlags UEFI variable
// 6. Lock TpmServFlags or register lock callback
// 7. If TPM2 present: call Tpm2AllocatePCR, read PCR banks
// 8. Install TrEE protocol and handlers
// 9. Update ACPI DSDT tables
// 10. Set active PCR banks
// 11. Register Tcg2Config protocol notify
// Return EFI_SUCCESS
static
EFI_STATUS
TreeDxeEntry (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
UINT64 Tpm2Handle;
UINT8 TpmDeviceCaps[27];
BOOLEAN IsTpmPresent;
UINT8 PcrResetFlag;
UINT32 PcrAllocValue;
DEBUG ((DEBUG_INFO, " TreeDxeEntry \n"));
// Phase 1: Locate TPM2 device protocol
Status = gBS->LocateProtocol (&gEfiTpm2DeviceProtocolGuid, NULL, (VOID **)&mTpm2Handle);
if (Status < 0) return Status;
gBS->CopyMem (TpmDeviceCaps, mTpm2Handle + 1, 27);
// Phase 2: Allocate ACPI buffer
Status = gBS->AllocatePool (EfiBootServicesData, 28, (VOID **)&mAcpiBuffer);
if (Status >= 0) {
gBS->SetMem (mAcpiBuffer, 28, 0);
// Phase 3: Register ACPI update event
Status = gBS->CreateEvent (
EVT_NOTIFY_SIGNAL,
TPL_CALLBACK,
Tpm20DxeAcpiUpdate,
NULL,
&mAcpiEvent
);
if (Status < 0) {
DEBUG ((DEBUG_INFO, " Tpm20DxeAcpiUpdate CreateEvent failed\n"));
return Status;
}
Status = gBS->RegisterProtocolNotify (
&gEfiAcpiEndOfTableProtocolGuid,
mAcpiEvent,
&mAcpiEvent
);
if (Status < 0) {
DEBUG ((DEBUG_INFO, " Tpm20DxeAcpiUpdate CreateEvent failed\n"));
return Status;
}
// Phase 4: Read TpmServFlags via RT->GetVariable
// (sub_7CA0 wrapper - retries if EFI_INVALID_PARAMETER)
// Phase 5: Lock TpmServFlags
EFI_LOCK_PROTOCOL *VariableLock;
Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLock);
if (Status >= 0) {
Status = VariableLock->RequestToLock (VariableLock,
L"TpmServFlags",
&gAmiTpmServFlagsGuid);
DEBUG ((DEBUG_INFO, "TpmServFlags Flags successfully locked\n"));
ASSERT_EFI_ERROR (Status);
} else {
// Register callback for when lock protocol appears
Status = gBS->CreateEvent (
EVT_NOTIFY_SIGNAL,
TPL_CALLBACK,
TpmServFlagsLockCallback,
NULL,
&mVariableLockProtocol
);
ASSERT_EFI_ERROR (Status);
}
ASSERT_EFI_ERROR (Status);
// Phase 6: Check TPM presence
if (TpmDeviceCaps[6] != 0) {
if (TpmDeviceCaps[1] != 0) {
IsTpmPresent = Tpm2IsCrbPresent ();
if (IsTpmPresent) {
// 6a: Allocate PCR banks
Tpm2AllocatePCR ();
// 6b: Read current PCR banks
PcrAllocValue = mActivePcrBankBitMap;
// 6c: Handle PCR allocation change
if (PcrAllocValue != mActivePcrBankBitMap) {
DEBUG ((DEBUG_INFO, "\tError: Reset failed???\n"));
Status = gBS->CreateEvent (
EVT_NOTIFY_SIGNAL,
TPL_CALLBACK,
DoResetNow,
NULL,
&mResetNotification
);
if (Status < 0 &&
(TpmDeviceCaps[6] == 0 ||
TpmDeviceCaps[1] == 0))
{
DEBUG ((DEBUG_INFO,
"\tRegister DoResetNow after Reset Architecture driver\n"));
Status = gBS->RegisterProtocolNotify (
&gEfiResetArchProtocolGuid,
mResetNotification,
&mResetNotification
);
}
}
// 6d: Save PCR reset flag
if (PcrResetFlag == 1) {
PcrResetFlag = 0;
gRT->SetVariable (
L"Tpm20PCRallocateReset",
&gAmiTpm20PcrAllocateResetGuid,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
1,
&PcrResetFlag
);
}
// Phase 7: Install protocols
gImageHandle = (UINT64)ImageHandle;
Status = gBS->InstallMultipleProtocolInterfaces (
&gImageHandle,
&gEfiTcg2ProtocolGuid,
&mTrEEProtocolTemplate,
&gTrEEHashLogProtocolGuid,
&mHashLogProtocolTemplate,
&gTrEEHashProtocolGuid,
&mHashProtocolTemplate,
NULL
);
ASSERT_EFI_ERROR (Status);
// Phase 8: Update ACPI tables
TrEEUpdateTpmDeviceASL ((VOID *)(UINTN)mTpmDeviceFlags, mAcpiEvent);
// Phase 9: Set TPM2 device active PCR banks
gBS->LocateProtocol (&gEfiTpm2DeviceProtocolGuid, NULL, (VOID **)&Tpm2Handle);
gBS->CopyMem (TpmDeviceCaps, Tpm2Handle + 1, 27);
TpmDeviceCaps[11] = 1; // StructureVersion
TpmDeviceCaps[12] = 0; // ProtocolSpecVersion
TpmDeviceCaps[7] = 0; // SupportedEventLogs
((VOID (**)(VOID *, UINT8))Tpm2Handle)[32] (TpmDeviceCaps, TRUE);
// Final: Register Tcg2Config protocol notify
Status = gBS->CreateEvent (
EVT_NOTIFY_SIGNAL,
TPL_CALLBACK,
TseHandleTcg2Config,
NULL,
&mResetNotification
);
Status = gBS->RegisterProtocolNotify (
&gAmiTcg2ConfigProtocolGuid,
mResetNotification,
&mResetNotification
);
return EFI_SUCCESS;
} else {
DEBUG ((DEBUG_INFO, " isTpm20CrbPresent returned false \n"));
EventLogTimer (EFI_SUCCESS, 50694658);
if (*(UINT32 *)0xFED40000 == 0xFFFFFFFF) {
EventLogTimer (EFI_SUCCESS, 50694660);
}
return EFI_SUCCESS;
}
} else {
((VOID (**)(VOID *, UINT8))mTpm2Handle)[32] (TpmDeviceCaps, FALSE);
return EFI_SUCCESS;
}
} else {
((VOID (**)(VOID *, UINT8))mTpm2Handle)[32] (TpmDeviceCaps, FALSE);
return EFI_SUCCESS;
}
}
return Status;
}
// ===========================================================================
// ModuleEntryPoint (0x3F4)
// ===========================================================================
EFI_STATUS
EFIAPI
ModuleEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
DriverInit (ImageHandle, SystemTable);
return TreeDxeEntry (ImageHandle, SystemTable);
}
// ===========================================================================
// SecureBootSetupCheck (sub_43C)
// ===========================================================================
// Reads SecureBootSetup and SetupMode variables to determine
// secure boot state. Called before main entry during init.
static
EFI_STATUS
SecureBootSetupCheck (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_RUNTIME_SERVICES *RuntimeServices;
UINT32 Attrib;
UINTN DataSize;
UINT16 VariableName;
if (gST_0) {
RuntimeServices = (EFI_RUNTIME_SERVICES *)RuntimeServices_0;
} else {
gST_0 = (UINT64)SystemTable;
gBS_0 = (UINT64)SystemTable->BootServices;
RuntimeServices = SystemTable->RuntimeServices;
RuntimeServices_0 = (UINT64)RuntimeServices;
}
DataSize = 7;
EFI_STATUS Status;
Status = RuntimeServices->GetVariable (
L"SecureBootSetup",
&gSecureBootSetupGuid,
&Attrib,
&DataSize,
&mSecureBootSetupVars
);
DEBUG ((DEBUG_INFO,
"SecureBootSetup (%r) Attrib=%x,\nSecBoot-%d, SecMode-%d, DefaultProvision-%d\n",
Status, Attrib,
(UINT8)mSecureBootSetupVars,
(UINT8)mSecureBootSetupVars[1],
(UINT8)mSecureBootSetupVars[2]
));
return 0;
}
// ===========================================================================
// End of Tcg2Dxe.c -- all functions renamed and documented
// ===========================================================================
// Address range summary:
// 0x000-0x2C0 HEADER (PE32+ headers)
// 0x2C0-0x3F4 Early init stubs (sub_2C0 through sub_3F0)
// 0x3F4 _ModuleEntryPoint
// 0x420 DriverInit (sub_420)
// 0x43C SecureBootSetupCheck (sub_43C)
// 0x610 Tpm2SequenceComplete (SM3 variant)
// 0x748 HashMultiAlg (combines all algorithm hashes)
// 0xD00 MorCheckAndClear
// 0xD70 Tpm2QueryPcrBanks
// 0x1100 Tpm2AllocatePCR
// 0x1728 TreeGetResultOfSetActivePcrs
// 0x1820 TreeSetActivePcrs
// 0x1928 TreeGetCapability
// 0x1EEC TreeGetEventLog
// 0x22FC InternalTcg20CommonExtend (TPM2 extend command)
// 0x2728 TpmHashLogExtendEvent
// 0x3414 TreeHashLogExtendEvent
// 0x411C CopyTcgLog
// 0x4324 TrEEUpdateTpmDeviceASL
// 0x4D50 TreeProcessDbVariable
// 0x4F3C TreeHashImageExtend
// 0x5AC0 HashAllAlgorithms
// 0x5C88 HashUpdateAll
// 0x5EDC HashBuffer
// 0x620C HashMultiAlgFull
// 0x711C TreeMeasurePeImage
// 0x7B88 TpmServFlagsLockCallback
// 0x7CA0 ReadTpmServFlags (with retry)
// 0x7DA4 Tpm20DxeAcpiUpdate
// 0x7ED8 InstallTrEEProtocol
// 0x8238 TreeDxeEntry (main driver entry)
// 0x91EC CopyDigestToOutput
// 0x92D0 WalkNextEventLogEntry
// 0x9504 GetLastEventLogEntry
// 0x9564 (walk helper for event log)
// 0x9750 Tpm2InitCommand
// 0x983C Tpm2SequenceUpdate
// 0x9A00 Tpm2SequenceComplete
// 0x9B4 Tcg2GetSpecVersion
// 0x9C8C DebugPrint (CMOS debug output)
// 0x9D14 DebugAssert
// 0x9D54 DebugEnabled (stub returning 1)
// 0x9D58 DebugLevelCheck (stub returning a1 != 0)
// 0x9D60 CopyMem
// 0xA3C Tpm2IsCrbPresent
// 0xA9DC Sha256BlockProcess (SHA256 transform)
// 0xBC6C Sha1Finalize
// 0xBD94 Sha1BlockProcess (SHA1 transform)
// 0xE384 Sha256Update
// 0xE454 Sha256Finalize
// 0xE5DC Sha384Init
// 0xE660 Sha512Finalize
// 0xE6A8 Sha512BlockProcess (SHA512 transform)
// 0xEC80 Sha512Update
// 0xED58 Sha512FinalCustom
// 0xEE80 Tpm2CopySwap (byte-swap copy)
// 0xFEAC LibGetDsdt
// 0x101A4 AcpiUpdateAmlTable
// 0x10750 GetImageContext (PE/COFF header parsing)
// 0x10ADC EventLogTimer
// 0x10B10 EventLogTimerWithData
// 0x10BF0 GetPpiServices