/** @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
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
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
//\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
//\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