]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableProtocol.c
MdeModulePkg/AcpiTableDxe: improve FADT.{DSDT,X_DSDT} mutual exclusion
[mirror_edk2.git] / MdeModulePkg / Universal / Acpi / AcpiTableDxe / AcpiTableProtocol.c
index f6229ca05c101ab2bf1ea4f8f7be03c1ab88d1ea..4bb848df5203f01e2ed92b39fc035a494fe65eb0 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   ACPI Table Protocol Implementation\r
 \r
-  Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>\r
   Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>\r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
@@ -430,6 +430,51 @@ ReallocateAcpiTableBuffer (
   mEfiAcpiMaxNumTables = NewMaxTableNumber;\r
   return EFI_SUCCESS;\r
 }\r
+\r
+/**\r
+  Determine whether the FADT table passed in as parameter requires mutual\r
+  exclusion between the DSDT and X_DSDT fields. (That is, whether there exists\r
+  an explicit requirement that at most one of those fields is permitted to be\r
+  nonzero.)\r
+\r
+  @param[in] Fadt  The EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE object to\r
+                   check.\r
+\r
+  @retval TRUE     Fadt requires mutual exclusion between DSDT and X_DSDT.\r
+  @retval FALSE    Otherwise.\r
+**/\r
+BOOLEAN\r
+RequireDsdtXDsdtExclusion (\r
+  IN EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt\r
+  )\r
+{\r
+  //\r
+  // Mantis ticket #1393 was addressed in ACPI 5.1 Errata B. Unfortunately, we\r
+  // can't tell apart 5.1 Errata A and 5.1 Errata B just from looking at the\r
+  // FADT table. Therefore let's require exclusion for table versions >= 5.1.\r
+  //\r
+  // While this needlessly covers 5.1 and 5.1A too, it is safer to require\r
+  // DSDT<->X_DSDT exclusion for lax (5.1, 5.1A) versions of the spec than to\r
+  // permit DSDT<->X_DSDT duplication for strict (5.1B) versions of the spec.\r
+  //\r
+  // The same applies to 6.0 vs. 6.0A. While 6.0 does not require the\r
+  // exclusion, 6.0A and 6.1 do. Since we cannot distinguish 6.0 from 6.0A\r
+  // based on just the FADT, we lump 6.0 in with the rest of >= 5.1.\r
+  //\r
+  if ((Fadt->Header.Revision < 5) ||\r
+      ((Fadt->Header.Revision == 5) &&\r
+       (((EFI_ACPI_5_1_FIXED_ACPI_DESCRIPTION_TABLE *)Fadt)->MinorVersion == 0))) {\r
+    //\r
+    // version <= 5.0\r
+    //\r
+    return FALSE;\r
+  }\r
+  //\r
+  // version >= 5.1\r
+  //\r
+  return TRUE;\r
+}\r
+\r
 /**\r
   This function adds an ACPI table to the table list.  It will detect FACS and\r
   allocate the correct type of memory and properly align the table.\r
@@ -646,17 +691,17 @@ AddTableToList (
         AcpiTableInstance->Fadt3->FirmwareCtrl = 0;\r
       }\r
       if ((UINT64)(UINTN)AcpiTableInstance->Dsdt3 < BASE_4GB) {\r
-        AcpiTableInstance->Fadt3->Dsdt  = (UINT32) (UINTN) AcpiTableInstance->Dsdt3;\r
-        ZeroMem (&AcpiTableInstance->Fadt3->XDsdt, sizeof (UINT64));\r
+        AcpiTableInstance->Fadt3->Dsdt = (UINT32) (UINTN) AcpiTableInstance->Dsdt3;\r
+        if (RequireDsdtXDsdtExclusion (AcpiTableInstance->Fadt3)) {\r
+          Buffer64 = 0;\r
+        } else {\r
+          Buffer64 = AcpiTableInstance->Fadt3->Dsdt;\r
+        }\r
       } else {\r
-        Buffer64                          = (UINT64) (UINTN) AcpiTableInstance->Dsdt3;\r
-        CopyMem (\r
-          &AcpiTableInstance->Fadt3->XDsdt,\r
-          &Buffer64,\r
-          sizeof (UINT64)\r
-          );\r
         AcpiTableInstance->Fadt3->Dsdt = 0;\r
+        Buffer64 = (UINT64) (UINTN) AcpiTableInstance->Dsdt3;\r
       }\r
+      CopyMem (&AcpiTableInstance->Fadt3->XDsdt, &Buffer64, sizeof (UINT64));\r
 \r
       //\r
       // RSDP OEM information is updated to match the FADT OEM information\r
@@ -850,14 +895,17 @@ AddTableToList (
       //\r
       if (AcpiTableInstance->Fadt3 != NULL) {\r
         if ((UINT64)(UINTN)AcpiTableInstance->Dsdt3 < BASE_4GB) {\r
-          AcpiTableInstance->Fadt3->Dsdt  = (UINT32) (UINTN) AcpiTableInstance->Dsdt3;\r
+          AcpiTableInstance->Fadt3->Dsdt = (UINT32) (UINTN) AcpiTableInstance->Dsdt3;\r
+          if (RequireDsdtXDsdtExclusion (AcpiTableInstance->Fadt3)) {\r
+            Buffer64 = 0;\r
+          } else {\r
+            Buffer64 = AcpiTableInstance->Fadt3->Dsdt;\r
+          }\r
+        } else {\r
+          AcpiTableInstance->Fadt3->Dsdt = 0;\r
+          Buffer64 = (UINT64) (UINTN) AcpiTableInstance->Dsdt3;\r
         }\r
-        Buffer64                          = (UINT64) (UINTN) AcpiTableInstance->Dsdt3;\r
-        CopyMem (\r
-          &AcpiTableInstance->Fadt3->XDsdt,\r
-          &Buffer64,\r
-          sizeof (UINT64)\r
-          );\r
+        CopyMem (&AcpiTableInstance->Fadt3->XDsdt, &Buffer64, sizeof (UINT64));\r
 \r
         //\r
         // Checksum FADT table\r
@@ -1132,7 +1180,7 @@ RemoveTableFromRsdt (
     //\r
     // Check if we have found the corresponding entry in both RSDT and XSDT\r
     //\r
-    if ((CurrentRsdtEntry == NULL || *CurrentRsdtEntry == (UINT32) (UINTN) Table->Table) &&\r
+    if (((Rsdt == NULL) || *CurrentRsdtEntry == (UINT32) (UINTN) Table->Table) &&\r
         ((Xsdt == NULL) || CurrentTablePointer64 == (UINT64) (UINTN) Table->Table)\r
         ) {\r
       //\r