acpidump: Add DSDT/FACS instance support for Linux and EFI

ACPI spec allows to configure different 32-bit/64-bit table addresses for
DSDT and FACS. And for FACS, it's meaningful to dump both of them as they
are used to support different suspend protocols.

While:
1. on Linux, only 1 instance is supported for DSDT/FACS; and
2. on EFI, the code in OslGetTable() is buggy with special table instances,
   causing endless file dump for such tables (reported by Shao Ming in link
   #2).

This patch adds DSDT/FACS instance support for Linux/EFI but doesn't cover
BSD as BSD acpidump needs a full refresh. Fixed by Lv Zheng.

Link: https://bugs.acpica.org/show_bug.cgi?id=1407 [#1]
Link: https://github.com/acpica/acpica/issues/285  [#2]
Reported-by: Shao Ming <smbest163@163.com>
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
This commit is contained in:
Lv Zheng 2017-07-12 17:44:44 +08:00 committed by Zheng
parent 01b8f5a235
commit 343fc31840
2 changed files with 133 additions and 50 deletions

View File

@ -782,7 +782,7 @@ OslListTables (
/* Skip NULL entries in RSDT/XSDT */
if (!TableAddress)
if (TableAddress == 0)
{
continue;
}
@ -835,7 +835,8 @@ OslGetTable (
UINT8 NumberOfTables;
UINT8 ItemSize;
UINT32 CurrentInstance = 0;
ACPI_PHYSICAL_ADDRESS TableAddress = 0;
ACPI_PHYSICAL_ADDRESS TableAddress;
ACPI_PHYSICAL_ADDRESS FirstTableAddress = 0;
UINT32 TableLength = 0;
ACPI_STATUS Status = AE_OK;
UINT32 i;
@ -849,6 +850,11 @@ OslGetTable (
ACPI_COMPARE_NAME (Signature, ACPI_SIG_DSDT) ||
ACPI_COMPARE_NAME (Signature, ACPI_SIG_FACS))
{
FindNextInstance:
TableAddress = 0;
/*
* Get the appropriate address, either 32-bit or 64-bit. Be very
* careful about the FADT length and validate table addresses.
@ -856,28 +862,34 @@ OslGetTable (
*/
if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_DSDT))
{
if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XDSDT) &&
Gbl_Fadt->XDsdt)
if (CurrentInstance < 2)
{
TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XDsdt;
}
else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_DSDT) &&
Gbl_Fadt->Dsdt)
{
TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Dsdt;
if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XDSDT) &&
Gbl_Fadt->XDsdt && CurrentInstance == 0)
{
TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XDsdt;
}
else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_DSDT) &&
Gbl_Fadt->Dsdt != FirstTableAddress)
{
TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Dsdt;
}
}
}
else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_FACS))
{
if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XFACS) &&
Gbl_Fadt->XFacs)
if (CurrentInstance < 2)
{
TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XFacs;
}
else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_FACS) &&
Gbl_Fadt->Facs)
{
TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Facs;
if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XFACS) &&
Gbl_Fadt->XFacs && CurrentInstance == 0)
{
TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XFacs;
}
else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_FACS) &&
Gbl_Fadt->Facs != FirstTableAddress)
{
TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Facs;
}
}
}
else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_XSDT))
@ -886,16 +898,32 @@ OslGetTable (
{
return (AE_BAD_SIGNATURE);
}
TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Rsdp.XsdtPhysicalAddress;
if (CurrentInstance == 0)
{
TableAddress =
(ACPI_PHYSICAL_ADDRESS) Gbl_Rsdp.XsdtPhysicalAddress;
}
}
else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_RSDT))
{
TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Rsdp.RsdtPhysicalAddress;
if (CurrentInstance == 0)
{
TableAddress =
(ACPI_PHYSICAL_ADDRESS) Gbl_Rsdp.RsdtPhysicalAddress;
}
}
else
{
TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_RsdpAddress;
Signature = ACPI_SIG_RSDP;
if (CurrentInstance == 0)
{
TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_RsdpAddress;
Signature = ACPI_SIG_RSDP;
}
}
if (TableAddress == 0)
{
goto ExitFindTable;
}
/* Now we can get the requested special table */
@ -907,6 +935,20 @@ OslGetTable (
}
TableLength = ApGetTableLength (MappedTable);
if (FirstTableAddress == 0)
{
FirstTableAddress = TableAddress;
}
/* Match table instance */
if (CurrentInstance != Instance)
{
OslUnmapTable (MappedTable);
MappedTable = NULL;
CurrentInstance++;
goto FindNextInstance;
}
}
else /* Case for a normal ACPI table */
{
@ -944,7 +986,7 @@ OslGetTable (
/* Skip NULL entries in RSDT/XSDT */
if (!TableAddress)
if (TableAddress == 0)
{
continue;
}
@ -979,6 +1021,8 @@ OslGetTable (
}
}
ExitFindTable:
if (!MappedTable)
{
return (AE_LIMIT);

View File

@ -988,7 +988,7 @@ OslListBiosTables (
/* Skip NULL entries in RSDT/XSDT */
if (!TableAddress)
if (TableAddress == 0)
{
continue;
}
@ -1041,7 +1041,8 @@ OslGetBiosTable (
UINT8 NumberOfTables;
UINT8 ItemSize;
UINT32 CurrentInstance = 0;
ACPI_PHYSICAL_ADDRESS TableAddress = 0;
ACPI_PHYSICAL_ADDRESS TableAddress;
ACPI_PHYSICAL_ADDRESS FirstTableAddress = 0;
UINT32 TableLength = 0;
ACPI_STATUS Status = AE_OK;
UINT32 i;
@ -1055,10 +1056,10 @@ OslGetBiosTable (
ACPI_COMPARE_NAME (Signature, ACPI_SIG_DSDT) ||
ACPI_COMPARE_NAME (Signature, ACPI_SIG_FACS))
{
if (Instance > 0)
{
return (AE_LIMIT);
}
FindNextInstance:
TableAddress = 0;
/*
* Get the appropriate address, either 32-bit or 64-bit. Be very
@ -1067,28 +1068,34 @@ OslGetBiosTable (
*/
if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_DSDT))
{
if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XDSDT) &&
Gbl_Fadt->XDsdt)
if (CurrentInstance < 2)
{
TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XDsdt;
}
else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_DSDT) &&
Gbl_Fadt->Dsdt)
{
TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Dsdt;
if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XDSDT) &&
Gbl_Fadt->XDsdt && CurrentInstance == 0)
{
TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XDsdt;
}
else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_DSDT) &&
Gbl_Fadt->Dsdt != FirstTableAddress)
{
TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Dsdt;
}
}
}
else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_FACS))
{
if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XFACS) &&
Gbl_Fadt->XFacs)
if (CurrentInstance < 2)
{
TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XFacs;
}
else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_FACS) &&
Gbl_Fadt->Facs)
{
TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Facs;
if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XFACS) &&
Gbl_Fadt->XFacs && CurrentInstance == 0)
{
TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XFacs;
}
else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_FACS) &&
Gbl_Fadt->Facs != FirstTableAddress)
{
TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Facs;
}
}
}
else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_XSDT))
@ -1097,16 +1104,32 @@ OslGetBiosTable (
{
return (AE_BAD_SIGNATURE);
}
TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Rsdp.XsdtPhysicalAddress;
if (CurrentInstance == 0)
{
TableAddress =
(ACPI_PHYSICAL_ADDRESS) Gbl_Rsdp.XsdtPhysicalAddress;
}
}
else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_RSDT))
{
TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Rsdp.RsdtPhysicalAddress;
if (CurrentInstance == 0)
{
TableAddress =
(ACPI_PHYSICAL_ADDRESS) Gbl_Rsdp.RsdtPhysicalAddress;
}
}
else
{
TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_RsdpAddress;
Signature = ACPI_SIG_RSDP;
if (CurrentInstance == 0)
{
TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_RsdpAddress;
Signature = ACPI_SIG_RSDP;
}
}
if (TableAddress == 0)
{
goto ExitFindTable;
}
/* Now we can get the requested special table */
@ -1118,6 +1141,20 @@ OslGetBiosTable (
}
TableLength = ApGetTableLength (MappedTable);
if (FirstTableAddress == 0)
{
FirstTableAddress = TableAddress;
}
/* Match table instance */
if (CurrentInstance != Instance)
{
OslUnmapTable (MappedTable);
MappedTable = NULL;
CurrentInstance++;
goto FindNextInstance;
}
}
else /* Case for a normal ACPI table */
{
@ -1155,7 +1192,7 @@ OslGetBiosTable (
/* Skip NULL entries in RSDT/XSDT */
if (!TableAddress)
if (TableAddress == 0)
{
continue;
}
@ -1190,6 +1227,8 @@ OslGetBiosTable (
}
}
ExitFindTable:
if (!MappedTable)
{
return (AE_LIMIT);