+/**\r
+ IORT 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
+ - IO Remapping Table, Platform Design Document, Revision C, 15 May 2017\r
+**/\r
+\r
+#include <IndustryStandard/IoRemappingTable.h>\r
+#include <Library/PrintLib.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
+\r
+/** The EIORT_NODE enum describes the IORT Node types.\r
+*/\r
+typedef enum IortNode {\r
+ EIORT_NODE_ITS_GROUP, ///< ITS Group node\r
+ EIORT_NODE_NAMED_COMPONENT, ///< Named Component node\r
+ EIORT_NODE_ROOT_COMPLEX, ///< Root Complex node\r
+ EIORT_NODE_SMMUV1_V2, ///< SMMU v1/v2 node\r
+ EIORT_NODE_SMMUV3, ///< SMMU v3 node\r
+ EIORT_NODE_PMCG, ///< PMC group node\r
+ EIORT_NODE_MAX\r
+} EIORT_NODE;\r
+\r
+// Local Variables\r
+STATIC CONST UINT32* IortNodeCount;\r
+STATIC CONST UINT32* IortNodeOffset;\r
+\r
+STATIC CONST UINT8* IortNodeType;\r
+STATIC CONST UINT16* IortNodeLength;\r
+STATIC CONST UINT32* IortIdMappingCount;\r
+STATIC CONST UINT32* IortIdMappingOffset;\r
+\r
+STATIC CONST UINT32* InterruptContextCount;\r
+STATIC CONST UINT32* InterruptContextOffset;\r
+STATIC CONST UINT32* PmuInterruptCount;\r
+STATIC CONST UINT32* PmuInterruptOffset;\r
+\r
+STATIC CONST UINT32* ItsCount;\r
+\r
+/** This function validates the ID Mapping array count for the ITS node.\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
+ValidateItsIdMappingCount (\r
+ IN UINT8* Ptr,\r
+ IN VOID* Context\r
+ );\r
+\r
+/** This function validates the ID Mapping array offset for the ITS node.\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
+ValidateItsIdArrayReference (\r
+ IN UINT8* Ptr,\r
+ IN VOID* Context\r
+ );\r
+\r
+/** Helper Macro for populating the IORT Node header in the ACPI_PARSER\r
+ array.\r
+\r
+ @param [out] ValidateIdMappingCount Optional pointer to a function for\r
+ validating the ID Mapping count.\r
+ @param [out] ValidateIdArrayReference Optional pointer to a function for\r
+ validating the ID Array reference.\r
+*/\r
+#define PARSE_IORT_NODE_HEADER(ValidateIdMappingCount, \\r
+ ValidateIdArrayReference) \\r
+ { L"Type", 1, 0, L"%d", NULL, (VOID**)&IortNodeType, NULL, NULL }, \\r
+ { L"Length", 2, 1, L"%d", NULL, (VOID**)&IortNodeLength, NULL, NULL }, \\r
+ { L"Revision", 1, 3, L"%d", NULL, NULL, NULL, NULL }, \\r
+ { L"Reserved", 4, 4, L"0x%x", NULL, NULL, NULL, NULL }, \\r
+ { L"Number of ID mappings", 4, 8, L"%d", NULL, \\r
+ (VOID**)&IortIdMappingCount, ValidateIdMappingCount, NULL }, \\r
+ { L"Reference to ID Array", 4, 12, L"0x%x", NULL, \\r
+ (VOID**)&IortIdMappingOffset, ValidateIdArrayReference, NULL }\r
+\r
+/** An ACPI_PARSER array describing the ACPI IORT Table\r
+*/\r
+STATIC CONST ACPI_PARSER IortParser[] = {\r
+ PARSE_ACPI_HEADER (&AcpiHdrInfo),\r
+ {L"Number of IORT Nodes", 4, 36, L"%d", NULL,\r
+ (VOID**)&IortNodeCount, NULL, NULL},\r
+ {L"Offset to Array of IORT Nodes", 4, 40, L"0x%x", NULL,\r
+ (VOID**)&IortNodeOffset, NULL, NULL},\r
+ {L"Reserved", 4, 44, L"0x%x", NULL, NULL, NULL, NULL}\r
+};\r
+\r
+/** An ACPI_PARSER array describing the IORT node header structure.\r
+*/\r
+STATIC CONST ACPI_PARSER IortNodeHeaderParser[] = {\r
+ PARSE_IORT_NODE_HEADER (NULL, NULL)\r
+};\r
+\r
+/** An ACPI_PARSER array describing the IORT SMMUv1/2 node.\r
+*/\r
+STATIC CONST ACPI_PARSER IortNodeSmmuV1V2Parser[] = {\r
+ PARSE_IORT_NODE_HEADER (NULL, NULL),\r
+ {L"Base Address", 8, 16, L"0x%lx", NULL, NULL, NULL, NULL},\r
+ {L"Span", 8, 24, L"0x%lx", NULL, NULL, NULL, NULL},\r
+ {L"Model", 4, 32, L"%d", NULL, NULL, NULL, NULL},\r
+ {L"Flags", 4, 36, L"0x%x", NULL, NULL, NULL, NULL},\r
+ {L"Reference to Global Interrupt Array", 4, 40, L"0x%x", NULL, NULL, NULL,\r
+ NULL},\r
+ {L"Number of context interrupts", 4, 44, L"%d", NULL,\r
+ (VOID**)&InterruptContextCount, NULL, NULL},\r
+ {L"Reference to Context Interrupt Array", 4, 48, L"0x%x", NULL,\r
+ (VOID**)&InterruptContextOffset, NULL, NULL},\r
+ {L"Number of PMU Interrupts", 4, 52, L"%d", NULL,\r
+ (VOID**)&PmuInterruptCount, NULL, NULL},\r
+ {L"Reference to PMU Interrupt Array", 4, 56, L"0x%x", NULL,\r
+ (VOID**)&PmuInterruptOffset, NULL, NULL},\r
+\r
+ // Interrupt Array\r
+ {L"SMMU_NSgIrpt", 4, 60, L"0x%x", NULL, NULL, NULL, NULL},\r
+ {L"SMMU_NSgIrpt interrupt flags", 4, 64, L"0x%x", NULL, NULL, NULL, NULL},\r
+ {L"SMMU_NSgCfgIrpt", 4, 68, L"0x%x", NULL, NULL, NULL, NULL},\r
+ {L"SMMU_NSgCfgIrpt interrupt flags", 4, 72, L"0x%x", NULL, NULL, NULL, NULL}\r
+};\r
+\r
+/** An ACPI_PARSER array describing the SMMUv1/2 Node Interrupt Array.\r
+*/\r
+STATIC CONST ACPI_PARSER InterruptArrayParser[] = {\r
+ {L" Interrupt GSIV", 4, 0, L"0x%x", NULL, NULL, NULL, NULL},\r
+ {L" Flags", 4, 4, L"0x%x", NULL, NULL, NULL, NULL}\r
+};\r
+\r
+/** An ACPI_PARSER array describing the IORT ID Mapping.\r
+*/\r
+STATIC CONST ACPI_PARSER IortNodeIdMappingParser[] = {\r
+ {L" Input base", 4, 0, L"0x%x", NULL, NULL, NULL, NULL},\r
+ {L" Number of IDs", 4, 4, L"0x%x", NULL, NULL, NULL, NULL},\r
+ {L" Output base", 4, 8, L"0x%x", NULL, NULL, NULL, NULL},\r
+ {L" Output reference", 4, 12, L"0x%x", NULL, NULL, NULL, NULL},\r
+ {L" Flags", 4, 16, L"0x%x", NULL, NULL, NULL, NULL}\r
+};\r
+\r
+/** An ACPI_PARSER array describing the IORT SMMUv3 node.\r
+*/\r
+STATIC CONST ACPI_PARSER IortNodeSmmuV3Parser[] = {\r
+ PARSE_IORT_NODE_HEADER (NULL, NULL),\r
+ {L"Base Address", 8, 16, L"0x%lx", NULL, NULL, NULL, NULL},\r
+ {L"Flags", 4, 24, L"0x%x", NULL, NULL, NULL, NULL},\r
+ {L"Reserved", 4, 28, L"0x%x", NULL, NULL, NULL, NULL},\r
+ {L"VATOS Address", 8, 32, L"0x%lx", NULL, NULL, NULL, NULL},\r
+ {L"Model", 4, 40, L"%d", NULL, NULL, NULL, NULL},\r
+ {L"Event", 4, 44, L"0x%x", NULL, NULL, NULL, NULL},\r
+ {L"PRI", 4, 48, L"0x%x", NULL, NULL, NULL, NULL},\r
+ {L"GERR", 4, 52, L"0x%x", NULL, NULL, NULL, NULL},\r
+ {L"Sync", 4, 56, L"0x%x", NULL, NULL, NULL, NULL}\r
+};\r
+\r
+/** An ACPI_PARSER array describing the IORT ITS node.\r
+*/\r
+STATIC CONST ACPI_PARSER IortNodeItsParser[] = {\r
+ PARSE_IORT_NODE_HEADER (\r
+ ValidateItsIdMappingCount,\r
+ ValidateItsIdArrayReference\r
+ ),\r
+ {L" Number of ITSs", 4, 16, L"%d", NULL, (VOID**)&ItsCount, NULL}\r
+};\r
+\r
+/** An ACPI_PARSER array describing the ITS ID.\r
+*/\r
+STATIC CONST ACPI_PARSER ItsIdParser[] = {\r
+ { L" GIC ITS Identifier", 4, 0, L"%d", NULL, NULL, NULL }\r
+};\r
+\r
+/** An ACPI_PARSER array describing the IORT Names Component node.\r
+*/\r
+STATIC CONST ACPI_PARSER IortNodeNamedComponentParser[] = {\r
+ PARSE_IORT_NODE_HEADER (NULL, NULL),\r
+ {L"Node Flags", 4, 16, L"%d", NULL, NULL, NULL, NULL},\r
+ {L"Memory access properties", 8, 20, L"0x%lx", NULL, NULL, NULL, NULL},\r
+ {L"Device memory address size limit", 1, 28, L"%d", NULL, NULL, NULL, NULL}\r
+};\r
+\r
+/** An ACPI_PARSER array describing the IORT Root Complex node.\r
+*/\r
+STATIC CONST ACPI_PARSER IortNodeRootComplexParser[] = {\r
+ PARSE_IORT_NODE_HEADER (NULL, NULL),\r
+ {L"Memory access properties", 8, 16, L"0x%lx", NULL, NULL, NULL, NULL},\r
+ {L"ATS Attribute", 4, 24, L"0x%x", NULL, NULL, NULL, NULL},\r
+ {L"PCI Segment number", 4, 28, L"0x%x", NULL, NULL, NULL, NULL}\r
+};\r
+\r
+/** An ACPI_PARSER array describing the IORT PMCG node.\r
+*/\r
+STATIC CONST ACPI_PARSER IortNodePmcgParser[] = {\r
+ PARSE_IORT_NODE_HEADER (NULL, NULL),\r
+ {L"Base Address", 8, 16, L"0x%lx", NULL, NULL, NULL, NULL},\r
+ {L"Overflow interrupt GSIV", 4, 24, L"0x%x", NULL, NULL, NULL, NULL},\r
+ {L"Node reference", 4, 28, L"0x%x", NULL, NULL, NULL, NULL},\r
+};\r
+\r
+/** This function validates the ID Mapping array count for the ITS node.\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
+ValidateItsIdMappingCount (\r
+ IN UINT8* Ptr,\r
+ VOID* Context\r
+ )\r
+{\r
+ if (*(UINT32*)Ptr != 0) {\r
+ IncrementErrorCount ();\r
+ Print (L"\nERROR: IORT ID Mapping count must be zero.");\r
+ }\r
+}\r
+\r
+/** This function validates the ID Mapping array offset for the ITS node.\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
+ValidateItsIdArrayReference (\r
+ IN UINT8* Ptr,\r
+ IN VOID* Context\r
+ )\r
+{\r
+ if (*(UINT32*)Ptr != 0) {\r
+ IncrementErrorCount ();\r
+ Print (L"\nERROR: IORT ID Mapping offset must be zero.");\r
+ }\r
+}\r
+\r
+/** This function parses the IORT Node Id Mapping array.\r
+\r
+ @param [in] Ptr Pointer to the start of the IORT Table.\r
+ @param [in] MappingCount The ID Mapping count.\r
+ @param [in] MappingOffset The offset of the ID Mapping array\r
+ from the start of the IORT table.\r
+*/\r
+STATIC\r
+VOID\r
+DumpIortNodeIdMappings (\r
+ IN UINT8* Ptr,\r
+ IN UINT32 MappingCount,\r
+ IN UINT32 MappingOffset\r
+ )\r
+{\r
+ UINT8* IdMappingPtr;\r
+ UINT32 Index;\r
+ UINT32 Offset;\r
+ CHAR8 Buffer[40]; // Used for AsciiName param of ParseAcpi\r
+\r
+ IdMappingPtr = Ptr + MappingOffset;\r
+ Index = 0;\r
+ while (Index < MappingCount) {\r
+ AsciiSPrint (\r
+ Buffer,\r
+ sizeof (Buffer),\r
+ "ID Mapping [%d]",\r
+ Index\r
+ );\r
+ Offset = ParseAcpi (\r
+ TRUE,\r
+ 4,\r
+ Buffer,\r
+ IdMappingPtr,\r
+ 20,\r
+ PARSER_PARAMS (IortNodeIdMappingParser)\r
+ );\r
+ IdMappingPtr += Offset;\r
+ Index++;\r
+ }\r
+}\r
+\r
+/** This function parses the IORT SMMUv1/2 node.\r
+\r
+ @param [in] Ptr Pointer to the start of the buffer.\r
+ @param [in] Length Length of the buffer.\r
+ @param [in] MappingCount The ID Mapping count.\r
+ @param [in] MappingOffset The offset of the ID Mapping array\r
+ from the start of the IORT table.\r
+*/\r
+STATIC\r
+VOID\r
+DumpIortNodeSmmuV1V2 (\r
+ IN UINT8* Ptr,\r
+ IN UINT16 Length,\r
+ IN UINT32 MappingCount,\r
+ IN UINT32 MappingOffset\r
+ )\r
+{\r
+ UINT32 Index;\r
+ UINT32 Offset;\r
+ CHAR8 Buffer[50]; // Used for AsciiName param of ParseAcpi\r
+\r
+ UINT8* ArrayPtr;\r
+\r
+ ParseAcpi (\r
+ TRUE,\r
+ 2,\r
+ "SMMUv1 or SMMUv2 Node",\r
+ Ptr,\r
+ Length,\r
+ PARSER_PARAMS (IortNodeSmmuV1V2Parser)\r
+ );\r
+\r
+ ArrayPtr = Ptr + *InterruptContextOffset;\r
+ Index = 0;\r
+ while (Index < *InterruptContextCount) {\r
+ AsciiSPrint (\r
+ Buffer,\r
+ sizeof (Buffer),\r
+ "Context Interrupts Array [%d]",\r
+ Index\r
+ );\r
+ Offset = ParseAcpi (\r
+ TRUE,\r
+ 4,\r
+ Buffer,\r
+ ArrayPtr,\r
+ 8,\r
+ PARSER_PARAMS (InterruptArrayParser)\r
+ );\r
+ ArrayPtr += Offset;\r
+ Index++;\r
+ }\r
+\r
+ ArrayPtr = Ptr + *PmuInterruptOffset;\r
+ Index = 0;\r
+ while (Index < *PmuInterruptCount) {\r
+ AsciiSPrint (\r
+ Buffer,\r
+ sizeof (Buffer),\r
+ "PMU Interrupts Array [%d]",\r
+ Index\r
+ );\r
+ Offset = ParseAcpi (\r
+ TRUE,\r
+ 4,\r
+ Buffer,\r
+ ArrayPtr,\r
+ 8,\r
+ PARSER_PARAMS (InterruptArrayParser)\r
+ );\r
+ ArrayPtr += Offset;\r
+ Index++;\r
+ }\r
+\r
+ if (*IortIdMappingCount != 0) {\r
+ DumpIortNodeIdMappings (Ptr, MappingCount, MappingOffset);\r
+ }\r
+}\r
+\r
+/** This function parses the IORT SMMUv3 node.\r
+\r
+ @param [in] Ptr Pointer to the start of the buffer.\r
+ @param [in] Length Length of the buffer.\r
+ @param [in] MappingCount The ID Mapping count.\r
+ @param [in] MappingOffset The offset of the ID Mapping array\r
+ from the start of the IORT table.\r
+*/\r
+STATIC\r
+VOID\r
+DumpIortNodeSmmuV3 (\r
+ IN UINT8* Ptr,\r
+ IN UINT16 Length,\r
+ IN UINT32 MappingCount,\r
+ IN UINT32 MappingOffset\r
+ )\r
+{\r
+ ParseAcpi (\r
+ TRUE,\r
+ 2,\r
+ "SMMUV3 Node",\r
+ Ptr,\r
+ Length,\r
+ PARSER_PARAMS (IortNodeSmmuV3Parser)\r
+ );\r
+\r
+ if (*IortIdMappingCount != 0) {\r
+ DumpIortNodeIdMappings (Ptr, MappingCount, MappingOffset);\r
+ }\r
+}\r
+\r
+/** This function parses the IORT ITS node.\r
+\r
+ @param [in] Ptr Pointer to the start of the buffer.\r
+ @param [in] Length Length of the buffer.\r
+*/\r
+STATIC\r
+VOID\r
+DumpIortNodeIts (\r
+ IN UINT8* Ptr,\r
+ IN UINT16 Length\r
+ )\r
+{\r
+ UINT32 Offset;\r
+ UINT32 Index;\r
+ UINT8* ItsIdPtr;\r
+ CHAR8 Buffer[80]; // Used for AsciiName param of ParseAcpi\r
+\r
+ Offset = ParseAcpi (\r
+ TRUE,\r
+ 2,\r
+ "ITS Node",\r
+ Ptr,\r
+ Length,\r
+ PARSER_PARAMS (IortNodeItsParser)\r
+ );\r
+\r
+ ItsIdPtr = Ptr + Offset;\r
+ Index = 0;\r
+ while (Index < *ItsCount) {\r
+ AsciiSPrint (\r
+ Buffer,\r
+ sizeof (Buffer),\r
+ "GIC ITS Identifier Array [%d]",\r
+ Index\r
+ );\r
+ Offset = ParseAcpi (\r
+ TRUE,\r
+ 4,\r
+ Buffer,\r
+ ItsIdPtr,\r
+ 4,\r
+ PARSER_PARAMS (ItsIdParser)\r
+ );\r
+ ItsIdPtr += Offset;\r
+ Index++;\r
+ }\r
+\r
+ // Note: ITS does not have the ID Mappings Array\r
+}\r
+\r
+/** This function parses the IORT Named Component node.\r
+\r
+ @param [in] Ptr Pointer to the start of the buffer.\r
+ @param [in] Length Length of the buffer.\r
+ @param [in] MappingCount The ID Mapping count.\r
+ @param [in] MappingOffset The offset of the ID Mapping array\r
+ from the start of the IORT table.\r
+*/\r
+STATIC\r
+VOID\r
+DumpIortNodeNamedComponent (\r
+ IN UINT8* Ptr,\r
+ IN UINT16 Length,\r
+ IN UINT32 MappingCount,\r
+ IN UINT32 MappingOffset\r
+ )\r
+{\r
+ UINT32 Offset;\r
+ UINT32 Index;\r
+ UINT8* DeviceNamePtr;\r
+ UINT32 DeviceNameLength;\r
+\r
+ Offset = ParseAcpi (\r
+ TRUE,\r
+ 2,\r
+ "Named Component Node",\r
+ Ptr,\r
+ Length,\r
+ PARSER_PARAMS (IortNodeNamedComponentParser)\r
+ );\r
+\r
+ DeviceNamePtr = Ptr + Offset;\r
+ // Estimate the Device Name length\r
+ DeviceNameLength = Length - Offset - (MappingCount * 20);\r
+ PrintFieldName (2, L"Device Object Name");\r
+ Index = 0;\r
+ while ((Index < DeviceNameLength) && (DeviceNamePtr[Index] != 0)) {\r
+ Print (L"%c", DeviceNamePtr[Index++]);\r
+ }\r
+ Print (L"\n");\r
+\r
+ if (*IortIdMappingCount != 0) {\r
+ DumpIortNodeIdMappings (Ptr, MappingCount, MappingOffset);\r
+ }\r
+}\r
+\r
+/** This function parses the IORT Root Complex node.\r
+\r
+ @param [in] Ptr Pointer to the start of the buffer.\r
+ @param [in] Length Length of the buffer.\r
+ @param [in] MappingCount The ID Mapping count.\r
+ @param [in] MappingOffset The offset of the ID Mapping array\r
+ from the start of the IORT table.\r
+*/\r
+STATIC\r
+VOID\r
+DumpIortNodeRootComplex (\r
+ IN UINT8* Ptr,\r
+ IN UINT16 Length,\r
+ IN UINT32 MappingCount,\r
+ IN UINT32 MappingOffset\r
+ )\r
+{\r
+ ParseAcpi (\r
+ TRUE,\r
+ 2,\r
+ "Root Complex Node",\r
+ Ptr,\r
+ Length,\r
+ PARSER_PARAMS (IortNodeRootComplexParser)\r
+ );\r
+\r
+ if (*IortIdMappingCount != 0) {\r
+ DumpIortNodeIdMappings (Ptr, MappingCount, MappingOffset);\r
+ }\r
+}\r
+\r
+/** This function parses the IORT PMCG node.\r
+\r
+ @param [in] Ptr Pointer to the start of the buffer.\r
+ @param [in] Length Length of the buffer.\r
+ @param [in] MappingCount The ID Mapping count.\r
+ @param [in] MappingOffset The offset of the ID Mapping array\r
+ from the start of the IORT table.\r
+*/\r
+STATIC\r
+VOID\r
+DumpIortNodePmcg (\r
+ IN UINT8* Ptr,\r
+ IN UINT16 Length,\r
+ IN UINT32 MappingCount,\r
+ IN UINT32 MappingOffset\r
+)\r
+{\r
+ ParseAcpi (\r
+ TRUE,\r
+ 2,\r
+ "PMCG Node",\r
+ Ptr,\r
+ Length,\r
+ PARSER_PARAMS (IortNodePmcgParser)\r
+ );\r
+\r
+ if (*IortIdMappingCount != 0) {\r
+ DumpIortNodeIdMappings (Ptr, MappingCount, MappingOffset);\r
+ }\r
+\r
+ if (*IortIdMappingCount > 1) {\r
+ IncrementErrorCount ();\r
+ Print (\r
+ L"ERROR: ID mapping must not be greater than 1. Id Mapping Count =%d\n",\r
+ *IortIdMappingCount\r
+ );\r
+ }\r
+}\r
+\r
+/** This function parses the ACPI IORT table.\r
+ When trace is enabled this function parses the IORT table and\r
+ traces the ACPI fields.\r
+\r
+ This function also parses the following nodes:\r
+ - ITS Group\r
+ - Named Component\r
+ - Root Complex\r
+ - SMMUv1/2\r
+ - SMMUv3\r
+ - PMCG\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
+ParseAcpiIort (\r
+ IN BOOLEAN Trace,\r
+ IN UINT8* Ptr,\r
+ IN UINT32 AcpiTableLength,\r
+ IN UINT8 AcpiTableRevision\r
+ )\r
+{\r
+ UINT32 Offset;\r
+ UINT32 Index;\r
+ UINT8* NodePtr;\r
+\r
+ if (!Trace) {\r
+ return;\r
+ }\r
+\r
+ ParseAcpi (\r
+ TRUE,\r
+ 0,\r
+ "IORT",\r
+ Ptr,\r
+ AcpiTableLength,\r
+ PARSER_PARAMS (IortParser)\r
+ );\r
+ Offset = *IortNodeOffset;\r
+ NodePtr = Ptr + Offset;\r
+ Index = 0;\r
+\r
+ while ((Index < *IortNodeCount) && (Offset < AcpiTableLength)) {\r
+ // Parse the IORT Node Header\r
+ ParseAcpi (\r
+ FALSE,\r
+ 0,\r
+ "IORT Node Header",\r
+ NodePtr,\r
+ 16,\r
+ PARSER_PARAMS (IortNodeHeaderParser)\r
+ );\r
+ if (*IortNodeLength == 0) {\r
+ IncrementErrorCount ();\r
+ Print (L"ERROR: Parser error. Invalid table data.\n");\r
+ return;\r
+ }\r
+\r
+ PrintFieldName (2, L"* Node Offset *");\r
+ Print (L"0x%x\n", Offset);\r
+\r
+ switch (*IortNodeType) {\r
+ case EIORT_NODE_ITS_GROUP:\r
+ DumpIortNodeIts (\r
+ NodePtr,\r
+ *IortNodeLength\r
+ );\r
+ break;\r
+ case EIORT_NODE_NAMED_COMPONENT:\r
+ DumpIortNodeNamedComponent (\r
+ NodePtr,\r
+ *IortNodeLength,\r
+ *IortIdMappingCount,\r
+ *IortIdMappingOffset\r
+ );\r
+ break;\r
+ case EIORT_NODE_ROOT_COMPLEX:\r
+ DumpIortNodeRootComplex (\r
+ NodePtr,\r
+ *IortNodeLength,\r
+ *IortIdMappingCount,\r
+ *IortIdMappingOffset\r
+ );\r
+ break;\r
+ case EIORT_NODE_SMMUV1_V2:\r
+ DumpIortNodeSmmuV1V2 (\r
+ NodePtr,\r
+ *IortNodeLength,\r
+ *IortIdMappingCount,\r
+ *IortIdMappingOffset\r
+ );\r
+ break;\r
+ case EIORT_NODE_SMMUV3:\r
+ DumpIortNodeSmmuV3 (\r
+ NodePtr,\r
+ *IortNodeLength,\r
+ *IortIdMappingCount,\r
+ *IortIdMappingOffset\r
+ );\r
+ break;\r
+ case EIORT_NODE_PMCG:\r
+ DumpIortNodePmcg (\r
+ NodePtr,\r
+ *IortNodeLength,\r
+ *IortIdMappingCount,\r
+ *IortIdMappingOffset\r
+ );\r
+ break;\r
+\r
+ default:\r
+ IncrementErrorCount ();\r
+ Print (L"ERROR: Unsupported IORT Node type = %d\n", *IortNodeType);\r
+ } // switch\r
+\r
+ NodePtr += (*IortNodeLength);\r
+ Offset += (*IortNodeLength);\r
+ } // while\r
+}\r