DynamicTablesPkg: add Tpm2DeviceTableLib to generate Tpm2 device table

Introduce Tpm2DeviceTableLib to generate SSDT table which describes
Tpm2 devices.

This dynamic table generation is controlled by PcdGenTpm2DeviceTable
which default value is FALSE.
When it is TRUE, the TPM2 device ssdt table is generated when TPM2 ACPI
table is generated.

Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
This commit is contained in:
Levi Yun
2025-03-18 14:15:03 +00:00
committed by mergify[bot]
parent faeedaa54b
commit 0d82e48221
10 changed files with 672 additions and 49 deletions

View File

@@ -25,6 +25,7 @@
SmbiosStringTableLib|DynamicTablesPkg/Library/Common/SmbiosStringTableLib/SmbiosStringTableLib.inf
MetadataObjLib|DynamicTablesPkg/Library/Common/MetadataObjLib/MetadataObjLib.inf
MetadataHandlerLib|DynamicTablesPkg/Library/Common/MetadataHandlerLib/MetadataHandlerLib.inf
Tpm2DeviceTableLib|DynamicTablesPkg/Library/Common/Tpm2DeviceTableLib/Tpm2DeviceTableLib.inf
[LibraryClasses.AARCH64]
DynamicTablesScmiInfoLib|DynamicTablesPkg/Library/DynamicTablesScmiInfoLib/DynamicTablesScmiInfoLib.inf

View File

