]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Gtdt/GtdtParser.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / ShellPkg / Library / UefiShellAcpiViewCommandLib / Parsers / Gtdt / GtdtParser.c
index f31c4a2761751c58d4b1d3eb75084e24ec318e7f..e62927098a010a0e1dad8361dcfc6559d32dcebf 100644 (file)
@@ -1,27 +1,30 @@
 /** @file\r
   GTDT table parser\r
 \r
-  Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.\r
+  Copyright (c) 2016 - 2021, ARM Limited. All rights reserved.\r
   SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
   @par Reference(s):\r
-    - ACPI 6.2 Specification - Errata A, September 2017\r
+    - ACPI 6.4 Specification - January 2021\r
   **/\r
 \r
 #include <IndustryStandard/Acpi.h>\r
 #include <Library/UefiLib.h>\r
 #include "AcpiParser.h"\r
 #include "AcpiTableParser.h"\r
+#include "AcpiViewConfig.h"\r
+\r
+// "The number of GT Block Timers must be less than or equal to 8"\r
+#define GT_BLOCK_TIMER_COUNT_MAX  8\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
+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 ACPI_DESCRIPTION_HEADER_INFO  AcpiHdrInfo;\r
 \r
 /**\r
   This function validates the GT Block timer count.\r
@@ -34,170 +37,188 @@ STATIC
 VOID\r
 EFIAPI\r
 ValidateGtBlockTimerCount (\r
-  IN UINT8* Ptr,\r
-  IN VOID*  Context\r
-  );\r
+  IN UINT8  *Ptr,\r
+  IN VOID   *Context\r
+  )\r
+{\r
+  UINT32  BlockTimerCount;\r
+\r
+  BlockTimerCount = *(UINT32 *)Ptr;\r
+\r
+  if (BlockTimerCount > GT_BLOCK_TIMER_COUNT_MAX) {\r
+    IncrementErrorCount ();\r
+    Print (\r
+      L"\nERROR: Timer Count = %d. Max Timer Count is %d.",\r
+      BlockTimerCount,\r
+      GT_BLOCK_TIMER_COUNT_MAX\r
+      );\r
+  }\r
+}\r
+\r
+/**\r
+  This function validates the GT Frame Number.\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
+ValidateGtFrameNumber (\r
+  IN UINT8  *Ptr,\r
+  IN VOID   *Context\r
+  )\r
+{\r
+  UINT8  FrameNumber;\r
+\r
+  FrameNumber = *(UINT8 *)Ptr;\r
+\r
+  if (FrameNumber >= GT_BLOCK_TIMER_COUNT_MAX) {\r
+    IncrementErrorCount ();\r
+    Print (\r
+      L"\nERROR: GT Frame Number = %d. GT Frame Number must be in range 0-%d.",\r
+      FrameNumber,\r
+      GT_BLOCK_TIMER_COUNT_MAX - 1\r
+      );\r
+  }\r
+}\r
 \r
 /**\r
   An ACPI_PARSER array describing the ACPI GTDT Table.\r
 **/\r
