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

ACPICA commit 343fc31840d40c06001f3b170ee5bcdfd3c7f3e0

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 osl_get_table() 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 acpidump. Fixed by
Lv Zheng.

Link: https://github.com/acpica/acpica/commit/343fc318
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>
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
tirimbino
Lv Zheng 8 years ago committed by Rafael J. Wysocki
parent 65082bfcb4
commit 03c5b6b0da
  1. 105
      tools/power/acpi/os_specific/service_layers/oslinuxtbl.c

@ -759,7 +759,7 @@ static acpi_status osl_list_bios_tables(void)
/* Skip NULL entries in RSDT/XSDT */ /* Skip NULL entries in RSDT/XSDT */
if (!table_address) { if (table_address == 0) {
continue; continue;
} }
@ -808,7 +808,8 @@ osl_get_bios_table(char *signature,
u8 number_of_tables; u8 number_of_tables;
u8 item_size; u8 item_size;
u32 current_instance = 0; u32 current_instance = 0;
acpi_physical_address table_address = 0; acpi_physical_address table_address;
acpi_physical_address first_table_address = 0;
u32 table_length = 0; u32 table_length = 0;
acpi_status status = AE_OK; acpi_status status = AE_OK;
u32 i; u32 i;
@ -820,9 +821,10 @@ osl_get_bios_table(char *signature,
ACPI_COMPARE_NAME(signature, ACPI_SIG_XSDT) || ACPI_COMPARE_NAME(signature, ACPI_SIG_XSDT) ||
ACPI_COMPARE_NAME(signature, ACPI_SIG_DSDT) || ACPI_COMPARE_NAME(signature, ACPI_SIG_DSDT) ||
ACPI_COMPARE_NAME(signature, ACPI_SIG_FACS)) { ACPI_COMPARE_NAME(signature, ACPI_SIG_FACS)) {
if (instance > 0) {
return (AE_LIMIT); find_next_instance:
}
table_address = 0;
/* /*
* Get the appropriate address, either 32-bit or 64-bit. Be very * Get the appropriate address, either 32-bit or 64-bit. Be very
@ -830,41 +832,66 @@ osl_get_bios_table(char *signature,
* Note: The 64-bit addresses have priority. * Note: The 64-bit addresses have priority.
*/ */
if (ACPI_COMPARE_NAME(signature, ACPI_SIG_DSDT)) { if (ACPI_COMPARE_NAME(signature, ACPI_SIG_DSDT)) {
if ((gbl_fadt->header.length >= MIN_FADT_FOR_XDSDT) && if (current_instance < 2) {
gbl_fadt->Xdsdt) { if ((gbl_fadt->header.length >=
table_address = MIN_FADT_FOR_XDSDT) && gbl_fadt->Xdsdt
(acpi_physical_address)gbl_fadt->Xdsdt; && current_instance == 0) {
} else table_address =
if ((gbl_fadt->header.length >= MIN_FADT_FOR_DSDT) (acpi_physical_address)gbl_fadt->
&& gbl_fadt->dsdt) { Xdsdt;
table_address = } else
(acpi_physical_address)gbl_fadt->dsdt; if ((gbl_fadt->header.length >=
MIN_FADT_FOR_DSDT)
&& gbl_fadt->dsdt !=
first_table_address) {
table_address =
(acpi_physical_address)gbl_fadt->
dsdt;
}
} }
} else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_FACS)) { } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_FACS)) {
if ((gbl_fadt->header.length >= MIN_FADT_FOR_XFACS) && if (current_instance < 2) {
gbl_fadt->Xfacs) { if ((gbl_fadt->header.length >=
table_address = MIN_FADT_FOR_XFACS) && gbl_fadt->Xfacs
(acpi_physical_address)gbl_fadt->Xfacs; && current_instance == 0) {
} else table_address =
if ((gbl_fadt->header.length >= MIN_FADT_FOR_FACS) (acpi_physical_address)gbl_fadt->
&& gbl_fadt->facs) { Xfacs;
table_address = } else
(acpi_physical_address)gbl_fadt->facs; if ((gbl_fadt->header.length >=
MIN_FADT_FOR_FACS)
&& gbl_fadt->facs !=
first_table_address) {
table_address =
(acpi_physical_address)gbl_fadt->
facs;
}
} }
} else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_XSDT)) { } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_XSDT)) {
if (!gbl_revision) { if (!gbl_revision) {
return (AE_BAD_SIGNATURE); return (AE_BAD_SIGNATURE);
} }
table_address = if (current_instance == 0) {
(acpi_physical_address)gbl_rsdp. table_address =
xsdt_physical_address; (acpi_physical_address)gbl_rsdp.
xsdt_physical_address;
}
} else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_RSDT)) { } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_RSDT)) {
table_address = if (current_instance == 0) {
(acpi_physical_address)gbl_rsdp. table_address =
rsdt_physical_address; (acpi_physical_address)gbl_rsdp.
rsdt_physical_address;
}
} else { } else {
table_address = (acpi_physical_address)gbl_rsdp_address; if (current_instance == 0) {
signature = ACPI_SIG_RSDP; table_address =
(acpi_physical_address)gbl_rsdp_address;
signature = ACPI_SIG_RSDP;
}
}
if (table_address == 0) {
goto exit_find_table;
} }
/* Now we can get the requested special table */ /* Now we can get the requested special table */
@ -875,6 +902,18 @@ osl_get_bios_table(char *signature,
} }
table_length = ap_get_table_length(mapped_table); table_length = ap_get_table_length(mapped_table);
if (first_table_address == 0) {
first_table_address = table_address;
}
/* Match table instance */
if (current_instance != instance) {
osl_unmap_table(mapped_table);
mapped_table = NULL;
current_instance++;
goto find_next_instance;
}
} else { /* Case for a normal ACPI table */ } else { /* Case for a normal ACPI table */
if (osl_can_use_xsdt()) { if (osl_can_use_xsdt()) {
@ -913,7 +952,7 @@ osl_get_bios_table(char *signature,
/* Skip NULL entries in RSDT/XSDT */ /* Skip NULL entries in RSDT/XSDT */
if (!table_address) { if (table_address == 0) {
continue; continue;
} }
@ -946,6 +985,8 @@ osl_get_bios_table(char *signature,
} }
} }
exit_find_table:
if (!mapped_table) { if (!mapped_table) {
return (AE_LIMIT); return (AE_LIMIT);
} }

Loading…
Cancel
Save