From patchwork Fri Mar 18 16:47:38 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 64087 Delivered-To: patch@linaro.org Received: by 10.112.199.169 with SMTP id jl9csp67805lbc; Fri, 18 Mar 2016 09:50:30 -0700 (PDT) X-Received: by 10.66.254.168 with SMTP id aj8mr25352656pad.18.1458319830424; Fri, 18 Mar 2016 09:50:30 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id wu1si6765018pab.71.2016.03.18.09.50.29; Fri, 18 Mar 2016 09:50:30 -0700 (PDT) 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; dkim=pass header.i=@linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753381AbcCRQu2 (ORCPT + 30 others); Fri, 18 Mar 2016 12:50:28 -0400 Received: from mail-wm0-f46.google.com ([74.125.82.46]:38384 "EHLO mail-wm0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753461AbcCRQsE (ORCPT ); Fri, 18 Mar 2016 12:48:04 -0400 Received: by mail-wm0-f46.google.com with SMTP id l68so45461230wml.1 for ; Fri, 18 Mar 2016 09:48:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=2lv4hwMpmyL9CkGe7ehF03VGsIQ08SENDWSMalOhhbw=; b=IKB98wJSV1UZAf5oEo/S1Pn2TtcVqjyUeegtKFRGmlg/AypUTfknlykYGcSkx8FMcg jBjxrVyVmb5tFQ+8UGY0Fruij/jqGtZIvJhmE+IMRKrJN64u5Mgb/boQ9qtkVLzBRwrk nTlUVJTpRRw3EQ+Bkp0hX4PDVdBrFuo7SeLBc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=2lv4hwMpmyL9CkGe7ehF03VGsIQ08SENDWSMalOhhbw=; b=hv8SjxXq6XIfmtuvxTvmIRaACLpa1IufRe4zVXA9vXThLiPFD7h8OrSbGsYdAd8/sE +bQjXyDnAcOYDHYZPzZbasTDKFlHtC9XmtNb/DZ35iUm6XIFfco/M8cusChF0q7g7Itw 84S+FBOlm6QMQqOO7n21pEaWIY94FwAZhO22yR5gQiwJWCrzV4Wsnk7ICGTGsW0mt6pD YXPRTq9RDGZFd8DIkhmQjGE01wIZS8QCAJvQg1OWclnsXBG9/qMV5Yk9NmLI72lOxNBU dEwK85H+423k2oa+aMwjvX/PW26c/5RgEWUdBWQV4rsS+RH75CclwPVGvN24vv0IR78d 9aqA== X-Gm-Message-State: AD7BkJJu7NSX1lrnaAvZrky49UBNeLZYXWLlGrVcRumrlTaer6GeFRYMcG1sllUqpypeeYCW X-Received: by 10.28.145.8 with SMTP id t8mr308579wmd.103.1458319682841; Fri, 18 Mar 2016 09:48:02 -0700 (PDT) Received: from localhost.localdomain ([195.55.142.58]) by smtp.gmail.com with ESMTPSA id c71sm118646wmd.4.2016.03.18.09.48.00 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 18 Mar 2016 09:48:02 -0700 (PDT) From: Ard Biesheuvel To: linux-kernel@vger.kernel.org, linux-efi@vger.kernel.org, linux-arm-kernel@lists.infradead.org, matt@codeblueprint.co.uk, catalin.marinas@arm.com, will.deacon@arm.com, linux@arm.linux.org.uk, pjones@redhat.com, dh.herrmann@gmail.com Cc: leif.lindholm@linaro.org, mark.rutland@arm.com, x86@kernel.org, Ard Biesheuvel Subject: [PATCH v2 6/9] efi/arm: libstub: make screen_info accessible to the UEFI stub Date: Fri, 18 Mar 2016 17:47:38 +0100 Message-Id: <1458319661-19762-7-git-send-email-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.5.0 In-Reply-To: <1458319661-19762-1-git-send-email-ard.biesheuvel@linaro.org> References: <1458319661-19762-1-git-send-email-ard.biesheuvel@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org In order to hand over the framebuffer described by the GOP protocol and discovered by the UEFI stub, make struct screen_info accessible by the stub. This involves allocating a loader data buffer and passing it to the kernel proper via a UEFI Configuration Table, since the UEFI stub executes in the context of the decompressor, and cannot access the kernel's copy of struct screen_info directly. Signed-off-by: Ard Biesheuvel --- arch/arm/include/asm/efi.h | 3 ++ arch/arm/kernel/setup.c | 3 +- drivers/firmware/efi/arm-init.c | 30 +++++++++++++++- drivers/firmware/efi/efi.c | 5 +-- drivers/firmware/efi/libstub/arm32-stub.c | 37 ++++++++++++++++++++ include/linux/efi.h | 11 +++++- 6 files changed, 84 insertions(+), 5 deletions(-) -- 2.5.0 diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h index ce1aa3454ca8..be12877e8609 100644 --- a/arch/arm/include/asm/efi.h +++ b/arch/arm/include/asm/efi.h @@ -63,6 +63,9 @@ void efi_virtmap_unload(void); #define __efi_call_early(f, ...) f(__VA_ARGS__) #define efi_is_64bit() (false) +struct screen_info *alloc_screen_info(efi_system_table_t *sys_table_arg); +void free_screen_info(efi_system_table_t *sys_table, struct screen_info *si); + /* * A reasonable upper bound for the uncompressed kernel size is 32 MBytes, * so we will reserve that amount of memory. We have no easy way to tell what diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 139791ed473d..2916abd6ec01 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -881,7 +881,8 @@ static void __init request_standard_resources(const struct machine_desc *mdesc) request_resource(&ioport_resource, &lp2); } -#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE) +#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE) || \ + defined(CONFIG_EFI) struct screen_info screen_info = { .orig_video_lines = 30, .orig_video_cols = 80, diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c index 9e15d571b53c..acd44de30504 100644 --- a/drivers/firmware/efi/arm-init.c +++ b/drivers/firmware/efi/arm-init.c @@ -11,12 +11,15 @@ * */ +#define pr_fmt(fmt) "efi: " fmt + #include #include #include #include #include #include +#include #include @@ -53,6 +56,28 @@ static phys_addr_t efi_to_phys(unsigned long addr) return addr; } +static __initdata unsigned long screen_info_table = EFI_INVALID_TABLE_ADDR; + +static __initdata efi_config_table_type_t arch_tables[] = { + {LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID, NULL, &screen_info_table}, + {NULL_GUID, NULL, NULL} +}; + +static void __init init_screen_info(void) +{ + struct screen_info *si; + + if (screen_info_table != EFI_INVALID_TABLE_ADDR) { + si = early_memremap_ro(screen_info_table, sizeof(*si)); + if (!si) { + pr_err("Could not map screen_info config table\n"); + return; + } + screen_info = *si; + early_memunmap(si, sizeof(*si)); + } +} + static int __init uefi_init(void) { efi_char16_t *c16; @@ -108,7 +133,8 @@ static int __init uefi_init(void) goto out; } retval = efi_config_parse_tables(config_tables, efi.systab->nr_tables, - sizeof(efi_config_table_t), NULL); + sizeof(efi_config_table_t), + arch_tables); early_memunmap(config_tables, table_size); out: @@ -206,4 +232,6 @@ void __init efi_init(void) memblock_mark_nomap(params.mmap & PAGE_MASK, PAGE_ALIGN(params.mmap_size + (params.mmap & ~PAGE_MASK))); + + init_screen_info(); } diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 2cd37dad67a6..cb46165a1fec 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -382,8 +382,9 @@ static __init int match_config_table(efi_guid_t *guid, for (i = 0; efi_guidcmp(table_types[i].guid, NULL_GUID); i++) { if (!efi_guidcmp(*guid, table_types[i].guid)) { *(table_types[i].ptr) = table; - pr_cont(" %s=0x%lx ", - table_types[i].name, table); + if (table_types[i].name) + pr_cont(" %s=0x%lx ", + table_types[i].name, table); return 1; } } diff --git a/drivers/firmware/efi/libstub/arm32-stub.c b/drivers/firmware/efi/libstub/arm32-stub.c index 495ebd657e38..83feff5e1b6e 100644 --- a/drivers/firmware/efi/libstub/arm32-stub.c +++ b/drivers/firmware/efi/libstub/arm32-stub.c @@ -9,6 +9,43 @@ #include #include +static efi_guid_t screen_info_guid = LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID; + +struct screen_info *alloc_screen_info(efi_system_table_t *sys_table_arg) +{ + struct screen_info *si; + efi_status_t status; + + /* + * Unlike on arm64, where we can directly fill out the screen_info + * structure from the stub, we need to allocate a buffer to hold + * its contents while we hand over to the kernel proper from the + * decompressor. + */ + status = efi_call_early(allocate_pool, EFI_RUNTIME_SERVICES_DATA, + sizeof(*si), (void **)&si); + + if (status != EFI_SUCCESS) + return NULL; + + status = efi_call_early(install_configuration_table, + &screen_info_guid, si); + if (status == EFI_SUCCESS) + return si; + + efi_call_early(free_pool, si); + return NULL; +} + +void free_screen_info(efi_system_table_t *sys_table_arg, struct screen_info *si) +{ + if (!si) + return; + + efi_call_early(install_configuration_table, &screen_info_guid, NULL); + efi_call_early(free_pool, si); +} + efi_status_t handle_kernel_image(efi_system_table_t *sys_table, unsigned long *image_addr, unsigned long *image_size, diff --git a/include/linux/efi.h b/include/linux/efi.h index c53432298d04..e746c1470c50 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -285,7 +285,7 @@ typedef struct { efi_status_t (*locate_handle)(int, efi_guid_t *, void *, unsigned long *, efi_handle_t *); void *locate_device_path; - void *install_configuration_table; + efi_status_t (*install_configuration_table)(efi_guid_t *, void *); void *load_image; void *start_image; void *exit; @@ -609,6 +609,15 @@ void efi_native_runtime_setup(void); EFI_GUID(0xd3b36f2c, 0xd551, 0x11d4, \ 0x9a, 0x46, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d) +/* + * This GUID is used to pass to the kernel proper the struct screen_info + * structure that was populated by the stub based on the GOP protocol instance + * associated with ConOut + */ +#define LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID \ + EFI_GUID(0xe03fc20a, 0x85dc, 0x406e, \ + 0xb9, 0xe, 0x4a, 0xb5, 0x02, 0x37, 0x1d, 0x95) + typedef struct { efi_guid_t guid; u64 table;