From 9b9f67922f618c5be0d6b866954a61bc245a6cfe Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Fri, 30 Jun 2017 09:25:54 +0800 Subject: [PATCH] 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 Signed-off-by: Lv Zheng --- source/os_specific/efi/osefitbl.c | 90 +++++++++++++----- .../os_specific/service_layers/oslinuxtbl.c | 93 +++++++++++++------ 2 files changed, 133 insertions(+), 50 deletions(-) diff --git a/source/os_specific/efi/osefitbl.c b/source/os_specific/efi/osefitbl.c index 238bfeb803..ad983efdfb 100644 --- a/source/os_specific/efi/osefitbl.c +++ b/source/os_specific/efi/osefitbl.c @@ -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) - { - TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XFacs; - } - else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_FACS) && - Gbl_Fadt->Facs) + if (CurrentInstance < 2) { - 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); diff --git a/source/os_specific/service_layers/oslinuxtbl.c b/source/os_specific/service_layers/oslinuxtbl.c index 4d2952e334..3572b8eb92 100644 --- a/source/os_specific/service_layers/oslinuxtbl.c +++ b/source/os_specific/service_layers/oslinuxtbl.c @@ -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) + { + FirstTableAdddress = 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);