Received: by 2002:ac0:8c9a:0:0:0:0:0 with SMTP id r26csp3546141ima; Mon, 4 Feb 2019 00:49:19 -0800 (PST) X-Google-Smtp-Source: AHgI3IY1ua8ZrGlGi9dEaIimrT45afWMN17C4dVmFWltDUZ94CZs3l+2DIESm+EuMA3axTZJOa/S X-Received: by 2002:a17:902:1:: with SMTP id 1mr4593105pla.276.1549270158960; Mon, 04 Feb 2019 00:49:18 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1549270158; cv=none; d=google.com; s=arc-20160816; b=WhfYSrJ8NxWeGhhJhLw8CRk4LrxZFKE8zKqFAX3wxRAzEJ1uLtun8YZW13TvokgwZE uPBQDsvPuSutEFmmjJR//1GNT9YL1TiKw4jZyYXgAenGTTMr2t9rJEPUrufL6CMuafUl 5NrsJl8AzqD2WuPa+dF5MZL1w/S65GecfuPKaF+/wl5/F9NPOIzbWHpgUTZ7eip/8W6F A8W5HQLa0FhEvPvuZzCuaSkvYAlWBkYWMk2w6s/vinbK3WJmNBRcBvV04Jd8bPKezJBY wGEiT8E5IgJ3IcqZUkACcTRhhTjTL5tlv0mey0YeScp24ukX7cAm/2x9uu86eaQYG/+0 8rsQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-disposition :content-transfer-encoding:mime-version:robot-unsubscribe:robot-id :git-commit-id:subject:to:references:in-reply-to:reply-to:cc :message-id:from:date; bh=UtScijx5JLl58tbrglFFvphfzHSCRvXWEx5jLtgmGSk=; b=sqZdo0C2zidIsxzPbLrS0xtfLlG/6roLhH1q0SKumE+Qqwv9Xuesa7N57GsSm9Y6i8 CO6TlQbG7jZZOkjmS8smMV4mpaQlnS9CeN1DDBXe2nZsQAJzz11RICqDT3mmD+g32LzV jfoV8Gxv68FxCfQJb3OunqtnjR0Vpgz2U5qWAcL1uk8FoiOFx8v5VMFuFMuu9f7NMGLC /Fw36lbqvb+oH6uN1ANm6kJp4NXL5s5rzvL75AW+05phVWSpCtpofTkNwRAdBTra93G4 jKbyMs9i4H1uHe02JIubmZQLgcUXshZxSvuWpwu0XTgG2hqgxTwGvfS3FI4CI7qZTyE1 QuxQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id t11si4562989pgv.251.2019.02.04.00.49.03; Mon, 04 Feb 2019 00:49:18 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728079AbfBDIsI (ORCPT + 99 others); Mon, 4 Feb 2019 03:48:08 -0500 Received: from terminus.zytor.com ([198.137.202.136]:47699 "EHLO terminus.zytor.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726320AbfBDIsI (ORCPT ); Mon, 4 Feb 2019 03:48:08 -0500 Received: from terminus.zytor.com (localhost [127.0.0.1]) by terminus.zytor.com (8.15.2/8.15.2) with ESMTPS id x148lTaD356644 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NO); Mon, 4 Feb 2019 00:47:29 -0800 Received: (from tipbot@localhost) by terminus.zytor.com (8.15.2/8.15.2/Submit) id x148lT7T356641; Mon, 4 Feb 2019 00:47:29 -0800 Date: Mon, 4 Feb 2019 00:47:29 -0800 X-Authentication-Warning: terminus.zytor.com: tipbot set sender to tipbot@zytor.com using -f From: tip-bot for Ard Biesheuvel Message-ID: Cc: sai.praneeth.prakhya@intel.com, torvalds@linux-foundation.org, ard.biesheuvel@linaro.org, peterz@infradead.org, hpa@zytor.com, agraf@suse.de, takahiro.akashi@linaro.org, bp@alien8.de, linux-kernel@vger.kernel.org, jhugo@codeaurora.org, tglx@linutronix.de, lee.jones@linaro.org, leif.lindholm@linaro.org, pjones@redhat.com, matt@codeblueprint.co.uk, mingo@kernel.org, bjorn.andersson@linaro.org, xypron.glpk@gmx.de Reply-To: sai.praneeth.prakhya@intel.com, torvalds@linux-foundation.org, ard.biesheuvel@linaro.org, peterz@infradead.org, hpa@zytor.com, agraf@suse.de, takahiro.akashi@linaro.org, linux-kernel@vger.kernel.org, jhugo@codeaurora.org, bp@alien8.de, tglx@linutronix.de, leif.lindholm@linaro.org, lee.jones@linaro.org, pjones@redhat.com, matt@codeblueprint.co.uk, mingo@kernel.org, bjorn.andersson@linaro.org, xypron.glpk@gmx.de In-Reply-To: <20190202094119.13230-11-ard.biesheuvel@linaro.org> References: <20190202094119.13230-11-ard.biesheuvel@linaro.org> To: linux-tip-commits@vger.kernel.org Subject: [tip:efi/core] acpi/bgrt: Parse BGRT to obtain BMP address before it gets clobbered Git-Commit-ID: 41dd9d30a0994a138d3d3b5a2e1e46bd1aa38ea2 X-Mailer: tip-git-log-daemon Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=UTF-8 Content-Disposition: inline X-Spam-Status: No, score=-0.8 required=5.0 tests=ALL_TRUSTED,BAYES_00, FREEMAIL_FORGED_REPLYTO,T_DATE_IN_FUTURE_96_Q autolearn=no autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on terminus.zytor.com Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Commit-ID: 41dd9d30a0994a138d3d3b5a2e1e46bd1aa38ea2 Gitweb: https://git.kernel.org/tip/41dd9d30a0994a138d3d3b5a2e1e46bd1aa38ea2 Author: Ard Biesheuvel AuthorDate: Sat, 2 Feb 2019 10:41:19 +0100 Committer: Ingo Molnar CommitDate: Mon, 4 Feb 2019 08:27:31 +0100 acpi/bgrt: Parse BGRT to obtain BMP address before it gets clobbered The bitmap left in the framebuffer by the firmware is described by an ACPI table called "BGRT", which describes the size, pixel format and the address of a BMP image in memory. While the BGRT ACPI table is guaranteed to reside in a "ACPI reclaim" memory region, which is never touched by Linux, the BMP image, however, typically resides in EFI Boot Services Memory, which may have been overwritten by the time the BGRT discovery routine runs. So instead, drop the handling from the ACPI init code, and call the BGRT parsing code immediately after going over the EFI configuration table array, at which time no memory has been touched yet except for the .data/.bss regions covered by the static kernel image. Unfortunately, this involves a non-trivial amount of ACPI entry point and root table parsing, but we cannot rely on the normal ACPI infrastructure yet this early in the boot. Also note that we cannot take the 'acpi_disabled' global variable into account, since it may not have assumed the correct value yet (on arm64, the default value is '1' which is overridden to '0' if no DT description has been made available by the firmware). Signed-off-by: Ard Biesheuvel Cc: AKASHI Takahiro Cc: Alexander Graf Cc: Bjorn Andersson Cc: Borislav Petkov Cc: Heinrich Schuchardt Cc: Jeffrey Hugo Cc: Lee Jones Cc: Leif Lindholm Cc: Linus Torvalds Cc: Matt Fleming Cc: Peter Jones Cc: Peter Zijlstra Cc: Sai Praneeth Prakhya Cc: Thomas Gleixner Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/20190202094119.13230-11-ard.biesheuvel@linaro.org Signed-off-by: Ingo Molnar --- arch/arm64/kernel/acpi.c | 2 - arch/x86/kernel/acpi/boot.c | 2 - drivers/acpi/bgrt.c | 6 --- drivers/firmware/efi/efi-bgrt.c | 84 +++++++++++++++++++++++++++++++++++++---- drivers/firmware/efi/efi.c | 13 +++++++ include/linux/efi-bgrt.h | 4 +- 6 files changed, 92 insertions(+), 19 deletions(-) diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c index 44e3c351e1ea..7429a811f76d 100644 --- a/arch/arm64/kernel/acpi.c +++ b/arch/arm64/kernel/acpi.c @@ -230,8 +230,6 @@ done: early_init_dt_scan_chosen_stdout(); } else { acpi_parse_spcr(earlycon_acpi_spcr_enable, true); - if (IS_ENABLED(CONFIG_ACPI_BGRT)) - acpi_table_parse(ACPI_SIG_BGRT, acpi_parse_bgrt); } } diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 2624de16cd7a..2d3535b62752 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -1633,8 +1633,6 @@ int __init acpi_boot_init(void) acpi_process_madt(); acpi_table_parse(ACPI_SIG_HPET, acpi_parse_hpet); - if (IS_ENABLED(CONFIG_ACPI_BGRT)) - acpi_table_parse(ACPI_SIG_BGRT, acpi_parse_bgrt); if (!acpi_noirq) x86_init.pci.init = pci_acpi_init; diff --git a/drivers/acpi/bgrt.c b/drivers/acpi/bgrt.c index 75af78361ce5..048413e06898 100644 --- a/drivers/acpi/bgrt.c +++ b/drivers/acpi/bgrt.c @@ -81,12 +81,6 @@ static const struct attribute_group bgrt_attribute_group = { .bin_attrs = bgrt_bin_attributes, }; -int __init acpi_parse_bgrt(struct acpi_table_header *table) -{ - efi_bgrt_init(table); - return 0; -} - static int __init bgrt_init(void) { int ret; diff --git a/drivers/firmware/efi/efi-bgrt.c b/drivers/firmware/efi/efi-bgrt.c index a2384184a7de..9c50d453b143 100644 --- a/drivers/firmware/efi/efi-bgrt.c +++ b/drivers/firmware/efi/efi-bgrt.c @@ -24,24 +24,94 @@ struct bmp_header { u32 size; } __packed; -void __init efi_bgrt_init(struct acpi_table_header *table) +void __init efi_bgrt_init(unsigned long rsdp_phys) { void *image; struct bmp_header bmp_header; struct acpi_table_bgrt *bgrt = &bgrt_tab; + struct acpi_table_bgrt *table = NULL; + struct acpi_table_rsdp *rsdp; + struct acpi_table_header *hdr; + u64 xsdt_phys = 0; + u32 rsdt_phys = 0; + size_t len; - if (acpi_disabled) + if (!efi_enabled(EFI_MEMMAP)) return; - if (!efi_enabled(EFI_MEMMAP)) + /* map the root pointer table to find the xsdt/rsdt values */ + rsdp = early_memremap_ro(rsdp_phys, sizeof(*rsdp)); + if (rsdp) { + if (ACPI_VALIDATE_RSDP_SIG(rsdp->signature)) { + xsdt_phys = rsdp->xsdt_physical_address; + rsdt_phys = rsdp->rsdt_physical_address; + } + early_memunmap(rsdp, sizeof(*rsdp)); + } + + if (WARN_ON(!xsdt_phys && !rsdt_phys)) return; - if (table->length < sizeof(bgrt_tab)) { - pr_notice("Ignoring BGRT: invalid length %u (expected %zu)\n", - table->length, sizeof(bgrt_tab)); + /* obtain the length of whichever table we will be using */ + hdr = early_memremap_ro(xsdt_phys ?: rsdt_phys, sizeof(*hdr)); + if (WARN_ON(!hdr)) + return; + len = hdr->length; + early_memunmap(hdr, sizeof(*hdr)); + + /* remap with the correct length */ + hdr = early_memremap_ro(xsdt_phys ?: rsdt_phys, len); + if (WARN_ON(!hdr)) + return; + + if (xsdt_phys) { + struct acpi_table_xsdt *xsdt = (void *)hdr; + int i; + + for (i = 0; i < (len - sizeof(*hdr)) / sizeof(u64); i++) { + table = early_memremap_ro(xsdt->table_offset_entry[i], + sizeof(*table)); + if (WARN_ON(!table)) + break; + + if (ACPI_COMPARE_NAME(table->header.signature, + ACPI_SIG_BGRT)) + break; + early_memunmap(table, sizeof(*table)); + table = NULL; + } + } else if (rsdt_phys) { + struct acpi_table_rsdt *rsdt = (void *)hdr; + int i; + + for (i = 0; i < (len - sizeof(*hdr)) / sizeof(u32); i++) { + table = early_memremap_ro(rsdt->table_offset_entry[i], + sizeof(*table)); + if (WARN_ON(!table)) + break; + + if (ACPI_COMPARE_NAME(table->header.signature, + ACPI_SIG_BGRT)) + break; + early_memunmap(table, sizeof(*table)); + table = NULL; + } + } + early_memunmap(hdr, len); + + if (!table) return; + + len = table->header.length; + memcpy(bgrt, table, min(len, sizeof(bgrt_tab))); + early_memunmap(table, sizeof(*table)); + + if (len < sizeof(bgrt_tab)) { + pr_notice("Ignoring BGRT: invalid length %zu (expected %zu)\n", + len, sizeof(bgrt_tab)); + goto out; } - *bgrt = *(struct acpi_table_bgrt *)table; + if (bgrt->version != 1) { pr_notice("Ignoring BGRT: invalid version %u (expected 1)\n", bgrt->version); diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 4c46ff6f2242..e5ef5c0eacc1 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -592,6 +593,18 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz, early_memunmap(tbl, sizeof(*tbl)); } + + /* + * We need to parse the BGRT table (which is an ACPI table not a UEFI + * configuration table) by hand and figure out where the bitmap it + * describes lives in memory so we can reserve it early on. Otherwise, + * it may be clobbered by the time we get to it during the ordinary ACPI + * table init sequence. + */ + if (IS_ENABLED(CONFIG_ACPI_BGRT) && + efi.acpi20 != EFI_INVALID_TABLE_ADDR) + efi_bgrt_init(efi.acpi20); + return 0; } diff --git a/include/linux/efi-bgrt.h b/include/linux/efi-bgrt.h index e6cd51005633..528ea62d99ec 100644 --- a/include/linux/efi-bgrt.h +++ b/include/linux/efi-bgrt.h @@ -6,7 +6,7 @@ #ifdef CONFIG_ACPI_BGRT -void efi_bgrt_init(struct acpi_table_header *table); +void efi_bgrt_init(unsigned long rsdp_phys); int __init acpi_parse_bgrt(struct acpi_table_header *table); /* The BGRT data itself; only valid if bgrt_image != NULL. */ @@ -15,7 +15,7 @@ extern struct acpi_table_bgrt bgrt_tab; #else /* !CONFIG_ACPI_BGRT */ -static inline void efi_bgrt_init(struct acpi_table_header *table) {} +static inline void efi_bgrt_init(unsigned long rsdp_phys) {} static inline int __init acpi_parse_bgrt(struct acpi_table_header *table) { return 0;