]> xenbits.xensource.com Git - people/aperard/ovmf.git/commitdiff
DynamicTablesPkg: Adds ACPI HPET table generator
authorAbdul Lateef Attar <AbdulLateef.Attar@amd.com>
Tue, 3 Sep 2024 09:46:36 +0000 (09:46 +0000)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Wed, 18 Sep 2024 07:53:07 +0000 (07:53 +0000)
Adds X64 ACPI HPET table generator library.
Updates acpi standard table enum with hpet.
Updates X64 namespace object.
Updates the object parser.
Updates the Readme.

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/DynamicTablesPkg.ci.yaml
DynamicTablesPkg/Include/AcpiTableGenerator.h
DynamicTablesPkg/Include/X64NameSpaceObjects.h
DynamicTablesPkg/Library/Acpi/X64/AcpiHpetLib/AcpiHpetLib.c [new file with mode: 0644]
DynamicTablesPkg/Library/Acpi/X64/AcpiHpetLib/AcpiHpetLib.inf [new file with mode: 0644]
DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c
DynamicTablesPkg/Readme.md

index f4866c2dd7403176410483744224830003556988..bbfc4c20b96d28e1caccb9951e745b4244aafb48 100644 (file)
@@ -56,6 +56,7 @@
   # Generators (IA32/X64 specific)\r
   #\r
   DynamicTablesPkg/Library/Acpi/X64/AcpiWsmtLib/AcpiWsmtLib.inf\r
+  DynamicTablesPkg/Library/Acpi/X64/AcpiHpetLib/AcpiHpetLib.inf\r
 \r
   #\r
   # Dynamic Table Factory Dxe\r
@@ -66,6 +67,7 @@
       #   Common\r
       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
   }\r
 \r
 [Components.ARM, Components.AARCH64]\r
index 07768ed648ea43c0adaff62dab03e153da6256c5..f7c8897fcbbe222f6ff766a4e6b184111305a9a0 100644 (file)
            "lgreater",\r
            "lless",\r
            "MPIDR",\r
+           "NAMESPACEID",\r
            "PASID",\r
            "PERIPHBASE",\r
            "phandle",\r
index d4ad603e2b856a01ca24e3693a10a745ddcb9f60..8923fefd54e8f98a37eb5274146044f4bd968c5e 100644 (file)
@@ -105,6 +105,7 @@ typedef enum StdAcpiTableId {
   EStdAcpiTableIdPcct,                          ///< PCCT Generator\r
   EStdAcpiTableIdTpm2,                          ///< TPM2 Generator\r
   EStdAcpiTableIdWsmt,                          ///< WSMT Generator\r
+  EStdAcpiTableIdHpet,                          ///< HPET Generator\r
   EStdAcpiTableIdMax\r
 } ESTD_ACPI_TABLE_ID;\r
 \r
index d897051d88b6f099a253359a5dd3264ed9a6e8c3..f153461be0cc9b7a62e827e8fa024c7a58e1f694 100644 (file)
@@ -32,7 +32,8 @@ typedef enum X64ObjectID {
   EX64ObjFadtResetBlockInfo,     ///<  8 - FADT Reset block info\r
   EX64ObjFadtMiscInfo,           ///<  9 - FADT Legacy fields info\r
   EX64ObjWsmtFlagsInfo,          ///< 10 - WSMT protection flags info\r
-  EX64ObjMax                     ///< 11 - Maximum Object ID\r
+  EX64ObjHpetInfo,               ///< 11 - HPET device info\r
+  EX64ObjMax                     ///< 12 - Maximum Object ID\r
 } EX64_OBJECT_ID;\r
 \r
 /** A structure that describes the\r
@@ -177,4 +178,14 @@ typedef struct CmX64WsmtFlagsInfo {
   UINT32    ProtectionFlags;\r
 } CM_X64_WSMT_FLAGS_INFO;\r
 \r
+/**\r
+  A structure that describes the HPET device information.\r
+\r
+  ID: EX64ObjHpetInfo\r
+*/\r
+typedef struct CmX64HpetInfo {\r
+  UINT32    BaseAddressLower32Bit;\r
+  UINT16    MainCounterMinimumClockTickInPeriodicMode;\r
+  UINT8     PageProtectionAndOemAttribute;\r
+} CM_X64_HPET_INFO;\r
 #endif // X64_NAMESPACE_OBJECTS_H_\r
