From patchwork Sat Feb 22 15:55:15 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 206536 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-10.1 required=3.0 tests=DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4F97DC35666 for ; Sat, 22 Feb 2020 15:56:40 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 26B0320702 for ; Sat, 22 Feb 2020 15:56:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1582387000; bh=b3QA5Fq14FDeuD2eCpur2e56WUI8cA6yX9c12b5NbVI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=SS4z45zgfjsJkrdmrWPSEAqFv+POQstmfdewWjS/XT7ES8B36lQMJqAlJVUPb/tJh oZrC7HLTr6L78bmBsrkbj+LH8C4+AYje5JWTgNjniuCvf/dNanmEzNiKP71EKKaR5E 1xjuaZ0yK6h2ZN/2Ukt7WTBq+AVjqO/33H0+vK3c= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727820AbgBVP4j (ORCPT ); Sat, 22 Feb 2020 10:56:39 -0500 Received: from mail.kernel.org ([198.145.29.99]:38284 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727230AbgBVP4j (ORCPT ); Sat, 22 Feb 2020 10:56:39 -0500 Received: from e123331-lin.home (amontpellier-657-1-18-247.w109-210.abo.wanadoo.fr [109.210.65.247]) (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 021B92071E; Sat, 22 Feb 2020 15:56:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1582386999; bh=b3QA5Fq14FDeuD2eCpur2e56WUI8cA6yX9c12b5NbVI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=zCzuDzs8Cu+dVW6NFInz3xPsCbUh8YfrWKwKg5DiP2ldJCPXjG9pPICAB6TU8UhUY GECQXJJszCwNnEacmWIVgK7W/J4m8wqJuhrRdmsHoUUFQqRLhplWqxDN4hM3RTGMpi kVpUrhbj02Z2qmexFiQnh/rzbbaI+/jZjgzXbbss= From: Ard Biesheuvel To: linux-efi@vger.kernel.org Cc: Ard Biesheuvel , hdegoede@redhat.com, nivedita@alum.mit.edu, x86@kernel.org Subject: [PATCH v3 2/6] efi/x86: Drop redundant .bss section Date: Sat, 22 Feb 2020 16:55:15 +0100 Message-Id: <20200222155519.23550-3-ardb@kernel.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200222155519.23550-1-ardb@kernel.org> References: <20200222155519.23550-1-ardb@kernel.org> Sender: linux-efi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.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 | 36 +++++++------------- 2 files changed, 13 insertions(+), 44 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 c08db2ee4ba2..f9f5761c5d05 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 + text_start - file_sz; pe_header = get_unaligned_le32(&buf[0x3c]); @@ -214,30 +216,18 @@ static void update_pecoff_text(unsigned int text_start, unsigned int file_sz) * Size of code: Subtract the size of the first sector (512 bytes) * which includes the header. */ - put_unaligned_le32(file_sz - 512, &buf[pe_header + 0x1c]); + put_unaligned_le32(file_sz - 512 + bss_sz, &buf[pe_header + 0x1c]); + + /* Size of image */ + put_unaligned_le32(init_sz + text_start, &buf[pe_header + 0x50]); /* * 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); + 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 +268,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 +395,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 + setup_sectors * 512); + update_pecoff_text(setup_sectors * 512, i + (sys_size * 16), init_sz); efi_stub_entry_update(); From patchwork Sat Feb 22 15:55:17 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 206535 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-10.1 required=3.0 tests=DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A4B23C35666 for ; Sat, 22 Feb 2020 15:56:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 7CDD720702 for ; Sat, 22 Feb 2020 15:56:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1582387003; bh=cdao8bj1y6LRYPb1ERhjwlQKtW1DKph5MLljiIwWieQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=A5IL3wgxlPf/dBlzL1US3fs8ppaRtU+ErWOo5ROxuozO+CEcVpeUPAVCF6sC/v8+l 6oEnGyMG7mcqJ/g3CFazgGnVNWIMfWTwKGQFyOEVQd/2+Iz4ulPhMC0fEW5qdo9J57 YSnxRX2U23QclfiJ9pC1jJNpgQDB9T9Q/eRCKus4= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727830AbgBVP4n (ORCPT ); Sat, 22 Feb 2020 10:56:43 -0500 Received: from mail.kernel.org ([198.145.29.99]:38334 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727681AbgBVP4n (ORCPT ); Sat, 22 Feb 2020 10:56:43 -0500 Received: from e123331-lin.home (amontpellier-657-1-18-247.w109-210.abo.wanadoo.fr [109.210.65.247]) (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 F308724650; Sat, 22 Feb 2020 15:56:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1582387002; bh=cdao8bj1y6LRYPb1ERhjwlQKtW1DKph5MLljiIwWieQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=brEJSuUDh8SQFSKhDl8b+N5I8XHZ6ldVGrsq8eO3PdxuaTT5aXdRE1gYC8dX6HFig +4w8G8OFAKJirlHxnFg/Ba+OpAwm99EadX1/GDKE4gr0M33jtex6ObacH5qf5H72e2 KikkN4f9tQM5ayOT1aRITKyeDX32WlZwaSS2tSRI= From: Ard Biesheuvel To: linux-efi@vger.kernel.org Cc: Ard Biesheuvel , hdegoede@redhat.com, nivedita@alum.mit.edu, x86@kernel.org Subject: [PATCH v3 4/6] efi/libstub/x86: Use Exit() boot service to exit the stub on errors Date: Sat, 22 Feb 2020 16:55:17 +0100 Message-Id: <20200222155519.23550-5-ardb@kernel.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200222155519.23550-1-ardb@kernel.org> References: <20200222155519.23550-1-ardb@kernel.org> Sender: linux-efi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org Currently, we either return with an error [from efi_pe_entry()] or enter a deadloop [in efi_main()] if any fatal errors occur during execution of the EFI stub. Let's switch to calling the Exit() EFI boot service instead in both cases, so that we a) can get rid of the deadloop, and simply return to the boot manager if any errors occur during execution of the stub, including during the call to ExitBootServices(), b) can also return cleanly from efi_pe_entry() or efi_main() in mixed mode, once we introduce support for LoadImage/StartImage based mixed mode in the next patch. Note that on systems running downstream GRUBs [which do not use LoadImage or StartImage to boot the kernel, and instead, pass their own image handle as the loaded image handle], calling Exit() will exit from GRUB rather than from the kernel, but this is a tolerable side effect. Signed-off-by: Ard Biesheuvel --- arch/x86/include/asm/efi.h | 8 ++++++++ drivers/firmware/efi/libstub/efistub.h | 5 ++++- drivers/firmware/efi/libstub/x86-stub.c | 20 +++++++++++++------- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index 0de57151c732..cdcf48d52a12 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h @@ -270,6 +270,11 @@ static inline void *efi64_zero_upper(void *p) return p; } +static inline u32 efi64_convert_status(efi_status_t status) +{ + return (u32)(status | (u64)status >> 32); +} + #define __efi64_argmap_free_pages(addr, size) \ ((addr), 0, (size)) @@ -288,6 +293,9 @@ static inline void *efi64_zero_upper(void *p) #define __efi64_argmap_locate_device_path(protocol, path, handle) \ ((protocol), (path), efi64_zero_upper(handle)) +#define __efi64_argmap_exit(handle, status, size, data) \ + ((handle), efi64_convert_status(status), (size), (data)) + /* PCI I/O */ #define __efi64_argmap_get_location(protocol, seg, bus, dev, func) \ ((protocol), efi64_zero_upper(seg), efi64_zero_upper(bus), \ diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h index 6960e730f990..cc90a748bcf0 100644 --- a/drivers/firmware/efi/libstub/efistub.h +++ b/drivers/firmware/efi/libstub/efistub.h @@ -144,7 +144,10 @@ union efi_boot_services { void *); void *load_image; void *start_image; - void *exit; + efi_status_t __noreturn (__efiapi *exit)(efi_handle_t, + efi_status_t, + unsigned long, + efi_char16_t *); void *unload_image; efi_status_t (__efiapi *exit_boot_services)(efi_handle_t, unsigned long); diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c index ce0c3caa3087..cec6baa14d5c 100644 --- a/drivers/firmware/efi/libstub/x86-stub.c +++ b/drivers/firmware/efi/libstub/x86-stub.c @@ -340,6 +340,13 @@ static void setup_graphics(struct boot_params *boot_params) } } + +static void __noreturn efi_exit(efi_handle_t handle, efi_status_t status) +{ + efi_bs_call(exit, handle, status, 0, NULL); + unreachable(); +} + void startup_32(struct boot_params *boot_params); void __noreturn efi_stub_entry(efi_handle_t handle, @@ -369,12 +376,12 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle, /* Check if we were booted by the EFI firmware */ if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) - return EFI_INVALID_PARAMETER; + efi_exit(handle, EFI_INVALID_PARAMETER); status = efi_bs_call(handle_protocol, handle, &proto, (void *)&image); if (status != EFI_SUCCESS) { efi_printk("Failed to get handle for LOADED_IMAGE_PROTOCOL\n"); - return status; + efi_exit(handle, status); } hdr = &((struct boot_params *)efi_table_attr(image, image_base))->hdr; @@ -384,7 +391,7 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle, above4g ? ULONG_MAX : UINT_MAX); if (status != EFI_SUCCESS) { efi_printk("Failed to allocate lowmem for boot params\n"); - return status; + efi_exit(handle, status); } memset(boot_params, 0x0, 0x4000); @@ -442,7 +449,7 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle, fail: efi_free(0x4000, (unsigned long)boot_params); - return status; + efi_exit(handle, status); } static void add_e820ext(struct boot_params *params, @@ -709,7 +716,7 @@ struct boot_params *efi_main(efi_handle_t handle, /* Check if we were booted by the EFI firmware */ if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) - goto fail; + efi_exit(handle, EFI_INVALID_PARAMETER); /* * If the kernel isn't already loaded at the preferred load @@ -793,6 +800,5 @@ struct boot_params *efi_main(efi_handle_t handle, fail: efi_printk("efi_main() failed!\n"); - for (;;) - asm("hlt"); + efi_exit(handle, status); } From patchwork Sat Feb 22 15:55:19 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 206534 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-10.1 required=3.0 tests=DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 630D4C35672 for ; Sat, 22 Feb 2020 15:56:46 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 30A97208C3 for ; Sat, 22 Feb 2020 15:56:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1582387006; bh=S/adx8ss8yYRmxdZJn+OYeBxFBzzhcJY6BQWelF0N2Y=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=cSnFGMGG0wGWnnIPqVshn0psT5X9QB9sOUZ9nvNtQlYUvJZpYm5wEIbwMhmjDOyME GqRqRHy1VdsuddUspJtpxofNF5pEGXB83M/Zew5+0YyIsP4EcNPBAmUAb1YujuJ5/F zJl2m7Ley5SPw5HII29BRYhDO5BDvnsmwkCIJy+Q= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727834AbgBVP4q (ORCPT ); Sat, 22 Feb 2020 10:56:46 -0500 Received: from mail.kernel.org ([198.145.29.99]:38396 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727681AbgBVP4p (ORCPT ); Sat, 22 Feb 2020 10:56:45 -0500 Received: from e123331-lin.home (amontpellier-657-1-18-247.w109-210.abo.wanadoo.fr [109.210.65.247]) (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 EF60520702; Sat, 22 Feb 2020 15:56:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1582387005; bh=S/adx8ss8yYRmxdZJn+OYeBxFBzzhcJY6BQWelF0N2Y=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=KuII7ZtHCXauBraW1Jv42y4K/jUALtI6D8WRzuprFU6a4old0U5buizLw+ZULynh8 dm1wkdzVNTT3OiByYNJXR/+KdscBJ70lVyyDUnKJohXYxcQvCv8Tm4WOIOS/ESrfU2 cx5RZ9WDZUEfJw+Qse24M7SLb877J9dCJOCgofeQ= From: Ard Biesheuvel To: linux-efi@vger.kernel.org Cc: Ard Biesheuvel , hdegoede@redhat.com, nivedita@alum.mit.edu, x86@kernel.org Subject: [PATCH v3 6/6] efi/x86: Add true mixed mode entry point into .compat section Date: Sat, 22 Feb 2020 16:55:19 +0100 Message-Id: <20200222155519.23550-7-ardb@kernel.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200222155519.23550-1-ardb@kernel.org> References: <20200222155519.23550-1-ardb@kernel.org> Sender: linux-efi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.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 still 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 | 50 +++++++++++++++++++- 3 files changed, 69 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..44aeb63ca6ae 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 0x42100040 # 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 f9f5761c5d05..90d403dfec80 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,10 @@ 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; +#ifdef CONFIG_EFI_MIXED + u32 compat_offset = reloc_offset + PECOFF_RELOC_RESERVE; +#endif u32 setup_size = reloc_offset - setup_offset; update_pecoff_section_header(".setup", setup_offset, setup_size); @@ -201,6 +211,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, @@ -212,6 +236,22 @@ static void update_pecoff_text(unsigned int text_start, unsigned int file_sz, pe_header = get_unaligned_le32(&buf[0x3c]); +#ifdef CONFIG_EFI_MIXED + /* + * In mixed mode, we will execute startup_32() at whichever offset in + * memory it happened to land when the PE/COFF loader loaded the image, + * which may be misaligned with respect to the kernel_alignment field + * in the setup header. + * + * In order for startup_32 to safely execute in place at this offset, + * we need to ensure that the CONFIG_PHYSICAL_ALIGN aligned allocation + * it creates for the page tables does not extend beyond the declared + * size of the image in the PE/COFF header. So add the required slack. + */ + bss_sz += CONFIG_PHYSICAL_ALIGN; + init_sz += CONFIG_PHYSICAL_ALIGN; +#endif + /* * Size of code: Subtract the size of the first sector (512 bytes) * which includes the header. @@ -279,6 +319,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 @@ -311,6 +357,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); @@ -354,6 +401,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 */