]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableProtocol.c
MdeModulePkg/AcpiTableDxe: use pool allocation for RSDP if possible
[mirror_edk2.git] / MdeModulePkg / Universal / Acpi / AcpiTableDxe / AcpiTableProtocol.c
index 56a83125e6750f822cd517352471fe8834f3b2ba..5a2afdff27e27816757adda513aa0391603818e0 100644 (file)
@@ -1,14 +1,9 @@
 /** @file\r
   ACPI Table Protocol Implementation\r
 \r
-  Copyright (c) 2006 - 2012, Intel Corporation. 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
-  which accompanies this distribution.  The full text of the license may be found at\r
-  http://opensource.org/licenses/bsd-license.php\r
-\r
-  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
 //\r
 #include "AcpiTable.h"\r
 //\r
-// The maximum number of tables that pre-allocated. \r
+// The maximum number of tables that pre-allocated.\r
+//\r
+UINTN         mEfiAcpiMaxNumTables = EFI_ACPI_MAX_NUM_TABLES;\r
+\r
+//\r
+// Allocation strategy to use for AllocatePages ().\r
+// Runtime value depends on PcdExposedAcpiTableVersions.\r
 //\r
-UINTN         mEfiAcpiMaxNumTables = EFI_ACPI_MAX_NUM_TABLES; \r
+STATIC EFI_ALLOCATE_TYPE      mAcpiTableAllocType;\r
 \r
 /**\r
   This function adds an ACPI table to the table list.  It will detect FACS and\r
@@ -98,109 +99,6 @@ ChecksumCommonTables (
 // Protocol function implementations.\r
 //\r
 \r
-/**\r
-  This function adds, removes, or updates ACPI tables.  If the address is not\r
-  null and the handle value is null, the table is added.  If both the address and \r
-  handle are not null, the table at handle is updated with the table at address.\r
-  If the address is null and the handle is not, the table at handle is deleted.\r
-\r
-  @param  AcpiTableInstance  Instance of the protocol.\r
-  @param  Table              Pointer to a table.\r
-  @param  Checksum           Boolean indicating if the checksum should be calculated.\r
-  @param  Version            Version(s) to set.\r
-  @param  Handle             Handle of the table.\r
-\r
-  @return EFI_SUCCESS             The function completed successfully.\r
-  @return EFI_INVALID_PARAMETER   Both the Table and *Handle were NULL.\r
-  @return EFI_ABORTED             Could not complete the desired request.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-SetAcpiTable (\r
-  IN EFI_ACPI_TABLE_INSTANCE              *AcpiTableInstance,\r
-  IN VOID                                 *Table OPTIONAL,\r
-  IN BOOLEAN                              Checksum,\r
-  IN EFI_ACPI_TABLE_VERSION               Version,\r
-  IN OUT UINTN                            *Handle\r
-  )\r
-{\r
-  UINTN                     SavedHandle;\r
-  EFI_STATUS                Status;\r
-\r
-  //\r
-  // Check for invalid input parameters\r
-  //\r
-  ASSERT (Handle);\r
-\r
-  //\r
-  // Initialize locals\r
-  //\r
-  //\r
-  // Determine desired action\r
-  //\r
-  if (*Handle == 0) {\r
-    if (Table == NULL) {\r
-      //\r
-      // Invalid parameter combination\r
-      //\r
-      return EFI_INVALID_PARAMETER;\r
-    } else {\r
-      //\r
-      // Add table\r
-      //\r
-      Status = AddTableToList (AcpiTableInstance, Table, Checksum, Version, Handle);\r
-    }\r
-  } else {\r
-    if (Table != NULL) {\r
-      //\r
-      // Update table\r
-      //\r
-      //\r
-      // Delete the table list entry\r
-      //\r
-      Status = RemoveTableFromList (AcpiTableInstance, Version, *Handle);\r
-      if (EFI_ERROR (Status)) {\r
-        //\r
-        // Should not get an error here ever, but abort if we do.\r
-        //\r
-        return EFI_ABORTED;\r
-      }\r
-      //\r
-      // Set the handle to replace the table at the same handle\r
-      //\r
-      SavedHandle                         = AcpiTableInstance->CurrentHandle;\r
-      AcpiTableInstance->CurrentHandle  = *Handle;\r
-\r
-      //\r
-      // Add the table\r
-      //\r
-      Status = AddTableToList (AcpiTableInstance, Table, Checksum, Version, Handle);\r
-\r
-      //\r
-      // Restore the saved current handle\r
-      //\r
-      AcpiTableInstance->CurrentHandle = SavedHandle;\r
-    } else {\r
-      //\r
-      // Delete table\r
-      //\r
-      Status = RemoveTableFromList (AcpiTableInstance, Version, *Handle);\r
-    }\r
-  }\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    //\r
-    // Should not get an error here ever, but abort if we do.\r
-    //\r
-    return EFI_ABORTED;\r
-  }\r
-  //\r
-  // Done\r
-  //\r
-  return EFI_SUCCESS;\r
-}\r
-\r
 /**\r
   This function publishes the specified versions of the ACPI tables by\r
   installing EFI configuration table entries for them.  Any combination of\r
@@ -236,11 +134,11 @@ PublishTables (
   if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {\r
     CurrentRsdtEntry  = (UINT32 *) ((UINT8 *) AcpiTableInstance->Rsdt1 + sizeof (EFI_ACPI_DESCRIPTION_HEADER));\r
     *CurrentRsdtEntry = (UINT32) (UINTN) AcpiTableInstance->Fadt1;\r
-  }\r
-  if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||\r
-      (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) {\r
+\r
     CurrentRsdtEntry  = (UINT32 *) ((UINT8 *) AcpiTableInstance->Rsdt3 + sizeof (EFI_ACPI_DESCRIPTION_HEADER));\r
     *CurrentRsdtEntry = (UINT32) (UINTN) AcpiTableInstance->Fadt3;\r
+  }\r
+  if ((Version & ACPI_TABLE_VERSION_GTE_2_0) != 0) {\r
     CurrentXsdtEntry  = (VOID *) ((UINT8 *) AcpiTableInstance->Xsdt + sizeof (EFI_ACPI_DESCRIPTION_HEADER));\r
     //\r
     // Add entry to XSDT, XSDT expects 64 bit pointers, but\r
@@ -263,25 +161,18 @@ PublishTables (
   // Add the RSD_PTR to the system table and store that we have installed the\r
   // tables.\r
   //\r
-  if (((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) &&\r
-      !AcpiTableInstance->TablesInstalled1) {\r
+  if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {\r
     Status = gBS->InstallConfigurationTable (&gEfiAcpi10TableGuid, AcpiTableInstance->Rsdp1);\r
     if (EFI_ERROR (Status)) {\r
       return EFI_ABORTED;\r
     }\r
-\r
-    AcpiTableInstance->TablesInstalled1 = TRUE;\r
   }\r
 \r
-  if (((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||\r
-       (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) &&\r
-      !AcpiTableInstance->TablesInstalled3) {\r
+  if ((Version & ACPI_TABLE_VERSION_GTE_2_0) != 0) {\r
     Status = gBS->InstallConfigurationTable (&gEfiAcpiTableGuid, AcpiTableInstance->Rsdp3);\r
     if (EFI_ERROR (Status)) {\r
       return EFI_ABORTED;\r
     }\r
-\r
-    AcpiTableInstance->TablesInstalled3= TRUE;\r
   }\r
 \r
   return EFI_SUCCESS;\r
@@ -299,10 +190,13 @@ PublishTables (
   @param  TableKey             Reurns a key to refer to the ACPI table.\r
 \r
   @return EFI_SUCCESS            The table was successfully inserted.\r
-  @return EFI_INVALID_PARAMETER  Either AcpiTableBuffer is NULL, TableKey is NULL, or AcpiTableBufferSize \r
+  @return EFI_INVALID_PARAMETER  Either AcpiTableBuffer is NULL, TableKey is NULL, or AcpiTableBufferSize\r
                                  and the size field embedded in the ACPI table pointed to by AcpiTableBuffer\r
                                  are not in sync.\r
   @return EFI_OUT_OF_RESOURCES   Insufficient resources exist to complete the request.\r
+  @retval EFI_ACCESS_DENIED      The table signature matches a table already\r
+                                 present in the system and platform policy\r
+                                 does not allow duplicate tables of this type.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -317,6 +211,7 @@ InstallAcpiTable (
   EFI_ACPI_TABLE_INSTANCE   *AcpiTableInstance;\r
   EFI_STATUS                Status;\r
   VOID                      *AcpiTableBufferConst;\r
+  EFI_ACPI_TABLE_VERSION    Version;\r
 \r
   //\r
   // Check for invalid input parameters\r
@@ -326,6 +221,8 @@ InstallAcpiTable (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
+  Version = PcdGet32 (PcdAcpiExposedTableVersions);\r
+\r
   //\r
   // Get the instance of the ACPI table protocol\r
   //\r
@@ -336,21 +233,21 @@ InstallAcpiTable (
   //\r
   AcpiTableBufferConst = AllocateCopyPool (AcpiTableBufferSize,AcpiTableBuffer);\r
   *TableKey = 0;\r
-  Status = SetAcpiTable (\r
+  Status = AddTableToList (\r
              AcpiTableInstance,\r
              AcpiTableBufferConst,\r
              TRUE,\r
-             EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0,\r
+             Version,\r
              TableKey\r
              );\r
   if (!EFI_ERROR (Status)) {\r
     Status = PublishTables (\r
                AcpiTableInstance,\r
-               EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0\r
+               Version\r
                );\r
   }\r
   FreePool (AcpiTableBufferConst);\r
-  \r
+\r
   //\r
   // Add a new table successfully, notify registed callback\r
   //\r
@@ -358,7 +255,7 @@ InstallAcpiTable (
     if (!EFI_ERROR (Status)) {\r
       SdtNotifyAcpiList (\r
         AcpiTableInstance,\r
-        EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0,\r
+        Version,\r
         *TableKey\r
         );\r
     }\r
@@ -387,26 +284,27 @@ UninstallAcpiTable (
 {\r
   EFI_ACPI_TABLE_INSTANCE   *AcpiTableInstance;\r
   EFI_STATUS                Status;\r
+  EFI_ACPI_TABLE_VERSION    Version;\r
 \r
   //\r
   // Get the instance of the ACPI table protocol\r
   //\r
   AcpiTableInstance = EFI_ACPI_TABLE_INSTANCE_FROM_THIS (This);\r
 \r
+  Version = PcdGet32 (PcdAcpiExposedTableVersions);\r
+\r
   //\r
   // Uninstall the ACPI table\r
   //\r
-  Status = SetAcpiTable (\r
+  Status = RemoveTableFromList (\r
              AcpiTableInstance,\r
-             NULL,\r
-             FALSE,\r
-             EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0,\r
-             &TableKey\r
+             Version,\r
+             TableKey\r
              );\r
   if (!EFI_ERROR (Status)) {\r
     Status = PublishTables (\r
                AcpiTableInstance,\r
-               EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0\r
+               Version\r
                );\r
   }\r
 \r
@@ -438,8 +336,8 @@ ReallocateAcpiTableBuffer (
   EFI_ACPI_TABLE_INSTANCE  TempPrivateData;\r
   EFI_STATUS               Status;\r
   UINT64                   CurrentData;\r
-   \r
-  CopyMem (&TempPrivateData, AcpiTableInstance, sizeof (EFI_ACPI_TABLE_INSTANCE)); \r
+\r
+  CopyMem (&TempPrivateData, AcpiTableInstance, sizeof (EFI_ACPI_TABLE_INSTANCE));\r
   //\r
   // Enlarge the max table number from mEfiAcpiMaxNumTables to mEfiAcpiMaxNumTables + EFI_ACPI_MAX_NUM_TABLES\r
   //\r
@@ -447,75 +345,125 @@ ReallocateAcpiTableBuffer (
   //\r
   // Create RSDT, XSDT structures and allocate buffers.\r
   //\r
-  TotalSize = sizeof (EFI_ACPI_DESCRIPTION_HEADER) +         // for ACPI 1.0 RSDT\r
-              NewMaxTableNumber * sizeof (UINT32) +\r
-              sizeof (EFI_ACPI_DESCRIPTION_HEADER) +         // for ACPI 2.0/3.0 RSDT\r
-              NewMaxTableNumber * sizeof (UINT32) +\r
-              sizeof (EFI_ACPI_DESCRIPTION_HEADER) +         // for ACPI 2.0/3.0 XSDT\r
+  TotalSize = sizeof (EFI_ACPI_DESCRIPTION_HEADER) +         // for ACPI 2.0/3.0 XSDT\r
               NewMaxTableNumber * sizeof (UINT64);\r
 \r
-  //\r
-  // Allocate memory in the lower 32 bit of address range for\r
-  // compatibility with ACPI 1.0 OS.\r
-  //\r
-  // This is done because ACPI 1.0 pointers are 32 bit values.\r
-  // ACPI 2.0 OS and all 64 bit OS must use the 64 bit ACPI table addresses.\r
-  // There is no architectural reason these should be below 4GB, it is purely\r
-  // for convenience of implementation that we force memory below 4GB.\r
-  //\r
-  PageAddress = 0xFFFFFFFF;\r
-  Status = gBS->AllocatePages (\r
-                  AllocateMaxAddress,\r
-                  EfiACPIReclaimMemory,\r
-                  EFI_SIZE_TO_PAGES (TotalSize),\r
-                  &PageAddress\r
-                  );\r
+  if ((PcdGet32 (PcdAcpiExposedTableVersions) & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {\r
+    TotalSize += sizeof (EFI_ACPI_DESCRIPTION_HEADER) +      // for ACPI 1.0 RSDT\r
+                 NewMaxTableNumber * sizeof (UINT32) +\r
+                 sizeof (EFI_ACPI_DESCRIPTION_HEADER) +      // for ACPI 2.0/3.0 RSDT\r
+                 NewMaxTableNumber * sizeof (UINT32);\r
+  }\r
+\r
+  if (mAcpiTableAllocType != AllocateAnyPages) {\r
+    //\r
+    // Allocate memory in the lower 32 bit of address range for\r
+    // compatibility with ACPI 1.0 OS.\r
+    //\r
+    // This is done because ACPI 1.0 pointers are 32 bit values.\r
+    // ACPI 2.0 OS and all 64 bit OS must use the 64 bit ACPI table addresses.\r
+    // There is no architectural reason these should be below 4GB, it is purely\r
+    // for convenience of implementation that we force memory below 4GB.\r
+    //\r
+    PageAddress = 0xFFFFFFFF;\r
+    Status = gBS->AllocatePages (\r
+                    mAcpiTableAllocType,\r
+                    EfiACPIReclaimMemory,\r
+                    EFI_SIZE_TO_PAGES (TotalSize),\r
+                    &PageAddress\r
+                    );\r
+  } else {\r
+    Status = gBS->AllocatePool (\r
+                    EfiACPIReclaimMemory,\r
+                    TotalSize,\r
+                    (VOID **)&Pointer\r
+                    );\r
+  }\r
 \r
   if (EFI_ERROR (Status)) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
-  Pointer = (UINT8 *) (UINTN) PageAddress;\r
+  if (mAcpiTableAllocType != AllocateAnyPages) {\r
+    Pointer = (UINT8 *)(UINTN)PageAddress;\r
+  }\r
+\r
   ZeroMem (Pointer, TotalSize);\r
-  \r
+\r
   AcpiTableInstance->Rsdt1 = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;\r
-  Pointer += (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + NewMaxTableNumber * sizeof (UINT32));\r
-  AcpiTableInstance->Rsdt3 = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;\r
-  Pointer += (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + NewMaxTableNumber * sizeof (UINT32));\r
+  if ((PcdGet32 (PcdAcpiExposedTableVersions) & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {\r
+    Pointer += (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + NewMaxTableNumber * sizeof (UINT32));\r
+    AcpiTableInstance->Rsdt3 = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;\r
+    Pointer += (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + NewMaxTableNumber * sizeof (UINT32));\r
+  }\r
   AcpiTableInstance->Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;\r
 \r
   //\r
   // Update RSDP to point to the new Rsdt and Xsdt address.\r
   //\r
-  AcpiTableInstance->Rsdp1->RsdtAddress = (UINT32) (UINTN) AcpiTableInstance->Rsdt1;\r
-  AcpiTableInstance->Rsdp3->RsdtAddress = (UINT32) (UINTN) AcpiTableInstance->Rsdt3;\r
+  if ((PcdGet32 (PcdAcpiExposedTableVersions) & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {\r
+    AcpiTableInstance->Rsdp1->RsdtAddress = (UINT32) (UINTN) AcpiTableInstance->Rsdt1;\r
+    AcpiTableInstance->Rsdp3->RsdtAddress = (UINT32) (UINTN) AcpiTableInstance->Rsdt3;\r
+  }\r
   CurrentData = (UINT64) (UINTN) AcpiTableInstance->Xsdt;\r
   CopyMem (&AcpiTableInstance->Rsdp3->XsdtAddress, &CurrentData, sizeof (UINT64));\r
 \r
   //\r
-  // copy the original Rsdt1, Rsdt3 and Xsdt structure to new buffer \r
+  // copy the original Rsdt1, Rsdt3 and Xsdt structure to new buffer\r
   //\r
-  CopyMem (AcpiTableInstance->Rsdt1, TempPrivateData.Rsdt1, (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + mEfiAcpiMaxNumTables * sizeof (UINT32))); \r
-  CopyMem (AcpiTableInstance->Rsdt3, TempPrivateData.Rsdt3, (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + mEfiAcpiMaxNumTables * sizeof (UINT32))); \r
+  if ((PcdGet32 (PcdAcpiExposedTableVersions) & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {\r
+    CopyMem (AcpiTableInstance->Rsdt1, TempPrivateData.Rsdt1, (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + mEfiAcpiMaxNumTables * sizeof (UINT32)));\r
+    CopyMem (AcpiTableInstance->Rsdt3, TempPrivateData.Rsdt3, (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + mEfiAcpiMaxNumTables * sizeof (UINT32)));\r
+  }\r
   CopyMem (AcpiTableInstance->Xsdt, TempPrivateData.Xsdt, (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + mEfiAcpiMaxNumTables * sizeof (UINT64)));\r
-  \r
-  //\r
-  // Calculate orignal ACPI table buffer size\r
-  //\r
-  TotalSize = sizeof (EFI_ACPI_DESCRIPTION_HEADER) +         // for ACPI 1.0 RSDT\r
-              mEfiAcpiMaxNumTables * sizeof (UINT32) +\r
-              sizeof (EFI_ACPI_DESCRIPTION_HEADER) +         // for ACPI 2.0/3.0 RSDT\r
-              mEfiAcpiMaxNumTables * sizeof (UINT32) +\r
-              sizeof (EFI_ACPI_DESCRIPTION_HEADER) +         // for ACPI 2.0/3.0 XSDT\r
-              mEfiAcpiMaxNumTables * sizeof (UINT64);\r
-  gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)TempPrivateData.Rsdt1, EFI_SIZE_TO_PAGES (TotalSize));\r
-  \r
+\r
+  if (mAcpiTableAllocType != AllocateAnyPages) {\r
+    //\r
+    // Calculate orignal ACPI table buffer size\r
+    //\r
+    TotalSize = sizeof (EFI_ACPI_DESCRIPTION_HEADER) +         // for ACPI 2.0/3.0 XSDT\r
+                mEfiAcpiMaxNumTables * sizeof (UINT64);\r
+\r
+    if ((PcdGet32 (PcdAcpiExposedTableVersions) & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {\r
+      TotalSize += sizeof (EFI_ACPI_DESCRIPTION_HEADER) +         // for ACPI 1.0 RSDT\r
+                   mEfiAcpiMaxNumTables * sizeof (UINT32) +\r
+                   sizeof (EFI_ACPI_DESCRIPTION_HEADER) +         // for ACPI 2.0/3.0 RSDT\r
+                   mEfiAcpiMaxNumTables * sizeof (UINT32);\r
+    }\r
+\r
+    gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)TempPrivateData.Rsdt1,\r
+           EFI_SIZE_TO_PAGES (TotalSize));\r
+  } else {\r
+    gBS->FreePool (TempPrivateData.Rsdt1);\r
+  }\r
+\r
   //\r
   // Update the Max ACPI table number\r
-  // \r
+  //\r
   mEfiAcpiMaxNumTables = NewMaxTableNumber;\r
   return EFI_SUCCESS;\r
 }\r
+\r
+/**\r
+  Free the memory associated with the provided EFI_ACPI_TABLE_LIST instance.\r
+\r
+  @param  TableEntry                EFI_ACPI_TABLE_LIST instance pointer\r
+\r
+**/\r
+STATIC\r
+VOID\r
+FreeTableMemory (\r
+  EFI_ACPI_TABLE_LIST   *TableEntry\r
+  )\r
+{\r
+  if (TableEntry->PoolAllocation) {\r
+    gBS->FreePool (TableEntry->Table);\r
+  } else {\r
+    gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)TableEntry->Table,\r
+           EFI_SIZE_TO_PAGES (TableEntry->TableSize));\r
+  }\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
@@ -528,8 +476,9 @@ ReallocateAcpiTableBuffer (
 \r
   @return EFI_SUCCESS               The function completed successfully.\r
   @return EFI_OUT_OF_RESOURCES      Could not allocate a required resource.\r
-  @return EFI_ABORTED               The table is a duplicate of a table that is required\r
-                                    to be unique.\r
+  @retval EFI_ACCESS_DENIED         The table signature matches a table already\r
+                                    present in the system and platform policy\r
+                                    does not allow duplicate tables of this type.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -541,14 +490,15 @@ AddTableToList (
   OUT UINTN                               *Handle\r
   )\r
 {\r
-  EFI_STATUS          Status;\r
-  EFI_ACPI_TABLE_LIST *CurrentTableList;\r
-  UINT32              CurrentTableSignature;\r
-  UINT32              CurrentTableSize;\r
-  UINT32              *CurrentRsdtEntry;\r
-  VOID                *CurrentXsdtEntry;\r
-  UINT64              Buffer64;\r
-  BOOLEAN             AddToRsdt;\r
+  EFI_STATUS            Status;\r
+  EFI_ACPI_TABLE_LIST   *CurrentTableList;\r
+  UINT32                CurrentTableSignature;\r
+  UINT32                CurrentTableSize;\r
+  UINT32                *CurrentRsdtEntry;\r
+  VOID                  *CurrentXsdtEntry;\r
+  EFI_PHYSICAL_ADDRESS  AllocPhysAddress;\r
+  UINT64                Buffer64;\r
+  BOOLEAN               AddToRsdt;\r
 \r
   //\r
   // Check for invalid input parameters\r
@@ -583,13 +533,14 @@ AddTableToList (
   // There is no architectural reason these should be below 4GB, it is purely\r
   // for convenience of implementation that we force memory below 4GB.\r
   //\r
-  CurrentTableList->PageAddress   = 0xFFFFFFFF;\r
-  CurrentTableList->NumberOfPages = EFI_SIZE_TO_PAGES (CurrentTableSize);\r
+  AllocPhysAddress                  = 0xFFFFFFFF;\r
+  CurrentTableList->TableSize       = CurrentTableSize;\r
+  CurrentTableList->PoolAllocation  = FALSE;\r
 \r
   //\r
   // Allocation memory type depends on the type of the table\r
   //\r
-  if ((CurrentTableSignature == EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) || \r
+  if ((CurrentTableSignature == EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) ||\r
       (CurrentTableSignature == EFI_ACPI_4_0_UEFI_ACPI_DATA_TABLE_SIGNATURE)) {\r
     //\r
     // Allocate memory for the FACS.  This structure must be aligned\r
@@ -605,19 +556,32 @@ AddTableToList (
     Status = gBS->AllocatePages (\r
                     AllocateMaxAddress,\r
                     EfiACPIMemoryNVS,\r
-                    CurrentTableList->NumberOfPages,\r
-                    &CurrentTableList->PageAddress\r
+                    EFI_SIZE_TO_PAGES (CurrentTableList->TableSize),\r
+                    &AllocPhysAddress\r
                     );\r
+  } else if (mAcpiTableAllocType == AllocateAnyPages) {\r
+    //\r
+    // If there is no allocation limit, there is also no need to use page\r
+    // based allocations for ACPI tables, which may be wasteful on platforms\r
+    // such as AArch64 that allocate multiples of 64 KB\r
+    //\r
+    Status = gBS->AllocatePool (\r
+                    EfiACPIReclaimMemory,\r
+                    CurrentTableList->TableSize,\r
+                    (VOID **)&CurrentTableList->Table\r
+                    );\r
+    CurrentTableList->PoolAllocation = TRUE;\r
   } else {\r
     //\r
     // All other tables are ACPI reclaim memory, no alignment requirements.\r
     //\r
     Status = gBS->AllocatePages (\r
-                    AllocateMaxAddress,\r
+                    mAcpiTableAllocType,\r
                     EfiACPIReclaimMemory,\r
-                    CurrentTableList->NumberOfPages,\r
-                    &CurrentTableList->PageAddress\r
+                    EFI_SIZE_TO_PAGES (CurrentTableList->TableSize),\r
+                    &AllocPhysAddress\r
                     );\r
+    CurrentTableList->Table = (EFI_ACPI_COMMON_HEADER *)(UINTN)AllocPhysAddress;\r
   }\r
   //\r
   // Check return value from memory alloc.\r
@@ -626,10 +590,10 @@ AddTableToList (
     gBS->FreePool (CurrentTableList);\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
-  //\r
-  // Update the table pointer with the allocated memory start\r
-  //\r
-  CurrentTableList->Table = (EFI_ACPI_COMMON_HEADER *) (UINTN) CurrentTableList->PageAddress;\r
+\r
+  if (!CurrentTableList->PoolAllocation) {\r
+    CurrentTableList->Table = (EFI_ACPI_COMMON_HEADER *)(UINTN)AllocPhysAddress;\r
+  }\r
 \r
   //\r
   // Initialize the table contents\r
@@ -660,12 +624,11 @@ AddTableToList (
     // Check that the table has not been previously added.\r
     //\r
     if (((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0 && AcpiTableInstance->Fadt1 != NULL) ||\r
-        ((Version & EFI_ACPI_TABLE_VERSION_2_0)  != 0 && AcpiTableInstance->Fadt3 != NULL) ||\r
-        ((Version & EFI_ACPI_TABLE_VERSION_3_0)  != 0 && AcpiTableInstance->Fadt3 != NULL)\r
+        ((Version & ACPI_TABLE_VERSION_GTE_2_0)  != 0 && AcpiTableInstance->Fadt3 != NULL)\r
         ) {\r
-      gBS->FreePages (CurrentTableList->PageAddress, CurrentTableList->NumberOfPages);\r
+      FreeTableMemory (CurrentTableList);\r
       gBS->FreePool (CurrentTableList);\r
-      return EFI_ABORTED;\r
+      return EFI_ACCESS_DENIED;\r
     }\r
     //\r
     // Add the table to the appropriate table version\r
@@ -708,8 +671,7 @@ AddTableToList (
       AcpiTableInstance->Rsdt1->OemRevision = AcpiTableInstance->Fadt1->Header.OemRevision;\r
     }\r
 \r
-    if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||\r
-        (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) {\r
+    if ((Version & ACPI_TABLE_VERSION_GTE_2_0) != 0) {\r
       //\r
       // Save a pointer to the table\r
       //\r
@@ -717,11 +679,12 @@ AddTableToList (
 \r
       //\r
       // Update pointers in FADT.  If tables don't exist this will put NULL pointers there.\r
-      // Note: If the FIRMWARE_CTRL is non-zero, then X_FIRMWARE_CTRL must be zero, and \r
+      // Note: If the FIRMWARE_CTRL is non-zero, then X_FIRMWARE_CTRL must be zero, and\r
       // vice-versa.\r
       //\r
       if ((UINT64)(UINTN)AcpiTableInstance->Facs3 < BASE_4GB) {\r
         AcpiTableInstance->Fadt3->FirmwareCtrl  = (UINT32) (UINTN) AcpiTableInstance->Facs3;\r
+        ZeroMem (&AcpiTableInstance->Fadt3->XFirmwareCtrl, sizeof (UINT64));\r
       } else {\r
         Buffer64 = (UINT64) (UINTN) AcpiTableInstance->Facs3;\r
         CopyMem (\r
@@ -729,14 +692,32 @@ AddTableToList (
           &Buffer64,\r
           sizeof (UINT64)\r
           );\r
+        AcpiTableInstance->Fadt3->FirmwareCtrl = 0;\r
       }\r
-      AcpiTableInstance->Fadt3->Dsdt  = (UINT32) (UINTN) AcpiTableInstance->Dsdt3;\r
-      Buffer64                          = (UINT64) (UINTN) AcpiTableInstance->Dsdt3;\r
-      CopyMem (\r
-        &AcpiTableInstance->Fadt3->XDsdt,\r
-        &Buffer64,\r
-        sizeof (UINT64)\r
-        );\r
+      if ((UINT64)(UINTN)AcpiTableInstance->Dsdt3 < BASE_4GB) {\r
+        AcpiTableInstance->Fadt3->Dsdt = (UINT32) (UINTN) AcpiTableInstance->Dsdt3;\r
+        //\r
+        // Comment block "the caller installs the tables in "DSDT, FADT" order"\r
+        // The below comments are also in "the caller installs the tables in "FADT, DSDT" order" comment block.\r
+        //\r
+        // The ACPI specification, up to and including revision 5.1 Errata A,\r
+        // allows the DSDT and X_DSDT fields to be both set in the FADT.\r
+        // (Obviously, this only makes sense if the DSDT address is representable in 4 bytes.)\r
+        // Starting with 5.1 Errata B, specifically for Mantis 1393 <https://mantis.uefi.org/mantis/view.php?id=1393>,\r
+        // the spec requires at most one of DSDT and X_DSDT fields to be set to a nonzero value,\r
+        // but strangely an exception is 6.0 that has no this requirement.\r
+        //\r
+        // Here we do not make the DSDT and X_DSDT fields mutual exclusion conditionally\r
+        // by checking FADT revision, but always set both DSDT and X_DSDT fields in the FADT\r
+        // to have better compatibility as some OS may have assumption to only consume X_DSDT\r
+        // field even the DSDT address is < 4G.\r
+        //\r
+        Buffer64 = AcpiTableInstance->Fadt3->Dsdt;\r
+      } else {\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
@@ -746,22 +727,24 @@ AddTableToList (
         &AcpiTableInstance->Fadt3->Header.OemId,\r
         6\r
         );\r
-      \r
-      //\r
-      // RSDT OEM information is updated to match FADT OEM information.\r
-      //\r
-      CopyMem (\r
-        &AcpiTableInstance->Rsdt3->OemId,\r
-        &AcpiTableInstance->Fadt3->Header.OemId,\r
-        6\r
-        );\r
-      CopyMem (\r
-        &AcpiTableInstance->Rsdt3->OemTableId,\r
-        &AcpiTableInstance->Fadt3->Header.OemTableId,\r
-        sizeof (UINT64)\r
-        );\r
-      AcpiTableInstance->Rsdt3->OemRevision = AcpiTableInstance->Fadt3->Header.OemRevision;\r
-      \r
+\r
+      if ((PcdGet32 (PcdAcpiExposedTableVersions) & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {\r
+        //\r
+        // RSDT OEM information is updated to match FADT OEM information.\r
+        //\r
+        CopyMem (\r
+          &AcpiTableInstance->Rsdt3->OemId,\r
+          &AcpiTableInstance->Fadt3->Header.OemId,\r
+          6\r
+          );\r
+        CopyMem (\r
+          &AcpiTableInstance->Rsdt3->OemTableId,\r
+          &AcpiTableInstance->Fadt3->Header.OemTableId,\r
+          sizeof (UINT64)\r
+          );\r
+        AcpiTableInstance->Rsdt3->OemRevision = AcpiTableInstance->Fadt3->Header.OemRevision;\r
+      }\r
+\r
       //\r
       // XSDT OEM information is updated to match FADT OEM information.\r
       //\r
@@ -776,7 +759,7 @@ AddTableToList (
         sizeof (UINT64)\r
         );\r
       AcpiTableInstance->Xsdt->OemRevision = AcpiTableInstance->Fadt3->Header.OemRevision;\r
-    }    \r
+    }\r
     //\r
     // Checksum the table\r
     //\r
@@ -795,12 +778,11 @@ AddTableToList (
     // Check that the table has not been previously added.\r
     //\r
     if (((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0 && AcpiTableInstance->Facs1 != NULL) ||\r
-        ((Version & EFI_ACPI_TABLE_VERSION_2_0)  != 0 && AcpiTableInstance->Facs3 != NULL) ||\r
-        ((Version & EFI_ACPI_TABLE_VERSION_3_0)  != 0 && AcpiTableInstance->Facs3 != NULL)\r
+        ((Version & ACPI_TABLE_VERSION_GTE_2_0)  != 0 && AcpiTableInstance->Facs3 != NULL)\r
         ) {\r
-      gBS->FreePages (CurrentTableList->PageAddress, CurrentTableList->NumberOfPages);\r
+      FreeTableMemory (CurrentTableList);\r
       gBS->FreePool (CurrentTableList);\r
-      return EFI_ABORTED;\r
+      return EFI_ACCESS_DENIED;\r
     }\r
     //\r
     // FACS is referenced by FADT and is not part of RSDT\r
@@ -834,8 +816,7 @@ AddTableToList (
       }\r
     }\r
 \r
-    if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||\r
-        (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) {\r
+    if ((Version & ACPI_TABLE_VERSION_GTE_2_0) != 0) {\r
       //\r
       // Save a pointer to the table\r
       //\r
@@ -846,11 +827,12 @@ AddTableToList (
       //\r
       if (AcpiTableInstance->Fadt3 != NULL) {\r
         //\r
-        // Note: If the FIRMWARE_CTRL is non-zero, then X_FIRMWARE_CTRL must be zero, and \r
+        // Note: If the FIRMWARE_CTRL is non-zero, then X_FIRMWARE_CTRL must be zero, and\r
         // vice-versa.\r
         //\r
         if ((UINT64)(UINTN)AcpiTableInstance->Facs3 < BASE_4GB) {\r
           AcpiTableInstance->Fadt3->FirmwareCtrl  = (UINT32) (UINTN) AcpiTableInstance->Facs3;\r
+          ZeroMem (&AcpiTableInstance->Fadt3->XFirmwareCtrl, sizeof (UINT64));\r
         } else {\r
           Buffer64 = (UINT64) (UINTN) AcpiTableInstance->Facs3;\r
           CopyMem (\r
@@ -858,6 +840,7 @@ AddTableToList (
             &Buffer64,\r
             sizeof (UINT64)\r
             );\r
+          AcpiTableInstance->Fadt3->FirmwareCtrl = 0;\r
         }\r
 \r
         //\r
@@ -879,12 +862,11 @@ AddTableToList (
     // Check that the table has not been previously added.\r
     //\r
     if (((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0 && AcpiTableInstance->Dsdt1 != NULL) ||\r
-        ((Version & EFI_ACPI_TABLE_VERSION_2_0)  != 0 && AcpiTableInstance->Dsdt3 != NULL) ||\r
-        ((Version & EFI_ACPI_TABLE_VERSION_3_0)  != 0 && AcpiTableInstance->Dsdt3 != NULL)\r
+        ((Version & ACPI_TABLE_VERSION_GTE_2_0)  != 0 && AcpiTableInstance->Dsdt3 != NULL)\r
         ) {\r
-      gBS->FreePages (CurrentTableList->PageAddress, CurrentTableList->NumberOfPages);\r
+      FreeTableMemory (CurrentTableList);\r
       gBS->FreePool (CurrentTableList);\r
-      return EFI_ABORTED;\r
+      return EFI_ACCESS_DENIED;\r
     }\r
     //\r
     // DSDT is referenced by FADT and is not part of RSDT\r
@@ -917,9 +899,8 @@ AddTableToList (
           );\r
       }\r
     }\r
-    \r
-    if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||\r
-        (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) {\r
+\r
+    if ((Version & ACPI_TABLE_VERSION_GTE_2_0) != 0) {\r
       //\r
       // Save a pointer to the table\r
       //\r
@@ -929,13 +910,30 @@ AddTableToList (
       // If FADT already exists, update table pointers.\r
       //\r
       if (AcpiTableInstance->Fadt3 != NULL) {\r
-        AcpiTableInstance->Fadt3->Dsdt  = (UINT32) (UINTN) AcpiTableInstance->Dsdt3;\r
-        Buffer64                          = (UINT64) (UINTN) AcpiTableInstance->Dsdt3;\r
-        CopyMem (\r
-          &AcpiTableInstance->Fadt3->XDsdt,\r
-          &Buffer64,\r
-          sizeof (UINT64)\r
-          );\r
+        if ((UINT64)(UINTN)AcpiTableInstance->Dsdt3 < BASE_4GB) {\r
+          AcpiTableInstance->Fadt3->Dsdt = (UINT32) (UINTN) AcpiTableInstance->Dsdt3;\r
+          //\r
+          // Comment block "the caller installs the tables in "FADT, DSDT" order"\r
+          // The below comments are also in "the caller installs the tables in "DSDT, FADT" order" comment block.\r
+          //\r
+          // The ACPI specification, up to and including revision 5.1 Errata A,\r
+          // allows the DSDT and X_DSDT fields to be both set in the FADT.\r
+          // (Obviously, this only makes sense if the DSDT address is representable in 4 bytes.)\r
+          // Starting with 5.1 Errata B, specifically for Mantis 1393 <https://mantis.uefi.org/mantis/view.php?id=1393>,\r
+          // the spec requires at most one of DSDT and X_DSDT fields to be set to a nonzero value,\r
+          // but strangely an exception is 6.0 that has no this requirement.\r
+          //\r
+          // Here we do not make the DSDT and X_DSDT fields mutual exclusion conditionally\r
+          // by checking FADT revision, but always set both DSDT and X_DSDT fields in the FADT\r
+          // to have better compatibility as some OS may have assumption to only consume X_DSDT\r
+          // field even the DSDT address is < 4G.\r
+          //\r
+          Buffer64 = AcpiTableInstance->Fadt3->Dsdt;\r
+        } else {\r
+          AcpiTableInstance->Fadt3->Dsdt = 0;\r
+          Buffer64 = (UINT64) (UINTN) AcpiTableInstance->Dsdt3;\r
+        }\r
+        CopyMem (&AcpiTableInstance->Fadt3->XDsdt, &Buffer64, sizeof (UINT64));\r
 \r
         //\r
         // Checksum FADT table\r
@@ -947,7 +945,7 @@ AddTableToList (
           Checksum)\r
           );\r
       }\r
-    }        \r
+    }\r
     //\r
     // Checksum the table\r
     //\r
@@ -1019,21 +1017,22 @@ AddTableToList (
   //\r
   // Add to ACPI 2.0/3.0  table tree\r
   //\r
-  if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||\r
-      (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) {\r
-     if (AddToRsdt) {\r
-       //\r
-       // If the table number exceed the gEfiAcpiMaxNumTables, enlarge the table buffer\r
-       //\r
-       if (AcpiTableInstance->NumberOfTableEntries3 >= mEfiAcpiMaxNumTables) {\r
-         Status = ReallocateAcpiTableBuffer (AcpiTableInstance);\r
-         ASSERT_EFI_ERROR (Status);\r
-       }\r
-       //\r
-       // At this time, it is assumed that RSDT and XSDT maintain parallel lists of tables.\r
-       // If it becomes necessary to maintain separate table lists, changes will be required.\r
-       //\r
-       CurrentRsdtEntry = (UINT32 *)\r
+  if ((Version & ACPI_TABLE_VERSION_GTE_2_0) != 0) {\r
+    if (AddToRsdt) {\r
+      //\r
+      // If the table number exceed the gEfiAcpiMaxNumTables, enlarge the table buffer\r
+      //\r
+      if (AcpiTableInstance->NumberOfTableEntries3 >= mEfiAcpiMaxNumTables) {\r
+        Status = ReallocateAcpiTableBuffer (AcpiTableInstance);\r
+        ASSERT_EFI_ERROR (Status);\r
+      }\r
+\r
+      if ((PcdGet32 (PcdAcpiExposedTableVersions) & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {\r
+        //\r
+        // At this time, it is assumed that RSDT and XSDT maintain parallel lists of tables.\r
+        // If it becomes necessary to maintain separate table lists, changes will be required.\r
+        //\r
+        CurrentRsdtEntry = (UINT32 *)\r
          (\r
            (UINT8 *) AcpiTableInstance->Rsdt3 +\r
            sizeof (EFI_ACPI_DESCRIPTION_HEADER) +\r
@@ -1041,45 +1040,46 @@ AddTableToList (
            sizeof (UINT32)\r
          );\r
 \r
-       //\r
-       // This pointer must not be directly dereferenced as the XSDT entries may not\r
-       // be 64 bit aligned resulting in a possible fault.  Use CopyMem to update.\r
-       //\r
-       CurrentXsdtEntry = (VOID *)\r
-         (\r
-           (UINT8 *) AcpiTableInstance->Xsdt +\r
-           sizeof (EFI_ACPI_DESCRIPTION_HEADER) +\r
-           AcpiTableInstance->NumberOfTableEntries3 *\r
-           sizeof (UINT64)\r
-         );\r
+        //\r
+        // Add entry to the RSDT\r
+        //\r
+        *CurrentRsdtEntry = (UINT32) (UINTN) CurrentTableList->Table;\r
 \r
-       //\r
-       // Add entry to the RSDT\r
-       //\r
-       *CurrentRsdtEntry = (UINT32) (UINTN) CurrentTableList->Table;\r
-\r
-       //\r
-       // Update RSDT length\r
-       //\r
-       AcpiTableInstance->Rsdt3->Length = AcpiTableInstance->Rsdt3->Length + sizeof (UINT32);\r
-\r
-       //\r
-       // Add entry to XSDT, XSDT expects 64 bit pointers, but\r
-       // the table pointers in XSDT are not aligned on 8 byte boundary.\r
-       //\r
-       Buffer64 = (UINT64) (UINTN) CurrentTableList->Table;\r
-       CopyMem (\r
-         CurrentXsdtEntry,\r
-         &Buffer64,\r
-         sizeof (UINT64)\r
-         );\r
+        //\r
+        // Update RSDT length\r
+        //\r
+        AcpiTableInstance->Rsdt3->Length = AcpiTableInstance->Rsdt3->Length + sizeof (UINT32);\r
+      }\r
 \r
-       //\r
-       // Update length\r
-       //\r
-       AcpiTableInstance->Xsdt->Length = AcpiTableInstance->Xsdt->Length + sizeof (UINT64);\r
+      //\r
+      // This pointer must not be directly dereferenced as the XSDT entries may not\r
+      // be 64 bit aligned resulting in a possible fault.  Use CopyMem to update.\r
+      //\r
+      CurrentXsdtEntry = (VOID *)\r
+        (\r
+          (UINT8 *) AcpiTableInstance->Xsdt +\r
+          sizeof (EFI_ACPI_DESCRIPTION_HEADER) +\r
+          AcpiTableInstance->NumberOfTableEntries3 *\r
+          sizeof (UINT64)\r
+        );\r
 \r
-       AcpiTableInstance->NumberOfTableEntries3++;\r
+      //\r
+      // Add entry to XSDT, XSDT expects 64 bit pointers, but\r
+      // the table pointers in XSDT are not aligned on 8 byte boundary.\r
+      //\r
+      Buffer64 = (UINT64) (UINTN) CurrentTableList->Table;\r
+      CopyMem (\r
+        CurrentXsdtEntry,\r
+        &Buffer64,\r
+        sizeof (UINT64)\r
+        );\r
+\r
+      //\r
+      // Update length\r
+      //\r
+      AcpiTableInstance->Xsdt->Length = AcpiTableInstance->Xsdt->Length + sizeof (UINT64);\r
+\r
+      AcpiTableInstance->NumberOfTableEntries3++;\r
     }\r
   }\r
 \r
@@ -1095,7 +1095,7 @@ AddTableToList (
 \r
   @param  Handle      Table to find.\r
   @param  TableList   Table list to search\r
-  @param  Table       Pointer to table found. \r
+  @param  Table       Pointer to table found.\r
 \r
   @return EFI_SUCCESS    The function completed successfully.\r
   @return EFI_NOT_FOUND  No table found matching the handle specified.\r
@@ -1145,7 +1145,7 @@ FindTableByHandle (
   For Acpi 1.0 tables, pass in the Rsdt.\r
   For Acpi 2.0 tables, pass in both Rsdt and Xsdt.\r
 \r
-  @param  Table                 Pointer to table found. \r
+  @param  Table                 Pointer to table found.\r
   @param  NumberOfTableEntries  Current number of table entries in the RSDT/XSDT\r
   @param  Rsdt                  Pointer to the RSDT to remove from\r
   @param  Xsdt                  Pointer to the Xsdt to remove from\r
@@ -1158,7 +1158,7 @@ EFI_STATUS
 RemoveTableFromRsdt (\r
   IN OUT EFI_ACPI_TABLE_LIST              * Table,\r
   IN OUT UINTN                            *NumberOfTableEntries,\r
-  IN OUT EFI_ACPI_DESCRIPTION_HEADER      * Rsdt,\r
+  IN OUT EFI_ACPI_DESCRIPTION_HEADER      * Rsdt OPTIONAL,\r
   IN OUT EFI_ACPI_DESCRIPTION_HEADER      * Xsdt OPTIONAL\r
   )\r
 {\r
@@ -1172,7 +1172,7 @@ RemoveTableFromRsdt (
   //\r
   ASSERT (Table);\r
   ASSERT (NumberOfTableEntries);\r
-  ASSERT (Rsdt);\r
+  ASSERT (Rsdt || Xsdt);\r
 \r
   //\r
   // Find the table entry in the RSDT and XSDT\r
@@ -1182,7 +1182,11 @@ RemoveTableFromRsdt (
     // At this time, it is assumed that RSDT and XSDT maintain parallel lists of tables.\r
     // If it becomes necessary to maintain separate table lists, changes will be required.\r
     //\r
-    CurrentRsdtEntry = (UINT32 *) ((UINT8 *) Rsdt + sizeof (EFI_ACPI_DESCRIPTION_HEADER) + Index * sizeof (UINT32));\r
+    if (Rsdt != NULL) {\r
+      CurrentRsdtEntry = (UINT32 *) ((UINT8 *) Rsdt + sizeof (EFI_ACPI_DESCRIPTION_HEADER) + Index * sizeof (UINT32));\r
+    } else {\r
+      CurrentRsdtEntry = NULL;\r
+    }\r
     if (Xsdt != NULL) {\r
       //\r
       // This pointer must not be directly dereferenced as the XSDT entries may not\r
@@ -1204,7 +1208,7 @@ RemoveTableFromRsdt (
     //\r
     // Check if we have found the corresponding entry in both RSDT and XSDT\r
     //\r
-    if (*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
@@ -1212,8 +1216,10 @@ RemoveTableFromRsdt (
       // We actually copy all + 1 to copy the initialized value of memory over\r
       // the last entry.\r
       //\r
-      CopyMem (CurrentRsdtEntry, CurrentRsdtEntry + 1, (*NumberOfTableEntries - Index) * sizeof (UINT32));\r
-      Rsdt->Length = Rsdt->Length - sizeof (UINT32);\r
+      if (Rsdt != NULL) {\r
+        CopyMem (CurrentRsdtEntry, CurrentRsdtEntry + 1, (*NumberOfTableEntries - Index) * sizeof (UINT32));\r
+        Rsdt->Length = Rsdt->Length - sizeof (UINT32);\r
+      }\r
       if (Xsdt != NULL) {\r
         CopyMem (CurrentXsdtEntry, ((UINT64 *) CurrentXsdtEntry) + 1, (*NumberOfTableEntries - Index) * sizeof (UINT64));\r
         Xsdt->Length = Xsdt->Length - sizeof (UINT64);\r
@@ -1229,12 +1235,14 @@ RemoveTableFromRsdt (
   //\r
   // Checksum the tables\r
   //\r
-  AcpiPlatformChecksum (\r
-    Rsdt,\r
-    Rsdt->Length,\r
-    OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,\r
-    Checksum)\r
-    );\r
+  if (Rsdt != NULL) {\r
+    AcpiPlatformChecksum (\r
+      Rsdt,\r
+      Rsdt->Length,\r
+      OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,\r
+      Checksum)\r
+      );\r
+  }\r
 \r
   if (Xsdt != NULL) {\r
     AcpiPlatformChecksum (\r
@@ -1352,18 +1360,12 @@ DeleteTable (
       }\r
     }\r
 \r
-    if ((Version & EFI_ACPI_TABLE_VERSION_2_0 & Table->Version) ||\r
-        (Version & EFI_ACPI_TABLE_VERSION_3_0 & Table->Version)) {\r
+    if (Version & ACPI_TABLE_VERSION_GTE_2_0 & Table->Version) {\r
       //\r
       // Remove this version from the table\r
       //\r
-      if (Version & EFI_ACPI_TABLE_VERSION_2_0 & Table->Version) {\r
-        Table->Version = Table->Version &~EFI_ACPI_TABLE_VERSION_2_0;\r
-      }      \r
-      if (Version & EFI_ACPI_TABLE_VERSION_3_0 & Table->Version) {\r
-        Table->Version = Table->Version &~EFI_ACPI_TABLE_VERSION_3_0;\r
-      }\r
-      \r
+      Table->Version = Table->Version &~(Version & ACPI_TABLE_VERSION_GTE_2_0);\r
+\r
       //\r
       // Remove from Rsdt and Xsdt.  We don't care about the return value\r
       // because it is acceptable for the table to not exist in Rsdt/Xsdt.\r
@@ -1377,7 +1379,7 @@ DeleteTable (
           AcpiTableInstance->Xsdt\r
           );\r
       }\r
-    }    \r
+    }\r
     //\r
     // Free the table, clean up any dependent tables and our private data pointers.\r
     //\r
@@ -1388,8 +1390,7 @@ DeleteTable (
         AcpiTableInstance->Fadt1 = NULL;\r
       }\r
 \r
-      if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||\r
-          (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) {\r
+      if ((Version & ACPI_TABLE_VERSION_GTE_2_0) != 0) {\r
         AcpiTableInstance->Fadt3 = NULL;\r
       }\r
       break;\r
@@ -1416,8 +1417,7 @@ DeleteTable (
         }\r
       }\r
 \r
-      if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||\r
-          (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) {\r
+      if ((Version & ACPI_TABLE_VERSION_GTE_2_0) != 0) {\r
         AcpiTableInstance->Facs3 = NULL;\r
 \r
         //\r
@@ -1437,7 +1437,7 @@ DeleteTable (
             Checksum)\r
             );\r
         }\r
-      }    \r
+      }\r
       break;\r
 \r
     case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:\r
@@ -1462,9 +1462,8 @@ DeleteTable (
         }\r
       }\r
 \r
-      \r
-      if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||\r
-          (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) {\r
+\r
+      if ((Version & ACPI_TABLE_VERSION_GTE_2_0) != 0) {\r
         AcpiTableInstance->Dsdt3 = NULL;\r
 \r
         //\r
@@ -1501,7 +1500,7 @@ DeleteTable (
     //\r
     // Free the Table\r
     //\r
-    gBS->FreePages (Table->PageAddress, Table->NumberOfPages);\r
+    FreeTableMemory (Table);\r
     RemoveEntryList (&(Table->Link));\r
     gBS->FreePool (Table);\r
   }\r
@@ -1629,12 +1628,14 @@ ChecksumCommonTables (
   //\r
   // RSDP ACPI 1.0 checksum for 1.0 table.  This is only the first 20 bytes of the structure\r
   //\r
-  AcpiPlatformChecksum (\r
-    AcpiTableInstance->Rsdp1,\r
-    sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER),\r
-    OFFSET_OF (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER,\r
-    Checksum)\r
-    );\r
+  if ((PcdGet32 (PcdAcpiExposedTableVersions) & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {\r
+    AcpiPlatformChecksum (\r
+      AcpiTableInstance->Rsdp1,\r
+      sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER),\r
+      OFFSET_OF (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER,\r
+      Checksum)\r
+      );\r
+  }\r
 \r
   //\r
   // RSDP ACPI 1.0 checksum for 2.0/3.0 table.  This is only the first 20 bytes of the structure\r
@@ -1656,22 +1657,24 @@ ChecksumCommonTables (
     ExtendedChecksum)\r
     );\r
 \r
-  //\r
-  // RSDT checksums\r
-  //\r
-  AcpiPlatformChecksum (\r
-    AcpiTableInstance->Rsdt1,\r
-    AcpiTableInstance->Rsdt1->Length,\r
-    OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,\r
-    Checksum)\r
-    );\r
+  if ((PcdGet32 (PcdAcpiExposedTableVersions) & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {\r
+    //\r
+    // RSDT checksums\r
+    //\r
+    AcpiPlatformChecksum (\r
+      AcpiTableInstance->Rsdt1,\r
+      AcpiTableInstance->Rsdt1->Length,\r
+      OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,\r
+      Checksum)\r
+      );\r
 \r
-  AcpiPlatformChecksum (\r
-    AcpiTableInstance->Rsdt3,\r
-    AcpiTableInstance->Rsdt3->Length,\r
-    OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,\r
-    Checksum)\r
-    );\r
+    AcpiPlatformChecksum (\r
+      AcpiTableInstance->Rsdt3,\r
+      AcpiTableInstance->Rsdt3->Length,\r
+      OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,\r
+      Checksum)\r
+      );\r
+  }\r
 \r
   //\r
   // XSDT checksum\r
@@ -1682,7 +1685,7 @@ ChecksumCommonTables (
     OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,\r
     Checksum)\r
     );\r
-  \r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -1714,6 +1717,16 @@ AcpiTableAcpiTableConstructor (
   //\r
   ASSERT (AcpiTableInstance);\r
 \r
+  //\r
+  // If ACPI v1.0b is among the ACPI versions we aim to support, we have to\r
+  // ensure that all memory allocations are below 4 GB.\r
+  //\r
+  if ((PcdGet32 (PcdAcpiExposedTableVersions) & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {\r
+    mAcpiTableAllocType = AllocateMaxAddress;\r
+  } else {\r
+    mAcpiTableAllocType = AllocateAnyPages;\r
+  }\r
+\r
   InitializeListHead (&AcpiTableInstance->TableList);\r
   AcpiTableInstance->CurrentHandle              = 1;\r
 \r
@@ -1727,124 +1740,164 @@ AcpiTableAcpiTableConstructor (
   //\r
   // Create RSDP table\r
   //\r
-  RsdpTableSize = sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER) +\r
-                  sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER);\r
+  RsdpTableSize = sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER);\r
+  if ((PcdGet32 (PcdAcpiExposedTableVersions) & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {\r
+    RsdpTableSize += sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER);\r
+  }\r
 \r
-  PageAddress = 0xFFFFFFFF;\r
-  Status = gBS->AllocatePages (\r
-                  AllocateMaxAddress,\r
-                  EfiACPIReclaimMemory,\r
-                  EFI_SIZE_TO_PAGES (RsdpTableSize),\r
-                  &PageAddress\r
-                  );\r
+  if (mAcpiTableAllocType != AllocateAnyPages) {\r
+    PageAddress = 0xFFFFFFFF;\r
+    Status = gBS->AllocatePages (\r
+                    mAcpiTableAllocType,\r
+                    EfiACPIReclaimMemory,\r
+                    EFI_SIZE_TO_PAGES (RsdpTableSize),\r
+                    &PageAddress\r
+                    );\r
+  } else {\r
+    Status = gBS->AllocatePool (\r
+                    EfiACPIReclaimMemory,\r
+                    RsdpTableSize,\r
+                    (VOID **)&Pointer\r
+                    );\r
+  }\r
 \r
   if (EFI_ERROR (Status)) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
-  Pointer = (UINT8 *) (UINTN) PageAddress;\r
+  if (mAcpiTableAllocType != AllocateAnyPages) {\r
+    Pointer = (UINT8 *)(UINTN)PageAddress;\r
+  }\r
   ZeroMem (Pointer, RsdpTableSize);\r
 \r
   AcpiTableInstance->Rsdp1 = (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *) Pointer;\r
-  Pointer += sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER);\r
+  if ((PcdGet32 (PcdAcpiExposedTableVersions) & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {\r
+    Pointer += sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER);\r
+  }\r
   AcpiTableInstance->Rsdp3 = (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *) Pointer;\r
 \r
   //\r
   // Create RSDT, XSDT structures\r
   //\r
-  TotalSize = sizeof (EFI_ACPI_DESCRIPTION_HEADER) +         // for ACPI 1.0 RSDT\r
-              mEfiAcpiMaxNumTables * sizeof (UINT32) +\r
-              sizeof (EFI_ACPI_DESCRIPTION_HEADER) +         // for ACPI 2.0/3.0 RSDT\r
-              mEfiAcpiMaxNumTables * sizeof (UINT32) +\r
-              sizeof (EFI_ACPI_DESCRIPTION_HEADER) +         // for ACPI 2.0/3.0 XSDT\r
+  TotalSize = sizeof (EFI_ACPI_DESCRIPTION_HEADER) +         // for ACPI 2.0/3.0 XSDT\r
               mEfiAcpiMaxNumTables * sizeof (UINT64);\r
 \r
-  //\r
-  // Allocate memory in the lower 32 bit of address range for\r
-  // compatibility with ACPI 1.0 OS.\r
-  //\r
-  // This is done because ACPI 1.0 pointers are 32 bit values.\r
-  // ACPI 2.0 OS and all 64 bit OS must use the 64 bit ACPI table addresses.\r
-  // There is no architectural reason these should be below 4GB, it is purely\r
-  // for convenience of implementation that we force memory below 4GB.\r
-  //\r
-  PageAddress = 0xFFFFFFFF;\r
-  Status = gBS->AllocatePages (\r
-                  AllocateMaxAddress,\r
-                  EfiACPIReclaimMemory,\r
-                  EFI_SIZE_TO_PAGES (TotalSize),\r
-                  &PageAddress\r
-                  );\r
+  if ((PcdGet32 (PcdAcpiExposedTableVersions) & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {\r
+    TotalSize += sizeof (EFI_ACPI_DESCRIPTION_HEADER) +      // for ACPI 1.0 RSDT\r
+                 mEfiAcpiMaxNumTables * sizeof (UINT32) +\r
+                 sizeof (EFI_ACPI_DESCRIPTION_HEADER) +      // for ACPI 2.0/3.0 RSDT\r
+                 mEfiAcpiMaxNumTables * sizeof (UINT32);\r
+  }\r
+\r
+  if (mAcpiTableAllocType != AllocateAnyPages) {\r
+    //\r
+    // Allocate memory in the lower 32 bit of address range for\r
+    // compatibility with ACPI 1.0 OS.\r
+    //\r
+    // This is done because ACPI 1.0 pointers are 32 bit values.\r
+    // ACPI 2.0 OS and all 64 bit OS must use the 64 bit ACPI table addresses.\r
+    // There is no architectural reason these should be below 4GB, it is purely\r
+    // for convenience of implementation that we force memory below 4GB.\r
+    //\r
+    PageAddress = 0xFFFFFFFF;\r
+    Status = gBS->AllocatePages (\r
+                    mAcpiTableAllocType,\r
+                    EfiACPIReclaimMemory,\r
+                    EFI_SIZE_TO_PAGES (TotalSize),\r
+                    &PageAddress\r
+                    );\r
+  } else {\r
+    Status = gBS->AllocatePool (\r
+                    EfiACPIReclaimMemory,\r
+                    TotalSize,\r
+                    (VOID **)&Pointer\r
+                    );\r
+  }\r
 \r
   if (EFI_ERROR (Status)) {\r
-    gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)AcpiTableInstance->Rsdp1, EFI_SIZE_TO_PAGES (RsdpTableSize));\r
+    if (mAcpiTableAllocType != AllocateAnyPages) {\r
+      gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)AcpiTableInstance->Rsdp1,\r
+             EFI_SIZE_TO_PAGES (RsdpTableSize));\r
+    } else {\r
+      gBS->FreePool (AcpiTableInstance->Rsdp1);\r
+    }\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
-  Pointer = (UINT8 *) (UINTN) PageAddress;\r
+  if (mAcpiTableAllocType != AllocateAnyPages) {\r
+    Pointer = (UINT8 *)(UINTN)PageAddress;\r
+  }\r
   ZeroMem (Pointer, TotalSize);\r
 \r
   AcpiTableInstance->Rsdt1 = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;\r
-  Pointer += (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + EFI_ACPI_MAX_NUM_TABLES * sizeof (UINT32));\r
-  AcpiTableInstance->Rsdt3 = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;\r
-  Pointer += (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + EFI_ACPI_MAX_NUM_TABLES * sizeof (UINT32));\r
+  if ((PcdGet32 (PcdAcpiExposedTableVersions) & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {\r
+    Pointer += (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + EFI_ACPI_MAX_NUM_TABLES * sizeof (UINT32));\r
+    AcpiTableInstance->Rsdt3 = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;\r
+    Pointer += (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + EFI_ACPI_MAX_NUM_TABLES * sizeof (UINT32));\r
+  }\r
   AcpiTableInstance->Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;\r
 \r
   //\r
   // Initialize RSDP\r
   //\r
-  CurrentData = EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE;\r
-  CopyMem (&AcpiTableInstance->Rsdp1->Signature, &CurrentData, sizeof (UINT64));\r
-  CopyMem (AcpiTableInstance->Rsdp1->OemId, EFI_ACPI_OEM_ID, 6);\r
-  AcpiTableInstance->Rsdp1->Reserved    = EFI_ACPI_RESERVED_BYTE;\r
-  AcpiTableInstance->Rsdp1->RsdtAddress = (UINT32) (UINTN) AcpiTableInstance->Rsdt1;\r
+  if ((PcdGet32 (PcdAcpiExposedTableVersions) & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {\r
+    CurrentData = EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE;\r
+    CopyMem (&AcpiTableInstance->Rsdp1->Signature, &CurrentData, sizeof (UINT64));\r
+    CopyMem (AcpiTableInstance->Rsdp1->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (AcpiTableInstance->Rsdp1->OemId));\r
+    AcpiTableInstance->Rsdp1->Reserved    = EFI_ACPI_RESERVED_BYTE;\r
+    AcpiTableInstance->Rsdp1->RsdtAddress = (UINT32) (UINTN) AcpiTableInstance->Rsdt1;\r
+  }\r
 \r
   CurrentData = EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE;\r
   CopyMem (&AcpiTableInstance->Rsdp3->Signature, &CurrentData, sizeof (UINT64));\r
-  CopyMem (AcpiTableInstance->Rsdp3->OemId, EFI_ACPI_OEM_ID, 6);\r
+  CopyMem (AcpiTableInstance->Rsdp3->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (AcpiTableInstance->Rsdp3->OemId));\r
   AcpiTableInstance->Rsdp3->Revision    = EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION;\r
-  AcpiTableInstance->Rsdp3->RsdtAddress = (UINT32) (UINTN) AcpiTableInstance->Rsdt3;\r
   AcpiTableInstance->Rsdp3->Length      = sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER);\r
+  if ((PcdGet32 (PcdAcpiExposedTableVersions) & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {\r
+    AcpiTableInstance->Rsdp3->RsdtAddress = (UINT32) (UINTN) AcpiTableInstance->Rsdt3;\r
+  }\r
   CurrentData = (UINT64) (UINTN) AcpiTableInstance->Xsdt;\r
   CopyMem (&AcpiTableInstance->Rsdp3->XsdtAddress, &CurrentData, sizeof (UINT64));\r
   SetMem (AcpiTableInstance->Rsdp3->Reserved, 3, EFI_ACPI_RESERVED_BYTE);\r
 \r
-  //\r
-  // Initialize Rsdt\r
-  //\r
-  // Note that we "reserve" one entry for the FADT so it can always be\r
-  // at the beginning of the list of tables.  Some OS don't seem\r
-  // to find it correctly if it is too far down the list.\r
-  //\r
-  AcpiTableInstance->Rsdt1->Signature = EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE;\r
-  AcpiTableInstance->Rsdt1->Length    = sizeof (EFI_ACPI_DESCRIPTION_HEADER);\r
-  AcpiTableInstance->Rsdt1->Revision  = EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_TABLE_REVISION;\r
-  CopyMem (AcpiTableInstance->Rsdt1->OemId, EFI_ACPI_OEM_ID, 6);\r
-  CurrentData = EFI_ACPI_OEM_TABLE_ID;\r
-  CopyMem (&AcpiTableInstance->Rsdt1->OemTableId, &CurrentData, sizeof (UINT64));\r
-  AcpiTableInstance->Rsdt1->OemRevision     = EFI_ACPI_OEM_REVISION;\r
-  AcpiTableInstance->Rsdt1->CreatorId       = EFI_ACPI_CREATOR_ID;\r
-  AcpiTableInstance->Rsdt1->CreatorRevision = EFI_ACPI_CREATOR_REVISION;\r
-  //\r
-  // We always reserve first one for FADT\r
-  //\r
-  AcpiTableInstance->NumberOfTableEntries1  = 1;\r
-  AcpiTableInstance->Rsdt1->Length          = AcpiTableInstance->Rsdt1->Length + sizeof(UINT32);\r
-\r
-  AcpiTableInstance->Rsdt3->Signature       = EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE;\r
-  AcpiTableInstance->Rsdt3->Length          = sizeof (EFI_ACPI_DESCRIPTION_HEADER);\r
-  AcpiTableInstance->Rsdt3->Revision        = EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_TABLE_REVISION;\r
-  CopyMem (AcpiTableInstance->Rsdt3->OemId, EFI_ACPI_OEM_ID, 6);\r
-  CurrentData = EFI_ACPI_OEM_TABLE_ID;\r
-  CopyMem (&AcpiTableInstance->Rsdt3->OemTableId, &CurrentData, sizeof (UINT64));\r
-  AcpiTableInstance->Rsdt3->OemRevision     = EFI_ACPI_OEM_REVISION;\r
-  AcpiTableInstance->Rsdt3->CreatorId       = EFI_ACPI_CREATOR_ID;\r
-  AcpiTableInstance->Rsdt3->CreatorRevision = EFI_ACPI_CREATOR_REVISION;\r
-  //\r
-  // We always reserve first one for FADT\r
-  //\r
+  if ((PcdGet32 (PcdAcpiExposedTableVersions) & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {\r
+    //\r
+    // Initialize Rsdt\r
+    //\r
+    // Note that we "reserve" one entry for the FADT so it can always be\r
+    // at the beginning of the list of tables.  Some OS don't seem\r
+    // to find it correctly if it is too far down the list.\r
+    //\r
+    AcpiTableInstance->Rsdt1->Signature = EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE;\r
+    AcpiTableInstance->Rsdt1->Length    = sizeof (EFI_ACPI_DESCRIPTION_HEADER);\r
+    AcpiTableInstance->Rsdt1->Revision  = EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_TABLE_REVISION;\r
+    CopyMem (AcpiTableInstance->Rsdt1->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (AcpiTableInstance->Rsdt1->OemId));\r
+    CurrentData = PcdGet64 (PcdAcpiDefaultOemTableId);\r
+    CopyMem (&AcpiTableInstance->Rsdt1->OemTableId, &CurrentData, sizeof (UINT64));\r
+    AcpiTableInstance->Rsdt1->OemRevision     = PcdGet32 (PcdAcpiDefaultOemRevision);\r
+    AcpiTableInstance->Rsdt1->CreatorId       = PcdGet32 (PcdAcpiDefaultCreatorId);\r
+    AcpiTableInstance->Rsdt1->CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);\r
+    //\r
+    // We always reserve first one for FADT\r
+    //\r
+    AcpiTableInstance->NumberOfTableEntries1  = 1;\r
+    AcpiTableInstance->Rsdt1->Length          = AcpiTableInstance->Rsdt1->Length + sizeof(UINT32);\r
+\r
+    AcpiTableInstance->Rsdt3->Signature       = EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE;\r
+    AcpiTableInstance->Rsdt3->Length          = sizeof (EFI_ACPI_DESCRIPTION_HEADER);\r
+    AcpiTableInstance->Rsdt3->Revision        = EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_TABLE_REVISION;\r
+    CopyMem (AcpiTableInstance->Rsdt3->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (AcpiTableInstance->Rsdt3->OemId));\r
+    CurrentData = PcdGet64 (PcdAcpiDefaultOemTableId);\r
+    CopyMem (&AcpiTableInstance->Rsdt3->OemTableId, &CurrentData, sizeof (UINT64));\r
+    AcpiTableInstance->Rsdt3->OemRevision     = PcdGet32 (PcdAcpiDefaultOemRevision);\r
+    AcpiTableInstance->Rsdt3->CreatorId       = PcdGet32 (PcdAcpiDefaultCreatorId);\r
+    AcpiTableInstance->Rsdt3->CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);\r
+    //\r
+    // We always reserve first one for FADT\r
+    //\r
+    AcpiTableInstance->Rsdt3->Length          = AcpiTableInstance->Rsdt3->Length + sizeof(UINT32);\r
+  }\r
   AcpiTableInstance->NumberOfTableEntries3  = 1;\r
-  AcpiTableInstance->Rsdt3->Length          = AcpiTableInstance->Rsdt3->Length + sizeof(UINT32);\r
 \r
   //\r
   // Initialize Xsdt\r
@@ -1852,12 +1905,12 @@ AcpiTableAcpiTableConstructor (
   AcpiTableInstance->Xsdt->Signature  = EFI_ACPI_3_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE;\r
   AcpiTableInstance->Xsdt->Length     = sizeof (EFI_ACPI_DESCRIPTION_HEADER);\r
   AcpiTableInstance->Xsdt->Revision   = EFI_ACPI_3_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_REVISION;\r
-  CopyMem (AcpiTableInstance->Xsdt->OemId, EFI_ACPI_OEM_ID, 6);\r
-  CurrentData = EFI_ACPI_OEM_TABLE_ID;\r
+  CopyMem (AcpiTableInstance->Xsdt->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (AcpiTableInstance->Xsdt->OemId));\r
+  CurrentData = PcdGet64 (PcdAcpiDefaultOemTableId);\r
   CopyMem (&AcpiTableInstance->Xsdt->OemTableId, &CurrentData, sizeof (UINT64));\r
-  AcpiTableInstance->Xsdt->OemRevision      = EFI_ACPI_OEM_REVISION;\r
-  AcpiTableInstance->Xsdt->CreatorId        = EFI_ACPI_CREATOR_ID;\r
-  AcpiTableInstance->Xsdt->CreatorRevision  = EFI_ACPI_CREATOR_REVISION;\r
+  AcpiTableInstance->Xsdt->OemRevision      = PcdGet32 (PcdAcpiDefaultOemRevision);\r
+  AcpiTableInstance->Xsdt->CreatorId        = PcdGet32 (PcdAcpiDefaultCreatorId);\r
+  AcpiTableInstance->Xsdt->CreatorRevision  = PcdGet32 (PcdAcpiDefaultCreatorRevision);\r
   //\r
   // We always reserve first one for FADT\r
   //\r