]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Madt/MadtParser.c
ShellPkg: Parse I/O APIC and x2APIC structure
[mirror_edk2.git] / ShellPkg / Library / UefiShellAcpiViewCommandLib / Parsers / Madt / MadtParser.c
index 59c3df0cc8a080497b517baf36fc63f1e4ab866f..2ba8c9ae521ac84b8742e23f30682050f27743e9 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   MADT 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
@@ -15,6 +15,7 @@
 #include <Library/UefiLib.h>\r
 #include "AcpiParser.h"\r
 #include "AcpiTableParser.h"\r
+#include "AcpiViewConfig.h"\r
 #include "MadtParser.h"\r
 \r
 // Local Variables\r
@@ -35,7 +36,15 @@ EFIAPI
 ValidateGICDSystemVectorBase (\r
   IN UINT8* Ptr,\r
   IN VOID*  Context\r
-  );\r
+)\r
+{\r
+  if (*(UINT32*)Ptr != 0) {\r
+    IncrementErrorCount ();\r
+    Print (\r
+      L"\nERROR: System Vector Base must be zero."\r
+    );\r
+  }\r
+}\r
 \r
 /**\r
   This function validates the SPE Overflow Interrupt in the GICC.\r
@@ -50,7 +59,41 @@ EFIAPI
 ValidateSpeOverflowInterrupt (\r
   IN UINT8* Ptr,\r
   IN VOID*  Context\r
-  );\r
+  )\r
+{\r
+  UINT16 SpeOverflowInterrupt;\r
+\r
+  SpeOverflowInterrupt = *(UINT16*)Ptr;\r
+\r
+  // SPE not supported by this processor\r
+  if (SpeOverflowInterrupt == 0) {\r
+    return;\r
+  }\r
+\r
+  if ((SpeOverflowInterrupt < ARM_PPI_ID_MIN) ||\r
+      ((SpeOverflowInterrupt > ARM_PPI_ID_MAX) &&\r
+       (SpeOverflowInterrupt < ARM_PPI_ID_EXTENDED_MIN)) ||\r
+      (SpeOverflowInterrupt > ARM_PPI_ID_EXTENDED_MAX)) {\r
+    IncrementErrorCount ();\r
+    Print (\r
+      L"\nERROR: SPE Overflow Interrupt ID of %d is not in the allowed PPI ID "\r
+        L"ranges of %d-%d or %d-%d (for GICv3.1 or later).",\r
+      SpeOverflowInterrupt,\r
+      ARM_PPI_ID_MIN,\r
+      ARM_PPI_ID_MAX,\r
+      ARM_PPI_ID_EXTENDED_MIN,\r
+      ARM_PPI_ID_EXTENDED_MAX\r
+    );\r
+  } else if (SpeOverflowInterrupt != ARM_PPI_ID_PMBIRQ) {\r
+    IncrementWarningCount();\r
+    Print (\r
+      L"\nWARNING: SPE Overflow Interrupt ID of %d is not compliant with SBSA "\r
+        L"Level 3 PPI ID assignment: %d.",\r
+      SpeOverflowInterrupt,\r
+      ARM_PPI_ID_PMBIRQ\r
+    );\r
+  }\r
+}\r
 \r
 /**\r
   An ACPI_PARSER array describing the GICC Interrupt Controller Structure.\r
@@ -138,6 +181,57 @@ STATIC CONST ACPI_PARSER GicITSParser[] = {
   {L"Reserved", 4, 16, L"0x%x", NULL, NULL, NULL, NULL}\r
 };\r
 \r
+/**\r
+  An ACPI_PARSER array describing the IO APIC Structure.\r
+**/\r
+STATIC CONST ACPI_PARSER IoApic[] = {\r
+  {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL},\r
+  {L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL},\r
+  {L"I/O APIC ID", 1, 2, L"0x%x", NULL, NULL, NULL, NULL},\r
+  {L"Reserved", 1, 3, L"0x%x", NULL, NULL, NULL, NULL},\r
+  {L"I/O APIC Address", 4, 4, L"0x%x", NULL, NULL, NULL, NULL},\r
+  {L"Global System Interrupt Base", 4, 8, L"0x%x", NULL, NULL, NULL, NULL}\r
+};\r
+\r
+/**\r
+  An ACPI_PARSER array describing the Interrupt Source Override Structure.\r
+**/\r
+STATIC CONST ACPI_PARSER InterruptSourceOverride[] = {\r
+  {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL},\r
+  {L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL},\r
+  {L"Bus", 1, 2, L"0x%x", NULL, NULL, NULL, NULL},\r
+  {L"Source", 1, 3, L"0x%x", NULL, NULL, NULL, NULL},\r
+  {L"Global System Interrupt", 4, 4, L"0x%x", NULL, NULL, NULL, NULL},\r
+  {L"Flags", 2, 8, L"0x%x", NULL, NULL, NULL, NULL}\r
+};\r
+\r
+\r
+/**\r
+  An ACPI_PARSER array describing the Processor Local x2APIC Structure.\r
+**/\r
+STATIC CONST ACPI_PARSER ProcessorLocalX2Apic[] = {\r
+  {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL},\r
+  {L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL},\r
+  {L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL},\r
+\r
+  {L"X2APIC ID", 4, 4, L"0x%x", NULL, NULL, NULL, NULL},\r
+  {L"Flags", 4, 8, L"0x%x", NULL, NULL, NULL, NULL},\r
+  {L"ACPI Processor UID", 4, 12, L"0x%x", NULL, NULL, NULL, NULL}\r
+};\r
+\r
+/**\r
+  An ACPI_PARSER array describing the Local x2APIC NMI Structure.\r
+**/\r
+STATIC CONST ACPI_PARSER LocalX2ApicNmi[] = {\r
+  {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL},\r
+  {L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL},\r
+  {L"Flags", 2, 2, L"0x%x", NULL, NULL, NULL, NULL},\r
+\r
+  {L"ACPI Processor UID", 4, 4, L"0x%x", NULL, NULL, NULL, NULL},\r
+  {L"Local x2APIC LINT#", 1, 8, L"0x%x", NULL, NULL, NULL, NULL},\r
+  {L"Reserved", 3, 9, L"0x%x%x%x", Dump3Chars, NULL, NULL, NULL}\r
+};\r
+\r
 /**\r
   An ACPI_PARSER array describing the ACPI MADT Table.\r
 **/\r
