]> git.proxmox.com Git - mirror_edk2.git/commitdiff
ShellPkg: Acpiview: IORT parser update for IORT Rev E.d spec
authorSami Mujawar <sami.mujawar@arm.com>
Thu, 14 Jul 2022 16:50:29 +0000 (17:50 +0100)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Fri, 29 Jul 2022 19:22:15 +0000 (19:22 +0000)
Bugzilla: 3458 - Add support IORT Rev E.d specification updates
          (https://bugzilla.tianocore.org/show_bug.cgi?id=3458)

The IO Remapping Table, Platform Design Document, Revision E.d,
Feb 2022 (https://developer.arm.com/documentation/den0049/)
introduces the following updates, collectively including the
updates and errata fixes to Rev E, Rev E.a, Rev E.b, Rev E.c:
 - increments the IORT table revision to 5.
 - updates the node definition to add an 'Identifier' field.
 - adds definition of node type 6 - Reserved Memory Range node.
 - adds definition for Memory Range Descriptors.
 - adds flag to indicate PRI support for root complexes.
 - adds flag to indicate if the root complex supports forwarding
   of PASID information on translated transactions to the SMMU.
 - adds flag to indicate if the root complex supports PASID.
 - adds flags to define access privilege and attributes for the
   memory ranges.

Therefore, update the IORT parser to:
  - parse the Identifier field.
  - parse Reserved Memory Range node.
  - parse Memory Range Descriptors.
  - add validations to check that the physical range base
    and size of the Memory Range Descriptor is 64KB aligned.
  - add validation to check that the IORT Table Revision is
    not 4 as IORT Rev E.c is deprecated.
  - add validation to check that the IORT RMR node revision
    is not 2 as it breaks backward compatibility and was
    deprecated as part of IORT Rev E.c.
  - skip parsing of IORT Rev E, Rev E.a, Rev E.b, Rev E.c as
    some fields were deprecated in these revisions.

Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
Reviewed-by: Zhichao Gao <zhichao.gao@intel.com>
Reviewed-by: Pierre Gondois <pierre.gondois@arm.com>
ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Iort/IortParser.c

index 44d633c5282463078a4cc990bb24ca1992f95634..599cf0ee8f7e4c7ed398fa604602604d1955d2e6 100644 (file)
@@ -1,14 +1,16 @@
 /** @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
@@ -26,6 +28,7 @@ STATIC CONST UINT32  *IortNodeOffset;
 \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
@@ -36,6 +39,9 @@ STATIC CONST UINT32  *PmuInterruptOffset;
 \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
@@ -100,6 +106,52 @@ ValidateItsIdArrayReference (
   }\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
@@ -108,15 +160,15 @@ ValidateItsIdArrayReference (
   @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
@@ -235,11 +287,13 @@ STATIC CONST ACPI_PARSER  IortNodeNamedComponentParser[] = {
 **/\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
@@ -253,6 +307,29 @@ STATIC CONST ACPI_PARSER  IortNodePmcgParser[] = {
   { 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
@@ -607,9 +684,102 @@ DumpIortNodePmcg (
     );\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
@@ -618,6 +788,7 @@ DumpIortNodePmcg (
     - SMMUv1/2\r
     - SMMUv3\r
     - PMCG\r
+    - RMR\r
 \r
   This function also performs validation of the ACPI table fields.\r
 \r
@@ -643,6 +814,22 @@ ParseAcpiIort (
     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
@@ -765,7 +952,14 @@ ParseAcpiIort (
           *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