Add checking code for GenAcpiTable tools.
[people/mcb30/edk2.git] / edk2 / Tools / CCode / Source / GenAcpiTable / GenAcpiTable.c
index 457ac65..ec866d3 100644 (file)
@@ -29,6 +29,15 @@ Abstract:
 #include "CommonLib.h"\r
 #include "EfiUtilityMsgs.h"\r
 \r
+//\r
+// Acpi Table definition\r
+//\r
+#include "Acpi.h"\r
+#include "Acpi1_0.h"\r
+#include "Acpi2_0.h"\r
+#include "Acpi3_0.h"\r
+#include "MemoryMappedConfigurationSpaceAccessTable.h"\r
+\r
 //\r
 // Version of this utility\r
 //\r
@@ -101,6 +110,13 @@ ParseCommandLine (
   char      *Argv[]\r
   );\r
 \r
+static\r
+STATUS\r
+CheckAcpiTable (\r
+  VOID      *AcpiTable,\r
+  UINT32    Length\r
+  );\r
+\r
 static\r
 STATUS\r
 CheckPE32File (\r
@@ -303,6 +319,15 @@ Returns:
         Error (NULL, 0, 0, InFileName, "failed to .data section");\r
         goto Finish;\r
       }\r
+\r
+      //\r
+      // Check Acpi Table\r
+      //\r
+      if (CheckAcpiTable (Buffer, SectionHeader.Misc.VirtualSize) != STATUS_SUCCESS) {\r
+        Error (NULL, 0, 0, InFileName, "failed to check ACPI table");\r
+        goto Finish;\r
+      }\r
+\r
       //\r
       // Now open our output file\r
       //\r
@@ -348,6 +373,147 @@ Finish:
   return Status;\r
 }\r
 \r
+static\r
+STATUS\r
+CheckAcpiTable (\r
+  VOID      *AcpiTable,\r
+  UINT32    Length\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+  Check Acpi Table \r
+\r
+Arguments:\r
+\r
+  AcpiTable     Buffer for AcpiSection\r
+  Length        AcpiSection Length\r
+\r
+Returns:\r
+\r
+  0             success\r
+  non-zero      otherwise\r
+\r
+--*/\r
+{\r
+  EFI_ACPI_DESCRIPTION_HEADER                   *AcpiHeader;\r
+  EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE  *Facs;\r
+  UINT32                                        ExpectedLength;\r
+\r
+  AcpiHeader = (EFI_ACPI_DESCRIPTION_HEADER *)AcpiTable;\r
+\r
+  //\r
+  // Generic check for AcpiTable length.\r
+  //\r
+  if (AcpiHeader->Length > Length) {\r
+    Error (NULL, 0, 0, "CheckAcpiTable", "failed to pass AcpiTable Length check");\r
+    return STATUS_ERROR;\r
+  }\r
+\r
+  //\r
+  // Currently, we only check must-have tables: FADT, FACS, DSDT,\r
+  // and some important tables: MADT, MCFG.\r
+  //\r
+  switch (AcpiHeader->Signature) {\r
+\r
+  //\r
+  // "FACP" Fixed ACPI Description Table\r
+  //\r
+  case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:\r
+    switch (AcpiHeader->Revision) {\r
+    case EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION:\r
+      ExpectedLength = sizeof(EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE);\r
+      break;\r
+    case EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION:\r
+      ExpectedLength = sizeof(EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE);\r
+      break;\r
+    case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION:\r
+      ExpectedLength = sizeof(EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE);\r
+      break;\r
+    default:\r
+      Error (NULL, 0, 0, "CheckAcpiTable", "failed to pass FACP revision check");\r
+      return STATUS_ERROR;\r
+    }\r
+    if (ExpectedLength != AcpiHeader->Length) {\r
+      Error (NULL, 0, 0, "CheckAcpiTable", "failed to pass FACP Length check");\r
+      return STATUS_ERROR;\r
+    }\r
+    break;\r
+\r
+  //\r
+  // "FACS" Firmware ACPI Control Structure\r
+  //\r
+  case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE:\r
+    Facs = (EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)AcpiTable;\r
+    if ((Facs->Version != 0) &&\r
+        (Facs->Version != EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) &&\r
+        (Facs->Version != EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION)){\r
+      Error (NULL, 0, 0, "CheckAcpiTable", "failed to pass FACS version check");\r
+      return STATUS_ERROR;\r
+    }\r
+    if ((Facs->Length != sizeof(EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE)) &&\r
+        (Facs->Length != sizeof(EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE)) &&\r
+        (Facs->Length != sizeof(EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE))) {\r
+      Error (NULL, 0, 0, "CheckAcpiTable", "failed to pass FACS Length check");\r
+      return STATUS_ERROR;\r
+    }\r
+    break;\r
+\r
+  //\r
+  // "DSDT" Differentiated System Description Table\r
+  //\r
+  case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:\r
+    if (AcpiHeader->Revision > EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_REVISION) {\r
+      Error (NULL, 0, 0, "CheckAcpiTable", "failed to pass DSDT revision check");\r
+      return STATUS_ERROR;\r
+    }\r
+    if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER)) {\r
+      Error (NULL, 0, 0, "CheckAcpiTable", "failed to pass DSDT Length check");\r
+      return STATUS_ERROR;\r
+    }\r
+    break;\r
+\r
+  //\r
+  // "APIC" Multiple APIC Description Table\r
+  //\r
+  case EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:\r
+    if ((AcpiHeader->Revision != EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION) &&\r
+        (AcpiHeader->Revision != EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION) &&\r
+        (AcpiHeader->Revision != EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION)) {\r
+      Error (NULL, 0, 0, "CheckAcpiTable", "failed to pass APIC revision check");\r
+      return STATUS_ERROR;\r
+    }\r
+    if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER) + sizeof(UINT32) + sizeof(UINT32)) {\r
+      Error (NULL, 0, 0, "CheckAcpiTable", "failed to pass APIC Length check");\r
+      return STATUS_ERROR;\r
+    }\r
+    break;\r
+\r
+  //\r
+  // "MCFG" PCI Express Memory Mapped Configuration Space Base Address Description Table\r
+  //\r
+  case EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE:\r
+    if (AcpiHeader->Revision != EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION) {\r
+      Error (NULL, 0, 0, "CheckAcpiTable", "failed to pass MCFG revision check");\r
+      return STATUS_ERROR;\r
+    }\r
+    if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER) + sizeof(UINT64)) {\r
+      Error (NULL, 0, 0, "CheckAcpiTable", "failed to pass MCFG Length check");\r
+      return STATUS_ERROR;\r
+    }\r
+    break;\r
+\r
+  //\r
+  // Other table pass check\r
+  //\r
+  default:\r
+    break;\r
+  }\r
+\r
+  return STATUS_SUCCESS;\r
+}\r
+\r
 static\r
 STATUS\r
 CheckPE32File (\r