mirror of
https://github.com/acpica/acpica/
synced 2025-02-24 17:34:43 +03:00
Remove use of unreliable FADT revision field.
The revision number in the FADT has been found to be completely unreliable and cannot be trusted. Only the table length can be used to infer the actual version. This change updates the ACPICA core and the disassembler so that both no longer even look at the FADT version and instead depend upon the FADT length.
This commit is contained in:
parent
62276d5441
commit
c47bd2bb9e
@ -124,6 +124,12 @@
|
||||
ACPI_MODULE_NAME ("dmtbdump")
|
||||
|
||||
|
||||
static void
|
||||
AcpiDmValidateFadtLength (
|
||||
UINT32 Revision,
|
||||
UINT32 Length);
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: AcpiDmDumpRsdp
|
||||
@ -273,6 +279,10 @@ AcpiDmDumpXsdt (
|
||||
*
|
||||
* DESCRIPTION: Format the contents of a FADT
|
||||
*
|
||||
* NOTE: We cannot depend on the FADT version to indicate the actual
|
||||
* contents of the FADT because of BIOS bugs. The table length
|
||||
* is the only reliable indicator.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
@ -280,20 +290,21 @@ AcpiDmDumpFadt (
|
||||
ACPI_TABLE_HEADER *Table)
|
||||
{
|
||||
|
||||
/* Common ACPI 1.0 portion of FADT */
|
||||
/* Always dump the minimum FADT revision 1 fields (ACPI 1.0) */
|
||||
|
||||
AcpiDmDumpTable (Table->Length, 0, Table, 0, AcpiDmTableInfoFadt1);
|
||||
|
||||
/* Check for ACPI 1.0B MS extensions (FADT revision 2) */
|
||||
/* Check for FADT revision 2 fields (ACPI 1.0B MS extensions) */
|
||||
|
||||
if (Table->Revision == 2)
|
||||
if ((Table->Length > ACPI_FADT_V1_SIZE) &&
|
||||
(Table->Length <= ACPI_FADT_V2_SIZE))
|
||||
{
|
||||
AcpiDmDumpTable (Table->Length, 0, Table, 0, AcpiDmTableInfoFadt2);
|
||||
}
|
||||
|
||||
/* Check for ACPI 2.0+ extended data (FADT revision 3+) */
|
||||
/* Check for FADT revision 3 fields and up (ACPI 2.0+ extended data) */
|
||||
|
||||
else if (Table->Length >= sizeof (ACPI_TABLE_FADT))
|
||||
else if (Table->Length > ACPI_FADT_V2_SIZE)
|
||||
{
|
||||
AcpiDmDumpTable (Table->Length, 0, Table, 0, AcpiDmTableInfoFadt3);
|
||||
}
|
||||
@ -301,6 +312,68 @@ AcpiDmDumpFadt (
|
||||
/* Validate various fields in the FADT, including length */
|
||||
|
||||
AcpiTbCreateLocalFadt (Table, Table->Length);
|
||||
|
||||
/* Validate FADT length against the revision */
|
||||
|
||||
AcpiDmValidateFadtLength (Table->Revision, Table->Length);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: AcpiDmValidateFadtLength
|
||||
*
|
||||
* PARAMETERS: Revision - FADT revision (Header->Revision)
|
||||
* Length - FADT length (Header->Length
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Check the FADT revision against the expected table length for
|
||||
* that revision. Issue a warning if the length is not what was
|
||||
* expected. This seems to be such a common BIOS bug that the
|
||||
* FADT revision has been rendered virtually meaningless.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static void
|
||||
AcpiDmValidateFadtLength (
|
||||
UINT32 Revision,
|
||||
UINT32 Length)
|
||||
{
|
||||
UINT32 ExpectedLength;
|
||||
|
||||
|
||||
switch (Revision)
|
||||
{
|
||||
case 0:
|
||||
AcpiOsPrintf ("// ACPI Warning: Invalid FADT revision: 0\n");
|
||||
return;
|
||||
|
||||
case 1:
|
||||
ExpectedLength = ACPI_FADT_V1_SIZE;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
ExpectedLength = ACPI_FADT_V2_SIZE;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
case 4:
|
||||
ExpectedLength = ACPI_FADT_V3_SIZE;
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (Length == ExpectedLength)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AcpiOsPrintf (
|
||||
"\n// ACPI Warning: FADT revision %X does not match length: found %X expected %X\n",
|
||||
Revision, Length, ExpectedLength);
|
||||
}
|
||||
|
||||
|
||||
|
@ -482,8 +482,11 @@ AcpiTbConvertFadt (
|
||||
*
|
||||
* The ACPI 1.0 reserved fields that will be zeroed are the bytes located
|
||||
* at offset 45, 55, 95, and the word located at offset 109, 110.
|
||||
*
|
||||
* Note: The FADT revision value is unreliable. Only the length can be
|
||||
* trusted.
|
||||
*/
|
||||
if (AcpiGbl_FADT.Header.Revision < 3)
|
||||
if (AcpiGbl_FADT.Header.Length <= ACPI_FADT_V2_SIZE)
|
||||
{
|
||||
AcpiGbl_FADT.PreferredProfile = 0;
|
||||
AcpiGbl_FADT.PstateControl = 0;
|
||||
|
@ -469,4 +469,20 @@ typedef struct acpi_table_desc
|
||||
|
||||
#define ACPI_FADT_OFFSET(f) (UINT8) ACPI_OFFSET (ACPI_TABLE_FADT, f)
|
||||
|
||||
/*
|
||||
* Sizes of the various flavors of FADT. We need to look closely
|
||||
* at the FADT length because the version number essentially tells
|
||||
* us nothing because of many BIOS bugs where the version does not
|
||||
* match the expected length. In other words, the length of the
|
||||
* FADT is the bottom line as to what the version really is.
|
||||
*
|
||||
* For reference, the values below are as follows:
|
||||
* FADT V1 size: 0x74
|
||||
* FADT V2 size: 0x84
|
||||
* FADT V3+ size: 0xF4
|
||||
*/
|
||||
#define ACPI_FADT_V1_SIZE (UINT32) (ACPI_FADT_OFFSET (Flags) + 4)
|
||||
#define ACPI_FADT_V2_SIZE (UINT32) (ACPI_FADT_OFFSET (Reserved4[0]) + 3)
|
||||
#define ACPI_FADT_V3_SIZE (UINT32) (sizeof (ACPI_TABLE_FADT))
|
||||
|
||||
#endif /* __ACTBL_H__ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user