summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAbdul Lateef Attar <AbdulLateef.Attar@amd.com>2024-09-06 05:15:07 +0000
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2024-09-18 07:53:07 +0000
commit5901f19a877c87de73f6b28265ad5db60b2239e1 (patch)
treef665e098ea3aee8bb2d10604570339d6322270a0
parentfada1cea46a80b5585af0e842b6870514c5eaf09 (diff)
downloadedk2-5901f19a877c87de73f6b28265ad5db60b2239e1.tar.gz
DynamicTablesPkg: Adds ACPI SSDT HPET table generator
Adds X64 ACPI SSDT HPET table generator library. Updates acpi standard table enum with hpet. Generate ACPI HPET device as per specification. Cc: Sami Mujawar <Sami.Mujawar@arm.com> Cc: Pierre Gondois <pierre.gondois@arm.com> Signed-off-by: Abdul Lateef Attar <AbdulLateef.Attar@amd.com>
-rw-r--r--DynamicTablesPkg/DynamicTables.dsc.inc2
-rw-r--r--DynamicTablesPkg/Include/AcpiTableGenerator.h1
-rw-r--r--DynamicTablesPkg/Library/Acpi/X64/AcpiSsdtHpetLib/AcpiSsdtHpetLib.c428
-rw-r--r--DynamicTablesPkg/Library/Acpi/X64/AcpiSsdtHpetLib/AcpiSsdtHpetLib.inf31
4 files changed, 462 insertions, 0 deletions
diff --git a/DynamicTablesPkg/DynamicTables.dsc.inc b/DynamicTablesPkg/DynamicTables.dsc.inc
index bbfc4c20b9..c9bfa756c7 100644
--- a/DynamicTablesPkg/DynamicTables.dsc.inc
+++ b/DynamicTablesPkg/DynamicTables.dsc.inc
@@ -57,6 +57,7 @@
#
DynamicTablesPkg/Library/Acpi/X64/AcpiWsmtLib/AcpiWsmtLib.inf
DynamicTablesPkg/Library/Acpi/X64/AcpiHpetLib/AcpiHpetLib.inf
+ DynamicTablesPkg/Library/Acpi/X64/AcpiSsdtHpetLib/AcpiSsdtHpetLib.inf
#
# Dynamic Table Factory Dxe
@@ -68,6 +69,7 @@
NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiFadtLib/AcpiFadtLib.inf
NULL|DynamicTablesPkg/Library/Acpi/X64/AcpiWsmtLib/AcpiWsmtLib.inf
NULL|DynamicTablesPkg/Library/Acpi/X64/AcpiHpetLib/AcpiHpetLib.inf
+ NULL|DynamicTablesPkg/Library/Acpi/X64/AcpiSsdtHpetLib/AcpiSsdtHpetLib.inf
}
[Components.ARM, Components.AARCH64]
diff --git a/DynamicTablesPkg/Include/AcpiTableGenerator.h b/DynamicTablesPkg/Include/AcpiTableGenerator.h
index 8923fefd54..69c012e675 100644
--- a/DynamicTablesPkg/Include/AcpiTableGenerator.h
+++ b/DynamicTablesPkg/Include/AcpiTableGenerator.h
@@ -106,6 +106,7 @@ typedef enum StdAcpiTableId {
EStdAcpiTableIdTpm2, ///< TPM2 Generator
EStdAcpiTableIdWsmt, ///< WSMT Generator
EStdAcpiTableIdHpet, ///< HPET Generator
+ EStdAcpiTableIdSsdtHpet, ///< SSDT HPET Generator
EStdAcpiTableIdMax
} ESTD_ACPI_TABLE_ID;
diff --git a/DynamicTablesPkg/Library/Acpi/X64/AcpiSsdtHpetLib/AcpiSsdtHpetLib.c b/DynamicTablesPkg/Library/Acpi/X64/AcpiSsdtHpetLib/AcpiSsdtHpetLib.c
new file mode 100644
index 0000000000..8d4bed1ee0
--- /dev/null
+++ b/DynamicTablesPkg/Library/Acpi/X64/AcpiSsdtHpetLib/AcpiSsdtHpetLib.c
@@ -0,0 +1,428 @@
+/** @file
+
+ Generate ACPI HPET table for AMD platforms.
+
+ Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+
+ SPDX-License-Identifier BSD-2-Clause-Patent
+**/
+
+#include <IndustryStandard/HighPrecisionEventTimerTable.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.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/AmlLib/AmlLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+#include <Library/IoLib.h>
+
+/** This macro defines supported HPET page protection flags
+*/
+#define HPET_VALID_PAGE_PROTECTION \
+ (EFI_ACPI_NO_PAGE_PROTECTION | \
+ EFI_ACPI_4KB_PAGE_PROTECTION | \
+ EFI_ACPI_64KB_PAGE_PROTECTION)
+
+/** This macro expands to a function that retrieves the
+ HPET device information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+ EObjNameSpaceX64,
+ EX64ObjHpetInfo,
+ CM_X64_HPET_INFO
+ );
+
+/** Update HPET table information.
+
+ @param [in] CfgMgrProtocol Pointer to the Configuration Manager
+ Protocol Interface.
+ @param [in, out] ScopeNode The Scope Node for the HPET table.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.
+ @retval EFI_NOT_FOUND The required object was not found or
+ the HPET is not enabled.
+ @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
+ Manager is less than the Object size for the
+ requested object.
+ @retval EFI_UNSUPPORTED If invalid protection and oem flags provided.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+SsdtHpetUpdateTableInfo (
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
+ IN OUT AML_OBJECT_NODE_HANDLE ScopeNode
+ )
+{
+ CM_X64_HPET_INFO *HpetInfo;
+ EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_BLOCK_ID HpetBlockId;
+ EFI_STATUS Status;
+ AML_OBJECT_NODE_HANDLE CrsNode;
+ AML_OBJECT_NODE_HANDLE HpetNode;
+ UINT32 EisaId;
+
+ ASSERT (CfgMgrProtocol != NULL);
+
+ // Get the HPET information from the Platform Configuration Manager
+ Status = GetEX64ObjHpetInfo (
+ CfgMgrProtocol,
+ CM_NULL_TOKEN,
+ &HpetInfo,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: HPET: Failed to get HPET information." \
+ " Status = %r\n",
+ Status
+ ));
+ return Status;
+ }
+
+ DEBUG ((
+ DEBUG_INFO,
+ "HPET: Device base address = 0x%x\n"
+ " : Minimum clock tick in periodic mode = 0x%x\n"
+ " : Page protection and Oem flags = 0x%x\n",
+ HpetInfo->BaseAddressLower32Bit,
+ HpetInfo->MainCounterMinimumClockTickInPeriodicMode,
+ HpetInfo->PageProtectionAndOemAttribute
+ ));
+
+ // Validate the page protection flags bit0 to bit3
+ if (((HpetInfo->PageProtectionAndOemAttribute & 0xF) & ~HPET_VALID_PAGE_PROTECTION) != 0) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: HPET: unsupported page protection flags = 0x%x\n",
+ HpetInfo->PageProtectionAndOemAttribute
+ ));
+ ASSERT_EFI_ERROR (EFI_UNSUPPORTED);
+ return EFI_UNSUPPORTED;
+ }
+
+ // Get HPET Capabilities ID register value and test if HPET is enabled
+ HpetBlockId.Uint32 = MmioRead32 (HpetInfo->BaseAddressLower32Bit);
+
+ // If mmio address is not mapped
+ if ((HpetBlockId.Uint32 == MAX_UINT32) || (HpetBlockId.Uint32 == 0)) {
+ DEBUG ((DEBUG_ERROR, "HPET Capabilities register read failed.\n"));
+ ASSERT_EFI_ERROR (EFI_NOT_FOUND);
+ return EFI_NOT_FOUND;
+ }
+
+ // Validate Reserved and Revision ID
+ if (HpetBlockId.Bits.Reserved != 0) {
+ DEBUG ((DEBUG_ERROR, "HPET Reserved bit is set.\n"));
+ ASSERT_EFI_ERROR (EFI_UNSUPPORTED);
+ return EFI_UNSUPPORTED;
+ }
+
+ if (HpetBlockId.Bits.Revision == 0) {
+ DEBUG ((DEBUG_ERROR, "HPET Revision is not set.\n"));
+ ASSERT_EFI_ERROR (EFI_UNSUPPORTED);
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = AmlCodeGenDevice ("HPET", ScopeNode, &HpetNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ Status = AmlGetEisaIdFromString ("PNP0103", &EisaId);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ Status = AmlCodeGenNameInteger ("_HID", EisaId, HpetNode, NULL);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ Status = AmlCodeGenNameInteger ("_UID", 0x00, HpetNode, NULL);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ Status = AmlCodeGenNameResourceTemplate ("_CRS", HpetNode, &CrsNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ Status = AmlCodeGenRdMemory32Fixed (
+ FALSE,
+ HpetInfo->BaseAddressLower32Bit,
+ SIZE_1KB,
+ CrsNode,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ if ((HpetInfo->PageProtectionAndOemAttribute & 0xF) != 0) {
+ Status = AmlCodeGenNameInteger (
+ "PAGE",
+ (HpetInfo->PageProtectionAndOemAttribute & 0xF),
+ HpetNode,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+ }
+
+ if ((HpetInfo->PageProtectionAndOemAttribute >> 4) != 0) {
+ Status = AmlCodeGenNameInteger (
+ "ATTR",
+ (HpetInfo->PageProtectionAndOemAttribute >> 4),
+ HpetNode,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+ }
+
+ return Status;
+}
+
+/** Construct the SSDT HPET table.
+
+ This function invokes the Configuration Manager protocol interface
+ to get the required information for generating the ACPI table.
+
+ If this function allocates any resources then they must be freed
+ in the FreeXXXXTableResources function.
+
+ @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 [out] Table Pointer to the constructed ACPI Table.
+
+ @retval EFI_SUCCESS Table generated successfully.
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.
+ @retval EFI_NOT_FOUND The required object was not found.
+ @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
+ Manager is less than the Object size for the
+ requested object.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+BuildSsdtHpetTable (
+ 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
+ )
+{
+ EFI_STATUS Status;
+ AML_ROOT_NODE_HANDLE RootNode;
+ AML_OBJECT_NODE_HANDLE ScopeNode;
+
+ ASSERT (This != NULL);
+ ASSERT (AcpiTableInfo != NULL);
+ ASSERT (CfgMgrProtocol != NULL);
+ ASSERT (Table != NULL);
+ ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+ ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
+
+ if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) ||
+ (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision))
+ {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: HPET: Requested table revision = %d, is not supported."
+ "Supported table revision: Minimum = %d, Maximum = %d\n",
+ AcpiTableInfo->AcpiTableRevision,
+ This->MinAcpiTableRevision,
+ This->AcpiTableRevision
+ ));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Table = NULL;
+
+ Status = AddSsdtAcpiHeader (
+ CfgMgrProtocol,
+ This,
+ AcpiTableInfo,
+ &RootNode
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = AmlCodeGenScope ("\\_SB_", RootNode, &ScopeNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ goto exit_handler;
+ }
+
+ // Update HPET table info
+ Status = SsdtHpetUpdateTableInfo (CfgMgrProtocol, ScopeNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ goto exit_handler;
+ }
+
+ Status = AmlSerializeDefinitionBlock (
+ RootNode,
+ Table
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-HPET: Failed to Serialize SSDT Table Data."
+ " Status = %r\n",
+ Status
+ ));
+ }
+
+exit_handler:
+ // Delete the RootNode and its attached children.
+ AmlDeleteTree (RootNode);
+ return Status;
+}
+
+/** Free any resources allocated for constructing the
+ SSDT HPET 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, out] Table Pointer to the ACPI Table.
+
+ @retval EFI_SUCCESS The resources were freed successfully.
+ @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+FreeSsdtHpetTableResources (
+ 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
+ )
+{
+ ASSERT (This != NULL);
+ ASSERT (AcpiTableInfo != NULL);
+ ASSERT (CfgMgrProtocol != NULL);
+ ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+ ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
+
+ if ((Table == NULL) || (*Table == NULL)) {
+ DEBUG ((DEBUG_ERROR, "ERROR: SSDT-HPET: Invalid Table Pointer\n"));
+ ASSERT ((Table != NULL) && (*Table != NULL));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FreePool (*Table);
+ *Table = NULL;
+ return EFI_SUCCESS;
+}
+
+/** This macro defines the HPET Table Generator revision.
+*/
+#define HPET_GENERATOR_REVISION CREATE_REVISION (1, 0)
+
+/** The interface for the HPET Table Generator.
+*/
+STATIC
+CONST
+ACPI_TABLE_GENERATOR SsdtHpetGenerator = {
+ // Generator ID
+ CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSsdtHpet),
+ // Generator Description
+ L"ACPI.STD.SSDT.HPET.GENERATOR",
+ // ACPI Table Signature
+ EFI_ACPI_6_5_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE,
+ // ACPI Table Revision supported by this Generator
+ 0,
+ // Minimum supported ACPI Table Revision
+ 0,
+ // Creator ID
+ TABLE_GENERATOR_CREATOR_ID,
+ // Creator Revision
+ HPET_GENERATOR_REVISION,
+ // Build Table function
+ BuildSsdtHpetTable,
+ // Free Resource function
+ FreeSsdtHpetTableResources,
+ // Extended build function not needed
+ NULL,
+ // Extended build function not implemented by the generator.
+ // Hence extended free resource function is not required.
+ NULL
+};
+
+/** Register the Generator with the ACPI Table Factory.
+
+ @param [in] ImageHandle The handle to the image.
+ @param [in] SystemTable Pointer to the System Table.
+
+ @retval EFI_SUCCESS The Generator is registered.
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.
+ @retval EFI_ALREADY_STARTED The Generator for the Table ID
+ is already registered.
+**/
+EFI_STATUS
+EFIAPI
+AcpiSsdtHpetLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = RegisterAcpiTableGenerator (&SsdtHpetGenerator);
+ DEBUG ((DEBUG_INFO, "HPET: Register Generator. Status = %r\n", Status));
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/** Deregister the Generator from the ACPI Table Factory.
+
+ @param [in] ImageHandle The handle to the image.
+ @param [in] SystemTable Pointer to the System Table.
+
+ @retval EFI_SUCCESS The Generator is deregistered.
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.
+ @retval EFI_NOT_FOUND The Generator is not registered.
+**/
+EFI_STATUS
+EFIAPI
+AcpiSsdtHpetLibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = DeregisterAcpiTableGenerator (&SsdtHpetGenerator);
+ DEBUG ((DEBUG_INFO, "HPET: Deregister Generator. Status = %r\n", Status));
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
diff --git a/DynamicTablesPkg/Library/Acpi/X64/AcpiSsdtHpetLib/AcpiSsdtHpetLib.inf b/DynamicTablesPkg/Library/Acpi/X64/AcpiSsdtHpetLib/AcpiSsdtHpetLib.inf
new file mode 100644
index 0000000000..a47e67eedf
--- /dev/null
+++ b/DynamicTablesPkg/Library/Acpi/X64/AcpiSsdtHpetLib/AcpiSsdtHpetLib.inf
@@ -0,0 +1,31 @@
+## @file
+# Creates ACPI SSDT HPET device for AMD platforms.
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 1.30
+ BASE_NAME = AcpiSsdtHpetLib
+ FILE_GUID = CEC214FF-A9F1-4C3F-B084-BC8AFBEE7EA2
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = NULL|DXE_DRIVER
+ CONSTRUCTOR = AcpiSsdtHpetLibConstructor
+ DESTRUCTOR = AcpiSsdtHpetLibDestructor
+
+[Sources]
+ AcpiSsdtHpetLib.c
+
+[Packages]
+ DynamicTablesPkg/DynamicTablesPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ IoLib