/** @file\r
ACPI Table Protocol Implementation\r
\r
- Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2006 - 2018, 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
- 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
+ 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
+UINTN mEfiAcpiMaxNumTables = EFI_ACPI_MAX_NUM_TABLES;\r
\r
//\r
// Allocation strategy to use for AllocatePages ().\r
@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
);\r
}\r
FreePool (AcpiTableBufferConst);\r
- \r
+\r
//\r
// Add a new table successfully, notify registed callback\r
//\r
{\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 = RemoveTableFromList (\r
AcpiTableInstance,\r
- EFI_ACPI_TABLE_VERSION_1_0B | ACPI_TABLE_VERSION_GTE_2_0,\r
+ Version,\r
TableKey\r
);\r
if (!EFI_ERROR (Status)) {\r
Status = PublishTables (\r
AcpiTableInstance,\r
- EFI_ACPI_TABLE_VERSION_1_0B | ACPI_TABLE_VERSION_GTE_2_0\r
+ Version\r
);\r
}\r
\r
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
\r
Pointer = (UINT8 *) (UINTN) PageAddress;\r
ZeroMem (Pointer, TotalSize);\r
- \r
+\r
AcpiTableInstance->Rsdt1 = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;\r
if ((PcdGet32 (PcdAcpiExposedTableVersions) & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {\r
Pointer += (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + NewMaxTableNumber * sizeof (UINT32));\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
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
+ 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
//\r
// Calculate orignal ACPI table buffer size\r
//\r
}\r
\r
gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)TempPrivateData.Rsdt1, EFI_SIZE_TO_PAGES (TotalSize));\r
- \r
+\r
//\r
// Update the Max ACPI table number\r
- // \r
+ //\r
mEfiAcpiMaxNumTables = NewMaxTableNumber;\r
return EFI_SUCCESS;\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
//\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
\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 = 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
+ //\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
- 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
&AcpiTableInstance->Fadt3->Header.OemId,\r
6\r
);\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
sizeof (UINT64)\r
);\r
AcpiTableInstance->Xsdt->OemRevision = AcpiTableInstance->Fadt3->Header.OemRevision;\r
- } \r
+ }\r
//\r
// Checksum the table\r
//\r
//\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
);\r
}\r
}\r
- \r
+\r
if ((Version & ACPI_TABLE_VERSION_GTE_2_0) != 0) {\r
//\r
// Save a pointer to the table\r
//\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
+ //\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
- 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
Checksum)\r
);\r
}\r
- } \r
+ }\r
//\r
// Checksum the table\r
//\r
\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
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
// Remove this version from the table\r
//\r
Table->Version = Table->Version &~(Version & ACPI_TABLE_VERSION_GTE_2_0);\r
- \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
AcpiTableInstance->Xsdt\r
);\r
}\r
- } \r
+ }\r
//\r
// Free the table, clean up any dependent tables and our private data pointers.\r
//\r
Checksum)\r
);\r
}\r
- } \r
+ }\r
break;\r
\r
case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:\r
}\r
}\r
\r
- \r
+\r
if ((Version & ACPI_TABLE_VERSION_GTE_2_0) != 0) {\r
AcpiTableInstance->Dsdt3 = NULL;\r
\r
OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,\r
Checksum)\r
);\r
- \r
+\r
return EFI_SUCCESS;\r
}\r
\r