Commit 03c5b6b0 authored by Lv Zheng's avatar Lv Zheng Committed by Rafael J. Wysocki
Browse files

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: default avatarShao Ming <smbest163@163.com>
Signed-off-by: default avatarLv Zheng <lv.zheng@intel.com>
Signed-off-by: default avatarBob Moore <robert.moore@intel.com>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 65082bfc
Loading
Loading
Loading
Loading
+73 −32
Original line number Diff line number Diff line
@@ -759,7 +759,7 @@ static acpi_status osl_list_bios_tables(void)

		/* Skip NULL entries in RSDT/XSDT */

		if (!table_address) {
		if (table_address == 0) {
			continue;
		}

@@ -808,7 +808,8 @@ osl_get_bios_table(char *signature,
	u8 number_of_tables;
	u8 item_size;
	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;
	acpi_status status = AE_OK;
	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_DSDT) ||
	    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
@@ -830,42 +832,67 @@ osl_get_bios_table(char *signature,
		 * Note: The 64-bit addresses have priority.
		 */
		if (ACPI_COMPARE_NAME(signature, ACPI_SIG_DSDT)) {
			if ((gbl_fadt->header.length >= MIN_FADT_FOR_XDSDT) &&
			    gbl_fadt->Xdsdt) {
			if (current_instance < 2) {
				if ((gbl_fadt->header.length >=
				     MIN_FADT_FOR_XDSDT) && gbl_fadt->Xdsdt
				    && current_instance == 0) {
					table_address =
				    (acpi_physical_address)gbl_fadt->Xdsdt;
					    (acpi_physical_address)gbl_fadt->
					    Xdsdt;
				} else
			    if ((gbl_fadt->header.length >= MIN_FADT_FOR_DSDT)
				&& 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;
					    (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 (current_instance < 2) {
				if ((gbl_fadt->header.length >=
				     MIN_FADT_FOR_XFACS) && gbl_fadt->Xfacs
				    && current_instance == 0) {
					table_address =
				    (acpi_physical_address)gbl_fadt->Xfacs;
					    (acpi_physical_address)gbl_fadt->
					    Xfacs;
				} else
			    if ((gbl_fadt->header.length >= MIN_FADT_FOR_FACS)
				&& 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;
					    (acpi_physical_address)gbl_fadt->
					    facs;
				}
			}
		} else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_XSDT)) {
			if (!gbl_revision) {
				return (AE_BAD_SIGNATURE);
			}
			if (current_instance == 0) {
				table_address =
				    (acpi_physical_address)gbl_rsdp.
				    xsdt_physical_address;
			}
		} else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_RSDT)) {
			if (current_instance == 0) {
				table_address =
				    (acpi_physical_address)gbl_rsdp.
				    rsdt_physical_address;
			}
		} else {
			table_address = (acpi_physical_address)gbl_rsdp_address;
			if (current_instance == 0) {
				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 */

@@ -875,6 +902,18 @@ osl_get_bios_table(char *signature,
		}

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

		if (osl_can_use_xsdt()) {
@@ -913,7 +952,7 @@ osl_get_bios_table(char *signature,

			/* Skip NULL entries in RSDT/XSDT */

			if (!table_address) {
			if (table_address == 0) {
				continue;
			}

@@ -946,6 +985,8 @@ osl_get_bios_table(char *signature,
		}
	}

exit_find_table:

	if (!mapped_table) {
		return (AE_LIMIT);
	}