@@ -54,7 +54,8 @@
"EmbeddedPkg/EmbeddedPkg.dec",
"DynamicTablesPkg/DynamicTablesPkg.dec",
"MdeModulePkg/MdeModulePkg.dec",
"MdePkg/MdePkg.dec"
"MdePkg/MdePkg.dec",
"SecurityPkg/SecurityPkg.dec"
],
# For host based unit tests
"AcceptableDependencies-HOST_APPLICATION":[

View File

@@ -52,6 +52,9 @@
## @libraryclass Defines a set of APIs to a handle Metadata generation/validation.
MetadataHandlerLib|Include/Library/MetadataHandlerLib.h
## @libraryclass Defines a set of methods for generating Tpm2 Device Table method.
Tpm2DeviceTableLib|Include/Library/Tpm2DeviceTableLib.h
[LibraryClasses.AARCH64]
## @libraryclass Defines a set of APIs to populate CmObj using SCMI.
DynamicTablesScmiInfoLib|Include/Library/DynamicTablesScmiInfoLib.h
@@ -84,5 +87,8 @@
# BIT0: Allow the absence of some registers in the _CPC object.
gEdkiiDynamicTablesPkgTokenSpaceGuid.PcdDevelopmentPlatformRelaxations|0|UINT64|0x4000000A
# Generate Tpm2 device table when generate TPM2 acpi table together.
gEdkiiDynamicTablesPkgTokenSpaceGuid.PcdGenTpm2DeviceTable|FALSE|BOOLEAN|0x4000000B
[Guids]
gEdkiiDynamicTablesPkgTokenSpaceGuid = { 0xab226e66, 0x31d8, 0x4613, { 0x87, 0x9d, 0xd2, 0xfa, 0xb6, 0x10, 0x26, 0x3c } }

View File

@@ -51,6 +51,7 @@
DynamicTablesPkg/Library/Common/SmbiosStringTableLib/SmbiosStringTableLib.inf
DynamicTablesPkg/Library/Common/MetadataObjLib/MetadataObjLib.inf
DynamicTablesPkg/Library/Common/MetadataHandlerLib/MetadataHandlerLib.inf
DynamicTablesPkg/Library/Common/Tpm2DeviceTableLib/Tpm2DeviceTableLib.inf
[Components.ARM, Components.AARCH64]
DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtHwInfoParserLib.inf

View File

@@ -0,0 +1,50 @@
/** @file
Tpm2 device table generating Library
Copyright (c) 2025, Arm Limited. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef TPM2_DEVICE_TABLE_LIB_H_
#define TPM2_DEVICE_TABLE_LIB_H_
/** Build a SSDT table describing the TPM2 device.
The table created by this function must be freed by FreeTpm2DeviceTable.
@param [in] TpmDevInfo TPM2 Device info to describe in the SSDT table.
@param [in] Name The Name to give to the Device.
Must be a NULL-terminated ASL NameString
e.g.: "DEV0", "DV15.DEV0", etc.
@param [in] Uid UID for the TPM@ device.
@param [out] Table If success, pointer to the created SSDT table.
@retval EFI_SUCCESS Table generated successfully.
@retval EFI_INVALID_PARAMETER A parameter is invalid.
@retval EFI_NOT_FOUND Could not find information.
@retval EFI_OUT_OF_RESOURCES Could not allocate memory.
**/
EFI_STATUS
EFIAPI
BuildTpm2DeviceTable (
IN CONST CM_ARCH_COMMON_TPM2_DEVICE_INFO *TpmDevInfo,
IN CONST CHAR8 *Name,
IN CONST UINT64 Uid,
OUT EFI_ACPI_DESCRIPTION_HEADER **Table
);
/** Free an Tpm2 device table previously created by
the BuildTpm2DeviceTable function.
@param [in] Table Pointer to a Tpm2 Device table allocated by
the BuildTpm2DeviceTable function.
**/
VOID
EFIAPI
FreeTpm2DeviceTable (
IN EFI_ACPI_DESCRIPTION_HEADER *Table
);
#endif // TPM2_DEVICE_TABLE_LIB_H_

View File

@@ -26,4 +26,9 @@
MdePkg/MdePkg.dec
[LibraryClasses]
AcpiHelperLib
BaseLib
Tpm2DeviceTableLib
[FixedPcd]
gEdkiiDynamicTablesPkgTokenSpaceGuid.PcdGenTpm2DeviceTable

View File

@@ -20,13 +20,16 @@
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/PcdLib.h>
#include <Protocol/AcpiTable.h>
// Module specific include files.
#include <AcpiTableGenerator.h>
#include <ConfigurationManagerObject.h>
#include <ConfigurationManagerHelper.h>
#include <Library/AcpiHelperLib.h>
#include <Library/TableHelperLib.h>
#include <Library/Tpm2DeviceTableLib.h>
#include <Protocol/ConfigurationManagerProtocol.h>
#include <IndustryStandard/Tpm2Acpi.h>
@@ -35,6 +38,9 @@
#define START_METHOD_CRB_WITH_SMC_PARAM_SIZE 12
#define START_METHOD_CRB_WITH_FFA_PARM_SIZE 12
#define TPM2_DEVICE_UID 0
#define MAX_TABLE_COUNT 2
/**
ARM standard TPM2 Generator
@@ -53,6 +59,12 @@ GET_OBJECT_LIST (
CM_ARCH_COMMON_TPM2_INTERFACE_INFO
);
GET_OBJECT_LIST (
EObjNameSpaceArchCommon,
EArchCommonObjTpm2DeviceInfo,
CM_ARCH_COMMON_TPM2_DEVICE_INFO
);
/**
Sanity check Start Method Specific Parameters field
@@ -122,6 +134,73 @@ AcpiTpm2CheckStartMethodParameters (
return EFI_SUCCESS;
}
/** Build a TPM2 ACPI table.
@param [in] This Pointer to the table generator.
@param [in] AcpiTableInfo Pointer to the ACPI Table Info.
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
Protocol Interface.
@param [in] TpmInfo TpmInfo to describe TPM2 device.
@param [in, out] Tpm2AcpiTable Tpm2AcpiTable.
@param [in] TableSize Size of Tpm2AcpiTable.
@retval EFI_SUCCESS Table generated successfully.
@retval EFI_INVALID_PARAMETER A parameter is invalid.
@retval EFI_NOT_FOUND Could not find information.
@retval EFI_OUT_OF_RESOURCES Could not allocate memory.
**/
STATIC
EFI_STATUS
EFIAPI
BuildTpm2AcpiTable (
IN CONST ACPI_TABLE_GENERATOR *CONST This,
IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo,
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
IN CONST CM_ARCH_COMMON_TPM2_INTERFACE_INFO *TpmInfo,
IN OUT EFI_TPM2_ACPI_TABLE *Tpm2AcpiTable,
IN UINT32 TableSize
)
{
EFI_STATUS Status;
UINT32 *Laml;
UINT64 *Lasa;
Status = AddAcpiHeader (
CfgMgrProtocol,
This,
&Tpm2AcpiTable->Header,
AcpiTableInfo,
TableSize
);
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_ERROR,
"ERROR: TPM2: Failed to add ACPI header. Status = %r\n",
Status
));
return Status;
}
Tpm2AcpiTable->Flags = TpmInfo->PlatformClass;
Tpm2AcpiTable->AddressOfControlArea = TpmInfo->AddressOfControlArea;
Tpm2AcpiTable->StartMethod = TpmInfo->StartMethod;
CopyMem (
Tpm2AcpiTable + 1,
TpmInfo->StartMethodParameters,
TpmInfo->StartMethodParametersSize
);
if (TpmInfo->Laml > 0) {
Lasa = (UINT64 *)((UINT8 *)Tpm2AcpiTable + TableSize - sizeof (TpmInfo->Lasa));
Laml = (UINT32 *)((UINT8 *)Lasa - sizeof (TpmInfo->Laml));
*Laml = TpmInfo->Laml;
*Lasa = TpmInfo->Lasa;
}
return EFI_SUCCESS;
}
/** Construct the TPM2 ACPI table.
Called by the Dynamic Table Manager, this function invokes the
@@ -135,7 +214,8 @@ AcpiTpm2CheckStartMethodParameters (
@param [in] AcpiTableInfo Pointer to the ACPI Table Info.
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
Protocol Interface.
@param [out] Table Pointer to the constructed ACPI Table.
@param [out] Table Pointer to a list of generated ACPI table(s).
@param [out] TableCount Number of generated ACPI table(s).
@retval EFI_SUCCESS Table generated successfully.
@retval EFI_INVALID_PARAMETER A parameter is invalid.
@@ -148,22 +228,24 @@ AcpiTpm2CheckStartMethodParameters (
STATIC
EFI_STATUS
EFIAPI
BuildTpm2Table (
BuildTpm2TableEx (
IN CONST ACPI_TABLE_GENERATOR *CONST This,
IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo,
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
OUT EFI_ACPI_DESCRIPTION_HEADER **CONST Table
OUT EFI_ACPI_DESCRIPTION_HEADER ***Table,
OUT UINTN *CONST TableCount
)
{
EFI_STATUS Status;
UINT32 TableSize;
CM_ARCH_COMMON_TPM2_INTERFACE_INFO *TpmInfo;
EFI_TPM2_ACPI_TABLE *Tpm2;
UINT32 *Laml;
UINT64 *Lasa;
CM_ARCH_COMMON_TPM2_DEVICE_INFO *TpmDevInfo;
UINT32 TableSize;
UINT32 MaxParameterSize;
EFI_ACPI_DESCRIPTION_HEADER **TableList;
CHAR8 NewName[AML_NAME_SEG_SIZE + 1];
*Table = NULL;
*Table = NULL;
*TableCount = 0;
ASSERT (
(This != NULL) &&
@@ -233,9 +315,24 @@ BuildTpm2Table (
TableSize += sizeof (TpmInfo->Laml) + sizeof (TpmInfo->Lasa);
}
// Allocate a table to store pointers to the TPM2 table and
// Ssdt table.for Tpm2 device description.
TableList = (EFI_ACPI_DESCRIPTION_HEADER **)
AllocateZeroPool (
(sizeof (EFI_ACPI_DESCRIPTION_HEADER *) * MAX_TABLE_COUNT)
);
if (TableList == NULL) {
DEBUG ((
DEBUG_ERROR,
"ERROR: TPM2: Failed to allocate memory for TableList.\n"
));
return EFI_OUT_OF_RESOURCES;
}
// Allocate the Buffer for TPM2 table
*Table = (EFI_ACPI_DESCRIPTION_HEADER *)AllocateZeroPool (TableSize);
if (*Table == NULL) {
TableList[0] = (EFI_ACPI_DESCRIPTION_HEADER *)AllocateZeroPool (TableSize);
if (TableList[0] == NULL) {
Status = EFI_OUT_OF_RESOURCES;
DEBUG ((
DEBUG_ERROR,
"ERROR: TPM2: Failed to allocate memory for TPM2 Table, Size = %d," \
@@ -243,51 +340,85 @@ BuildTpm2Table (
TableSize,
Status
));
return EFI_OUT_OF_RESOURCES;
goto ErrorHandler;
}
Tpm2 = (EFI_TPM2_ACPI_TABLE *)*Table;
Status = AddAcpiHeader (
CfgMgrProtocol,
Status = BuildTpm2AcpiTable (
This,
&Tpm2->Header,
AcpiTableInfo,
CfgMgrProtocol,
TpmInfo,
(EFI_TPM2_ACPI_TABLE *)TableList[0],
TableSize
);
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_ERROR,
"ERROR: TPM2: Failed to add ACPI header. Status = %r\n",
"ERROR: TPM2: Failed to Build TPM2 ACPI Table, " \
" Status = %r\n",
Status
));
goto error_handler;
goto ErrorHandler;
}
Tpm2->Flags = TpmInfo->PlatformClass;
Tpm2->AddressOfControlArea = TpmInfo->AddressOfControlArea;
Tpm2->StartMethod = TpmInfo->StartMethod;
*TableCount += 1;
CopyMem (
Tpm2 + 1,
TpmInfo->StartMethodParameters,
TpmInfo->StartMethodParametersSize
);
// Generate TPM2 device SSDT table.
if (FixedPcdGetBool (PcdGenTpm2DeviceTable)) {
Status = GetEArchCommonObjTpm2DeviceInfo (
CfgMgrProtocol,
CM_NULL_TOKEN,
&TpmDevInfo,
NULL
);
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_ERROR,
"%a: Failed to get TPM2 Device CM Object %r\n",
__func__,
Status
));
goto ErrorHandler;
}
if (TpmInfo->Laml > 0) {
Laml = (UINT32 *)((UINT8 *)Tpm2 + sizeof (EFI_TPM2_ACPI_TABLE) + MaxParameterSize);
Lasa = (UINT64 *)((UINT8 *)Laml + sizeof (TpmInfo->Laml));
*Laml = TpmInfo->Laml;
*Lasa = TpmInfo->Lasa;
NewName[0] = 'T';
NewName[1] = 'P';
NewName[2] = 'M';
NewName[3] = AsciiFromHex ((UINT8)(TPM2_DEVICE_UID));
NewName[4] = '\0';
Status = BuildTpm2DeviceTable (
TpmDevInfo,
NewName,
TPM2_DEVICE_UID,
&TableList[1]
);
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_ERROR,
"ERROR: TPM2: Failed to Build SSDT table for TPM2 device," \
" Status = %r\n",
Status
));
goto ErrorHandler;
}
*TableCount += 1;
}
*Table = TableList;
return EFI_SUCCESS;
error_handler:
ErrorHandler:
*TableCount = 0;
if (*Table != NULL) {
FreePool (*Table);
*Table = NULL;
if (TableList != NULL) {
if (TableList[0] != NULL) {
FreePool (TableList[0]);
}
FreePool (TableList);
}
return Status;
@@ -299,7 +430,10 @@ error_handler:
@param [in] AcpiTableInfo Pointer to the ACPI Table Info.
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
Protocol Interface.
@param [in, out] Table Pointer to the ACPI Table.
@param [in, out] Table Pointer to an array of pointers
to ACPI Table(s).
@param [in] TableCount Number of ACPI table(s).
@retval EFI_SUCCESS The resources were freed successfully.
@retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
@@ -307,13 +441,17 @@ error_handler:
STATIC
EFI_STATUS
EFIAPI
FreeTpm2TableResources (
IN CONST ACPI_TABLE_GENERATOR *CONST This,
IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo,
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
IN OUT EFI_ACPI_DESCRIPTION_HEADER **CONST Table
FreeTpm2TableResourcesEx (
IN CONST ACPI_TABLE_GENERATOR *CONST This,
IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo,
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
IN OUT EFI_ACPI_DESCRIPTION_HEADER ***CONST Table,
IN CONST UINTN TableCount
)
{
UINTN Idx;
EFI_ACPI_DESCRIPTION_HEADER **TableList;
ASSERT (
(This != NULL) &&
(AcpiTableInfo != NULL) &&
@@ -322,12 +460,27 @@ FreeTpm2TableResources (
(AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature)
);
if ((Table == NULL) || (*Table == NULL)) {
if ((Table == NULL) || (*Table == NULL) || (TableCount == 0)) {
DEBUG ((DEBUG_ERROR, "ERROR: TPM2: Invalid Table Pointer\n"));
return EFI_INVALID_PARAMETER;
}
FreePool (*Table);
TableList = *Table;
for (Idx = 0; Idx < TableCount; Idx++) {
switch (TableList[Idx]->Signature) {
case EFI_ACPI_6_5_TRUSTED_COMPUTING_PLATFORM_2_TABLE_SIGNATURE:
FreePool (TableList[Idx]);
break;
case EFI_ACPI_6_5_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
FreeTpm2DeviceTable (TableList[Idx]);
break;
default:
ASSERT (0);
}
}
FreePool (TableList);
*Table = NULL;
return EFI_SUCCESS;
@@ -357,14 +510,14 @@ ACPI_TABLE_GENERATOR Tpm2Generator = {
// Creator Revision
TPM2_GENERATOR_REVISION,
// Build Table function
BuildTpm2Table,
// Free Resource function
FreeTpm2TableResources,
// Extended build function not needed
NULL,
// Free Resource function
NULL,
// Extended build function not needed
BuildTpm2TableEx,
// Extended build function not implemented by the generator.
// Hence extended free resource function is not required.
NULL
FreeTpm2TableResourcesEx
};
/** Register the Generator with the ACPI Table Factory.

View File

@@ -0,0 +1,329 @@
/** @file
Tpm2 device table generating Library
Copyright (c) 2025, Arm Limited. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@par Reference(s):
- TCG ACPI specification.
(https://trustedcomputinggroup.org/resource/tcg-acpi-specification/)
**/
#include <IndustryStandard/DebugPort2Table.h>
#include <Library/AcpiLib.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/PcdLib.h>
#include <Protocol/AcpiTable.h>
// Module specific include files.
#include <AcpiTableGenerator.h>
#include <ConfigurationManagerObject.h>
#include <ConfigurationManagerHelper.h>
#include <Library/AcpiHelperLib.h>
#include <Library/AmlLib/AmlLib.h>
#include <Protocol/ConfigurationManagerProtocol.h>
/** C array containing the compiled AML template.
This symbol is defined in the auto generated C file
containing the AML bytecode array.
*/
extern CHAR8 tpm2devicetabletemplate_aml_code[];
/** Fixup the TPM2 device UID (_UID).
@param [in] RootNodeHandle Pointer to the root of an AML tree.
@param [in] Uid UID for the TPM2 device.
@retval EFI_SUCCESS The function completed successfully.
@retval EFI_INVALID_PARAMETER Invalid parameter.
@retval EFI_NOT_FOUND Could not find information.
@retval EFI_OUT_OF_RESOURCES Out of resources.
**/
STATIC
EFI_STATUS
EFIAPI
FixupTpm2DeviceUid (
IN AML_ROOT_NODE_HANDLE RootNodeHandle,
IN CONST UINT64 Uid
)
{
EFI_STATUS Status;
AML_OBJECT_NODE_HANDLE NameOpIdNode;
// Get the _UID NameOp object defined by the "Name ()" statement,
// and update its value.
Status = AmlFindNode (
RootNodeHandle,
"\\_SB_.TPM0._UID",
&NameOpIdNode
);
if (EFI_ERROR (Status)) {
return Status;
}
return AmlNameOpUpdateInteger (NameOpIdNode, (UINT64)Uid);
}
/** Fixup the Tpm2 device name.
@param [in] RootNodeHandle Pointer to the root of an AML tree.
@param [in] Name The Name to give to the Device.
Must be a NULL-terminated ASL NameString
e.g.: "DEV0", "DV15.DEV0", etc.
@retval EFI_SUCCESS The function completed successfully.
@retval EFI_INVALID_PARAMETER Invalid parameter.
@retval EFI_NOT_FOUND Could not find information.
@retval EFI_OUT_OF_RESOURCES Out of resources.
**/
STATIC
EFI_STATUS
EFIAPI
FixupTpm2DeviceName (
IN AML_ROOT_NODE_HANDLE RootNodeHandle,
IN CONST CHAR8 *Name
)
{
EFI_STATUS Status;
AML_OBJECT_NODE_HANDLE DeviceNode;
// Get the COM0 variable defined by the "Device ()" statement.
Status = AmlFindNode (RootNodeHandle, "\\_SB_.TPM0", &DeviceNode);
if (EFI_ERROR (Status)) {
return Status;
}
// Update the Device's name.
return AmlDeviceOpUpdateName (DeviceNode, Name);
}
/** Fixup the Tpm2 device _CRS values (BaseAddress, ...).
@param [in] RootNodeHandle Pointer to the root of an AML tree.
@param [in] TpmDevInfo Pointer to a TPM2 device Information
structure.
Get the device size Information from there.
@retval EFI_SUCCESS The function completed successfully.
@retval EFI_INVALID_PARAMETER Invalid parameter.
@retval EFI_NOT_FOUND Could not find information.
@retval EFI_OUT_OF_RESOURCES Out of resources.
**/
STATIC
EFI_STATUS
EFIAPI
FixupTpm2DeviceCrs (
IN AML_ROOT_NODE_HANDLE RootNodeHandle,
IN CONST CM_ARCH_COMMON_TPM2_DEVICE_INFO *TpmDevInfo
)
{
EFI_STATUS Status;
AML_OBJECT_NODE_HANDLE NameOpCrsNode;
AML_DATA_NODE_HANDLE QWordRdNode;
// Get the "_CRS" object defined by the "Name ()" statement.
Status = AmlFindNode (
RootNodeHandle,
"\\_SB_.TPM0._CRS",
&NameOpCrsNode
);
if (EFI_ERROR (Status)) {
return Status;
}
// Get the first Rd node in the "_CRS" object.
Status = AmlNameOpGetFirstRdNode (NameOpCrsNode, &QWordRdNode);
if (EFI_ERROR (Status)) {
return Status;
}
if (QWordRdNode == NULL) {
return EFI_INVALID_PARAMETER;
}
// Update the TPM2 device's base address and length.
Status = AmlUpdateRdQWord (
QWordRdNode,
TpmDevInfo->Tpm2DeviceBaseAddress,
TpmDevInfo->Tpm2DeviceSize
);
if (EFI_ERROR (Status)) {
return Status;
}
return Status;
}
/** Fixup the Tpm2 Device in the AML tree.
For each template value:
- find the node to update;
- update the value.
@param [in] RootNodeHandle Pointer to the root of the AML tree.
@param [in] TpmDevInfo Pointer to a TPM2 device Information
structure.
@param [in] Name The Name to give to the Device.
Must be a NULL-terminated ASL NameString
e.g.: "DEV0", "DV15.DEV0", etc.
@param [in] Uid UID for the TPM2 device.
@retval EFI_SUCCESS The function completed successfully.
@retval EFI_INVALID_PARAMETER Invalid parameter.
@retval EFI_NOT_FOUND Could not find information.
@retval EFI_OUT_OF_RESOURCES Out of resources.
**/
STATIC
EFI_STATUS
EFIAPI
FixupTpm2DeviceInfo (
IN AML_ROOT_NODE_HANDLE RootNodeHandle,
IN CONST CM_ARCH_COMMON_TPM2_DEVICE_INFO *TpmDevInfo,
IN CONST CHAR8 *Name,
IN CONST UINT64 Uid
)
{
EFI_STATUS Status;
ASSERT (RootNodeHandle != NULL);
ASSERT (TpmDevInfo != NULL);
ASSERT (Name != NULL);
// Fixup the _UID value.
Status = FixupTpm2DeviceUid (RootNodeHandle, Uid);
if (EFI_ERROR (Status)) {
return Status;
}
// Fixup the _CRS values.
Status = FixupTpm2DeviceCrs (RootNodeHandle, TpmDevInfo);
if (EFI_ERROR (Status)) {
return Status;
}
// Fixup the Tpm2 device name.
// This MUST be done at the end, otherwise AML paths won't be valid anymore.
return FixupTpm2DeviceName (RootNodeHandle, Name);
}
/** Build a SSDT table describing the TPM2 device.
The table created by this function must be freed by FreeSImpleTpm2DeviceTable.
@param [in] TpmDevInfo TPM2 device info to describe in the SSDT table.
@param [in] Name The Name to give to the Device.
Must be a NULL-terminated ASL NameString
e.g.: "DEV0", "DV15.DEV0", etc.
@param [in] Uid UID for the TPM2 device
@param [out] Table If success, pointer to the created SSDT table.
@retval EFI_SUCCESS Table generated successfully.
@retval EFI_INVALID_PARAMETER A parameter is invalid.
@retval EFI_NOT_FOUND Could not find information.
@retval EFI_OUT_OF_RESOURCES Could not allocate memory.
**/
EFI_STATUS
EFIAPI
BuildTpm2DeviceTable (
IN CONST CM_ARCH_COMMON_TPM2_DEVICE_INFO *TpmDevInfo,
IN CONST CHAR8 *Name,
IN CONST UINT64 Uid,
OUT EFI_ACPI_DESCRIPTION_HEADER **Table
)
{
EFI_STATUS Status;
EFI_STATUS Status1;
AML_ROOT_NODE_HANDLE RootNodeHandle;
ASSERT (TpmDevInfo != NULL);
ASSERT (Name != NULL);
ASSERT (Table != NULL);
// Parse the Tpm2 Device Table Template.
Status = AmlParseDefinitionBlock (
(EFI_ACPI_DESCRIPTION_HEADER *)tpm2devicetabletemplate_aml_code,
&RootNodeHandle
);
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_ERROR,
"ERROR: TPM2-DEVICE-FIXUP:"
" Failed to parse SSDT TPM2 device Template. Status = %r\n",
Status
));
return Status;
}
// Fixup the template values.
Status = FixupTpm2DeviceInfo (
RootNodeHandle,
TpmDevInfo,
Name,
Uid
);
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_ERROR,
"ERROR: TPM2-DEVICE-FIXUP: Failed to fixup SSDT TPM2 Device Table."
" Status = %r\n",
Status
));
goto ExitHandler;
}
// Serialize the tree.
Status = AmlSerializeDefinitionBlock (
RootNodeHandle,
Table
);
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_ERROR,
"ERROR: TPM2-DEVICE-FIXUP: Failed to Serialize SSDT Table Data."
" Status = %r\n",
Status
));
}
ExitHandler:
// Cleanup
if (RootNodeHandle != NULL) {
Status1 = AmlDeleteTree (RootNodeHandle);
if (EFI_ERROR (Status1)) {
DEBUG ((
DEBUG_ERROR,
"ERROR: TPM2-DEVICE-FIXUP: Failed to cleanup AML tree."
" Status = %r\n",
Status1
));
// If Status was success but we failed to delete the AML Tree
// return Status1 else return the original error code, i.e. Status.
if (!EFI_ERROR (Status)) {
return Status1;
}
}
}
return Status;
}
/** Free an Tpm2 device table previously created by
the BuildTpm2DeviceTable function.
@param [in] Table Pointer to a Tpm2 Device table allocated by
the BuildTpm2DeviceTable function.
**/
VOID
EFIAPI
FreeTpm2DeviceTable (
IN EFI_ACPI_DESCRIPTION_HEADER *Table
)
{
ASSERT (Table != NULL);
FreePool (Table);
}

