]> xenbits.xensource.com Git - people/aperard/ovmf.git/commitdiff
DynamicTablesPkg: Adds ACPI SSDT HPET table generator
authorAbdul Lateef Attar <AbdulLateef.Attar@amd.com>
Fri, 6 Sep 2024 05:15:07 +0000 (05:15 +0000)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Wed, 18 Sep 2024 07:53:07 +0000 (07:53 +0000)
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>
DynamicTablesPkg/DynamicTables.dsc.inc
DynamicTablesPkg/Include/AcpiTableGenerator.h
DynamicTablesPkg/Library/Acpi/X64/AcpiSsdtHpetLib/AcpiSsdtHpetLib.c [new file with mode: 0644]
DynamicTablesPkg/Library/Acpi/X64/AcpiSsdtHpetLib/AcpiSsdtHpetLib.inf [new file with mode: 0644]

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