diff --git a/DynamicTablesPkg/DynamicTables.dsc.inc b/DynamicTablesPkg/DynamicTables.dsc.inc index 95b64076b7..d8c92dece5 100644 --- a/DynamicTablesPkg/DynamicTables.dsc.inc +++ b/DynamicTablesPkg/DynamicTables.dsc.inc @@ -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 diff --git a/DynamicTablesPkg/DynamicTablesPkg.ci.yaml b/DynamicTablesPkg/DynamicTablesPkg.ci.yaml index 5c4efb4035..56069e286f 100644 --- a/DynamicTablesPkg/DynamicTablesPkg.ci.yaml +++ b/DynamicTablesPkg/DynamicTablesPkg.ci.yaml @@ -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":[ diff --git a/DynamicTablesPkg/DynamicTablesPkg.dec b/DynamicTablesPkg/DynamicTablesPkg.dec index 87934c52cf..71e76e6233 100644 --- a/DynamicTablesPkg/DynamicTablesPkg.dec +++ b/DynamicTablesPkg/DynamicTablesPkg.dec @@ -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 } } diff --git a/DynamicTablesPkg/DynamicTablesPkg.dsc b/DynamicTablesPkg/DynamicTablesPkg.dsc index 823b3fe624..d8c04779b9 100644 --- a/DynamicTablesPkg/DynamicTablesPkg.dsc +++ b/DynamicTablesPkg/DynamicTablesPkg.dsc @@ -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 diff --git a/DynamicTablesPkg/Include/Library/Tpm2DeviceTableLib.h b/DynamicTablesPkg/Include/Library/Tpm2DeviceTableLib.h new file mode 100644 index 0000000000..5da8117e84 --- /dev/null +++ b/DynamicTablesPkg/Include/Library/Tpm2DeviceTableLib.h @@ -0,0 +1,50 @@ +/** @file + Tpm2 device table generating Library + + Copyright (c) 2025, Arm Limited. All rights reserved.
+ + 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_ diff --git a/DynamicTablesPkg/Library/Acpi/Common/AcpiTpm2Lib/AcpiTpm2Lib.inf b/DynamicTablesPkg/Library/Acpi/Common/AcpiTpm2Lib/AcpiTpm2Lib.inf index ee50fc6f70..1623e4d2fe 100644 --- a/DynamicTablesPkg/Library/Acpi/Common/AcpiTpm2Lib/AcpiTpm2Lib.inf +++ b/DynamicTablesPkg/Library/Acpi/Common/AcpiTpm2Lib/AcpiTpm2Lib.inf @@ -26,4 +26,9 @@ MdePkg/MdePkg.dec [LibraryClasses] + AcpiHelperLib BaseLib + Tpm2DeviceTableLib + +[FixedPcd] + gEdkiiDynamicTablesPkgTokenSpaceGuid.PcdGenTpm2DeviceTable diff --git a/DynamicTablesPkg/Library/Acpi/Common/AcpiTpm2Lib/Tpm2Generator.c b/DynamicTablesPkg/Library/Acpi/Common/AcpiTpm2Lib/Tpm2Generator.c index c743e20c6f..9e39eb54fd 100644 --- a/DynamicTablesPkg/Library/Acpi/Common/AcpiTpm2Lib/Tpm2Generator.c +++ b/DynamicTablesPkg/Library/Acpi/Common/AcpiTpm2Lib/Tpm2Generator.c @@ -20,13 +20,16 @@ #include #include #include +#include #include // Module specific include files. #include #include #include +#include #include +#include #include #include @@ -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. diff --git a/DynamicTablesPkg/Library/Common/Tpm2DeviceTableLib/Tpm2DeviceTableLib.c b/DynamicTablesPkg/Library/Common/Tpm2DeviceTableLib/Tpm2DeviceTableLib.c new file mode 100644 index 0000000000..22bd0018a8 --- /dev/null +++ b/DynamicTablesPkg/Library/Common/Tpm2DeviceTableLib/Tpm2DeviceTableLib.c @@ -0,0 +1,329 @@ +/** @file + Tpm2 device table generating Library + + Copyright (c) 2025, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Reference(s): + - TCG ACPI specification. + (https://trustedcomputinggroup.org/resource/tcg-acpi-specification/) +**/ +#include +#include +#include +#include +#include +#include +#include + +#include + +// Module specific include files. +#include +#include +#include +#include +#include +#include + +/** 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); +} diff --git a/DynamicTablesPkg/Library/Common/Tpm2DeviceTableLib/Tpm2DeviceTableLib.inf b/DynamicTablesPkg/Library/Common/Tpm2DeviceTableLib/Tpm2DeviceTableLib.inf new file mode 100644 index 0000000000..6c69a9c24a --- /dev/null +++ b/DynamicTablesPkg/Library/Common/Tpm2DeviceTableLib/Tpm2DeviceTableLib.inf @@ -0,0 +1,33 @@ +## @file +# Tpm2 Device table generating library +# +# Copyright (c) 2025, Arm Limited. All rights reserved.
+# +# 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 diff --git a/DynamicTablesPkg/Library/Common/Tpm2DeviceTableLib/Tpm2DeviceTableTemplate.asl b/DynamicTablesPkg/Library/Common/Tpm2DeviceTableLib/Tpm2DeviceTableTemplate.asl new file mode 100644 index 0000000000..9b9976794a --- /dev/null +++ b/DynamicTablesPkg/Library/Common/Tpm2DeviceTableLib/Tpm2DeviceTableTemplate.asl @@ -0,0 +1,44 @@ +/** @file + TPM2 Device Table Template + + Copyright (c) 2025, ARM Ltd. All rights reserved.
+ 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) +}