From patchwork Thu Feb 13 14:59:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 11380519 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0BD1A139A for ; Thu, 13 Feb 2020 15:00:13 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id D36F02073C for ; Thu, 13 Feb 2020 15:00:12 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="JwftL6Jk"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=kernel.org header.i=@kernel.org header.b="wtHnBCqA" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org D36F02073C Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=kernel.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=RTDkv/v5ZF4reLqMavxTKsYwWLIJh9JcpJrdboRbifM=; b=JwftL6JkYrVwBXSPxm900JpADC fco2UxazxPxXqDXj/yJBIzr+YXkf64IC3z/ZqOuKGnHb3O4D8D5EXgqQsC9Q2nl/8WEJMHGh/v49t 5trf5D7aMJVAbWMutG6uj7YKlM2quQSrr+RBRseAEvyHK2Z6w/vvmmPq0lbA8Q3S5W/JtxcFntfxI SiYy2aHK2lvLVcM+kMNWhJUBhSEKECf0Eyhf+tzJaYdYUoSg1tTheNqbz+pgEIh3wt1SxDje2yuBI hNsRywX3X5xMY+CY6FzKb1rc+dEXNNdITahY4dJ/ny9FcpJZBPGn8xnhTyzuKcODozlAk4GGjfnPU 6nU+QjEQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1j2FyF-0001cL-TA; Thu, 13 Feb 2020 15:00:03 +0000 Received: from mail.kernel.org ([198.145.29.99]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1j2Fy2-0001SS-Ti for linux-arm-kernel@lists.infradead.org; Thu, 13 Feb 2020 14:59:52 +0000 Received: from cam-smtp0.cambridge.arm.com (fw-tnat.cambridge.arm.com [217.140.96.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 96EF3218AC; Thu, 13 Feb 2020 14:59:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1581605990; bh=dzXGEwPuXZ+ThiLE83ovGglZj5LrVvfa4e0a9juvxuU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=wtHnBCqALVbLhbo8hURER56BK+MTrVKkiDo3sAmQyWwtVEJUfFeLWNd3DfzUChHJj 1a86/2gx5cxXcZly4NqcuM1CuZ0BxDerG5+fiLyaKNQWVu2ANeSFLHBYU3f8AeyIJI ODQB3FiQakHD+n7/ZrMPEzbyZjygZ1UcscBEcNsQ= From: Ard Biesheuvel To: linux-efi@vger.kernel.org Subject: [RFC PATCH 1/3] efi/x86: drop redundant .bss section Date: Thu, 13 Feb 2020 15:59:26 +0100 Message-Id: <20200213145928.7047-2-ardb@kernel.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200213145928.7047-1-ardb@kernel.org> References: <20200213145928.7047-1-ardb@kernel.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200213_065951_022718_FBB0436A X-CRM114-Status: GOOD ( 12.93 ) X-Spam-Score: -5.2 (-----) X-Spam-Report: SpamAssassin version 3.4.3 on bombadil.infradead.org summary: Content analysis details: (-5.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -5.0 RCVD_IN_DNSWL_HI RBL: Sender listed at https://www.dnswl.org/, high trust [198.145.29.99 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.0 DKIMWL_WL_HIGH DKIMwl.org - Whitelisted High sender X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: mingo@kernel.org, agraf@csgraf.de, daniel.kiper@oracle.com, mjg59@google.com, mbrown@fensystems.co.uk, hdegoede@redhat.com, nivedita@alum.mit.edu, pjones@redhat.com, leif@nuviainc.com, lersek@redhat.com, Ard Biesheuvel , linux-arm-kernel@lists.infradead.org MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org In commit c7fb93ec51d462ec ("x86/efi: Include a .bss section within the PE/COFF headers"), we added a separate .bss section to the PE/COFF header of the compressed kernel describing the static memory footprint of the decompressor, to ensure that it has enough headroom to decompress itself. We can achieve the exact same result by increasing the virtual size of the .text section, without changing the raw size, which, as per the PE/COFF specification, requires the loader to zero initialize the delta. Doing so frees up a slot in the section table, which we will use later to describe the mixed mode entrypoint. Signed-off-by: Ard Biesheuvel --- arch/x86/boot/header.S | 21 +----------- arch/x86/boot/tools/build.c | 35 ++++++++------------ 2 files changed, 14 insertions(+), 42 deletions(-) diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S index 97d9b6d6c1af..d59f6604bb42 100644 --- a/arch/x86/boot/header.S +++ b/arch/x86/boot/header.S @@ -106,7 +106,7 @@ coff_header: #else .word 0x8664 # x86-64 #endif - .word 4 # nr_sections + .word 3 # nr_sections .long 0 # TimeDateStamp .long 0 # PointerToSymbolTable .long 1 # NumberOfSymbols @@ -248,25 +248,6 @@ section_table: .word 0 # NumberOfLineNumbers .long 0x60500020 # Characteristics (section flags) - # - # The offset & size fields are filled in by build.c. - # - .ascii ".bss" - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .long 0 - .long 0x0 - .long 0 # Size of initialized data - # on disk - .long 0x0 - .long 0 # PointerToRelocations - .long 0 # PointerToLineNumbers - .word 0 # NumberOfRelocations - .word 0 # NumberOfLineNumbers - .long 0xc8000080 # Characteristics (section flags) - #endif /* CONFIG_EFI_STUB */ # Kernel attributes; used by setup. This is part 1 of the diff --git a/arch/x86/boot/tools/build.c b/arch/x86/boot/tools/build.c index 55e669d29e54..0c8c5a52f1f0 100644 --- a/arch/x86/boot/tools/build.c +++ b/arch/x86/boot/tools/build.c @@ -203,10 +203,12 @@ static void update_pecoff_setup_and_reloc(unsigned int size) put_unaligned_le32(10, &buf[reloc_offset + 4]); } -static void update_pecoff_text(unsigned int text_start, unsigned int file_sz) +static void update_pecoff_text(unsigned int text_start, unsigned int file_sz, + unsigned int init_sz) { unsigned int pe_header; unsigned int text_sz = file_sz - text_start; + unsigned int bss_sz = init_sz - file_sz; pe_header = get_unaligned_le32(&buf[0x3c]); @@ -216,28 +218,19 @@ static void update_pecoff_text(unsigned int text_start, unsigned int file_sz) */ put_unaligned_le32(file_sz - 512, &buf[pe_header + 0x1c]); - /* - * Address of entry point for PE/COFF executable - */ - put_unaligned_le32(text_start + efi_pe_entry, &buf[pe_header + 0x28]); - - update_pecoff_section_header(".text", text_start, text_sz); -} - -static void update_pecoff_bss(unsigned int file_sz, unsigned int init_sz) -{ - unsigned int pe_header; - unsigned int bss_sz = init_sz - file_sz; - - pe_header = get_unaligned_le32(&buf[0x3c]); - /* Size of uninitialized data */ put_unaligned_le32(bss_sz, &buf[pe_header + 0x24]); /* Size of image */ put_unaligned_le32(init_sz, &buf[pe_header + 0x50]); - update_pecoff_section_header_fields(".bss", file_sz, bss_sz, 0, 0); + /* + * Address of entry point for PE/COFF executable + */ + put_unaligned_le32(text_start + efi_pe_entry, &buf[pe_header + 0x28]); + + update_pecoff_section_header_fields(".text", text_start, text_sz + bss_sz, + text_sz, text_start); } static int reserve_pecoff_reloc_section(int c) @@ -278,9 +271,8 @@ static void efi_stub_entry_update(void) static inline void update_pecoff_setup_and_reloc(unsigned int size) {} static inline void update_pecoff_text(unsigned int text_start, - unsigned int file_sz) {} -static inline void update_pecoff_bss(unsigned int file_sz, - unsigned int init_sz) {} + unsigned int file_sz, + unsigned int init_sz) {} static inline void efi_stub_defaults(void) {} static inline void efi_stub_entry_update(void) {} @@ -406,9 +398,8 @@ int main(int argc, char ** argv) buf[0x1f1] = setup_sectors-1; put_unaligned_le32(sys_size, &buf[0x1f4]); - update_pecoff_text(setup_sectors * 512, i + (sys_size * 16)); init_sz = get_unaligned_le32(&buf[0x260]); - update_pecoff_bss(i + (sys_size * 16), init_sz); + update_pecoff_text(setup_sectors * 512, i + (sys_size * 16), init_sz); efi_stub_entry_update(); From patchwork Thu Feb 13 14:59:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 11380521 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E0ADC138D for ; Thu, 13 Feb 2020 15:00:26 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id B85A02082F for ; Thu, 13 Feb 2020 15:00:26 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="QOb/WhBL"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=kernel.org header.i=@kernel.org header.b="jmCmL6S+" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org B85A02082F Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=kernel.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=HCzSbIt1nm6rvp+5x3zxyZubsHhD6W1ARw9S1BK1J3Y=; b=QOb/WhBLWRRZ8ReTHCQHFFGoqw J5MjS2GH2kO3mOu5FW4TZpgcMMx6Y6XNJHGhCR98N51qYrXi5XOilMorQp0AedMf9EswPr7S+CcbM VVb4c6GSNxRNfoSgCUwG3y2MXj7OlRy3gUrvKvqo/LGglWPWIS53Xs+t2vh52TBwPkjawB6UgL2Kf hHzkOYEaL34UhPS4WmUvbQCMDPqQAeglAFH41WkpeDakRcNtAR2SFmEzr/uGrwo/VU4CSA+8psYTq X9BZNjtwoCUlDeoHuqmalkcRR3HANwGQCHf+dlH/hyTI1X1gtGrVjpjqM/a4t43PHCQxe899NCzuV nr2RZYbw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1j2FyW-00031j-D9; Thu, 13 Feb 2020 15:00:20 +0000 Received: from mail.kernel.org ([198.145.29.99]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1j2Fy7-0001XM-2A for linux-arm-kernel@lists.infradead.org; Thu, 13 Feb 2020 14:59:56 +0000 Received: from cam-smtp0.cambridge.arm.com (fw-tnat.cambridge.arm.com [217.140.96.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 1B4AE2082F; Thu, 13 Feb 2020 14:59:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1581605994; bh=tP/nrC7vqmTYk59YGXGbjbDeHTY+3bz/+I3O4muIg1Y=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=jmCmL6S+RZ4t0UJu/CDPzcpFn1jwmsGuhH6HHICJm8ZHRPFEunNaSXg0GWXeJDrg3 CrnMEkDW1H/XZvkaI4ZdIxIfnGfmdIQz9rEo5UClNBLsqpSjyEfFd2iUjqjYVBOP6f PEu1N2G3zp+KDbUwcqNAtzuGr5slHjzqi4pRHNtw= From: Ard Biesheuvel To: linux-efi@vger.kernel.org Subject: [RFC PATCH 2/3] efi/x86: add true mixed mode entry point into .compat section Date: Thu, 13 Feb 2020 15:59:27 +0100 Message-Id: <20200213145928.7047-3-ardb@kernel.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200213145928.7047-1-ardb@kernel.org> References: <20200213145928.7047-1-ardb@kernel.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200213_065955_273514_B65CC87D X-CRM114-Status: GOOD ( 15.69 ) X-Spam-Score: -5.2 (-----) X-Spam-Report: SpamAssassin version 3.4.3 on bombadil.infradead.org summary: Content analysis details: (-5.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -5.0 RCVD_IN_DNSWL_HI RBL: Sender listed at https://www.dnswl.org/, high trust [198.145.29.99 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.0 DKIMWL_WL_HIGH DKIMwl.org - Whitelisted High sender X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: mingo@kernel.org, agraf@csgraf.de, daniel.kiper@oracle.com, mjg59@google.com, mbrown@fensystems.co.uk, hdegoede@redhat.com, nivedita@alum.mit.edu, pjones@redhat.com, leif@nuviainc.com, lersek@redhat.com, Ard Biesheuvel , linux-arm-kernel@lists.infradead.org MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Currently, mixed mode is closely tied to the EFI handover protocol and relies on intimate knowledge of the bootparams structure, setup header etc, all of which are rather byzantine and entirely specific to x86. Even though no other EFI supported architectures are currently known that could support something like mixed mode, it makes sense to abstract a bit from this, and make it part of a generic Linux on EFI boot protocol. To that end, add a .compat section to the mixed mode binary, and populate it with the PE machine type and entry point address, allowing firmware implementations to match it to their native machine type, and invoke non-native binaries using a secondary entry point. Signed-off-by: Ard Biesheuvel --- arch/x86/boot/Makefile | 2 +- arch/x86/boot/header.S | 20 +++++++++++- arch/x86/boot/tools/build.c | 32 +++++++++++++++++++- 3 files changed, 51 insertions(+), 3 deletions(-) diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile index 012b82fc8617..ef9e1f2c836c 100644 --- a/arch/x86/boot/Makefile +++ b/arch/x86/boot/Makefile @@ -88,7 +88,7 @@ $(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE SETUP_OBJS = $(addprefix $(obj)/,$(setup-y)) -sed-zoffset := -e 's/^\([0-9a-fA-F]*\) [a-zA-Z] \(startup_32\|startup_64\|efi32_stub_entry\|efi64_stub_entry\|efi_pe_entry\|input_data\|kernel_info\|_end\|_ehead\|_text\|z_.*\)$$/\#define ZO_\2 0x\1/p' +sed-zoffset := -e 's/^\([0-9a-fA-F]*\) [a-zA-Z] \(startup_32\|startup_64\|efi32_stub_entry\|efi64_stub_entry\|efi_pe_entry\|efi32_pe_entry\|input_data\|kernel_info\|_end\|_ehead\|_text\|z_.*\)$$/\#define ZO_\2 0x\1/p' quiet_cmd_zoffset = ZOFFSET $@ cmd_zoffset = $(NM) $< | sed -n $(sed-zoffset) > $@ diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S index d59f6604bb42..76a485013771 100644 --- a/arch/x86/boot/header.S +++ b/arch/x86/boot/header.S @@ -106,7 +106,7 @@ coff_header: #else .word 0x8664 # x86-64 #endif - .word 3 # nr_sections + .word section_count # nr_sections .long 0 # TimeDateStamp .long 0 # PointerToSymbolTable .long 1 # NumberOfSymbols @@ -230,6 +230,23 @@ section_table: .word 0 # NumberOfLineNumbers .long 0x42100040 # Characteristics (section flags) +#ifdef CONFIG_EFI_MIXED + # + # The offset & size fields are filled in by build.c. + # + .asciz ".compat" + .long 0 + .long 0x0 + .long 0 # Size of initialized data + # on disk + .long 0x0 + .long 0 # PointerToRelocations + .long 0 # PointerToLineNumbers + .word 0 # NumberOfRelocations + .word 0 # NumberOfLineNumbers + .long 0x60500020 # Characteristics (section flags) +#endif + # # The offset & size fields are filled in by build.c. # @@ -248,6 +265,7 @@ section_table: .word 0 # NumberOfLineNumbers .long 0x60500020 # Characteristics (section flags) + .set section_count, (. - section_table) / 40 #endif /* CONFIG_EFI_STUB */ # Kernel attributes; used by setup. This is part 1 of the diff --git a/arch/x86/boot/tools/build.c b/arch/x86/boot/tools/build.c index 0c8c5a52f1f0..707b979566ca 100644 --- a/arch/x86/boot/tools/build.c +++ b/arch/x86/boot/tools/build.c @@ -53,9 +53,16 @@ u8 buf[SETUP_SECT_MAX*512]; #define PECOFF_RELOC_RESERVE 0x20 +#ifdef CONFIG_EFI_MIXED +#define PECOFF_COMPAT_RESERVE 0x20 +#else +#define PECOFF_COMPAT_RESERVE 0x0 +#endif + unsigned long efi32_stub_entry; unsigned long efi64_stub_entry; unsigned long efi_pe_entry; +unsigned long efi32_pe_entry; unsigned long kernel_info; unsigned long startup_64; @@ -189,7 +196,8 @@ static void update_pecoff_section_header(char *section_name, u32 offset, u32 siz static void update_pecoff_setup_and_reloc(unsigned int size) { u32 setup_offset = 0x200; - u32 reloc_offset = size - PECOFF_RELOC_RESERVE; + u32 reloc_offset = size - PECOFF_RELOC_RESERVE - PECOFF_COMPAT_RESERVE; + u32 compat_offset = reloc_offset + PECOFF_RELOC_RESERVE; u32 setup_size = reloc_offset - setup_offset; update_pecoff_section_header(".setup", setup_offset, setup_size); @@ -201,6 +209,20 @@ static void update_pecoff_setup_and_reloc(unsigned int size) */ put_unaligned_le32(reloc_offset + 10, &buf[reloc_offset]); put_unaligned_le32(10, &buf[reloc_offset + 4]); + +#ifdef CONFIG_EFI_MIXED + update_pecoff_section_header(".compat", compat_offset, PECOFF_COMPAT_RESERVE); + + /* + * Put the IA-32 machine type (0x14c) and the associated entry point + * address in the .compat section, so loaders can figure out which other + * execution modes this image supports. + */ + buf[compat_offset] = 0x1; + buf[compat_offset + 1] = 0x8; + put_unaligned_le16(0x14c, &buf[compat_offset + 2]); + put_unaligned_le32(efi32_pe_entry + size, &buf[compat_offset + 4]); +#endif } static void update_pecoff_text(unsigned int text_start, unsigned int file_sz, @@ -282,6 +304,12 @@ static inline int reserve_pecoff_reloc_section(int c) } #endif /* CONFIG_EFI_STUB */ +static int reserve_pecoff_compat_section(int c) +{ + /* Reserve 0x20 bytes for .compat section */ + memset(buf+c, 0, PECOFF_COMPAT_RESERVE); + return PECOFF_COMPAT_RESERVE; +} /* * Parse zoffset.h and find the entry points. We could just #include zoffset.h @@ -314,6 +342,7 @@ static void parse_zoffset(char *fname) PARSE_ZOFS(p, efi32_stub_entry); PARSE_ZOFS(p, efi64_stub_entry); PARSE_ZOFS(p, efi_pe_entry); + PARSE_ZOFS(p, efi32_pe_entry); PARSE_ZOFS(p, kernel_info); PARSE_ZOFS(p, startup_64); @@ -357,6 +386,7 @@ int main(int argc, char ** argv) die("Boot block hasn't got boot flag (0xAA55)"); fclose(file); + c += reserve_pecoff_compat_section(c); c += reserve_pecoff_reloc_section(c); /* Pad unused space with zeros */ From patchwork Thu Feb 13 14:59:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 11380523 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id EE00C139A for ; Thu, 13 Feb 2020 15:00:44 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id BD6162082F for ; Thu, 13 Feb 2020 15:00:44 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="UGy+AE/O"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=kernel.org header.i=@kernel.org header.b="1CK2t9sl" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org BD6162082F Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=kernel.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=fMek9l50b05co3J6aGoMdKwCJv4pA4iPcj0F3YjSkVI=; b=UGy+AE/Orf7d3+I8rdtXJNUc5S zEDRYMDs3U99xCEbMKe2CvdVQsDylu8YwtPdIBWGTg93xqwa9PyjzCg9TFrex4lGvd3iAaUxqrW4v es/UfOoDEvWFDNl9Qdb7mcyQSuIjhksGyFe1Jo/VIA3y1uaqFJ/SrV94aM+FM/aot5Im2MronysWM W6N9mxdptT9Ilc7PTwb66GvgAMGg+hApsaIpaNTSxmJdrZCQpoPTeVex7Ba8FCSq6fCVkzzcT0qod Q9bH/Jc4cYoaYDhVGS47wAt+9LKH9HSs4h7ieH7fI639A8RtNuBWdCD2BRgeQ8/NOx2cX0SGF+BR9 JX2q5Lgw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1j2Fyp-0003NS-4p; Thu, 13 Feb 2020 15:00:39 +0000 Received: from mail.kernel.org ([198.145.29.99]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1j2FyA-0001bG-VW for linux-arm-kernel@lists.infradead.org; Thu, 13 Feb 2020 15:00:00 +0000 Received: from cam-smtp0.cambridge.arm.com (fw-tnat.cambridge.arm.com [217.140.96.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id C8A2724649; Thu, 13 Feb 2020 14:59:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1581605998; bh=DOTtRdFIB/hKfBqsFmk6QEVi/+0venotMXHhie8bOHg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=1CK2t9slELuYxzfifGliWa30UPhanY+znLU/D2XckDAK1e1oyfSDsgf4Mf0p/lUd6 80wr7d4KiG8o3Pd6637iUOAXZKTKmuUTRUjNTZaXQ+pOWqR5HMo+bq0UZKNZXrm/pK NpjjgA4B3yTRgKuskKiUUujDoE5rJCBctr2dlCCA= From: Ard Biesheuvel To: linux-efi@vger.kernel.org Subject: [RFC PATCH 3/3] efi/x86: implement mixed mode boot without the handover protocol Date: Thu, 13 Feb 2020 15:59:28 +0100 Message-Id: <20200213145928.7047-4-ardb@kernel.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200213145928.7047-1-ardb@kernel.org> References: <20200213145928.7047-1-ardb@kernel.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200213_065959_090906_C51AA4AE X-CRM114-Status: GOOD ( 13.68 ) X-Spam-Score: -5.2 (-----) X-Spam-Report: SpamAssassin version 3.4.3 on bombadil.infradead.org summary: Content analysis details: (-5.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -5.0 RCVD_IN_DNSWL_HI RBL: Sender listed at https://www.dnswl.org/, high trust [198.145.29.99 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.0 DKIMWL_WL_HIGH DKIMwl.org - Whitelisted High sender X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: mingo@kernel.org, agraf@csgraf.de, daniel.kiper@oracle.com, mjg59@google.com, mbrown@fensystems.co.uk, hdegoede@redhat.com, nivedita@alum.mit.edu, pjones@redhat.com, leif@nuviainc.com, lersek@redhat.com, Ard Biesheuvel , linux-arm-kernel@lists.infradead.org MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Add support for booting 64-bit x86 kernels from 32-bit firmware running on 64-bit capable CPUs without requiring the bootloader to implement the EFI handover protocol, allocate the setup block etc etc, all of which can be done by the stub using code we have already implemented. Instead, create an ordinary EFI application entrypoint but implemented in 32-bit code, so that it can be invoked by 32-bit firmware, and stash the address of this 32-bit entrypoint in the .compat section where the bootloader can find it. Note that we use the setup block embedded in the binary to go through startup_32(), but it gets reallocated and copied in efi_pe_entry(), using the same code that runs when the x86 kernel is booted in EFI mode from native firmware. This requires the loaded image protocol to be installed on the kernel image's EFI handle, and point to the kernel image itself and not to its loader. This, in turn, requires the bootloader to use the LoadImage() boot services to load the 64-bit image from 32-bit firmware, which is in fact supported by firmware based on EDK2. (Only StartImage() will fail, and instead, the newly added entrypoint needs to be invoked) Signed-off-by: Ard Biesheuvel --- arch/x86/boot/compressed/head_64.S | 61 +++++++++++++++++++- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S index a4f5561c1c0e..7baaf9c97f5a 100644 --- a/arch/x86/boot/compressed/head_64.S +++ b/arch/x86/boot/compressed/head_64.S @@ -207,8 +207,8 @@ SYM_FUNC_START(startup_32) cmp $0, %edi jz 1f leal efi64_stub_entry(%ebp), %eax - movl %esi, %edx movl efi32_boot_args+4(%ebp), %esi + movl efi32_boot_args+8(%ebp), %edx // saved bootparams pointer 1: #endif pushl %eax @@ -233,6 +233,8 @@ SYM_FUNC_START(efi32_stub_entry) 1: pop %ebp subl $1b, %ebp + movl %esi, efi32_boot_args+8(%ebp) +2: movl %ecx, efi32_boot_args(%ebp) movl %edx, efi32_boot_args+4(%ebp) movb $0, efi_is64(%ebp) @@ -249,6 +251,49 @@ SYM_FUNC_START(efi32_stub_entry) jmp startup_32 SYM_FUNC_END(efi32_stub_entry) + +#define ST32_boottime 60 // offsetof(efi_system_table_32_t, boottime) +#define BS32_handle_protocol 88 // offsetof(efi_boot_services_32_t, handle_protocol) +#define LI32_image_base 32 // offsetof(efi_loaded_image_32_t, image_base) + + .subsection 1 + .code32 +SYM_FUNC_START(efi32_pe_entry) + pushl %ebp + + call 3f +3: pop %ebp + subl $3b, %ebp + + /* Get the loaded image protocol pointer from the image handle */ + subl $12, %esp // space for the loaded image pointer + pushl %esp // pass its address + leal 5f(%ebp), %eax + pushl %eax // pass the GUID address + pushl 28(%esp) // pass the image handle + + movl 36(%esp), %eax // sys_table + movl ST32_boottime(%eax), %eax // sys_table->boottime + call *BS32_handle_protocol(%eax) // sys_table->boottime->handle_protocol + cmp $0, %eax + jnz 4f + + movl 32(%esp), %ecx // image_handle + movl 36(%esp), %edx // sys_table + movl 12(%esp), %esi // loaded_image + movl LI32_image_base(%esi), %esi // loaded_image->image_base + jmp 2b + +4: addl $24, %esp + popl %ebp + ret +SYM_FUNC_END(efi32_pe_entry) + + /* EFI loaded image protocol GUID */ +5: .long 0x5B1B31A1 + .word 0x9562, 0x11d2 + .byte 0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B + .previous #endif .code64 @@ -465,11 +510,23 @@ SYM_CODE_END(startup_64) SYM_FUNC_START(efi64_stub_entry) SYM_FUNC_START_ALIAS(efi_stub_entry) and $~0xf, %rsp /* realign the stack */ +#ifdef CONFIG_EFI_MIXED + cmpl $0, %edx + jz 0f +#endif call efi_main movq %rax,%rsi movl BP_code32_start(%esi), %eax leaq startup_64(%rax), %rax jmp *%rax + +#ifdef CONFIG_EFI_MIXED +0: movl %edi, %ecx // MS calling convention + movl %esi, %edx + call efi_pe_entry +1: hlt + jmp 1b +#endif SYM_FUNC_END(efi64_stub_entry) SYM_FUNC_END_ALIAS(efi_stub_entry) #endif @@ -641,7 +698,7 @@ SYM_DATA_START_LOCAL(gdt) SYM_DATA_END_LABEL(gdt, SYM_L_LOCAL, gdt_end) #ifdef CONFIG_EFI_MIXED -SYM_DATA_LOCAL(efi32_boot_args, .long 0, 0) +SYM_DATA_LOCAL(efi32_boot_args, .long 0, 0, 0) SYM_DATA(efi_is64, .byte 1) #endif