summaryrefslogtreecommitdiffstats
path: root/source/components/tables/tbfadt.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/components/tables/tbfadt.c')
-rw-r--r--source/components/tables/tbfadt.c313
1 files changed, 172 insertions, 141 deletions
diff --git a/source/components/tables/tbfadt.c b/source/components/tables/tbfadt.c
index eb4e0e5..5e315ef 100644
--- a/source/components/tables/tbfadt.c
+++ b/source/components/tables/tbfadt.c
@@ -65,13 +65,15 @@ AcpiTbConvertFadt (
void);
static void
-AcpiTbValidateFadt (
- void);
-
-static void
AcpiTbSetupFadtRegisters (
void);
+static UINT64
+AcpiTbSelectAddress (
+ char *RegisterName,
+ UINT32 Address32,
+ UINT64 Address64);
+
/* Table for conversion of FADT to common internal format and FADT validation */
@@ -194,6 +196,7 @@ static ACPI_FADT_PM_INFO FadtPmInfoTable[] =
* SpaceId - ACPI Space ID for this register
* ByteWidth - Width of this register
* Address - Address of the register
+ * RegisterName - ASCII name of the ACPI register
*
* RETURN: None
*
@@ -245,6 +248,72 @@ AcpiTbInitGenericAddress (
/*******************************************************************************
*
+ * FUNCTION: AcpiTbSelectAddress
+ *
+ * PARAMETERS: RegisterName - ASCII name of the ACPI register
+ * Address32 - 32-bit address of the register
+ * Address64 - 64-bit address of the register
+ *
+ * RETURN: The resolved 64-bit address
+ *
+ * DESCRIPTION: Select between 32-bit and 64-bit versions of addresses within
+ * the FADT. Used for the FACS and DSDT addresses.
+ *
+ * NOTES:
+ *
+ * Check for FACS and DSDT address mismatches. An address mismatch between
+ * the 32-bit and 64-bit address fields (FIRMWARE_CTRL/X_FIRMWARE_CTRL and
+ * DSDT/X_DSDT) could be a corrupted address field or it might indicate
+ * the presence of two FACS or two DSDT tables.
+ *
+ * November 2013:
+ * By default, as per the ACPICA specification, a valid 64-bit address is
+ * used regardless of the value of the 32-bit address. However, this
+ * behavior can be overridden via the AcpiGbl_Use32BitFadtAddresses flag.
+ *
+ ******************************************************************************/
+
+static UINT64
+AcpiTbSelectAddress (
+ char *RegisterName,
+ UINT32 Address32,
+ UINT64 Address64)
+{
+
+ if (!Address64)
+ {
+ /* 64-bit address is zero, use 32-bit address */
+
+ return ((UINT64) Address32);
+ }
+
+ if (Address32 &&
+ (Address64 != (UINT64) Address32))
+ {
+ /* Address mismatch between 32-bit and 64-bit versions */
+
+ ACPI_BIOS_WARNING ((AE_INFO,
+ "32/64X %s address mismatch in FADT: "
+ "0x%8.8X/0x%8.8X%8.8X, using %u-bit address",
+ RegisterName, Address32, ACPI_FORMAT_UINT64 (Address64),
+ AcpiGbl_Use32BitFadtAddresses ? 32 : 64));
+
+ /* 32-bit address override */
+
+ if (AcpiGbl_Use32BitFadtAddresses)
+ {
+ return ((UINT64) Address32);
+ }
+ }
+
+ /* Default is to use the 64-bit address */
+
+ return (Address64);
+}
+
+
+/*******************************************************************************
+ *
* FUNCTION: AcpiTbParseFadt
*
* PARAMETERS: TableIndex - Index for the FADT
@@ -365,10 +434,6 @@ AcpiTbCreateLocalFadt (
AcpiTbConvertFadt ();
- /* Validate FADT values now, before we make any changes */
-
- AcpiTbValidateFadt ();
-
/* Initialize the global ACPI register structures */
AcpiTbSetupFadtRegisters ();
@@ -379,33 +444,43 @@ AcpiTbCreateLocalFadt (
*
* FUNCTION: AcpiTbConvertFadt
*
- * PARAMETERS: None, uses AcpiGbl_FADT
+ * PARAMETERS: None - AcpiGbl_FADT is used.
*
* RETURN: None
*
* DESCRIPTION: Converts all versions of the FADT to a common internal format.
- * Expand 32-bit addresses to 64-bit as necessary.
+ * Expand 32-bit addresses to 64-bit as necessary. Also validate
+ * important fields within the FADT.
*
- * NOTE: AcpiGbl_FADT must be of size (ACPI_TABLE_FADT),
- * and must contain a copy of the actual FADT.
+ * NOTE: AcpiGbl_FADT must be of size (ACPI_TABLE_FADT), and must
+ * contain a copy of the actual BIOS-provided FADT.
*
* Notes on 64-bit register addresses:
*
* After this FADT conversion, later ACPICA code will only use the 64-bit "X"
* fields of the FADT for all ACPI register addresses.
*
- * The 64-bit "X" fields are optional extensions to the original 32-bit FADT
+ * The 64-bit X fields are optional extensions to the original 32-bit FADT
* V1.0 fields. Even if they are present in the FADT, they are optional and
* are unused if the BIOS sets them to zero. Therefore, we must copy/expand
- * 32-bit V1.0 fields if the corresponding X field is zero.
+ * 32-bit V1.0 fields to the 64-bit X fields if the the 64-bit X field is
+ * originally zero.
*
- * For ACPI 1.0 FADTs, all 32-bit address fields are expanded to the
- * corresponding "X" fields in the internal FADT.
+ * For ACPI 1.0 FADTs (that contain no 64-bit addresses), all 32-bit address
+ * fields are expanded to the corresponding 64-bit X fields in the internal
+ * common FADT.
*
* For ACPI 2.0+ FADTs, all valid (non-zero) 32-bit address fields are expanded
- * to the corresponding 64-bit X fields. For compatibility with other ACPI
- * implementations, we ignore the 64-bit field if the 32-bit field is valid,
- * regardless of whether the host OS is 32-bit or 64-bit.
+ * to the corresponding 64-bit X fields, if the 64-bit field is originally
+ * zero. Adhering to the ACPI specification, we completely ignore the 32-bit
+ * field if the 64-bit field is valid, regardless of whether the host OS is
+ * 32-bit or 64-bit.
+ *
+ * Possible additional checks:
+ * (AcpiGbl_FADT.Pm1EventLength >= 4)
+ * (AcpiGbl_FADT.Pm1ControlLength >= 2)
+ * (AcpiGbl_FADT.PmTimerLength >= 4)
+ * Gpe block lengths must be multiple of 2
*
******************************************************************************/
@@ -413,25 +488,14 @@ static void
AcpiTbConvertFadt (
void)
{
+ char *Name;
ACPI_GENERIC_ADDRESS *Address64;
UINT32 Address32;
+ UINT8 Length;
UINT32 i;
/*
- * Expand the 32-bit FACS and DSDT addresses to 64-bit as necessary.
- * Later code will always use the X 64-bit field.
- */
- if (!AcpiGbl_FADT.XFacs)
- {
- AcpiGbl_FADT.XFacs = (UINT64) AcpiGbl_FADT.Facs;
- }
- if (!AcpiGbl_FADT.XDsdt)
- {
- AcpiGbl_FADT.XDsdt = (UINT64) AcpiGbl_FADT.Dsdt;
- }
-
- /*
* For ACPI 1.0 FADTs (revision 1 or 2), ensure that reserved fields which
* should be zero are indeed zero. This will workaround BIOSs that
* inadvertently place values in these fields.
@@ -458,113 +522,14 @@ AcpiTbConvertFadt (
AcpiGbl_FADT.Header.Length = sizeof (ACPI_TABLE_FADT);
/*
- * Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X"
- * generic address structures as necessary. Later code will always use
- * the 64-bit address structures.
- *
- * March 2009:
- * We now always use the 32-bit address if it is valid (non-null). This
- * is not in accordance with the ACPI specification which states that
- * the 64-bit address supersedes the 32-bit version, but we do this for
- * compatibility with other ACPI implementations. Most notably, in the
- * case where both the 32 and 64 versions are non-null, we use the 32-bit
- * version. This is the only address that is guaranteed to have been
- * tested by the BIOS manufacturer.
- */
- for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++)
- {
- Address32 = *ACPI_ADD_PTR (UINT32,
- &AcpiGbl_FADT, FadtInfoTable[i].Address32);
-
- Address64 = ACPI_ADD_PTR (ACPI_GENERIC_ADDRESS,
- &AcpiGbl_FADT, FadtInfoTable[i].Address64);
-
- /*
- * If both 32- and 64-bit addresses are valid (non-zero),
- * they must match.
- */
- if (Address64->Address && Address32 &&
- (Address64->Address != (UINT64) Address32))
- {
- ACPI_BIOS_ERROR ((AE_INFO,
- "32/64X address mismatch in FADT/%s: "
- "0x%8.8X/0x%8.8X%8.8X, using 32",
- FadtInfoTable[i].Name, Address32,
- ACPI_FORMAT_UINT64 (Address64->Address)));
- }
-
- /* Always use 32-bit address if it is valid (non-null) */
-
- if (Address32)
- {
- /*
- * Copy the 32-bit address to the 64-bit GAS structure. The
- * Space ID is always I/O for 32-bit legacy address fields
- */
- AcpiTbInitGenericAddress (Address64, ACPI_ADR_SPACE_SYSTEM_IO,
- *ACPI_ADD_PTR (UINT8, &AcpiGbl_FADT, FadtInfoTable[i].Length),
- (UINT64) Address32, FadtInfoTable[i].Name);
- }
- }
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiTbValidateFadt
- *
- * PARAMETERS: Table - Pointer to the FADT to be validated
- *
- * RETURN: None
- *
- * DESCRIPTION: Validate various important fields within the FADT. If a problem
- * is found, issue a message, but no status is returned.
- * Used by both the table manager and the disassembler.
- *
- * Possible additional checks:
- * (AcpiGbl_FADT.Pm1EventLength >= 4)
- * (AcpiGbl_FADT.Pm1ControlLength >= 2)
- * (AcpiGbl_FADT.PmTimerLength >= 4)
- * Gpe block lengths must be multiple of 2
- *
- ******************************************************************************/
-
-static void
-AcpiTbValidateFadt (
- void)
-{
- char *Name;
- ACPI_GENERIC_ADDRESS *Address64;
- UINT8 Length;
- UINT32 i;
-
-
- /*
- * Check for FACS and DSDT address mismatches. An address mismatch between
- * the 32-bit and 64-bit address fields (FIRMWARE_CTRL/X_FIRMWARE_CTRL and
- * DSDT/X_DSDT) would indicate the presence of two FACS or two DSDT tables.
+ * Expand the 32-bit FACS and DSDT addresses to 64-bit as necessary.
+ * Later ACPICA code will always use the X 64-bit field.
*/
- if (AcpiGbl_FADT.Facs &&
- (AcpiGbl_FADT.XFacs != (UINT64) AcpiGbl_FADT.Facs))
- {
- ACPI_BIOS_WARNING ((AE_INFO,
- "32/64X FACS address mismatch in FADT - "
- "0x%8.8X/0x%8.8X%8.8X, using 32",
- AcpiGbl_FADT.Facs, ACPI_FORMAT_UINT64 (AcpiGbl_FADT.XFacs)));
+ AcpiGbl_FADT.XFacs = AcpiTbSelectAddress ("FACS",
+ AcpiGbl_FADT.Facs, AcpiGbl_FADT.XFacs);
- AcpiGbl_FADT.XFacs = (UINT64) AcpiGbl_FADT.Facs;
- }
-
- if (AcpiGbl_FADT.Dsdt &&
- (AcpiGbl_FADT.XDsdt != (UINT64) AcpiGbl_FADT.Dsdt))
- {
- ACPI_BIOS_WARNING ((AE_INFO,
- "32/64X DSDT address mismatch in FADT - "
- "0x%8.8X/0x%8.8X%8.8X, using 32",
- AcpiGbl_FADT.Dsdt, ACPI_FORMAT_UINT64 (AcpiGbl_FADT.XDsdt)));
-
- AcpiGbl_FADT.XDsdt = (UINT64) AcpiGbl_FADT.Dsdt;
- }
+ AcpiGbl_FADT.XDsdt = AcpiTbSelectAddress ("DSDT",
+ AcpiGbl_FADT.Dsdt, AcpiGbl_FADT.XDsdt);
/* If Hardware Reduced flag is set, we are all done */
@@ -578,16 +543,82 @@ AcpiTbValidateFadt (
for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++)
{
/*
- * Generate pointer to the 64-bit address, get the register
- * length (width) and the register name
+ * Get the 32-bit and 64-bit addresses, as well as the register
+ * length and register name.
*/
+ Address32 = *ACPI_ADD_PTR (UINT32,
+ &AcpiGbl_FADT, FadtInfoTable[i].Address32);
+
Address64 = ACPI_ADD_PTR (ACPI_GENERIC_ADDRESS,
- &AcpiGbl_FADT, FadtInfoTable[i].Address64);
+ &AcpiGbl_FADT, FadtInfoTable[i].Address64);
+
Length = *ACPI_ADD_PTR (UINT8,
- &AcpiGbl_FADT, FadtInfoTable[i].Length);
+ &AcpiGbl_FADT, FadtInfoTable[i].Length);
+
Name = FadtInfoTable[i].Name;
/*
+ * Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X"
+ * generic address structures as necessary. Later code will always use
+ * the 64-bit address structures.
+ *
+ * November 2013:
+ * Now always use the 64-bit address if it is valid (non-zero), in
+ * accordance with the ACPI specification which states that a 64-bit
+ * address supersedes the 32-bit version. This behavior can be
+ * overridden by the AcpiGbl_Use32BitFadtAddresses flag.
+ *
+ * During 64-bit address construction and verification,
+ * these cases are handled:
+ *
+ * Address32 zero, Address64 [don't care] - Use Address64
+ *
+ * Address32 non-zero, Address64 zero - Copy/use Address32
+ * Address32 non-zero == Address64 non-zero - Use Address64
+ * Address32 non-zero != Address64 non-zero - Warning, use Address64
+ *
+ * Override: if AcpiGbl_Use32BitFadtAddresses is TRUE, and:
+ * Address32 non-zero != Address64 non-zero - Warning, copy/use Address32
+ *
+ * Note: SpaceId is always I/O for 32-bit legacy address fields
+ */
+ if (Address32)
+ {
+ if (!Address64->Address)
+ {
+ /* 64-bit address is zero, use 32-bit address */
+
+ AcpiTbInitGenericAddress (Address64,
+ ACPI_ADR_SPACE_SYSTEM_IO,
+ *ACPI_ADD_PTR (UINT8, &AcpiGbl_FADT,
+ FadtInfoTable[i].Length),
+ (UINT64) Address32, Name);
+ }
+ else if (Address64->Address != (UINT64) Address32)
+ {
+ /* Address mismatch */
+
+ ACPI_BIOS_WARNING ((AE_INFO,
+ "32/64X address mismatch in FADT/%s: "
+ "0x%8.8X/0x%8.8X%8.8X, using %u-bit address",
+ Name, Address32,
+ ACPI_FORMAT_UINT64 (Address64->Address),
+ AcpiGbl_Use32BitFadtAddresses ? 32 : 64));
+
+ if (AcpiGbl_Use32BitFadtAddresses)
+ {
+ /* 32-bit address override */
+
+ AcpiTbInitGenericAddress (Address64,
+ ACPI_ADR_SPACE_SYSTEM_IO,
+ *ACPI_ADD_PTR (UINT8, &AcpiGbl_FADT,
+ FadtInfoTable[i].Length),
+ (UINT64) Address32, Name);
+ }
+ }
+ }
+
+ /*
* For each extended field, check for length mismatch between the
* legacy length field and the corresponding 64-bit X length field.
* Note: If the legacy length field is > 0xFF bits, ignore this
OpenPOWER on IntegriCloud