]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Iort/IortParser.c
ShellPkg/AcpiView: Refactor configuration
[mirror_edk2.git] / ShellPkg / Library / UefiShellAcpiViewCommandLib / Parsers / Iort / IortParser.c
index a91a4f9db13a52285bf56abe33f359a771fc04bd..f7447947b2308d35d4d2890373778f0fd2f97f9e 100644 (file)
@@ -1,11 +1,11 @@
 /** @file\r
   IORT table parser\r
 \r
-  Copyright (c) 2016 - 2019, ARM Limited. All rights reserved.\r
+  Copyright (c) 2016 - 2020, 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 C, 15 May 2017\r
+    - IO Remapping Table, Platform Design Document, Revision D, March 2018\r
 **/\r
 \r
 #include <IndustryStandard/IoRemappingTable.h>\r
@@ -13,6 +13,7 @@
 #include <Library/UefiLib.h>\r
 #include "AcpiParser.h"\r
 #include "AcpiTableParser.h"\r
+#include "AcpiViewConfig.h"\r
 \r
 // Local variables\r
 STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;\r
@@ -45,7 +46,35 @@ EFIAPI
 ValidateItsIdMappingCount (\r
   IN UINT8* Ptr,\r
   IN VOID*  Context\r
-  );\r
+  )\r
+{\r
+  if (*(UINT32*)Ptr != 0) {\r
+    IncrementErrorCount ();\r
+    Print (L"\nERROR: IORT ID Mapping count must be zero.");\r
+  }\r
+}\r
+\r
+/**\r
+  This function validates the ID Mapping array count for the Performance\r
+  Monitoring Counter Group (PMCG) 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
+ValidatePmcgIdMappingCount (\r
+  IN UINT8* Ptr,\r
+  IN VOID*  Context\r
+  )\r
+{\r
+  if (*(UINT32*)Ptr > 1) {\r
+    IncrementErrorCount ();\r
+    Print (L"\nERROR: IORT ID Mapping count must not be greater than 1.");\r
+  }\r
+}\r
 \r
 /**\r
   This function validates the ID Mapping array offset for the ITS node.\r
@@ -60,7 +89,13 @@ EFIAPI
 ValidateItsIdArrayReference (\r
   IN UINT8* Ptr,\r
   IN VOID*  Context\r
-  );\r
+  )\r
+{\r
+  if (*(UINT32*)Ptr != 0) {\r
+    IncrementErrorCount ();\r
+    Print (L"\nERROR: IORT ID Mapping offset must be zero.");\r
+  }\r
+}\r
 \r
 /**\r
   Helper Macro for populating the IORT Node header in the ACPI_PARSER array.\r
@@ -131,19 +166,19 @@ STATIC CONST ACPI_PARSER IortNodeSmmuV1V2Parser[] = {
   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
+  {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
 /**\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
+  {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
 /**\r
@@ -159,7 +194,9 @@ STATIC CONST ACPI_PARSER IortNodeSmmuV3Parser[] = {
   {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
+  {L"Sync", 4, 56, L"0x%x", NULL, NULL, NULL, NULL},\r
+  {L"Proximity domain", 4, 60, L"0x%x", NULL, NULL, NULL, NULL},\r
+  {L"Device ID mapping index", 4, 64, L"%d", NULL, NULL, NULL, NULL}\r
 };\r
 \r
 /**\r
@@ -170,14 +207,14 @@ STATIC CONST ACPI_PARSER IortNodeItsParser[] = {
     ValidateItsIdMappingCount,\r
     ValidateItsIdArrayReference\r
     ),\r
-  {L"  Number of ITSs", 4, 16, L"%d", NULL, (VOID**)&ItsCount, NULL}\r
+  {L"Number of ITSs", 4, 16, L"%d", NULL, (VOID**)&ItsCount, NULL}\r
 };\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
+  { L"GIC ITS Identifier", 4, 0, L"%d", NULL, NULL, NULL }\r
 };\r
 \r
 /**\r
@@ -197,100 +234,60 @@ STATIC CONST ACPI_PARSER IortNodeRootComplexParser[] = {
   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"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
 };\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
+  PARSE_IORT_NODE_HEADER (ValidatePmcgIdMappingCount, NULL),\r
+  {L"Page 0 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
+  {L"Page 1 Base Address", 8, 32, L"0x%lx", NULL, NULL, NULL, NULL}\r
 };\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
-  IN 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
-/**\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
 /**\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] Ptr            Pointer to the start of the ID mapping array.\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
 DumpIortNodeIdMappings (\r
   IN UINT8* Ptr,\r
-  IN UINT32 MappingCount,\r
-  IN UINT32 MappingOffset\r
+  IN UINT32 Length,\r
+  IN UINT32 MappingCount\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
+  Offset = 0;\r
+\r
+  while ((Index < MappingCount) &&\r
+         (Offset < Length)) {\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
+    Offset += ParseAcpi (\r
+                TRUE,\r
+                4,\r
+                Buffer,\r
+                Ptr + Offset,\r
+                Length - Offset,\r
+                PARSER_PARAMS (IortNodeIdMappingParser)\r
+                );\r
     Index++;\r
   }\r
 }\r
@@ -317,8 +314,6 @@ DumpIortNodeSmmuV1V2 (
   UINT32 Offset;\r
   CHAR8  Buffer[50];  // Used for AsciiName param of ParseAcpi\r
 \r
-  UINT8* ArrayPtr;\r
-\r
   ParseAcpi (\r
     TRUE,\r
     2,\r
@@ -328,51 +323,69 @@ DumpIortNodeSmmuV1V2 (
     PARSER_PARAMS (IortNodeSmmuV1V2Parser)\r
     );\r
 \r
-  ArrayPtr = Ptr + *InterruptContextOffset;\r
+  // Check if the values used to control the parsing logic have been\r
+  // successfully read.\r
+  if ((InterruptContextCount == NULL)   ||\r
+      (InterruptContextOffset == NULL)  ||\r
+      (PmuInterruptCount == NULL)       ||\r
+      (PmuInterruptOffset == NULL)) {\r
+    IncrementErrorCount ();\r
+    Print (\r
+      L"ERROR: Insufficient SMMUv1/2 node length. Length = %d\n",\r
+      Length\r
+      );\r
+    return;\r
+  }\r
+\r
+  Offset = *InterruptContextOffset;\r
   Index = 0;\r
-  while (Index < *InterruptContextCount) {\r
+\r
+  while ((Index < *InterruptContextCount) &&\r
+         (Offset < Length)) {\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
+    Offset += ParseAcpi (\r
+                TRUE,\r
+                4,\r
+                Buffer,\r
+                Ptr + Offset,\r
+                Length - Offset,\r
+                PARSER_PARAMS (InterruptArrayParser)\r
+                );\r
     Index++;\r
   }\r
 \r
-  ArrayPtr = Ptr + *PmuInterruptOffset;\r
+  Offset = *PmuInterruptOffset;\r
   Index = 0;\r
-  while (Index < *PmuInterruptCount) {\r
+\r
+  while ((Index < *PmuInterruptCount) &&\r
+         (Offset < Length)) {\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
+    Offset += ParseAcpi (\r
+                TRUE,\r
+                4,\r
+                Buffer,\r
+                Ptr + Offset,\r
+                Length - Offset,\r
+                PARSER_PARAMS (InterruptArrayParser)\r
+                );\r
     Index++;\r
   }\r
 \r
-  if (*IortIdMappingCount != 0) {\r
-    DumpIortNodeIdMappings (Ptr, MappingCount, MappingOffset);\r
-  }\r
+  DumpIortNodeIdMappings (\r
+    Ptr + MappingOffset,\r
+    Length - MappingOffset,\r
+    MappingCount\r
+    );\r
 }\r
 \r
 /**\r
@@ -402,9 +415,11 @@ DumpIortNodeSmmuV3 (
     PARSER_PARAMS (IortNodeSmmuV3Parser)\r
     );\r
 \r
-  if (*IortIdMappingCount != 0) {\r
-    DumpIortNodeIdMappings (Ptr, MappingCount, MappingOffset);\r
-  }\r
+  DumpIortNodeIdMappings (\r
+    Ptr + MappingOffset,\r
+    Length - MappingOffset,\r
+    MappingCount\r
+    );\r
 }\r
 \r
 /**\r
@@ -422,40 +437,51 @@ DumpIortNodeIts (
 {\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
+            TRUE,\r
+            2,\r
+            "ITS Node",\r
+            Ptr,\r
+            Length,\r
+            PARSER_PARAMS (IortNodeItsParser)\r
+            );\r
+\r
+  // Check if the values used to control the parsing logic have been\r
+  // successfully read.\r
+  if (ItsCount == NULL) {\r
+    IncrementErrorCount ();\r
+    Print (\r
+      L"ERROR: Insufficient ITS group length. Length = %d.\n",\r
+      Length\r
+      );\r
+    return;\r
+  }\r
 \r
-  ItsIdPtr = Ptr + Offset;\r
   Index = 0;\r
-  while (Index < *ItsCount) {\r
+\r
+  while ((Index < *ItsCount) &&\r
+         (Offset < Length)) {\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
+    Offset += ParseAcpi (\r
+                TRUE,\r
+                4,\r
+                Buffer,\r
+                Ptr + Offset,\r
+                Length - Offset,\r
+                PARSER_PARAMS (ItsIdParser)\r
+                );\r
     Index++;\r
   }\r
 \r
   // Note: ITS does not have the ID Mappings Array\r
+\r
 }\r
 \r
 /**\r
@@ -477,9 +503,6 @@ DumpIortNodeNamedComponent (
   )\r
 {\r
   UINT32 Offset;\r
-  UINT32 Index;\r
-  UINT8* DeviceNamePtr;\r
-  UINT32 DeviceNameLength;\r
 \r
   Offset = ParseAcpi (\r
              TRUE,\r
@@ -490,19 +513,21 @@ DumpIortNodeNamedComponent (
              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
+  while ((*(Ptr + Offset) != 0) &&\r
+         (Offset < Length)) {\r
+    Print (L"%c", *(Ptr + Offset));\r
+    Offset++;\r
   }\r
   Print (L"\n");\r
 \r
-  if (*IortIdMappingCount != 0) {\r
-    DumpIortNodeIdMappings (Ptr, MappingCount, MappingOffset);\r
-  }\r
+  DumpIortNodeIdMappings (\r
+    Ptr + MappingOffset,\r
+    Length - MappingOffset,\r
+    MappingCount\r
+    );\r
 }\r
 \r
 /**\r
@@ -532,9 +557,11 @@ DumpIortNodeRootComplex (
     PARSER_PARAMS (IortNodeRootComplexParser)\r
     );\r
 \r
-  if (*IortIdMappingCount != 0) {\r
-    DumpIortNodeIdMappings (Ptr, MappingCount, MappingOffset);\r
-  }\r
+  DumpIortNodeIdMappings (\r
+    Ptr + MappingOffset,\r
+    Length - MappingOffset,\r
+    MappingCount\r
+    );\r
 }\r
 \r
 /**\r
@@ -562,19 +589,13 @@ DumpIortNodePmcg (
     Ptr,\r
     Length,\r
     PARSER_PARAMS (IortNodePmcgParser)\r
-  );\r
-\r
-  if (*IortIdMappingCount != 0) {\r
-    DumpIortNodeIdMappings (Ptr, MappingCount, MappingOffset);\r
-  }\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
+  DumpIortNodeIdMappings (\r
+    Ptr + MappingOffset,\r
+    Length - MappingOffset,\r
+    MappingCount\r
+    );\r
 }\r
 \r
 /**\r
@@ -621,23 +642,63 @@ ParseAcpiIort (
     AcpiTableLength,\r
     PARSER_PARAMS (IortParser)\r
     );\r
+\r
+  // Check if the values used to control the parsing logic have been\r
+  // successfully read.\r
+  if ((IortNodeCount == NULL) ||\r
+      (IortNodeOffset == NULL)) {\r
+    IncrementErrorCount ();\r
+    Print (\r
+      L"ERROR: Insufficient table length. AcpiTableLength = %d.\n",\r
+      AcpiTableLength\r
+      );\r
+    return;\r
+  }\r
+\r
   Offset = *IortNodeOffset;\r
   NodePtr = Ptr + Offset;\r
   Index = 0;\r
 \r
-  while ((Index < *IortNodeCount) && (Offset < AcpiTableLength)) {\r
+  // Parse the specified number of IORT nodes or the IORT table buffer length.\r
+  // Whichever is minimum.\r
+  while ((Index++ < *IortNodeCount) &&\r
+         (Offset < AcpiTableLength)) {\r
     // Parse the IORT Node Header\r
     ParseAcpi (\r
       FALSE,\r
       0,\r
       "IORT Node Header",\r
       NodePtr,\r
-      16,\r
+      AcpiTableLength - Offset,\r
       PARSER_PARAMS (IortNodeHeaderParser)\r
       );\r
-    if (*IortNodeLength == 0) {\r
+\r
+    // Check if the values used to control the parsing logic have been\r
+    // successfully read.\r
+    if ((IortNodeType == NULL)        ||\r
+        (IortNodeLength == NULL)      ||\r
+        (IortIdMappingCount == NULL)  ||\r
+        (IortIdMappingOffset == NULL)) {\r
+      IncrementErrorCount ();\r
+      Print (\r
+        L"ERROR: Insufficient remaining table buffer length to read the " \\r
+          L"IORT node header. Length = %d.\n",\r
+        AcpiTableLength - Offset\r
+        );\r
+      return;\r
+    }\r
+\r
+    // Validate IORT Node length\r
+    if ((*IortNodeLength == 0) ||\r
+        ((Offset + (*IortNodeLength)) > AcpiTableLength)) {\r
       IncrementErrorCount ();\r
-      Print (L"ERROR: Parser error. Invalid table data.\n");\r
+      Print (\r
+        L"ERROR: Invalid IORT Node length. " \\r
+          L"Length = %d. Offset = %d. AcpiTableLength = %d.\n",\r
+        *IortNodeLength,\r
+        Offset,\r
+        AcpiTableLength\r
+        );\r
       return;\r
     }\r
 \r