View File

@@ -0,0 +1,33 @@
## @file
# Tpm2 Device table generating library
#
# Copyright (c) 2025, Arm Limited. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
##
[Defines]
INF_VERSION = 0x0001001B
BASE_NAME = DynamicTpm2DeviceTableLib
FILE_GUID = b09d0390-0400-11f0-a447-cfc17b482322
VERSION_STRING = 1.0
MODULE_TYPE = DXE_DRIVER
LIBRARY_CLASS = Tpm2DeviceTableLib
[Sources]
Tpm2DeviceTableLib.c
Tpm2DeviceTableTemplate.asl
[Packages.common]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
EmbeddedPkg/EmbeddedPkg.dec
DynamicTablesPkg/DynamicTablesPkg.dec
[Packages.ARM, Packages.AARCH64]
ArmPkg/ArmPkg.dec
[LibraryClasses]
AcpiHelperLib
AmlLib
BaseLib

View File

@@ -0,0 +1,44 @@
/** @file
TPM2 Device Table Template
Copyright (c) 2025, ARM Ltd. All rights reserved.<BR>
All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
@par Reference(s)
- TCG ACPI Specification
- TCG PC Client Platform Firmware Profile Specification
@par Glossary:
- {template} - Data fixed up using AML Fixup APIs.
**/
DefinitionBlock("Tpm2DeviceTableTemplate.aml", "SSDT", 2, "ARMLTD", "TPM2CRB", 1) {
Scope(_SB) {
Device (TPM0) { // {template}
Name (_HID, "MSFT0101")
Name (_UID, 0) // {template}
Name (_CRS, ResourceTemplate () {
QWordMemory (
ResourceProducer,
PosDecode,
MinFixed,
MaxFixed,
NonCacheable,
ReadWrite,
0x0000000000000000, // Granularity
0x00000000FFDFB000, // Range Minimum // {template}
0x00000000FFDFFFFF, // Range Maximum // {template}
0x0000000000000000, // Translation Offset
0x0000000000005000, // Length // {template}
,
,
,
AddressRangeReserved,
TypeStatic
) // QWordMemory
}) // Name
} // Device
} // Scope(_SB)
}