diff --git a/DynamicTablesPkg/Library/Acpi/X64/AcpiHpetLib/AcpiHpetLib.c b/DynamicTablesPkg/Library/Acpi/X64/AcpiHpetLib/AcpiHpetLib.c
new file mode 100644 (file)
index 0000000..b53518d
--- /dev/null
@@ -0,0 +1,327 @@
+/** @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 <AcpiTableGenerator.h>\r
+#include <ConfigurationManagerHelper.h>\r
+#include <ConfigurationManagerObject.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/TableHelperLib.h>\r
+#include <Protocol/AcpiTable.h>\r
+#include <Protocol/ConfigurationManagerProtocol.h>\r
+#include <X64NameSpaceObjects.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
+/** The ACPI HPET Table.\r
+*/\r
+STATIC\r
+EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER  AcpiHpet = {\r
+  ACPI_HEADER (\r
+    EFI_ACPI_6_5_HIGH_PRECISION_EVENT_TIMER_TABLE_SIGNATURE,\r
+    EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER,\r
+    EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_REVISION\r
+    ),\r
+  // EventTimerBlockId,\r
+  0,\r
+  // BaseAddressLower32Bit\r
+  { EFI_ACPI_6_5_SYSTEM_MEMORY,                             64,0, EFI_ACPI_RESERVED_BYTE, 0 },\r
+  // HpetNumber\r
+  0,\r
+  // MainCounterMinimumClockTickInPeriodicMode\r
+  0,\r
+  // PageProtectionAndOemAttribute\r
+  EFI_ACPI_NO_PAGE_PROTECTION\r
+};\r
+\r
+/** Update HPET table information.\r
+\r
+  @param [in]  CfgMgrProtocol Pointer to the Configuration Manager\r
+                              Protocol Interface.\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
+HpetUpdateTableInfo (\r
+  IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *CONST  CfgMgrProtocol\r
+  )\r
+{\r
+  CM_X64_HPET_INFO                              *HpetInfo;\r
+  EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_BLOCK_ID  HpetBlockId;\r
+  EFI_STATUS                                    Status;\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
+  // Fill the Event Timer Block ID\r
+  AcpiHpet.EventTimerBlockId = HpetBlockId.Uint32;\r
+\r
+  // Fill the Base Address\r
+  AcpiHpet.BaseAddressLower32Bit.Address = HpetInfo->BaseAddressLower32Bit;\r
+\r
+  // Minimum clock tick in periodic mode\r
+  AcpiHpet.MainCounterMinimumClockTickInPeriodicMode = HpetInfo->MainCounterMinimumClockTickInPeriodicMode;\r
+\r
+  // Page protection and OEM attribute\r
+  AcpiHpet.PageProtectionAndOemAttribute = HpetInfo->PageProtectionAndOemAttribute;\r
+\r
+  return Status;\r
+}\r
+\r
+/** Construct the 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
+BuildHpetTable (\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
+\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 = AddAcpiHeader (\r
+             CfgMgrProtocol,\r
+             This,\r
+             (EFI_ACPI_DESCRIPTION_HEADER *)&AcpiHpet,\r
+             AcpiTableInfo,\r
+             sizeof (EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER)\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((\r
+      DEBUG_ERROR,\r
+      "ERROR: HPET: Failed to add ACPI header. Status = %r\n",\r
+      Status\r
+      ));\r
+    goto error_handler;\r
+  }\r
+\r
+  // Update HPET table info\r
+  Status = HpetUpdateTableInfo (CfgMgrProtocol);\r
+  if (EFI_ERROR (Status)) {\r
+    goto error_handler;\r
+  }\r
+\r
+  *Table = (EFI_ACPI_DESCRIPTION_HEADER *)&AcpiHpet;\r
+error_handler:\r
+  return Status;\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  HpetGenerator = {\r
+  // Generator ID\r
+  CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdHpet),\r
+  // Generator Description\r
+  L"ACPI.STD.HPET.GENERATOR",\r
+  // ACPI Table Signature\r
+  EFI_ACPI_6_5_HIGH_PRECISION_EVENT_TIMER_TABLE_SIGNATURE,\r
+  // ACPI Table Revision supported by this Generator\r
+  EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_REVISION,\r
+  // Minimum supported ACPI Table Revision\r
+  EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_REVISION,\r
+  // Creator ID\r
+  TABLE_GENERATOR_CREATOR_ID,\r
+  // Creator Revision\r
+  HPET_GENERATOR_REVISION,\r
+  // Build Table function\r
+  BuildHpetTable,\r
+  // No additional resources are allocated by the generator.\r
+  // Hence the Free Resource function is not required.\r
+  NULL,\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
+AcpiHpetLibConstructor (\r
+  IN  EFI_HANDLE        ImageHandle,\r
+  IN  EFI_SYSTEM_TABLE  *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  Status = RegisterAcpiTableGenerator (&HpetGenerator);\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
+AcpiHpetLibDestructor (\r
+  IN  EFI_HANDLE        ImageHandle,\r
+  IN  EFI_SYSTEM_TABLE  *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  Status = DeregisterAcpiTableGenerator (&HpetGenerator);\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/AcpiHpetLib/AcpiHpetLib.inf b/DynamicTablesPkg/Library/Acpi/X64/AcpiHpetLib/AcpiHpetLib.inf
new file mode 100644 (file)
index 0000000..3afc104
--- /dev/null
@@ -0,0 +1,31 @@
+## @file\r
+#  Creates ACPI HPET tables 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         = AcpiHpetLib\r
+  FILE_GUID         = 858FA64F-8C39-4D4F-A5F1-5DCD61CB79D4\r
+  MODULE_TYPE       = DXE_DRIVER\r
+  VERSION_STRING    = 1.0\r
+  LIBRARY_CLASS     = NULL|DXE_DRIVER\r
+  CONSTRUCTOR       = AcpiHpetLibConstructor\r
+  DESTRUCTOR        = AcpiHpetLibDestructor\r
+\r
+[Sources]\r
+  AcpiHpetLib.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
index c9737f67c3792c98c2e1dd3a3f2b3fbe3c696cf9..0f74f3d6b9a4f76c0bea849a0277ab6c369598e0 100644 (file)
@@ -856,6 +856,14 @@ STATIC CONST CM_OBJ_PARSER  CmX64ObjWsmtFlagsInfoParser[] = {
   { "WsmtFlags", 4, "0x%x", NULL }\r
 };\r
 \r
+/** A parser for EX64ObjHpetInfo.\r
+*/\r
+STATIC CONST CM_OBJ_PARSER  CmX64ObjHpetInfoParser[] = {\r
+  { "BaseAddressLower32Bit",                     4, "0x%x", NULL },\r
+  { "MainCounterMinimumClockTickInPeriodicMode", 2, "0x%x", NULL },\r
+  { "PageProtectionAndOemAttribute",             1, "0x%x", NULL }\r
+};\r
+\r
 /** A parser for X64 namespace objects.\r
 */\r
 STATIC CONST CM_OBJ_PARSER_ARRAY  X64NamespaceObjectParser[] = {\r
@@ -870,6 +878,7 @@ STATIC CONST CM_OBJ_PARSER_ARRAY  X64NamespaceObjectParser[] = {
   CM_PARSER_ADD_OBJECT (EX64ObjFadtResetBlockInfo,CmX64ObjFadtResetBlockInfoParser),\r
   CM_PARSER_ADD_OBJECT (EX64ObjFadtMiscInfo,      CmX64ObjFadtMiscInfoParser),\r
   CM_PARSER_ADD_OBJECT (EX64ObjWsmtFlagsInfo,     CmX64ObjWsmtFlagsInfoParser),\r
+  CM_PARSER_ADD_OBJECT (EX64ObjHpetInfo,          CmX64ObjHpetInfoParser),\r
   CM_PARSER_ADD_OBJECT_RESERVED (EX64ObjMax)\r
 };\r
 \r
index 84d7ca9fafd6e57133103f28d55fb4a805aa0ea5..7a3d499af8ff255a3e9ac9a2da44b59366cee855 100644 (file)
@@ -515,4 +515,5 @@ The CM_OBJECT_ID type is used to identify the Configuration Manager
 |   8   | Reset Block Info                          | |\r
 |   9   | Miscellaneous Block Info                  | |\r
 |  10   | Windows protection flag Info              | |\r
+|  11   | HPET device Info                          | |\r
 |  `*`  | All other values are reserved.            | |\r