Newer
Older
AMI-Aptio-BIOS-Reversed / Build / Tcg2Dxe / Tcg2Dxe.c
@Ajax Dong Ajax Dong 2 days ago 32 KB Restructure the repo
/**
 * 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