Newer
Older
AMI-Aptio-BIOS-Reversed / TcgLegacy / TcgLegacy.md
@Ajax Dong Ajax Dong 2 days ago 10 KB Init

TcgLegacy

Function Table

Address Name Description
ReadUnaligned64
DebugPrint
DebugAssert
ZeroMem
IsHobGuidMatch
LocateFirmwareVolumeFile
AllocateAndZeroPages
AllocateAndZeroPagesWrapper
ScanAndPatchBfi
LinkTPM32Driver
UnlinkTPM32FromEFI
NullCallback
GenericCallback
ModuleEntryPoint
InitTCGLegacyInterface
External global data references (populated by ModuleEntryPoint)
These are written once by the DXE core bootstrap code before the driver's
entry point is called; the entry point simply caches them in variables.
Legacy BIOS interface function pointer (stored at 0x1DD0)
When byte_1DE0 == 0: points to the EFI_LEGACY_BIOS_PROTOCOL instance.
When byte_1DE0 == 1: set to the TCG2 protocol interface.
UINT64 qword_1DD0 = 0;
Installed TPM32 header pointer (stored at 0x1DD8)
UINT64 qword_1DD8 = 0;
Protocol selection flag (stored at 0x1DE0 as byte)
If 0: Legacy BIOS Protocol is used.
If 1: TCG2 Protocol is used instead.
UINT8 byte_1DE0 = 0;
TCG2 Protocol pointer (stored at 0x1DE8)
Valid only when byte_1DE0 == 1.
UINT64 qword_1DE8 = 0;
System Table pointer (stored at 0x1DF0)
EFI_SYSTEM_TABLE *gST = NULL;
Boot Services pointer (stored at 0x1DF8)
EFI_BOOT_SERVICES *gBS = NULL;
Image handle (stored at 0x1E00)
EFI_HANDLE gImageHandle = NULL;
Runtime Services pointer (stored at 0x1E08)
EFI_RUNTIME_SERVICES *gRT = NULL;
Debug Console Output protocol (stored at 0x1E10, cached from GetTcgProtocol)
EFI_TCG_PROTOCOL *gTcgProtocol = NULL;
HOB List pointer (stored at 0x1E18)
VOID *gHobList = NULL;
CMOS variable byte read from NVRAM index 0x4B (stored at 0x1E20)
Used by DebugPrint to determine verbosity level.
UINT8 gDebugNvramByte = 0;
LEGX16 configuration words (stored at 0x1E28-0x1E30)
These are saved from the LEGX16 header and written to legacy BIOS
configuration space during install.
UINT16 gLegX16Segment = 0; // +0x1E28
TPM Vendor ID Lookup Table (stored at 0x1DC0)
Each 4-byte entry contains a TPM hardware vendor/device ID.
The table is compared against MEMORY[0xFED40F00] to detect if
TPM hardware is already present.
Entry 0: 0xF5190100 (vendor:device flags)
Entry 1: 0x011B4E01 (vendor: "NS" = National Semiconductor?)
Entry 2: 0x00020000 (placeholder/end marker)
UINT32 gTpmVendorIdTable[3] = {
GUID data blocks (must match the GUIDs declared in the header)
EFI_GUID gEfiTcgEventLogFormatGuid = TCG_EVENT_LOG_FORMAT_GUID;
Internal / Library function implementations
Zero the buffer using UINT64-aligned writes for the bulk
and byte writes for the remainder.
ZeroMem (Buffer, Length);
Read CMOS NVRAM index 0x4B to determine debug verbosity.
NvramByte = IoRead8 (0x70);
Read platform-specific debug flag from 0xFDAF0490.
NvramStatus *= ((volatile UINT8 *)0xFDAF0490 & 2) 1;**
Determine print level: EFI_D_INFO (0x80000004) if verbosity == 1
EFI_D_WARN (0x80000006) otherwise.
if ((NvramStatus - 1) <= 0xFD) {
If the message's error level matches the current verbosity, print it.
if ((PrintLevel & ErrorLevel) != 0) {
Found the HOB List entry; cache the pointer.
gHobList = gST->ConfigurationTable[Index].VendorTable;
Read CMOS index 0x4B to determine NVRAM bank size.
IoWrite8 (0x70, 0x4B);
NVRAM bank is 16 bytes or fewer; try to locate the TCG protocol.
if (gBS->LocateProtocol (
Locate all FV protocol handles.
Status = gBS->LocateHandleBuffer (
Scan each FV for the file by GUID.
for (Index = 0; Index < HandleCount; Index++) {
Found the file.
Forward declaration of internal helper.
UINT16 *
Each entry is 24 bytes; navigate backwards from the end.
EntryBase = DevicePathTable + (NumberOfTableEntries - 1 - Index) * 24;
Compare first 16 bytes against the TCG event log GUID.
if (InternalCompareMem (
Walk the vendor data entries following the GUID.
Current = Entry;
Skip to next entry (advance by the entry's total length).
Current = (UINT16 )((UINT8 )Current + Current[1]);
Type 4 entry: check if the next 16 bytes match the expected data.
Alternative GUID for comparison
128 KB / 4
Size field in next dword
Calculate checksum over the BFI structure bytes.
while (Count > 0) {
Valid BFI with matching checksum
Patch the LEGX16 segment into the BFI structure (offset 35 words = byte 70).
Recalculate the checksum after patching.
Recalculate checksum.
BfiData = BfiEntry + 4; // Skip the signature dword itself
Clear first byte of remaining structure
Length of the checksummed region
Store the two's complement checksum.
Offset +0x42 (2 bytes), cleared initially
Offset +0x04
Cache the Legacy BIOS interface pointer globally.
qword_1DD0 = (UINT64)LegBios;
TCG2 path: register a null callback and use TCG2 protocol for init.
if (qword_1DE8 == 0) {
nullsub_1 Status = ((EFI_TCG2_PROTOCOL *)qword_1DE8)->RegisterCallback (
32 KB log buffer
Legacy BIOS Protocol path: call the interface's callback registration.
sub_410 LegBios->Callback (
Ensure PM entry is cleared after init
TCG2 path: unregister via TCG2 protocol.
if (qword_1DE8 != 0) {
Legacy BIOS path: unregister via Legacy BIOS Protocol callback.
Zero TpmLogAddress and TpmLogSize
Intentionally empty.
Main initialization and entry point
Save global handles required by the boot and runtime services libraries.
gImageHandle = ImageHandle;
Initialize the HOB list for platform configuration.
GetHobList ();
Perform the TCG Legacy interface initialization.
return InitTCGLegacyInterface ();
Step 1: Check if there is already TPM hardware at the legacy TPM
for (Index = 0; Index < TPM_VENDOR_ID_COUNT; Index++) {
TPM hardware is already present; nothing for us to do.
return EFI_SUCCESS;
Step 2: Ensure TPM32 is not already installed.
if (qword_1DD8 != 0) {
Step 3: Locate the Legacy BIOS Protocol (0x1DB0) or TCG2 protocol.
TCG2 not found; try the AMI TCG protocol.
LegBios = NULL;
Use TCG2 / AMI TCG protocol path
Step 4: Locate the Legacy BIOS Platform Protocol (0x1D80).
Step 5: Locate the Legacy BIOS Protocol (0x1D60).
Step 6: Load the LEGX16 binary from a firmware volume file GUID.
LegX16Addr = 0;
Placeholder GUID; actual file GUID
Step 7: Allocate legacy region via Legacy BIOS Platform Protocol (+72).
This allocates a region in the F000-E000 area for LEGX16.
Status = LegBiosPlatform->AllocateLegacyRegion (
Step 8: Load the TPM32 binary from firmware volume.
Status = LocateFirmwareVolumeFile (
Placeholder (VOID )&Tpm32Buffer**
Step 9: Allocate page-aligned memory for the TPM32 code.
TpmCodePhysAddr = AllocateAndZeroPagesWrapper (
Step 9b: Copy the TPM32 binary to the allocated page.
Step 10: Allocate a TPM log/data page for the TPM32 driver's use.
TpmEntry = AllocateAndZeroPagesWrapper (1); // 1 page = 4 KB
Free the previously allocated TPM code pages.
Step 11: Check for vendor ACPI table match (MPTPM or ACPI entry).
TPM hardware already present; find matching ACPI device path entry.
UINT16 *MatchingEntry;
Calculate size
Skip MPTPM loading
Step 12: Load MPTPM (multi-processor TPM) if needed.
Placeholder (VOID )&MptpmBuffer**
Step 13: Set the TPM32 header fields.
TpmSegEntry = LegX16Addr;
Write the TPM32 entry point into the LEGX16 header at the correct offset.
Step 14: Link the TPM32 driver into the legacy BIOS interface.
LinkTPM32Driver (Tpm32Header, LegBios);
Step 15: Set the LEGX16 control flag (-7424 = 0xE300 shadow enable).
Step 16: Copy the LEGX16 image to the final F000-E000 legacy region.
Status = LegBiosPlatform->CopyLegacyRegion (
Step 17: Install the legacy interrupt handler.
The second legacy BIOS protocol instance (0x1D80) provides interrupt
LegBiosPlatform = (EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *)LegBios; // Reuse for platform operations
Initialize the shadow region data structure (48 bytes).
ZeroMem (v46, 48);
Use Legacy BIOS Platform Protocol function +8 to install the interrupt.
Save LEGX16 configuration words for later use.
gLegX16Segment = (UINT16)(ShadowBase >> 4);
Step 18: Allocate legacy region for the configuration data.
Write the configuration words to the legacy region.
Step 19: Release and re-acquire the legacy region for shadow operations.
Step 20: Scan and patch the BFI marker in the legacy ROM region.
ScanAndPatchBfi ((UINT64)LegBiosPlatform, (UINT64)LegBios, gLegX16Segment);
Step 21: Release the shadow region.
Step 22: Save the installed TPM32 header pointer.
qword_1DD8 = (UINT64)Tpm32Header;
Step 23: Register a Legacy Boot notification event.
Release the shadow region on error.
Free allocated pages on error.
if (TpmCodePhysAddr != 0xFFFFFFFFFFFFFFFFULL) {

Generated by HR650X BIOS Decompilation Project