-STATIC CONST ACPI_PARSER GtdtParser[] = {\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
+  { 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
+  { L"Virtual EL2 Timer GSIV",        4,      96,  L"0x%x",  NULL, NULL,NULL,  NULL },\r
+  { L"Virtual EL2 Timer Flags",       4,      100, L"0x%x",  NULL, NULL,NULL,  NULL }\r
 };\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
+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
 /**\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
+STATIC CONST ACPI_PARSER  GtBlockParser[] = {\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"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
 /**\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
+STATIC CONST ACPI_PARSER  GtBlockTimerParser[] = {\r
+  { L"Frame Number",                   1, 0,  L"%d",       NULL,       NULL, ValidateGtFrameNumber, 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
 /**\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
+STATIC CONST ACPI_PARSER  ArmGenericWatchdogParser[] = {\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
 /**\r
-  This function validates the GT Block timer count.\r
+  This function parses the Platform GT Block.\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
+  @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
-EFIAPI\r
-ValidateGtBlockTimerCount (\r
-  IN UINT8* Ptr,\r
-  IN VOID*  Context\r
+DumpGTBlock (\r
+  IN UINT8   *Ptr,\r
+  IN UINT16  Length\r
   )\r
 {\r
-  UINT32 BlockTimerCount;\r
+  UINT32  Index;\r
+  UINT32  Offset;\r
 \r
-  BlockTimerCount = *(UINT32*)Ptr;\r
+  ParseAcpi (\r
+    TRUE,\r
+    2,\r
+    "GT Block",\r
+    Ptr,\r
+    Length,\r
+    PARSER_PARAMS (GtBlockParser)\r
+    );\r
 \r
-  if (BlockTimerCount > 8) {\r
+  // Check if the values used to control the parsing logic have been\r
+  // successfully read.\r
+  if ((GtBlockTimerCount == NULL) ||\r
+      (GtBlockTimerOffset == NULL))\r
+  {\r
     IncrementErrorCount ();\r
     Print (\r
-      L"\nERROR: Timer Count = %d. Max Timer Count is 8.",\r
-      BlockTimerCount\r
+      L"ERROR: Insufficient GT Block Structure length. Length = %d.\n",\r
+      Length\r
       );\r
+    return;\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 UINT32 Length\r
-  )\r
-{\r
-  UINT32 Index;\r
-  UINT32 Offset;\r
-  UINT32 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
+  Offset = *GtBlockTimerOffset;\r
+  Index  = 0;\r
+\r
+  // Parse the specified number of GT Block Timer Structures or the GT Block\r
+  // Structure buffer length. Whichever is minimum.\r
+  while ((Index++ < *GtBlockTimerCount) &&\r
+         (Offset < Length))\r
+  {\r
+    Offset += ParseAcpi (\r
+                TRUE,\r
+                2,\r
+                "GT Block Timer",\r
+                Ptr + Offset,\r
+                Length - Offset,\r
+                PARSER_PARAMS (GtBlockTimerParser)\r
+                );\r
   }\r
 }\r
 \r
@@ -210,17 +231,17 @@ DumpGTBlock (
 STATIC\r
 VOID\r
 DumpWatchdogTimer (\r
-  IN UINT8Ptr,\r
-  IN UINT16 Length\r
+  IN UINT8   *Ptr,\r
+  IN UINT16  Length\r
   )\r
 {\r
   ParseAcpi (\r
     TRUE,\r
     2,\r
-    "SBSA Generic Watchdog",\r
+    "Arm Generic Watchdog",\r
     Ptr,\r
     Length,\r
-    PARSER_PARAMS (SBSAGenericWatchdogParser)\r
+    PARSER_PARAMS (ArmGenericWatchdogParser)\r
     );\r
 }\r
 \r
@@ -243,14 +264,15 @@ DumpWatchdogTimer (
 VOID\r
 EFIAPI\r
 ParseAcpiGtdt (\r
-  IN BOOLEAN Trace,\r
-  IN UINT8*  Ptr,\r
-  IN UINT32  AcpiTableLength,\r
-  IN UINT8   AcpiTableRevision\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
+  UINT32  Index;\r
+  UINT32  Offset;\r
+  UINT8   *TimerPtr;\r
 \r
   if (!Trace) {\r
     return;\r
@@ -265,36 +287,84 @@ ParseAcpiGtdt (
     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
+  // Check if the values used to control the parsing logic have been\r
+  // successfully read.\r
+  if ((GtdtPlatformTimerCount == NULL) ||\r
+      (GtdtPlatformTimerOffset == NULL))\r
+  {\r
+    IncrementErrorCount ();\r
+    Print (\r
+      L"ERROR: Insufficient table length. AcpiTableLength = %d.\n",\r
+      AcpiTableLength\r
+      );\r
+    return;\r
   }\r
+\r
+  TimerPtr = Ptr + *GtdtPlatformTimerOffset;\r
+  Offset   = *GtdtPlatformTimerOffset;\r
+  Index    = 0;\r
+\r
+  // Parse the specified number of Platform Timer Structures or the GTDT\r
+  // buffer length. Whichever is minimum.\r
+  while ((Index++ < *GtdtPlatformTimerCount) &&\r
+         (Offset < AcpiTableLength))\r
+  {\r
+    // Parse the Platform Timer Header to obtain Length and Type\r
+    ParseAcpi (\r
+      FALSE,\r
+      0,\r
+      NULL,\r
+      TimerPtr,\r
+      AcpiTableLength - Offset,\r
+      PARSER_PARAMS (GtPlatformTimerHeaderParser)\r
+      );\r
+\r
+    // Check if the values used to control the parsing logic have been\r
+    // successfully read.\r
+    if ((PlatformTimerType == NULL) ||\r
+        (PlatformTimerLength == NULL))\r
+    {\r
+      IncrementErrorCount ();\r
+      Print (\r
+        L"ERROR: Insufficient remaining table buffer length to read the " \\r
+        L"Platform Timer Structure header. Length = %d.\n",\r
+        AcpiTableLength - Offset\r
+        );\r
+      return;\r
+    }\r
+\r
+    // Validate Platform Timer Structure length\r
+    if ((*PlatformTimerLength == 0) ||\r
+        ((Offset + (*PlatformTimerLength)) > AcpiTableLength))\r
+    {\r
+      IncrementErrorCount ();\r
+      Print (\r
+        L"ERROR: Invalid Platform Timer Structure length. " \\r
+        L"Length = %d. Offset = %d. AcpiTableLength = %d.\n",\r
+        *PlatformTimerLength,\r
+        Offset,\r
+        AcpiTableLength\r
+        );\r
+      return;\r
+    }\r
+\r
+    switch (*PlatformTimerType) {\r
+      case EFI_ACPI_6_4_GTDT_GT_BLOCK:\r
+        DumpGTBlock (TimerPtr, *PlatformTimerLength);\r
+        break;\r
+      case EFI_ACPI_6_4_GTDT_ARM_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
+\r
+    TimerPtr += *PlatformTimerLength;\r
+    Offset   += *PlatformTimerLength;\r
+  } // while\r
 }\r