--- /dev/null
+/** @file\r
+ APMT table parser\r
+\r
+ Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.\r
+ Copyright (c) 2017 - 2018, 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
+**/\r
+\r
+#include <IndustryStandard/Acpi.h>\r
+#include <IndustryStandard/ArmPerformanceMonitoringUnitTable.h>\r
+#include <Library/UefiLib.h>\r
+#include "AcpiParser.h"\r
+#include "AcpiTableParser.h"\r
+\r
+// Local variables\r
+STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;\r
+STATIC CONST UINT16 *NodeLength;\r
+\r
+/**\r
+ An ACPI_PARSER array describing the ACPI APMT Table.\r
+**/\r
+STATIC CONST ACPI_PARSER ApmtParser[] = {\r
+ PARSE_ACPI_HEADER (&AcpiHdrInfo)\r
+};\r
+\r
+/**\r
+ An ACPI_PARSER array describing the ACPI Arm PMU Node.\r
+**/\r
+STATIC CONST ACPI_PARSER ArmPmuNodeParser[] = {\r
+ { L"Length", 2, 0, L"0x%x", NULL, (VOID **)&NodeLength, NULL, NULL },\r
+ { L"Node flags", 1, 2, L"0x%x", NULL, NULL, NULL, NULL },\r
+ { L"Node type", 1, 3, L"0x%x", NULL, NULL, NULL, NULL },\r
+ { L"Identifier", 4, 4, L"0x%x", NULL, NULL, NULL, NULL },\r
+ { L"Node Instance primary", 8, 8, L"0x%lx", NULL, NULL, NULL, NULL },\r
+ { L"Node Instance secondary", 4, 16, L"0x%x", NULL, NULL, NULL, NULL },\r
+ { L"Base address 0", 8, 20, L"0x%lx", NULL, NULL, NULL, NULL },\r
+ { L"Base address 1", 8, 28, L"0x%lx", NULL, NULL, NULL, NULL },\r
+ { L"Overflow interrupt", 4, 36, L"0x%x", NULL, NULL, NULL, NULL },\r
+ { L"Reserved1", 4, 40, L"0x%x", NULL, NULL, NULL, NULL },\r
+ { L"Overflow interrupt flags", 4, 44, L"0x%x", NULL, NULL, NULL, NULL },\r
+ { L"Processor affinity", 4, 48, L"0x%x", NULL, NULL, NULL, NULL },\r
+ { L"Implementation ID", 4, 52, L"0x%x", NULL, NULL, NULL, NULL }\r
+};\r
+\r
+/**\r
+ This function parses the ACPI APMT table.\r
+ When trace is enabled this function parses the APMT table and\r
+ traces the ACPI table fields.\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
+ParseAcpiApmt (\r
+ IN BOOLEAN Trace,\r
+ IN UINT8 *Ptr,\r
+ IN UINT32 AcpiTableLength,\r
+ IN UINT8 AcpiTableRevision\r
+ )\r
+{\r
+ UINT32 Offset;\r
+\r
+ if (!Trace) {\r
+ return;\r
+ }\r
+\r
+ ParseAcpi (\r
+ Trace,\r
+ 0,\r
+ "APMT",\r
+ Ptr,\r
+ AcpiTableLength,\r
+ PARSER_PARAMS (ApmtParser)\r
+ );\r
+ Offset = sizeof (EFI_ACPI_DESCRIPTION_HEADER);\r
+\r
+ while (Offset < AcpiTableLength) {\r
+ ParseAcpi (\r
+ Trace,\r
+ 2,\r
+ "Arm PMU node",\r
+ Ptr + Offset,\r
+ (AcpiTableLength - Offset),\r
+ PARSER_PARAMS (ArmPmuNodeParser)\r
+ );\r
+ if (NodeLength == NULL) {\r
+ Print (\r
+ L"ERROR: Insufficient remaining table buffer length to read the " \\r
+ L"Node structure. Length = %d.\n",\r
+ (AcpiTableLength - Offset)\r
+ );\r
+ IncrementErrorCount ();\r
+ break;\r
+ }\r
+\r
+ Offset += *NodeLength;\r
+ }\r
+}\r