/** @file
TcgPlatformSetupPolicy.c -- TCG Platform Setup Policy DXE driver.
This DXE driver manages TCG (Trusted Computing Group) platform setup policy
variables and installs a protocol to expose them to other platform drivers.
Functional overview:
1. Entry point (TcgPlatformSetupPolicyDxeEntryPoint, =0x860):
- Caches UEFI table pointers (ImageHandle, SystemTable, BootServices, RuntimeServices)
- Allocates a runtime pool buffer (40 bytes) for the protocol interface
- Reads the TcgInternalSyncFlag variable to check for an in-progress sync
- Reads the 814-byte "Setup" NV variable (gSetupVariableGuid)
- Initializes the 27-byte TCG_PLATFORM_SETUP_POLICY from Setup fields
- Reads the "PCRBitmap" variable to apply PCR enable bits
- Caches individual policy bytes to global shadow variables (byte_1450..byte_1467)
- Installs the TCG_PLATFORM_SETUP_POLICY_PROTOCOL on ImageHandle
- Registers a notification event (TPL_CALLBACK) -> TcgPlatformSetupPolicyNotify (=0x7F4)
- Locates the HOB list via configuration table
2. SetPolicy callback (TcgPlatformSetPolicyData, =0x408):
- Accepts updated TPM policy data from other drivers
- Updates shadow globals from policy bytes
- Merges policy fields back into the appropriate Setup variable offsets
- Updates PCRBitmap variable if needed
- Writes TcgInternalSyncFlag to signal other components
3. Notification callback (TcgPlatformSetupPolicyNotify, =0x7F4):
- Triggered when the protocol is installed (EVT_NOTIFY_SIGNAL)
- Locates the TCG_PLATFORM_SETUP_POLICY_PROTOCOL
- Copies 27 bytes of policy from protocol interface+1
- Calls SetPolicy (at protocol interface+32) with (policyData, TRUE)
- Closes the notification event
Binary info:
Module: TcgPlatformSetupPolicy.efi
Architecture: x86_64 (UEFI DXE driver)
Image size: 0x15A0 (5536 bytes)
MD5: e203632565eb9a0fd0caad1a87e0bb43
SHA256: d51f30be6a4b3c180cc5ab354957ecacf316cb64b639f72287ecf69bfcf528f8
Copyright (c) Lenovo. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
Reverse-engineered from Lenovo HR650X BIOS (2024/3647 AJAX).
**/
#include <Uefi.h>
#include <Library/BaseMemoryLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/DebugLib.h>
#include <Library/IoLib.h>
#include <Library/HobLib.h>
#include "TcgPlatformSetupPolicy.h"
//=============================================================================
// GUID Definitions
//=============================================================================
///
/// TCG Platform Setup Policy Protocol GUID:
/// {BB6CBEFF-E072-40D2-A6EB-BAB75BDE87E7}
///
EFI_GUID gTcgPlatformSetupPolicyProtocolGuid = TCG_PLATFORM_SETUP_POLICY_PROTOCOL_GUID;
///
/// TCG Internal Sync Flag variable GUID:
/// {F3ED95DF-828E-41C7-BCA0-16C41965A634}
///
EFI_GUID gTcgInternalSyncFlagGuid = TCG_INTERNAL_SYNC_FLAG_GUID;
///
/// Setup variable GUID:
/// {EC87D643-EBA4-4BB5-A1E5-3F3E36B20DA9}
///
EFI_GUID gSetupVariableGuid = SETUP_VARIABLE_GUID;
///
/// PCRBitmap variable GUID:
/// {70FFF0FF-A543-45B9-8BE3-1BDB90412080}
///
EFI_GUID gPcrBitmapVariableGuid = PCR_BITMAP_VARIABLE_GUID;
//=============================================================================
// Global Variables -- .data section (0x1410..0x1467)
//=============================================================================
///
/// mTcgPolicyBuffer -- qword_1410
/// The allocated protocol interface buffer (40 bytes allocated, 32 used).
/// byte [0] = Revision (3)
/// bytes [1..27] = TCG_PLATFORM_SETUP_POLICY data
/// qword[4] (=offset 32) = SetPolicy function pointer
///
TCG_PLATFORM_SETUP_POLICY_PROTOCOL *mTcgPolicyProtocol = NULL;
///
/// mHobList -- qword_1440
/// Cached pointer to the HOB list, located from the system configuration table.
///
VOID *mHobList = NULL;
///
/// mDebugProtocol -- qword_1438
/// Cached pointer to the debug/assert protocol interface.
/// Located (under TPL protection) and cached on first use.
/// Protocol interface has a function pointer at offset +8 for assert.
///
VOID *mDebugProtocol = NULL;
///
/// mVariableAttributes -- n3 at 0x1448
/// Attributes used for GetVariable/SetVariable calls.
/// Set to 3 (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS).
///
UINT32 mVariableAttributes = 3;
///
/// Shadow copies of policy bytes -- byte_1450..byte_1466
/// These are populated by the entry point and can be read by external
/// debug tools or other firmware components via direct memory access.
///
UINT8 mTpm1Enable = 0; // byte_1450 -- Policy[0]: TPM 1.2 Enable
UINT8 mTpmOperation = 0; // byte_1451 -- Policy[1]: TPM Operation
UINT8 mTpm2Enable = 0; // byte_1452 -- Policy[2]: TPM 2.0 Enable
UINT8 mTpmSelect = 0; // byte_1453 -- Policy[3]: TPM Select
UINT8 mReserved1 = 0; // byte_1454 -- (not set by entry point)
UINT8 mPcrBankTpm2 = 0; // byte_1455 -- Policy[5]: PCR Bank TPM2
UINT8 mPcrBankTpm12 = 0; // byte_1456 -- Policy[6]: PCR Bank TPM1.2
UINT8 mReserved2 = 0; // byte_1457 -- (not set by entry point)
UINT8 mTpm1Support = 0; // byte_1458 -- Policy[8]: TPM 1.2 Support
UINT8 mTpm2Support = 0; // byte_1459 -- Policy[9]: TPM 2.0 Support
UINT8 mTpmExistence = 0; // byte_145A -- Policy[10]: TPM Existence
UINT8 mReserved3 = 0; // byte_145B -- (not set by entry point)
UINT8 mReserved4 = 0; // byte_145C -- (not set by entry point)
UINT8 mTpmPolicy = 0; // byte_145D -- Policy[13]: TPM Policy
UINT8 mTpmPhysicalPresence = 0; // byte_145E -- Policy[15]: TPM Physical Presence
UINT8 mTpmPhysPresence2 = 0; // byte_145F -- Policy[16]: (reserved / extra)
UINT8 mReserved5 = 0; // byte_1460 -- (not set)
UINT8 mReserved6 = 0; // byte_1461 -- (not set)
UINT8 mReserved7 = 0; // byte_1462 -- (not set)
UINT8 mTpmFirmwareUpdate = 0; // byte_1463 (actually at 0x1462 in IDA, but Policy[19])
UINT8 mTpmSupplierConfig = 0; // byte_1464 -- Policy[20]
UINT8 mTpmSupplier = 0; // byte_1465 -- Policy[21]
UINT8 mTpmDevice = 0; // byte_1466 -- Policy[22]
UINT32 mPcrBitmap = 0; // dword_1467 -- Policy[23..26]
//=============================================================================
// Library Helpers
//=============================================================================
/**
Locates and caches the debug/assert protocol ({36232936-0E76-31C8-
A13A-3AF2FC1C3932}). Uses RaiseTPL/RestoreTPL for single-thread safety.
@return Pointer to the debug protocol, or NULL.
**/
VOID *
LocateDebugProtocol (
VOID
)
{
EFI_TPL OldTpl;
if (mDebugProtocol != NULL) {
return mDebugProtocol;
}
//
// Raise TPL to TPL_HIGH_LEVEL (31) to guard against re-entrancy.
//
OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
gBS->RestoreTPL (OldTpl);
//
// Only proceed if the system was at TPL_NOTIFY or below.
//
if (OldTpl <= TPL_NOTIFY) {
//
// Locate the debug protocol via its custom GUID.
// The actual GUID is proprietary to Lenovo.
//
gBS->LocateProtocol (
&mDebugProtocolGuid,
NULL,
&mDebugProtocol
);
}
return mDebugProtocol;
}
/**
Reports an ASSERT failure via the debug protocol.
@param[in] FileName Source file name.
@param[in] LineNumber Line number.
@param[in] Description Assert description string.
**/
VOID
EFIAPI
ReportAssert (
IN CONST CHAR8 *FileName,
IN UINTN LineNumber,
IN CONST CHAR8 *Description
)
{
VOID *DebugProtocol;
VOID (*AssertFunc)(CONST CHAR8 *, UINTN, CONST CHAR8 *);
DebugProtocol = LocateDebugProtocol ();
if (DebugProtocol != NULL) {
//
// The function pointer is at offset +8 in the protocol interface.
//
AssertFunc = (VOID (*)(CONST CHAR8 *, UINTN, CONST CHAR8 *))
*((UINT64 *)((UINTN)DebugProtocol + 8));
AssertFunc (FileName, LineNumber, Description);
}
}
/**
Compares two GUIDs by comparing them as two 64-bit halves.
@param[in] Guid1 Pointer to first GUID.
@param[in] Guid2 Pointer to second GUID.
@retval TRUE GUIDs are equal.
@retval FALSE GUIDs differ.
**/
BOOLEAN
EFIAPI
CompareGuid (
IN CONST EFI_GUID *Guid1,
IN CONST EFI_GUID *Guid2
)
{
return (ReadUnaligned64 ((CONST UINT64 *)Guid1) ==
ReadUnaligned64 ((CONST UINT64 *)Guid2)) &&
(ReadUnaligned64 ((CONST UINT64 *)Guid1 + 1) ==
ReadUnaligned64 ((CONST UINT64 *)Guid2 + 1));
}
/**
Reads a UINT64 from possibly-unaligned memory.
@param[in] Buffer The pointer to read from.
@return The 64-bit value at Buffer.
**/
UINT64
EFIAPI
ReadUnaligned64 (
IN CONST VOID *Buffer
)
{
if (Buffer == NULL) {
ReportAssert (
"e:\\hs\\MdePkg\\Library\\BaseLib\\Unaligned.c",
192,
"Buffer != ((void *) 0)"
);
}
return *((UINT64 *)Buffer);
}
/**
Locates the HOB list from the EFI configuration table.
Searches the system table's ConfigurationTable[] for the
gEfiHobListGuid entry ({7739F24C-93D7-11D4-9A3A-0090273FC14D}).
@return Pointer to the HOB list, or NULL.
**/
VOID *
EFIAPI
GetHobList (
VOID
)
{
UINTN Index;
EFI_CONFIGURATION_TABLE *ConfigTable;
if (mHobList != NULL) {
return mHobList;
}
ConfigTable = gST->ConfigurationTable;
for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {
if (CompareGuid (&ConfigTable[Index].VendorGuid, &gEfiHobListGuid)) {
mHobList = ConfigTable[Index].VendorTable;
return mHobList;
}
}
//
// HOB list not found -- assert (this is a fatal firmware error).
//
ReportAssert (
"e:\\hs\\MdePkg\\Library\\DxeHobLib\\HobLib.c",
54,
"!EFI_ERROR (Status)"
);
ReportAssert (
"e:\\hs\\MdePkg\\Library\\DxeHobLib\\HobLib.c",
55,
"mHobList != ((void *) 0)"
);
return NULL;
}
/**
Reads TPM boot path from CMOS register 0x4B.
Checks the TPM boot path configuration stored in CMOS to determine
whether a given feature (identified by FeatureMask) should be executed.
@param[in] FeatureMask Bitmask identifying the feature to check.
@retval TRUE The feature should be executed.
@retval FALSE The feature should be skipped.
**/
BOOLEAN
EFIAPI
TpmBootPathCmosCheck (
IN UINT32 FeatureMask
)
{
VOID *DebugProtocol;
UINT64 (*ExecuteFunc)(UINT32 Feature, UINT64 Arg1, ...);
UINT8 CmosIndex;
UINT8 CmosValue;
DebugProtocol = LocateDebugProtocol ();
if (DebugProtocol == NULL) {
return FALSE;
}
//
// Write CMOS address 0x4B to port 0x70 (preserving NMI disable bit 7).
//
IoWrite8 (0x70, (IoRead8 (0x70) & 0x80) | 0x4B);
//
// Read the TPM boot path value from CMOS port 0x71.
//
CmosValue = IoRead8 (0x71);
if (CmosValue > 3) {
CmosValue = 0;
}
if (CmosValue == 0) {
//
// Read the platform type register at MMIO 0xFDAF0490.
// Bits: bit 0 = TPM present, bit 1 = TPM type.
//
CmosValue = (IoRead8 (0xFDAF0490) & 2) | 1;
}
//
// Translate CMOS value:
// CmosValue == 1 -> TPM boot is disabled
// CmosValue == 2 -> TPM1 boot path
// CmosValue == 3 -> TPM2 boot path
//
if (CmosValue == 1) {
//
// Feature 0x8000000C (debug print) is active.
//
ExecuteFunc = (UINT64 (*)(UINT32, UINT64, ...))
*((UINT64 *)(UINTN)DebugProtocol);
return (BOOLEAN)ExecuteFunc (FeatureMask, (UINT64)"\nASSERT_EFI_ERROR (Status = %r)\n");
} else {
//
// Features 0x80000004-0x8000000C may be active.
//
return (BOOLEAN)((FeatureMask & TCG_BOOT_PATH_ENABLE) != 0);
}
}
//=============================================================================
// Core Driver Functions
//=============================================================================
/**
Initializes the policy structure from the Setup variable buffer.
Maps Setup variable fields (by byte offset) into the 27-byte
TCG_PLATFORM_SETUP_POLICY structure.
@param[out] Policy The 27-byte policy structure to fill.
@param[in] SetupBuffer The raw 814-byte Setup variable buffer.
@param[in] SetupSize Size of data in SetupBuffer.
**/
VOID
EFIAPI
TcgPlatformInitPolicyFromSetup (
OUT TCG_PLATFORM_SETUP_POLICY *Policy,
IN UINT8 *SetupBuffer,
IN UINTN SetupSize
)
{
UINT8 *Bytes;
UINT32 PcrBitmapValue;
Bytes = (UINT8 *)Policy;
//
// Zero the entire 27-byte policy structure.
//
ZeroMem (Bytes, TCG_PLATFORM_SETUP_POLICY_DATA_SIZE);
//
// Map each Setup field to the corresponding policy byte.
//
Bytes[ 0] = SetupBuffer[18]; // TPM1 Enable
Bytes[ 1] = SetupBuffer[13]; // TPM Operation
Bytes[ 2] = SetupBuffer[22]; // TPM2 Enable
Bytes[ 3] = SetupBuffer[14]; // TPM Select
Bytes[ 5] = SetupBuffer[26]; // PCR Bank TPM2
Bytes[ 6] = SetupBuffer[31]; // PCR Bank TPM1.2
Bytes[ 8] = SetupBuffer[15]; // TPM1 Support
Bytes[ 9] = SetupBuffer[16]; // TPM2 Support
Bytes[10] = SetupBuffer[17]; // TPM Existence
Bytes[13] = SetupBuffer[24]; // TPM Policy
Bytes[15] = SetupBuffer[32]; // TPM Physical Presence
Bytes[19] = SetupBuffer[27]; // TPM Firmware Update
Bytes[20] = SetupBuffer[28]; // TPM Supplier Config
Bytes[21] = SetupBuffer[29]; // TPM Supplier
Bytes[22] = SetupBuffer[30]; // TPM Device
//
// PCR Bitmap: DWORD at Setup offsets 38-41.
//
PcrBitmapValue = SetupBuffer[38];
PcrBitmapValue |= SetupBuffer[39] << 8;
PcrBitmapValue |= SetupBuffer[40] << 16;
PcrBitmapValue |= SetupBuffer[41] << 24;
*(UINT32 *)(Bytes + 23) = PcrBitmapValue;
}
/**
Writes policy data back to UEFI NV variables.
If WriteToNv is TRUE, reads the current Setup variable, applies the
policy values to the appropriate byte offsets, writes Setup back,
and writes the TcgInternalSyncFlag.
@param[in] PolicyData Pointer to the policy data.
@param[in] WriteToNv TRUE to commit to NV variables.
@retval EFI_SUCCESS Policy committed.
@retval EFI_INVALID_PARAMETER PolicyData is NULL.
@retval Others Error from GetVariable/SetVariable.
**/
EFI_STATUS
EFIAPI
TcgPlatformSetPolicyData (
IN TCG_PLATFORM_SETUP_POLICY *PolicyData,
IN BOOLEAN WriteToNv
)
{
EFI_STATUS Status;
UINT8 *Bytes;
UINT8 SetupBuffer[SETUP_VARIABLE_MAX_SIZE];
UINTN SetupSize;
UINTN SyncFlagSize;
UINT32 Attributes;
UINT32 PcrBitmapValue;
UINT32 PcrBitmapCopy;
UINTN PcrBitmapSize;
UINT32 PcrBitmapArray[5];
UINT8 *PolicyByte;
UINT8 Val;
UINTN Index;
Bytes = (UINT8 *)PolicyData;
if (PolicyData == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Update shadow global variables from the policy data.
//
mTpm1Enable = Bytes[ 0];
mTpmOperation = Bytes[ 1];
mTpm2Enable = Bytes[ 2];
mTpmSelect = Bytes[ 3];
mPcrBankTpm2 = Bytes[ 5];
mPcrBankTpm12 = Bytes[ 6];
mTpm1Support = Bytes[ 8];
mTpm2Support = Bytes[ 9];
mTpmExistence = Bytes[10];
mTpmPolicy = Bytes[13];
mTpmPhysicalPresence = Bytes[15];
mTpmFirmwareUpdate = Bytes[19];
mTpmSupplierConfig = Bytes[20];
mTpmSupplier = Bytes[21];
mTpmDevice = Bytes[22];
mPcrBitmap = *(UINT32 *)(Bytes + 23);
if (!WriteToNv) {
return EFI_SUCCESS;
}
//
// Read the current Setup variable.
//
Attributes = mVariableAttributes;
SetupSize = sizeof (SetupBuffer);
Status = gRT->GetVariable (
VARNAME_SETUP,
&gSetupVariableGuid,
&Attributes,
&SetupSize,
SetupBuffer
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Write back all policy fields at their respective Setup offsets.
//
SetupBuffer[18] = Bytes[ 0]; // TPM1 Enable
SetupBuffer[13] = Bytes[ 1]; // TPM Operation
SetupBuffer[22] = Bytes[ 2]; // TPM2 Enable
SetupBuffer[14] = Bytes[ 3]; // TPM Select
SetupBuffer[26] = Bytes[ 5]; // PCR Bank TPM2
SetupBuffer[31] = Bytes[ 6]; // PCR Bank TPM1.2
SetupBuffer[15] = Bytes[ 8]; // TPM1 Support
SetupBuffer[16] = Bytes[ 9]; // TPM2 Support
SetupBuffer[17] = Bytes[10]; // TPM Existence
SetupBuffer[24] = Bytes[13]; // TPM Policy
SetupBuffer[32] = Bytes[15]; // TPM Physical Presence
SetupBuffer[27] = Bytes[19]; // TPM Firmware Update
SetupBuffer[28] = Bytes[20]; // TPM Supplier Config
SetupBuffer[29] = Bytes[21]; // TPM Supplier
SetupBuffer[30] = Bytes[22]; // TPM Device
//
// PCR Bitmap DWORD at offsets 38-41.
//
PcrBitmapCopy = *(UINT32 *)(Bytes + 23);
SetupBuffer[38] = (UINT8)(PcrBitmapCopy & 0xFF);
SetupBuffer[39] = (UINT8)((PcrBitmapCopy >> 8) & 0xFF);
SetupBuffer[40] = (UINT8)((PcrBitmapCopy >> 16) & 0xFF);
SetupBuffer[41] = (UINT8)((PcrBitmapCopy >> 24) & 0xFF);
//
// Write the modified Setup variable.
//
Status = gRT->SetVariable (
VARNAME_SETUP,
&gSetupVariableGuid,
mVariableAttributes,
SetupSize,
SetupBuffer
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Apply PCR variable flags (bits 0-4 -> SHA1/SHA256/SHA384/SHA512/SM3).
//
{
//
// Read the PCRBitmap variable.
//
PcrBitmapSize = sizeof (PcrBitmapArray);
Status = gRT->GetVariable (
VARNAME_PCR_BITMAP,
&gPcrBitmapVariableGuid,
&Attributes,
&PcrBitmapSize,
PcrBitmapArray
);
if (!EFI_ERROR (Status)) {
//
// Apply PCR enable bits to policy.
// Bit 0 -> Bytes[4] = 1 (SHA1 enable -- v12 in dec)
// Bit 1 -> Bytes[5] = 1 (SHA256 enable -- v13 in dec)
// Bit 2 -> Bytes[6] = 1 (SHA384 enable -- v14 in dec)
// Bit 3 -> Bytes[7] = 1 (SHA512 enable -- v15 in dec)
// Bit 4 -> Bytes[8] = 1 (SM3 enable -- v16 in dec)
//
if (PcrBitmapArray[0] & 1) Bytes[4] = 1;
if (PcrBitmapArray[0] & 2) Bytes[5] = 1;
if (PcrBitmapArray[0] & 4) Bytes[6] = 1;
if (PcrBitmapArray[0] & 8) Bytes[7] = 1;
if (PcrBitmapArray[0] & 0x10) Bytes[8] = 1;
}
}
//
// Write TcgInternalSyncFlag to 1 to signal sync completion.
//
Bytes[14] = 1; // Set the sync flag in policy
Status = gRT->SetVariable (
VARNAME_TCG_INTERNAL_SYNC,
&gTcgInternalSyncFlagGuid,
mVariableAttributes,
1,
&Bytes[14]
);
if (Status == EFI_NOT_FOUND) {
//
// Variable does not exist yet; create it.
//
Status = gRT->SetVariable (
VARNAME_TCG_INTERNAL_SYNC,
&gTcgInternalSyncFlagGuid,
mVariableAttributes,
1,
&Bytes[14]
);
}
return Status;
}
//=============================================================================
// Notification Callback
//=============================================================================
/**
Notification callback for the SetProtocol interface.
Triggered by the protocol installation event. Locates the protocol,
reads the 27-byte policy, and calls SetPolicy to commit it.
@param[in] Event The notification event.
@param[in] Context Unused.
**/
VOID
EFIAPI
TcgPlatformSetupPolicyNotify (
IN EFI_EVENT Event,
IN VOID *Context
)
{
EFI_STATUS Status;
TCG_PLATFORM_SETUP_POLICY_PROTOCOL *Protocol;
TCG_PLATFORM_SETUP_POLICY Policy;
Protocol = NULL;
//
// Locate our protocol interface.
//
Status = gBS->LocateProtocol (
&gTcgPlatformSetupPolicyProtocolGuid,
NULL,
(VOID **)&Protocol
);
if (EFI_ERROR (Status) || Protocol == NULL) {
return;
}
//
// Copy the 27-byte policy data from the protocol interface (offset 1).
//
CopyMem (
&Policy,
(UINT8 *)Protocol + 1,
TCG_PLATFORM_SETUP_POLICY_DATA_SIZE
);
//
// Call the SetPolicy function (at offset 32 in the protocol interface).
//
Protocol->SetPolicy (&Policy, TRUE);
//
// Close the notification event.
//
gBS->CloseEvent (Event);
}
//=============================================================================
// Driver Entry Point
//=============================================================================
/**
Entry point for TcgPlatformSetupPolicy DXE driver.
@param[in] ImageHandle EFI image handle.
@param[in] SystemTable EFI system table.
@retval EFI_SUCCESS Protocol installed.
@retval EFI_OUT_OF_RESOURCES Pool allocation failed.
@retval Others Protocol install failed.
**/
EFI_STATUS
EFIAPI
TcgPlatformSetupPolicyDxeEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
UINTN SetupSize;
UINT8 SetupBuffer[SETUP_VARIABLE_MAX_SIZE];
UINTN PcrBitmapSize;
UINT32 PcrBitmapArray[5];
UINTN SyncFlagSize;
UINT8 SyncFlagValue;
UINT32 Attributes;
EFI_EVENT NotificationEvent;
VOID *Registration;
//
// The UEFI core initializes gImageHandle, gST, gBS, gRT in the
// library constructors. sub_DD8 (GetHobList) is called here in the
// original decompilation.
//
GetHobList ();
//
// Allocate runtime pool for the protocol interface (40 bytes).
//
Status = gBS->AllocatePool (
EfiRuntimeServicesData,
sizeof (TCG_PLATFORM_SETUP_POLICY_PROTOCOL) + 8,
(VOID **)&mTcgPolicyProtocol
);
if (EFI_ERROR (Status)) {
return EFI_OUT_OF_RESOURCES;
}
ZeroMem (mTcgPolicyProtocol, sizeof (TCG_PLATFORM_SETUP_POLICY_PROTOCOL));
mTcgPolicyProtocol->Revision = TCG_PLATFORM_SETUP_POLICY_REVISION;
//
// Read the TcgInternalSyncFlag to check for pending sync.
//
SyncFlagSize = 1;
Status = gRT->GetVariable (
VARNAME_TCG_INTERNAL_SYNC,
&gTcgInternalSyncFlagGuid,
&Attributes,
&SyncFlagSize,
&SyncFlagValue
);
if (EFI_ERROR (Status)) {
SyncFlagValue = 0;
}
//
// Read the Setup variable.
//
Attributes = mVariableAttributes;
SetupSize = sizeof (SetupBuffer);
Status = gRT->GetVariable (
VARNAME_SETUP,
&gSetupVariableGuid,
&Attributes,
&SetupSize,
SetupBuffer
);
if (!EFI_ERROR (Status)) {
//
// Initialize policy from Setup.
//
TcgPlatformInitPolicyFromSetup (
&mTcgPolicyProtocol->PolicyData,
SetupBuffer,
SetupSize
);
//
// Propagate TcgInternalSyncFlag.
//
if (SyncFlagSize == 1) {
*((UINT8 *)&mTcgPolicyProtocol->PolicyData + 14) = SyncFlagValue;
}
//
// Read PCRBitmap variable and apply PCR enable bits.
//
PcrBitmapSize = sizeof (PcrBitmapArray);
Status = gRT->GetVariable (
VARNAME_PCR_BITMAP,
&gPcrBitmapVariableGuid,
NULL,
&PcrBitmapSize,
PcrBitmapArray
);
if (!EFI_ERROR (Status)) {
//
// Apply PCR bits to the policy structure (v12..v16 fields).
//
UINT8 *PolicyBytes = (UINT8 *)&mTcgPolicyProtocol->PolicyData;
PolicyBytes[ 4] = 0; // v12
if (PcrBitmapArray[0] & 1) PolicyBytes[ 4] = 1; // SHA1
if (PcrBitmapArray[0] & 2) PolicyBytes[ 5] = 1; // SHA256 (actually
// Policy[5], but
// already set from
// Setup)
// Note: bits 4,8,0x10 correspond to different PCR indexes.
}
} else {
//
// Setup variable not found; policy was zeroed by ZeroMem.
//
}
//===========================================================================
// Cache all policy fields to shadow global variables.
//===========================================================================
{
UINT8 *Bytes;
Bytes = (UINT8 *)&mTcgPolicyProtocol->PolicyData;
mTpm1Enable = Bytes[ 0]; // byte_1450
mTpmOperation = Bytes[ 1]; // byte_1451
mTpm2Enable = Bytes[ 2]; // byte_1452
mTpmSelect = Bytes[ 3]; // byte_1453
// Bytes[ 4]; // byte_1454 -- NOT saved to global!
mPcrBankTpm2 = Bytes[ 5]; // byte_1455
mPcrBankTpm12 = Bytes[ 6]; // byte_1456
// Bytes[ 7]; // byte_1457 -- NOT saved to global!
mTpm1Support = Bytes[ 8]; // byte_1458
mTpm2Support = Bytes[ 9]; // byte_1459
mTpmExistence = Bytes[10]; // byte_145A
// Bytes[11]; // byte_145B -- NOT saved to global!
// Bytes[12]; // byte_145C -- NOT saved to global!
mTpmPolicy = Bytes[13]; // byte_145D
mTpmPhysicalPresence = Bytes[15]; // byte_145E
mTpmPhysPresence2 = Bytes[16]; // byte_145F
// Bytes[17]; // byte_1460 -- NOT saved to global!
// Bytes[18]; // byte_1461 -- NOT saved to global!
mTpmFirmwareUpdate = Bytes[19]; // byte_1462
mTpmSupplierConfig = Bytes[20]; // byte_1463
mTpmSupplier = Bytes[21]; // byte_1464
mTpmDevice = Bytes[22]; // byte_1465
mPcrBitmap = *(UINT32 *)(Bytes + 23); // dword_1467
}
//===========================================================================
// Install the protocol on ImageHandle.
//===========================================================================
Status = gBS->InstallProtocolInterface (
&ImageHandle,
&gTcgPlatformSetupPolicyProtocolGuid,
EFI_NATIVE_INTERFACE,
(VOID *)mTcgPolicyProtocol
);
if (EFI_ERROR (Status)) {
gBS->FreePool (mTcgPolicyProtocol);
return Status;
}
//===========================================================================
// Register the notification event.
// Type = EVT_NOTIFY_SIGNAL (512), NotifyTpl = TPL_CALLBACK (8),
// NotifyFunction = TcgPlatformSetupPolicyNotify
//===========================================================================
Status = gBS->CreateEvent (
EVT_NOTIFY_SIGNAL,
TPL_CALLBACK,
TcgPlatformSetupPolicyNotify,
NULL,
&NotificationEvent
);
if (EFI_ERROR (Status)) {
//
// Non-fatal; the protocol is already installed even if the
// notification event fails.
//
}
return EFI_SUCCESS;
}
//=============================================================================
// Function Summary for Reference
//=============================================================================
//
// Address Name Size Role
// ------- ---- ---- ----
// 0x280 ZeroBuffer 17 memset(buf, val, size)
// 0x350 _ModuleEntryPoint 184 UEFI entry, calls sub_DD8 + sub_860
// 0x408 TcgPlatformSetPolicyData 1002 Read Setup, merge policy, write NV
// 0x7F4 TcgPlatformSetupPolicyNotify 107 Locate protocol, copy policy, call SetPolicy
// 0x860 TcgPlatformSetupPolicyDxe.. 990 Main entry: alloc, init, install protocol
// 0xC40 ZeroMem/SetMem 80 Wrapper for ZeroBuffer
// 0xC90 LocateDebugProtocol 127 RaiseTPL, LocateProtocol, cache result
// 0xD10 TpmBootPathCmosCheck 136 Read CMOS 0x4B for TPM boot path
// 0xD98 ReportAssert 62 Call assert via debug protocol offset+8
// 0xDD8 GetHobList 214 Search config table for gEfiHobListGuid
// 0xEB0 ReadUnaligned64 47 64-bit unaligned read with NULL check
// 0xEE0 CompareGuid 110 Compare two GUIDs via 64-bit halves