/** @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
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
STATIC\r
VOID\r
DumpWatchdogTimer (\r
- IN UINT8* Ptr,\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
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
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