/** @file\r
IORT table parser\r
\r
- Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.\r
+ Copyright (c) 2016 - 2022, Arm Limited. All rights reserved.\r
SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
@par Reference(s):\r
- - IO Remapping Table, Platform Design Document, Revision D, March 2018\r
+ - IO Remapping Table, Platform Design Document, Revision E.d, Feb 2022\r
+ (https://developer.arm.com/documentation/den0049/)\r
\r
@par Glossary:\r
- Ref - Reference\r
+ - Desc - Descriptor\r
**/\r
\r
#include <IndustryStandard/IoRemappingTable.h>\r
\r
STATIC CONST UINT8 *IortNodeType;\r
STATIC CONST UINT16 *IortNodeLength;\r
+STATIC CONST UINT8 *IortNodeRevision;\r
STATIC CONST UINT32 *IortIdMappingCount;\r
STATIC CONST UINT32 *IortIdMappingOffset;\r
\r
\r
STATIC CONST UINT32 *ItsCount;\r
\r
+STATIC CONST UINT32 *RmrMemDescCount;\r
+STATIC CONST UINT32 *RmrMemDescOffset;\r
+\r
/**\r
This function validates the ID Mapping array count for the ITS node.\r
\r
}\r
}\r
\r
+/**\r
+ This function validates that the Physical Range address or length is not zero\r
+ and is 64K aligned.\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
+ValidatePhysicalRange (\r
+ IN UINT8 *Ptr,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ UINT64 Value;\r
+\r
+ Value = *(UINT64 *)Ptr;\r
+ if ((Value == 0) || ((Value & (SIZE_64KB - 1)) != 0)) {\r
+ IncrementErrorCount ();\r
+ Print (L"\nERROR: Physical Range must be 64K aligned and cannot be zero.");\r
+ }\r
+}\r
+\r
+/**\r
+ This function validates that the RMR memory range descriptor 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
+ValidateRmrMemDescCount (\r
+ IN UINT8 *Ptr,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ if (*(UINT32 *)Ptr == 0) {\r
+ IncrementErrorCount ();\r
+ Print (L"\nERROR: Memory Range Descriptor count must be >=1.");\r
+ }\r
+}\r
+\r
/**\r
Helper Macro for populating the IORT Node header in the ACPI_PARSER array.\r
\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
+#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, (VOID**)&IortNodeRevision, NULL, NULL }, \\r
+ { L"Identifier", 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
/**\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
- { L"Memory access size limit",1, 32, L"0x%x", NULL, NULL, NULL, NULL },\r
- { L"Reserved", 3, 33, L"%x %x %x", Dump3Chars, NULL, 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
+ { L"Memory access size limit",1, 32, L"0x%x", NULL, NULL, NULL, NULL },\r
+ { L"PASID capabilities", 2, 33, L"0x%x", NULL, NULL, NULL, NULL },\r
+ { L"Reserved", 1, 35, L"%x", NULL, NULL, NULL, NULL },\r
+ { L"Flags", 4, 36, L"0x%x", NULL, NULL, NULL, NULL },\r
};\r
\r
/**\r
{ L"Page 1 Base Address", 8, 32, L"0x%lx", NULL, NULL, NULL, NULL }\r
};\r
\r
+/**\r
+ An ACPI_PARSER array describing the IORT RMR node.\r
+**/\r
+STATIC CONST ACPI_PARSER IortNodeRmrParser[] = {\r
+ PARSE_IORT_NODE_HEADER (NULL, NULL),\r
+ { L"Flags", 4, 16, L"0x%x", NULL, NULL, NULL, NULL },\r
+ { L"Memory Range Desc count", 4, 20, L"%d", NULL,\r
+ (VOID **)&RmrMemDescCount, ValidateRmrMemDescCount,NULL },\r
+ { L"Memory Range Desc Ref", 4, 24, L"0x%x", NULL,\r
+ (VOID **)&RmrMemDescOffset, NULL, NULL }\r
+};\r
+\r
+/**\r
+ An ACPI_PARSER array describing the IORT RMR Memory Range Descriptor.\r
+**/\r
+STATIC CONST ACPI_PARSER IortNodeRmrMemRangeDescParser[] = {\r
+ { L"Physical Range offset", 8, 0, L"0x%lx", NULL, NULL, ValidatePhysicalRange,\r
+ NULL },\r
+ { L"Physical Range length", 8, 8, L"0x%lx", NULL, NULL, ValidatePhysicalRange,\r
+ NULL },\r
+ { L"Reserved", 4, 16, L"0x%x", NULL, NULL, NULL, NULL}\r
+};\r
+\r
/**\r
This function parses the IORT Node Id Mapping array.\r
\r
);\r
}\r
\r
+/**\r
+ This function parses the IORT RMR Node Memory Range Descriptor array.\r
+\r
+ @param [in] Ptr Pointer to the start of the Memory Range Descriptor\r
+ array.\r
+ @param [in] Length Length of the buffer.\r
+ @param [in] DescCount Memory Range Descriptor count.\r
+**/\r
+STATIC\r
+VOID\r
+DumpIortNodeRmrMemRangeDesc (\r
+ IN UINT8 *Ptr,\r
+ IN UINT32 Length,\r
+ IN UINT32 DescCount\r
+ )\r
+{\r
+ UINT32 Index;\r
+ UINT32 Offset;\r
+ CHAR8 Buffer[40]; // Used for AsciiName param of ParseAcpi\r
+\r
+ Index = 0;\r
+ Offset = 0;\r
+\r
+ while ((Index < DescCount) &&\r
+ (Offset < Length))\r
+ {\r
+ AsciiSPrint (\r
+ Buffer,\r
+ sizeof (Buffer),\r
+ "Mem range Descriptor [%d]",\r
+ Index\r
+ );\r
+ Offset += ParseAcpi (\r
+ TRUE,\r
+ 4,\r
+ Buffer,\r
+ Ptr + Offset,\r
+ Length - Offset,\r
+ PARSER_PARAMS (IortNodeRmrMemRangeDescParser)\r
+ );\r
+ Index++;\r
+ }\r
+}\r
+\r
+/**\r
+ This function parses the IORT RMR 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
+DumpIortNodeRmr (\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
+ "RMR Node",\r
+ Ptr,\r
+ Length,\r
+ PARSER_PARAMS (IortNodeRmrParser)\r
+ );\r
+\r
+ if (*IortNodeRevision == EFI_ACPI_IORT_RMR_NODE_REVISION_02) {\r
+ IncrementErrorCount ();\r
+ Print (\r
+ L"ERROR: RMR node Rev 2 (defined in IORT Rev E.c) must not be used."\r
+ L" IORT tabe Revision E.c is deprecated and must not be used.\n"\r
+ );\r
+ }\r
+\r
+ DumpIortNodeIdMappings (\r
+ Ptr + MappingOffset,\r
+ Length - MappingOffset,\r
+ MappingCount\r
+ );\r
+\r
+ DumpIortNodeRmrMemRangeDesc (\r
+ Ptr + (*RmrMemDescOffset),\r
+ Length - (*RmrMemDescOffset),\r
+ *RmrMemDescCount\r
+ );\r
+}\r
+\r
/**\r
This function parses the ACPI IORT table.\r
- When trace is enabled this function parses the IORT table and traces the ACPI fields.\r
+ When trace is enabled this function parses the IORT table and traces the ACPI\r
+ fields.\r
\r
This function also parses the following nodes:\r
- ITS Group\r
- SMMUv1/2\r
- SMMUv3\r
- PMCG\r
+ - RMR\r
\r
This function also performs validation of the ACPI table fields.\r
\r
return;\r
}\r
\r
+ if ((AcpiTableRevision > EFI_ACPI_IO_REMAPPING_TABLE_REVISION_00) &&\r
+ (AcpiTableRevision < EFI_ACPI_IO_REMAPPING_TABLE_REVISION_05))\r
+ {\r
+ Print (\r
+ L"ERROR: Parsing not supported for IORT tabe Revision E, E.<a,b,c>.\n"\r
+ );\r
+ if (AcpiTableRevision == EFI_ACPI_IO_REMAPPING_TABLE_REVISION_04) {\r
+ IncrementErrorCount ();\r
+ Print (\r
+ L"ERROR: IORT tabe Revision E.c is deprecated and must not be used.\n"\r
+ );\r
+ }\r
+\r
+ return;\r
+ }\r
+\r
ParseAcpi (\r
TRUE,\r
0,\r
*IortIdMappingOffset\r
);\r
break;\r
-\r
+ case EFI_ACPI_IORT_TYPE_RMR:\r
+ DumpIortNodeRmr (\r
+ NodePtr,\r
+ *IortNodeLength,\r
+ *IortIdMappingCount,\r
+ *IortIdMappingOffset\r
+ );\r
+ break;\r
default:\r
IncrementErrorCount ();\r
Print (L"ERROR: Unsupported IORT Node type = %d\n", *IortNodeType);\r