From patchwork Thu Mar 10 05:40:06 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 63733 Delivered-To: patch@linaro.org Received: by 10.112.199.169 with SMTP id jl9csp244294lbc; Wed, 9 Mar 2016 21:43:50 -0800 (PST) X-Received: by 10.66.167.237 with SMTP id zr13mr2348373pab.85.1457588630788; Wed, 09 Mar 2016 21:43:50 -0800 (PST) Return-Path: Received: from bombadil.infradead.org (bombadil.infradead.org. [2001:1868:205::9]) by mx.google.com with ESMTPS id o64si3494053pfj.112.2016.03.09.21.43.50 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 09 Mar 2016 21:43:50 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org designates 2001:1868:205::9 as permitted sender) client-ip=2001:1868:205::9; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org designates 2001:1868:205::9 as permitted sender) smtp.mailfrom=linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org; dkim=neutral (body hash did not verify) header.i=@linaro.org Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1adtMG-0007xi-SW; Thu, 10 Mar 2016 05:42:00 +0000 Received: from mail-pf0-x232.google.com ([2607:f8b0:400e:c00::232]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1adtLH-0007QI-3G for linux-arm-kernel@lists.infradead.org; Thu, 10 Mar 2016 05:41:02 +0000 Received: by mail-pf0-x232.google.com with SMTP id 129so60081766pfw.1 for ; Wed, 09 Mar 2016 21:40:38 -0800 (PST) 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=kaFQ1RzwPKC3cKFPgG4EOyiTWjqzMtoCLO5QGZ79uXI=; b=cbmke9YLaRCBtPObVuGUtlkcyIcn11kUsm/uoyREj9gldBWo6Ds+K92HMe5tn8NOeT EIBIJuuTblsK7jNShjnIRWQWDYCSBgxu1S7u1s513zgKearBrDoQ28R2mfucuxK6u6y6 s+k3VyrEPqFSdSeNbb64kGe2myDZ2WKoUTouk= 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=kaFQ1RzwPKC3cKFPgG4EOyiTWjqzMtoCLO5QGZ79uXI=; b=GVrSl0MCFeYPNSRKuw37Eeys67kSvcvzV6WKKqt4Y0mjbp8L5J8QXU58+Ru2/3aIu/ 8vhLMmGc/pRwIfD4zI8UHKOlE3zqWmwmbgAwK2xJMmFA511xq6Pk5BDkOLW7VK7FXYfH mXUZs11KjZV0P+T7SDJEdOPGQ9iaP01LDZlAJo3g9fHdPxEaYEK8k6dW4Jl9nWw7Px7T 3+4fXYa7SY6/GeerkjA4BnXLuC2vkXRg4rJu4fHLZ+lheMKC0x3Ud9NduJtEb5fIL36J xU7OHzg0POzYpyKuMWvKLOjoCeWu1wcfWwHfMq2RkZXsOGT7hS23eWyqj5p/h4II6NGW LHsg== X-Gm-Message-State: AD7BkJLC8JjtMGsTnBKFvKAP4FGHp+9C+Im/nWogAL7fCoLiz9yat+BsIofQH3uzb1T1K+yJ X-Received: by 10.98.19.18 with SMTP id b18mr2407466pfj.22.1457588438351; Wed, 09 Mar 2016 21:40:38 -0800 (PST) Received: from ards-macbook-pro.cgcwfunction (110-170-137-253.static.asianet.co.th. [110.170.137.253]) by smtp.gmail.com with ESMTPSA id r5sm2127864pap.7.2016.03.09.21.40.35 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 09 Mar 2016 21:40:37 -0800 (PST) From: Ard Biesheuvel To: linux-efi@vger.kernel.org, linux-arm-kernel@lists.infradead.org, matt@codeblueprint.co.uk, linux@arm.linux.org.uk, catalin.marinas@arm.com, will.deacon@arm.com Subject: [PATCH 6/8] efi/arm*: libstub: wire up GOP handling into the ARM UEFI stub Date: Thu, 10 Mar 2016 12:40:06 +0700 Message-Id: <1457588408-19309-7-git-send-email-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1457588408-19309-1-git-send-email-ard.biesheuvel@linaro.org> References: <1457588408-19309-1-git-send-email-ard.biesheuvel@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160309_214059_361157_35BBDED3 X-CRM114-Status: GOOD ( 21.54 ) X-Spam-Score: -2.7 (--) X-Spam-Report: SpamAssassin version 3.4.0 on bombadil.infradead.org summary: Content analysis details: (-2.7 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [2607:f8b0:400e:c00:0:0:0:232 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: mark.rutland@arm.com, x86@kernel.org, leif.lindholm@linaro.org, Ard Biesheuvel MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org This enables the EFI stub side of handling the EFI Graphics Output Protocol. It involves invoking the generic GOP code to discover the GOP handle that also drives the console, and using its metadata to populate the screen_info structure. For arm64, the stub and the kernel proper live in the same executable, so we can simply access screen_info directly. For ARM, we need to allocate a struct screen_info in the stub, and install it as a configuration table so that the core kernel can go and fetch it to copy its contents into the real screen_info structure. Signed-off-by: Ard Biesheuvel --- arch/arm/include/asm/efi.h | 12 +++++++ arch/arm/kernel/setup.c | 3 +- arch/arm64/include/asm/efi.h | 3 ++ arch/arm64/kernel/efi.c | 3 ++ arch/arm64/kernel/image.h | 1 + drivers/firmware/efi/libstub/arm-stub.c | 23 ++++++++++++ drivers/firmware/efi/libstub/arm32-stub.c | 38 ++++++++++++++++++++ 7 files changed, 82 insertions(+), 1 deletion(-) -- 1.9.1 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h index daebcfe6c35a..6329b5be1eca 100644 --- a/arch/arm/include/asm/efi.h +++ b/arch/arm/include/asm/efi.h @@ -63,6 +63,18 @@ void efi_virtmap_unload(void); #define __efi_call_early(f, ...) f(__VA_ARGS__) #define efi_is_64bit() (0) +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); + +/* + * 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_ARM32_SCREEN_INFO_TABLE_GUID \ + EFI_GUID(0xe03fc20a, 0x85dc, 0x406e, \ + 0xb9, 0xe, 0x4a, 0xb5, 0x02, 0x37, 0x1d, 0x95) + /* * 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 7d0cba6f1cc5..149a7787b40f 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/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h index e3d707131bba..a6c14f29b970 100644 --- a/arch/arm64/include/asm/efi.h +++ b/arch/arm64/include/asm/efi.h @@ -54,6 +54,9 @@ int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md); #define __efi_call_early(f, ...) f(__VA_ARGS__) #define efi_is_64bit() (1) +#define alloc_screen_info(x...) &screen_info +#define free_screen_info(x...) + #define EFI_ALLOC_ALIGN SZ_64K /* diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index b6abc852f2a1..6f4b3ea359db 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c @@ -17,6 +17,9 @@ #include +/* we will fill this structure from the stub, so don't put it in .bss */ +struct screen_info screen_info __section(.data); + int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md) { pteval_t prot_val; diff --git a/arch/arm64/kernel/image.h b/arch/arm64/kernel/image.h index 5ff892f40a0a..fa52ebdfc93e 100644 --- a/arch/arm64/kernel/image.h +++ b/arch/arm64/kernel/image.h @@ -115,6 +115,7 @@ __efistub___memset = KALLSYMS_HIDE(__pi_memset); __efistub__text = KALLSYMS_HIDE(_text); __efistub__end = KALLSYMS_HIDE(_end); __efistub__edata = KALLSYMS_HIDE(_edata); +__efistub_screen_info = KALLSYMS_HIDE(screen_info); #endif diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c index 4deb3e7faa0e..94bd51cfb71e 100644 --- a/drivers/firmware/efi/libstub/arm-stub.c +++ b/drivers/firmware/efi/libstub/arm-stub.c @@ -147,6 +147,25 @@ void efi_char16_printk(efi_system_table_t *sys_table_arg, out->output_string(out, str); } +static struct screen_info *setup_graphics(efi_system_table_t *sys_table_arg) +{ + efi_guid_t gop_proto = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; + efi_status_t status; + unsigned long size; + void **gop_handle = NULL; + struct screen_info *si = NULL; + + size = 0; + status = efi_call_early(locate_handle, EFI_LOCATE_BY_PROTOCOL, + &gop_proto, NULL, &size, gop_handle); + if (status == EFI_BUFFER_TOO_SMALL) { + si = alloc_screen_info(sys_table_arg); + if (!si) + return NULL; + efi_setup_gop(sys_table_arg, si, &gop_proto, size); + } + return si; +} /* * This function handles the architcture specific differences between arm and @@ -185,6 +204,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, efi_guid_t loaded_image_proto = LOADED_IMAGE_PROTOCOL_GUID; unsigned long reserve_addr = 0; unsigned long reserve_size = 0; + struct screen_info *si; /* Check if we were booted by the EFI firmware */ if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) @@ -233,6 +253,8 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, __nokaslr = true; } + si = setup_graphics(sys_table); + status = handle_kernel_image(sys_table, image_addr, &image_size, &reserve_addr, &reserve_size, @@ -305,6 +327,7 @@ fail_free_image: efi_free(sys_table, image_size, *image_addr); efi_free(sys_table, reserve_size, reserve_addr); fail_free_cmdline: + free_screen_info(sys_table, si); efi_free(sys_table, cmdline_size, (unsigned long)cmdline_ptr); fail: return EFI_ERROR; diff --git a/drivers/firmware/efi/libstub/arm32-stub.c b/drivers/firmware/efi/libstub/arm32-stub.c index 495ebd657e38..0fbe00f13186 100644 --- a/drivers/firmware/efi/libstub/arm32-stub.c +++ b/drivers/firmware/efi/libstub/arm32-stub.c @@ -9,6 +9,44 @@ #include #include +static const efi_guid_t screen_info_guid = LINUX_ARM32_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, + (efi_guid_t *)&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, + (efi_guid_t *)&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,