@@ -158,78 +252,6 @@ STATIC CONST ACPI_PARSER MadtInterruptControllerHeaderParser[] = {
   {L"Reserved", 2, 2, NULL, NULL, NULL, NULL, NULL}\r
 };\r
 \r
-/**\r
-  This function validates the System Vector Base in the GICD.\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
-ValidateGICDSystemVectorBase (\r
-  IN UINT8* Ptr,\r
-  IN VOID*  Context\r
-)\r
-{\r
-  if (*(UINT32*)Ptr != 0) {\r
-    IncrementErrorCount ();\r
-    Print (\r
-      L"\nERROR: System Vector Base must be zero."\r
-    );\r
-  }\r
-}\r
-\r
-/**\r
-  This function validates the SPE Overflow Interrupt in the GICC.\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
-ValidateSpeOverflowInterrupt (\r
-  IN UINT8* Ptr,\r
-  IN VOID*  Context\r
-  )\r
-{\r
-  UINT16 SpeOverflowInterrupt;\r
-\r
-  SpeOverflowInterrupt = *(UINT16*)Ptr;\r
-\r
-  // SPE not supported by this processor\r
-  if (SpeOverflowInterrupt == 0) {\r
-    return;\r
-  }\r
-\r
-  if ((SpeOverflowInterrupt < ARM_PPI_ID_MIN) ||\r
-      ((SpeOverflowInterrupt > ARM_PPI_ID_MAX) &&\r
-       (SpeOverflowInterrupt < ARM_PPI_ID_EXTENDED_MIN)) ||\r
-      (SpeOverflowInterrupt > ARM_PPI_ID_EXTENDED_MAX)) {\r
-    IncrementErrorCount ();\r
-    Print (\r
-      L"\nERROR: SPE Overflow Interrupt ID of %d is not in the allowed PPI ID "\r
-        L"ranges of %d-%d or %d-%d (for GICv3.1 or later).",\r
-      SpeOverflowInterrupt,\r
-      ARM_PPI_ID_MIN,\r
-      ARM_PPI_ID_MAX,\r
-      ARM_PPI_ID_EXTENDED_MIN,\r
-      ARM_PPI_ID_EXTENDED_MAX\r
-    );\r
-  } else if (SpeOverflowInterrupt != ARM_PPI_ID_PMBIRQ) {\r
-    IncrementWarningCount();\r
-    Print (\r
-      L"\nWARNING: SPE Overflow Interrupt ID of %d is not compliant with SBSA "\r
-        L"Level 3 PPI ID assignment: %d.",\r
-      SpeOverflowInterrupt,\r
-      ARM_PPI_ID_PMBIRQ\r
-    );\r
-  }\r
-}\r
-\r
 /**\r
   This function parses the ACPI MADT table.\r
   When trace is enabled this function parses the MADT table and\r
@@ -286,20 +308,35 @@ ParseAcpiMadt (
       0,\r
       NULL,\r
       InterruptContollerPtr,\r
-      2,  //  Length is 1 byte at offset 1\r
+      AcpiTableLength - Offset,\r
       PARSER_PARAMS (MadtInterruptControllerHeaderParser)\r
       );\r
 \r
-    if (((Offset + (*MadtInterruptControllerLength)) > AcpiTableLength) ||\r
-        (*MadtInterruptControllerLength < 4)) {\r
+    // Check if the values used to control the parsing logic have been\r
+    // successfully read.\r
+    if ((MadtInterruptControllerType == NULL) ||\r
+        (MadtInterruptControllerLength == NULL)) {\r
       IncrementErrorCount ();\r
       Print (\r
-         L"ERROR: Invalid Interrupt Controller Length,"\r
-          L" Type = %d, Length = %d\n",\r
-         *MadtInterruptControllerType,\r
-         *MadtInterruptControllerLength\r
-         );\r
-      break;\r
+        L"ERROR: Insufficient remaining table buffer length to read the " \\r
+          L"Interrupt Controller Structure header. Length = %d.\n",\r
+        AcpiTableLength - Offset\r
+        );\r
+      return;\r
+    }\r
+\r
+    // Validate Interrupt Controller Structure length\r
+    if ((*MadtInterruptControllerLength == 0) ||\r
+        ((Offset + (*MadtInterruptControllerLength)) > AcpiTableLength)) {\r
+      IncrementErrorCount ();\r
+      Print (\r
+        L"ERROR: Invalid Interrupt Controller Structure length. " \\r
+          L"Length = %d. Offset = %d. AcpiTableLength = %d.\n",\r
+        *MadtInterruptControllerLength,\r
+        Offset,\r
+        AcpiTableLength\r
+        );\r
+      return;\r
     }\r
 \r
     switch (*MadtInterruptControllerType) {\r
@@ -371,6 +408,54 @@ ParseAcpiMadt (
         break;\r
       }\r
 \r
+      case EFI_ACPI_6_3_IO_APIC: {\r
+        ParseAcpi (\r
+          TRUE,\r
+          2,\r
+          "IO APIC",\r
+          InterruptContollerPtr,\r
+          *MadtInterruptControllerLength,\r
+          PARSER_PARAMS (IoApic)\r
+          );\r
+        break;\r
+      }\r
+\r
+      case EFI_ACPI_6_3_INTERRUPT_SOURCE_OVERRIDE: {\r
+        ParseAcpi (\r
+          TRUE,\r
+          2,\r
+          "INTERRUPT SOURCE OVERRIDE",\r
+          InterruptContollerPtr,\r
+          *MadtInterruptControllerLength,\r
+          PARSER_PARAMS (InterruptSourceOverride)\r
+          );\r
+        break;\r
+      }\r
+\r
+      case EFI_ACPI_6_3_PROCESSOR_LOCAL_X2APIC: {\r
+        ParseAcpi (\r
+          TRUE,\r
+          2,\r
+          "PROCESSOR LOCAL X2APIC",\r
+          InterruptContollerPtr,\r
+          *MadtInterruptControllerLength,\r
+          PARSER_PARAMS (ProcessorLocalX2Apic)\r
+          );\r
+        break;\r
+      }\r
+\r
+      case EFI_ACPI_6_3_LOCAL_X2APIC_NMI: {\r
+        ParseAcpi (\r
+          TRUE,\r
+          2,\r
+          "LOCAL x2APIC NMI",\r
+          InterruptContollerPtr,\r
+          *MadtInterruptControllerLength,\r
+          PARSER_PARAMS (LocalX2ApicNmi)\r
+          );\r
+        break;\r
+      }\r
+\r
       default: {\r
         IncrementErrorCount ();\r
         Print (\r