]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Gtdt/GtdtParser.c
ShellPkg: Add acpiview tool to dump ACPI tables
[mirror_edk2.git] / ShellPkg / Library / UefiShellAcpiViewCommandLib / Parsers / Gtdt / GtdtParser.c
diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Gtdt/GtdtParser.c b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Gtdt/GtdtParser.c
new file mode 100644 (file)
index 0000000..ce96604
--- /dev/null
@@ -0,0 +1,293 @@
+/**\r
+  GTDT table parser\r
+\r
+  Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+  @par Reference(s):\r
+    - ACPI 6.2 Specification - Errata A, September 2017\r
+  **/\r
+\r
+#include <IndustryStandard/Acpi.h>\r
+#include <Library/UefiLib.h>\r
+#include "AcpiParser.h"\r
+#include "AcpiTableParser.h"\r
+\r
+// Local variables\r
+STATIC CONST UINT32* GtdtPlatformTimerCount;\r
+STATIC CONST UINT32* GtdtPlatformTimerOffset;\r
+STATIC CONST UINT8*  PlatformTimerType;\r
+STATIC CONST UINT16* PlatformTimerLength;\r
+STATIC CONST UINT32* GtBlockTimerCount;\r
+STATIC CONST UINT32* GtBlockTimerOffset;\r
+STATIC CONST UINT16* GtBlockLength;\r
+STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;\r
+\r
+/** This function validates the GT Block timer count.\r
+\r
+  @param [in] Ptr     Pointer to the start of the field data.\r
+  @param [in] Context Pointer to context specific information e.g. this\r
+                      could be a pointer to the ACPI table header.\r
+*/\r
+STATIC\r
+VOID\r
+EFIAPI\r
+ValidateGtBlockTimerCount (\r
+  IN UINT8* Ptr,\r
+  IN VOID*  Context\r
+  );\r
+\r
+/** An ACPI_PARSER array describing the ACPI GTDT Table.\r
+*/\r
+STATIC CONST ACPI_PARSER GtdtParser[] = {\r
+  PARSE_ACPI_HEADER (&AcpiHdrInfo),\r
+  {L"CntControlBase Physical Address", 8, 36, L"0x%lx", NULL, NULL,\r
+   NULL, NULL},\r
+  {L"Reserved", 4, 44, L"0x%x", NULL, NULL, NULL, NULL},\r
+  {L"Secure EL1 timer GSIV", 4, 48, L"0x%x", NULL, NULL, NULL, NULL},\r
+  {L"Secure EL1 timer FLAGS", 4, 52, L"0x%x", NULL, NULL, NULL, NULL},\r
+\r
+  {L"Non-Secure EL1 timer GSIV", 4, 56, L"0x%x", NULL, NULL, NULL, NULL},\r
+  {L"Non-Secure EL1 timer FLAGS", 4, 60, L"0x%x", NULL, NULL, NULL, NULL},\r
+\r
+  {L"Virtual timer GSIV", 4, 64, L"0x%x", NULL, NULL, NULL, NULL},\r
+  {L"Virtual timer FLAGS", 4, 68, L"0x%x", NULL, NULL, NULL, NULL},\r
+\r
+  {L"Non-Secure EL2 timer GSIV", 4, 72, L"0x%x", NULL, NULL, NULL, NULL},\r
+  {L"Non-Secure EL2 timer FLAGS", 4, 76, L"0x%x", NULL, NULL, NULL, NULL},\r
+\r
+  {L"CntReadBase Physical address", 8, 80, L"0x%lx", NULL, NULL, NULL, NULL},\r
+  {L"Platform Timer Count", 4, 88, L"%d", NULL,\r
+   (VOID**)&GtdtPlatformTimerCount, NULL, NULL},\r
+  {L"Platform Timer Offset", 4, 92, L"0x%x", NULL,\r
+   (VOID**)&GtdtPlatformTimerOffset, NULL, NULL}\r
+};\r
+\r
+/** An ACPI_PARSER array describing the Platform timer header.\r
+*/\r
+STATIC CONST ACPI_PARSER GtPlatformTimerHeaderParser[] = {\r
+  {L"Type", 1, 0, NULL, NULL, (VOID**)&PlatformTimerType, NULL, NULL},\r
+  {L"Length", 2, 1, NULL, NULL, (VOID**)&PlatformTimerLength, NULL, NULL},\r
+  {L"Reserved", 1, 3, NULL, NULL, NULL, NULL, NULL}\r
+};\r
+\r
+/** An ACPI_PARSER array describing the Platform GT Block.\r
+*/\r
+STATIC CONST ACPI_PARSER GtBlockParser[] = {\r
+  {L"Type", 1, 0, L"%d", NULL, NULL, NULL, NULL},\r
+  {L"Length", 2, 1, L"%d", NULL, (VOID**)&GtBlockLength, NULL, NULL},\r
+  {L"Reserved", 1, 3, L"%x", NULL, NULL, NULL, NULL},\r
+  {L"Physical address (CntCtlBase)", 8, 4, L"0x%lx", NULL, NULL, NULL, NULL},\r
+  {L"Timer Count", 4, 12, L"%d", NULL, (VOID**)&GtBlockTimerCount,\r
+   ValidateGtBlockTimerCount, NULL},\r
+  {L"Timer Offset", 4, 16, L"%d", NULL, (VOID**)&GtBlockTimerOffset, NULL,\r
+    NULL}\r
+};\r
+\r
+/** An ACPI_PARSER array describing the GT Block timer.\r
+*/\r
+STATIC CONST ACPI_PARSER GtBlockTimerParser[] = {\r
+  {L"Frame Number", 1, 0, L"%d", NULL, NULL, NULL, NULL},\r
+  {L"Reserved", 3, 1, L"%x %x %x", Dump3Chars, NULL, NULL, NULL},\r
+  {L"Physical address (CntBaseX)", 8, 4, L"0x%lx", NULL, NULL, NULL, NULL},\r
+  {L"Physical address (CntEL0BaseX)", 8, 12, L"0x%lx", NULL, NULL, NULL,\r
+    NULL},\r
+  {L"Physical Timer GSIV", 4, 20, L"0x%x", NULL, NULL, NULL, NULL},\r
+  {L"Physical Timer Flags", 4, 24, L"0x%x", NULL, NULL, NULL, NULL},\r
+  {L"Virtual Timer GSIV", 4, 28, L"0x%x", NULL, NULL, NULL, NULL},\r
+  {L"Virtual Timer Flags", 4, 32, L"0x%x", NULL, NULL, NULL, NULL},\r
+  {L"Common Flags", 4, 36, L"0x%x", NULL, NULL, NULL, NULL}\r
+};\r
+\r
+/** An ACPI_PARSER array describing the Platform Watchdog.\r
+*/\r
+STATIC CONST ACPI_PARSER SBSAGenericWatchdogParser[] = {\r
+  {L"Type", 1, 0, L"%d", NULL, NULL, NULL, NULL},\r
+  {L"Length", 2, 1, L"%d", NULL, NULL, NULL, NULL},\r
+  {L"Reserved", 1, 3, L"%x", NULL, NULL, NULL, NULL},\r
+  {L"RefreshFrame Physical address", 8, 4, L"0x%lx", NULL, NULL, NULL, NULL},\r
+  {L"ControlFrame Physical address", 8, 12, L"0x%lx", NULL, NULL, NULL, NULL},\r
+  {L"Watchdog Timer GSIV", 4, 20, L"0x%x", NULL, NULL, NULL, NULL},\r
+  {L"Watchdog Timer Flags", 4, 24, L"0x%x", NULL, NULL, NULL, NULL}\r
+};\r
+\r
+/** This function validates the GT Block timer count.\r
+\r
+  @param [in] Ptr     Pointer to the start of the field data.\r
+  @param [in] Context Pointer to context specific information e.g. this\r
+                      could be a pointer to the ACPI table header.\r
+*/\r
+STATIC\r
+VOID\r
+EFIAPI\r
+ValidateGtBlockTimerCount (\r
+  IN UINT8* Ptr,\r
+  IN VOID*  Context\r
+  )\r
+{\r
+  UINT32 BlockTimerCount = *(UINT32*)Ptr;\r
+  if (BlockTimerCount > 8) {\r
+    IncrementErrorCount ();\r
+    Print (\r
+      L"\nERROR: Timer Count = %d. Max Timer Count is 8.",\r
+      BlockTimerCount\r
+      );\r
+  }\r
+}\r
+\r
+/** This function parses the Platform GT Block.\r
+\r
+  @param [in] Ptr     Pointer to the start of the GT Block data.\r
+  @param [in] Length  Length of the GT Block structure.\r
+*/\r
+STATIC\r
+VOID\r
+DumpGTBlock (\r
+  IN UINT8* Ptr,\r
+  IN UINT16 Length\r
+  )\r
+{\r
+  UINT32 Index;\r
+  UINT32 Offset;\r
+  UINT16 GTBlockTimerLength;\r
+\r
+  Offset = ParseAcpi (\r
+             TRUE,\r
+             2,\r
+             "GT Block",\r
+             Ptr,\r
+             Length,\r
+             PARSER_PARAMS (GtBlockParser)\r
+             );\r
+  GTBlockTimerLength = (*GtBlockLength - Offset) / (*GtBlockTimerCount);\r
+  Length -= Offset;\r
+\r
+  if (*GtBlockTimerCount != 0) {\r
+    Ptr += (*GtBlockTimerOffset);\r
+    Index = 0;\r
+    while ((Index < (*GtBlockTimerCount)) && (Length >= GTBlockTimerLength)) {\r
+      Offset = ParseAcpi (\r
+                 TRUE,\r
+                 2,\r
+                 "GT Block Timer",\r
+                 Ptr,\r
+                 GTBlockTimerLength,\r
+                 PARSER_PARAMS (GtBlockTimerParser)\r
+                 );\r
+      // Increment by GT Block Timer structure size\r
+      Ptr += Offset;\r
+      Length -= Offset;\r
+      Index++;\r
+    }\r
+\r
+    if (Length != 0) {\r
+      IncrementErrorCount ();\r
+      Print (\r
+        L"ERROR:GT Block Timer length mismatch. Unparsed %d bytes.\n",\r
+        Length\r
+        );\r
+    }\r
+  }\r
+}\r
+\r
+/** This function parses the Platform Watchdog timer.\r
+\r
+  @param [in] Ptr     Pointer to the start of the watchdog timer data.\r
+  @param [in] Length  Length of the watchdog timer structure.\r
+*/\r
+STATIC\r
+VOID\r
+DumpWatchdogTimer (\r
+  IN UINT8* Ptr,\r
+  IN UINT16 Length\r
+  )\r
+{\r
+  ParseAcpi (\r
+    TRUE,\r
+    2,\r
+    "SBSA Generic Watchdog",\r
+    Ptr,\r
+    Length,\r
+    PARSER_PARAMS (SBSAGenericWatchdogParser)\r
+    );\r
+}\r
+\r
+/** This function parses the ACPI GTDT table.\r
+  When trace is enabled this function parses the GTDT table and\r
+  traces the ACPI table fields.\r
+\r
+  This function also parses the following platform timer structures:\r
+    - GT Block timer\r
+    - Watchdog timer\r
+\r
+  This function also performs validation of the ACPI table fields.\r
+\r
+  @param [in] Trace              If TRUE, trace the ACPI fields.\r
+  @param [in] Ptr                Pointer to the start of the buffer.\r
+  @param [in] AcpiTableLength    Length of the ACPI table.\r
+  @param [in] AcpiTableRevision  Revision of the ACPI table.\r
+*/\r
+VOID\r
+EFIAPI\r
+ParseAcpiGtdt (\r
+  IN BOOLEAN Trace,\r
+  IN UINT8*  Ptr,\r
+  IN UINT32  AcpiTableLength,\r
+  IN UINT8   AcpiTableRevision\r
+  )\r
+{\r
+  UINT32 Index;\r
+  UINT8* TimerPtr;\r
+\r
+  if (!Trace) {\r
+    return;\r
+  }\r
+\r
+  ParseAcpi (\r
+    TRUE,\r
+    0,\r
+    "GTDT",\r
+    Ptr,\r
+    AcpiTableLength,\r
+    PARSER_PARAMS (GtdtParser)\r
+    );\r
+\r
+  if (*GtdtPlatformTimerCount != 0) {\r
+    TimerPtr = Ptr + (*GtdtPlatformTimerOffset);\r
+    Index = 0;\r
+    do {\r
+      // Parse the Platform Timer Header\r
+      ParseAcpi (\r
+        FALSE,\r
+        0,\r
+        NULL,\r
+        TimerPtr,\r
+        4,  // GT Platform Timer structure header length.\r
+        PARSER_PARAMS (GtPlatformTimerHeaderParser)\r
+        );\r
+      switch (*PlatformTimerType) {\r
+        case EFI_ACPI_6_2_GTDT_GT_BLOCK:\r
+          DumpGTBlock (TimerPtr, *PlatformTimerLength);\r
+          break;\r
+        case EFI_ACPI_6_2_GTDT_SBSA_GENERIC_WATCHDOG:\r
+          DumpWatchdogTimer (TimerPtr, *PlatformTimerLength);\r
+          break;\r
+        default:\r
+          IncrementErrorCount ();\r
+          Print (\r
+            L"ERROR: INVALID Platform Timer Type = %d\n",\r
+            *PlatformTimerType\r
+            );\r
+          break;\r
+      } // switch\r
+      TimerPtr += (*PlatformTimerLength);\r
+      Index++;\r
+    } while (Index < *GtdtPlatformTimerCount);\r
+  }\r
+}\r