From patchwork Sun Oct 25 13:49:34 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 285505 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=-12.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS, 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 4C8F7C55178 for ; Sun, 25 Oct 2020 13:49:56 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0C8C82225E for ; Sun, 25 Oct 2020 13:49:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1414854AbgJYNtz (ORCPT ); Sun, 25 Oct 2020 09:49:55 -0400 Received: from foss.arm.com ([217.140.110.172]:46292 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1416426AbgJYNtz (ORCPT ); Sun, 25 Oct 2020 09:49:55 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 1BBB312FC; Sun, 25 Oct 2020 06:49:55 -0700 (PDT) Received: from e123331-lin.nice.arm.com (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 5E9543F68F; Sun, 25 Oct 2020 06:49:53 -0700 (PDT) From: Ard Biesheuvel To: linux-efi@vger.kernel.org Cc: Ard Biesheuvel , grub-devel@gnu.org, daniel.kiper@oracle.com, leif@nuviainc.com Subject: [PATCH v2 1/8] linux/arm: fix ARM Linux header layout Date: Sun, 25 Oct 2020 14:49:34 +0100 Message-Id: <20201025134941.4805-2-ard.biesheuvel@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201025134941.4805-1-ard.biesheuvel@arm.com> References: <20201025134941.4805-1-ard.biesheuvel@arm.com> Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org The hdr_offset member of the ARM Linux image header appears at offset 0x3c, matching the PE/COFF spec's placement of the COFF header offset in the MS-DOS header. We're currently off by four, so fix that. Signed-off-by: Ard Biesheuvel --- include/grub/arm/linux.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/grub/arm/linux.h b/include/grub/arm/linux.h index 2e98a6689696..bcd5a7eb186e 100644 --- a/include/grub/arm/linux.h +++ b/include/grub/arm/linux.h @@ -30,7 +30,7 @@ struct linux_arm_kernel_header { grub_uint32_t magic; grub_uint32_t start; /* _start */ grub_uint32_t end; /* _edata */ - grub_uint32_t reserved2[4]; + grub_uint32_t reserved2[3]; grub_uint32_t hdr_offset; }; From patchwork Sun Oct 25 13:49:35 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 293123 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=-12.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS, 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 2E170C5517A for ; Sun, 25 Oct 2020 13:49:58 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E531E2225E for ; Sun, 25 Oct 2020 13:49:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1416428AbgJYNt5 (ORCPT ); Sun, 25 Oct 2020 09:49:57 -0400 Received: from foss.arm.com ([217.140.110.172]:46302 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1416426AbgJYNt5 (ORCPT ); Sun, 25 Oct 2020 09:49:57 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id D9D2B1435; Sun, 25 Oct 2020 06:49:56 -0700 (PDT) Received: from e123331-lin.nice.arm.com (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 754153F68F; Sun, 25 Oct 2020 06:49:55 -0700 (PDT) From: Ard Biesheuvel To: linux-efi@vger.kernel.org Cc: Ard Biesheuvel , grub-devel@gnu.org, daniel.kiper@oracle.com, leif@nuviainc.com Subject: [PATCH v2 2/8] loader/linux: permit NULL argument for argv[] in grub_initrd_load() Date: Sun, 25 Oct 2020 14:49:35 +0100 Message-Id: <20201025134941.4805-3-ard.biesheuvel@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201025134941.4805-1-ard.biesheuvel@arm.com> References: <20201025134941.4805-1-ard.biesheuvel@arm.com> Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org grub_initrd_load() takes a char *argv[] argument which is only used when an error occurs, to print the name of the file that caused the error. In order to be able to split initrd loading from handling the initrd command, let's permit argv to be NULL, and fall back to the file names recorded in the file handles. Signed-off-by: Ard Biesheuvel Reviewed-by: Leif Lindholm --- grub-core/loader/linux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/loader/linux.c b/grub-core/loader/linux.c index 3fe390f17ec6..8c01381778c6 100644 --- a/grub-core/loader/linux.c +++ b/grub-core/loader/linux.c @@ -317,7 +317,7 @@ grub_initrd_load (struct grub_linux_initrd_context *initrd_ctx, { if (!grub_errno) grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), - argv[i]); + argv ? argv[i] : initrd_ctx->components[i].file->name); grub_initrd_close (initrd_ctx); return grub_errno; } From patchwork Sun Oct 25 13:49:36 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 285504 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=-12.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS, 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 D2128C55178 for ; Sun, 25 Oct 2020 13:49:59 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A26A62225E for ; Sun, 25 Oct 2020 13:49:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1416429AbgJYNt7 (ORCPT ); Sun, 25 Oct 2020 09:49:59 -0400 Received: from foss.arm.com ([217.140.110.172]:46312 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1416426AbgJYNt7 (ORCPT ); Sun, 25 Oct 2020 09:49:59 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 6E66530E; Sun, 25 Oct 2020 06:49:58 -0700 (PDT) Received: from e123331-lin.nice.arm.com (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 23B903F68F; Sun, 25 Oct 2020 06:49:57 -0700 (PDT) From: Ard Biesheuvel To: linux-efi@vger.kernel.org Cc: Ard Biesheuvel , grub-devel@gnu.org, daniel.kiper@oracle.com, leif@nuviainc.com Subject: [PATCH v2 3/8] efi: move MS-DOS stub out of generic PE header definition Date: Sun, 25 Oct 2020 14:49:36 +0100 Message-Id: <20201025134941.4805-4-ard.biesheuvel@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201025134941.4805-1-ard.biesheuvel@arm.com> References: <20201025134941.4805-1-ard.biesheuvel@arm.com> Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org The PE/COFF spec permits the COFF signature and file header to appear anywhere in the file, and the actual offset is recorded in 4 byte little endian field at offset 0x3c of the image. When GRUB is emitted as a PE/COFF binary, we reuse the 128 byte MS-DOS stub (even for non-x86 architectures), putting the COFF signature and file header at offset 0x80. However, other PE/COFF images may use different values, and non-x86 Linux kernels use an offset of 0x40 instead. So let's get rid of the grub_pe32_header struct from pe32.h, given that it does not represent anything defined by the PE/COFF spec. Instead, use the GRUB_PE32_MSDOS_STUB_SIZE macro explicitly to reference the COFF header in the only place in the code where we rely on this. The remaining fields are moved into a struct grub_coff_image_header, which we will use later to access COFF header fields of arbitrary images (and which may therefore appear at different offsets) Signed-off-by: Ard Biesheuvel --- grub-core/kern/efi/efi.c | 5 +++-- include/grub/efi/pe32.h | 5 +---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c index e0165e74c587..9e5a72be538d 100644 --- a/grub-core/kern/efi/efi.c +++ b/grub-core/kern/efi/efi.c @@ -282,7 +282,7 @@ grub_addr_t grub_efi_modules_addr (void) { grub_efi_loaded_image_t *image; - struct grub_pe32_header *header; + struct grub_coff_image_header *header; struct grub_pe32_coff_header *coff_header; struct grub_pe32_section_table *sections; struct grub_pe32_section_table *section; @@ -293,7 +293,8 @@ grub_efi_modules_addr (void) if (! image) return 0; - header = image->image_base; + header = (struct grub_coff_image_header *) ((char *) image->image_base + + GRUB_PE32_MSDOS_STUB_SIZE); coff_header = &(header->coff_header); sections = (struct grub_pe32_section_table *) ((char *) coff_header diff --git a/include/grub/efi/pe32.h b/include/grub/efi/pe32.h index 0ed8781f0376..a2da4b318c85 100644 --- a/include/grub/efi/pe32.h +++ b/include/grub/efi/pe32.h @@ -254,11 +254,8 @@ struct grub_pe32_section_table #define GRUB_PE32_SIGNATURE_SIZE 4 -struct grub_pe32_header +struct grub_coff_image_header { - /* This should be filled in with GRUB_PE32_MSDOS_STUB. */ - grub_uint8_t msdos_stub[GRUB_PE32_MSDOS_STUB_SIZE]; - /* This is always PE\0\0. */ char signature[GRUB_PE32_SIGNATURE_SIZE]; From patchwork Sun Oct 25 13:49:37 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 293122 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=-12.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,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 AAEC5C388F7 for ; Sun, 25 Oct 2020 13:50:01 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6C7DB2225E for ; Sun, 25 Oct 2020 13:50:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1416430AbgJYNuB (ORCPT ); Sun, 25 Oct 2020 09:50:01 -0400 Received: from foss.arm.com ([217.140.110.172]:46324 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1416426AbgJYNuA (ORCPT ); Sun, 25 Oct 2020 09:50:00 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 0E3FA12FC; Sun, 25 Oct 2020 06:50:00 -0700 (PDT) Received: from e123331-lin.nice.arm.com (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id AF1383F68F; Sun, 25 Oct 2020 06:49:58 -0700 (PDT) From: Ard Biesheuvel To: linux-efi@vger.kernel.org Cc: Ard Biesheuvel , grub-devel@gnu.org, daniel.kiper@oracle.com, leif@nuviainc.com Subject: [PATCH v2 4/8] linux/arm: unify ARM/arm64 vs Xen PE/COFF header handling Date: Sun, 25 Oct 2020 14:49:37 +0100 Message-Id: <20201025134941.4805-5-ard.biesheuvel@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201025134941.4805-1-ard.biesheuvel@arm.com> References: <20201025134941.4805-1-ard.biesheuvel@arm.com> Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org Xen has its own version of the image header, to account for the additional PE/COFF header fields. Since we are adding references to those in the shared EFI loader code, update the common definitions and drop the Xen specific one which no longer has a purpose. Signed-off-by: Ard Biesheuvel --- grub-core/loader/arm64/linux.c | 12 +++++----- grub-core/loader/arm64/xen_boot.c | 23 ++++---------------- include/grub/arm/linux.h | 6 +++++ include/grub/arm64/linux.h | 4 ++++ include/grub/efi/efi.h | 4 +++- 5 files changed, 24 insertions(+), 25 deletions(-) diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c index ef3e9f9444ca..915b6ad7292d 100644 --- a/grub-core/loader/arm64/linux.c +++ b/grub-core/loader/arm64/linux.c @@ -49,8 +49,13 @@ static grub_addr_t initrd_start; static grub_addr_t initrd_end; grub_err_t -grub_arch_efi_linux_check_image (struct linux_arch_kernel_header * lh) +grub_arch_efi_linux_load_image_header (grub_file_t file, + struct linux_arch_kernel_header * lh) { + grub_file_seek (file, 0); + if (grub_file_read (file, lh, sizeof (*lh)) < (long) sizeof (*lh)) + return grub_error(GRUB_ERR_FILE_READ_ERROR, "failed to read Linux image header"); + if (lh->magic != GRUB_LINUX_ARMXX_MAGIC_SIGNATURE) return grub_error(GRUB_ERR_BAD_OS, "invalid magic number"); @@ -304,10 +309,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), kernel_size = grub_file_size (file); - if (grub_file_read (file, &lh, sizeof (lh)) < (long) sizeof (lh)) - return grub_errno; - - if (grub_arch_efi_linux_check_image (&lh) != GRUB_ERR_NONE) + if (grub_arch_efi_linux_load_image_header (file, &lh) != GRUB_ERR_NONE) goto fail; grub_loader_unset(); diff --git a/grub-core/loader/arm64/xen_boot.c b/grub-core/loader/arm64/xen_boot.c index 22cc25eccd9d..e5895ee78218 100644 --- a/grub-core/loader/arm64/xen_boot.c +++ b/grub-core/loader/arm64/xen_boot.c @@ -31,7 +31,6 @@ #include #include #include -#include /* required by struct xen_hypervisor_header */ #include #include @@ -65,18 +64,6 @@ enum module_type }; typedef enum module_type module_type_t; -struct xen_hypervisor_header -{ - struct linux_arm64_kernel_header efi_head; - - /* This is always PE\0\0. */ - grub_uint8_t signature[GRUB_PE32_SIGNATURE_SIZE]; - /* The COFF file header. */ - struct grub_pe32_coff_header coff_header; - /* The Optional header. */ - struct grub_pe64_optional_header optional_header; -}; - struct xen_boot_binary { struct xen_boot_binary *next; @@ -452,7 +439,7 @@ static grub_err_t grub_cmd_xen_hypervisor (grub_command_t cmd __attribute__ ((unused)), int argc, char *argv[]) { - struct xen_hypervisor_header sh; + struct linux_arm64_kernel_header lh; grub_file_t file = NULL; grub_dl_ref (my_mod); @@ -467,10 +454,7 @@ grub_cmd_xen_hypervisor (grub_command_t cmd __attribute__ ((unused)), if (!file) goto fail; - if (grub_file_read (file, &sh, sizeof (sh)) != (long) sizeof (sh)) - goto fail; - if (grub_arch_efi_linux_check_image - ((struct linux_arch_kernel_header *) &sh) != GRUB_ERR_NONE) + if (grub_arch_efi_linux_load_image_header (file, &lh) != GRUB_ERR_NONE) goto fail; grub_file_seek (file, 0); @@ -484,7 +468,8 @@ grub_cmd_xen_hypervisor (grub_command_t cmd __attribute__ ((unused)), return grub_errno; xen_hypervisor->is_hypervisor = 1; - xen_hypervisor->align = (grub_size_t) sh.optional_header.section_alignment; + xen_hypervisor->align + = (grub_size_t) lh.coff_image_header.optional_header.section_alignment; xen_boot_binary_load (xen_hypervisor, file, argc, argv); if (grub_errno == GRUB_ERR_NONE) diff --git a/include/grub/arm/linux.h b/include/grub/arm/linux.h index bcd5a7eb186e..ea815db13417 100644 --- a/include/grub/arm/linux.h +++ b/include/grub/arm/linux.h @@ -22,6 +22,8 @@ #include "system.h" +#include + #define GRUB_LINUX_ARM_MAGIC_SIGNATURE 0x016f2818 struct linux_arm_kernel_header { @@ -32,6 +34,10 @@ struct linux_arm_kernel_header { grub_uint32_t end; /* _edata */ grub_uint32_t reserved2[3]; grub_uint32_t hdr_offset; + +#if defined GRUB_MACHINE_EFI + struct grub_coff_image_header coff_image_header; +#endif }; #if defined(__arm__) diff --git a/include/grub/arm64/linux.h b/include/grub/arm64/linux.h index 4269adc6dae5..e5a7ed3749d1 100644 --- a/include/grub/arm64/linux.h +++ b/include/grub/arm64/linux.h @@ -19,6 +19,8 @@ #ifndef GRUB_ARM64_LINUX_HEADER #define GRUB_ARM64_LINUX_HEADER 1 +#include + #define GRUB_LINUX_ARM64_MAGIC_SIGNATURE 0x644d5241 /* 'ARM\x64' */ /* From linux/Documentation/arm64/booting.txt */ @@ -34,6 +36,8 @@ struct linux_arm64_kernel_header grub_uint64_t res4; /* reserved */ grub_uint32_t magic; /* Magic number, little endian, "ARM\x64" */ grub_uint32_t hdr_offset; /* Offset of PE/COFF header */ + + struct grub_coff_image_header coff_image_header; }; #if defined(__aarch64__) diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h index e90e00dc431b..93cb2f5bc732 100644 --- a/include/grub/efi/efi.h +++ b/include/grub/efi/efi.h @@ -94,7 +94,9 @@ extern void (*EXPORT_VAR(grub_efi_net_config)) (grub_efi_handle_t hnd, void *EXPORT_FUNC(grub_efi_get_firmware_fdt)(void); grub_err_t EXPORT_FUNC(grub_efi_get_ram_base)(grub_addr_t *); #include -grub_err_t grub_arch_efi_linux_check_image(struct linux_arch_kernel_header *lh); +#include +grub_err_t grub_arch_efi_linux_load_image_header(grub_file_t file, + struct linux_arch_kernel_header *lh); grub_err_t grub_arch_efi_linux_boot_image(grub_addr_t addr, grub_size_t size, char *args); #endif From patchwork Sun Oct 25 13:49:38 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 285503 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=-12.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS, 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 A032BC55178 for ; Sun, 25 Oct 2020 13:50:02 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 623272225E for ; Sun, 25 Oct 2020 13:50:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1416431AbgJYNuC (ORCPT ); Sun, 25 Oct 2020 09:50:02 -0400 Received: from foss.arm.com ([217.140.110.172]:46334 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1416426AbgJYNuB (ORCPT ); Sun, 25 Oct 2020 09:50:01 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 4DBED1435; Sun, 25 Oct 2020 06:50:01 -0700 (PDT) Received: from e123331-lin.nice.arm.com (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 4F6D63F68F; Sun, 25 Oct 2020 06:50:00 -0700 (PDT) From: Ard Biesheuvel To: linux-efi@vger.kernel.org Cc: Ard Biesheuvel , grub-devel@gnu.org, daniel.kiper@oracle.com, leif@nuviainc.com Subject: [PATCH v2 5/8] linux/arm: account for COFF headers appearing at unexpected offsets Date: Sun, 25 Oct 2020 14:49:38 +0100 Message-Id: <20201025134941.4805-6-ard.biesheuvel@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201025134941.4805-1-ard.biesheuvel@arm.com> References: <20201025134941.4805-1-ard.biesheuvel@arm.com> Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org The way we load the Linux and PE/COFF image headers depends on a fixed placement of the COFF header at offset 0x40 into the file. This is a reasonable default, given that this is where Linux emits it today. However, in order to comply with the PE/COFF spec, which permits this header to appear anywhere in the file, let's ensure that we read the header from where it actually appears in the file if it is not located at offset 0x40. Signed-off-by: Ard Biesheuvel --- grub-core/loader/arm64/linux.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c index 915b6ad7292d..28ff8584a3b5 100644 --- a/grub-core/loader/arm64/linux.c +++ b/grub-core/loader/arm64/linux.c @@ -66,6 +66,21 @@ grub_arch_efi_linux_load_image_header (grub_file_t file, grub_dprintf ("linux", "UEFI stub kernel:\n"); grub_dprintf ("linux", "PE/COFF header @ %08x\n", lh->hdr_offset); + /* + * The PE/COFF spec permits the COFF header to appear anywhere in the file, so + * we need to double check whether it was where we expected it, and if not, we + * must load it from the correct offset into the coff_image_header field of + * struct linux_arch_kernel_header. + */ + if ((grub_uint8_t *) lh + lh->hdr_offset != (grub_uint8_t *) &lh->coff_image_header) + { + grub_file_seek (file, lh->hdr_offset); + + if (grub_file_read (file, &lh->coff_image_header, sizeof(struct grub_coff_image_header)) + != sizeof(struct grub_coff_image_header)) + return grub_error(GRUB_ERR_FILE_READ_ERROR, "failed to read COFF image header"); + } + return GRUB_ERR_NONE; } From patchwork Sun Oct 25 13:49:39 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 293121 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=-12.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,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 92DDFC388F7 for ; Sun, 25 Oct 2020 13:50:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4CC5D2225E for ; Sun, 25 Oct 2020 13:50:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1416432AbgJYNuE (ORCPT ); Sun, 25 Oct 2020 09:50:04 -0400 Received: from foss.arm.com ([217.140.110.172]:46340 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1416426AbgJYNuD (ORCPT ); Sun, 25 Oct 2020 09:50:03 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id B8AE430E; Sun, 25 Oct 2020 06:50:02 -0700 (PDT) Received: from e123331-lin.nice.arm.com (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 9A33C3F68F; Sun, 25 Oct 2020 06:50:01 -0700 (PDT) From: Ard Biesheuvel To: linux-efi@vger.kernel.org Cc: Ard Biesheuvel , grub-devel@gnu.org, daniel.kiper@oracle.com, leif@nuviainc.com Subject: [PATCH v2 6/8] efi: add definition of LoadFile2 protocol Date: Sun, 25 Oct 2020 14:49:39 +0100 Message-Id: <20201025134941.4805-7-ard.biesheuvel@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201025134941.4805-1-ard.biesheuvel@arm.com> References: <20201025134941.4805-1-ard.biesheuvel@arm.com> Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org Incorporate the EFI_LOAD_FILE2_PROTOCOL GUID and C types from the UEFI spec. Signed-off-by: Ard Biesheuvel Reviewed-by: Leif Lindholm --- grub-core/commands/efi/lsefi.c | 1 + include/grub/efi/api.h | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/grub-core/commands/efi/lsefi.c b/grub-core/commands/efi/lsefi.c index d1ce99af4389..145cbfcdaf5c 100644 --- a/grub-core/commands/efi/lsefi.c +++ b/grub-core/commands/efi/lsefi.c @@ -55,6 +55,7 @@ struct known_protocol { GRUB_EFI_ABSOLUTE_POINTER_PROTOCOL_GUID, "absolute pointer" }, { GRUB_EFI_DRIVER_BINDING_PROTOCOL_GUID, "EFI driver binding" }, { GRUB_EFI_LOAD_FILE_PROTOCOL_GUID, "load file" }, + { GRUB_EFI_LOAD_FILE2_PROTOCOL_GUID, "load file 2" }, { GRUB_EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID, "simple FS" }, { GRUB_EFI_TAPE_IO_PROTOCOL_GUID, "tape I/O" }, { GRUB_EFI_UNICODE_COLLATION_PROTOCOL_GUID, "unicode collation" }, diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h index 1dcaa12f59e8..8bc040d9251b 100644 --- a/include/grub/efi/api.h +++ b/include/grub/efi/api.h @@ -149,6 +149,11 @@ { 0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B } \ } +#define GRUB_EFI_LOAD_FILE2_PROTOCOL_GUID \ + { 0x4006c0c1, 0xfcb3, 0x403e, \ + { 0x99, 0x6d, 0x4a, 0x6c, 0x87, 0x24, 0xe0, 0x6d } \ + } + #define GRUB_EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID \ { 0x0964e5b22, 0x6459, 0x11d2, \ { 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ @@ -1694,6 +1699,16 @@ struct grub_efi_block_io }; typedef struct grub_efi_block_io grub_efi_block_io_t; +struct grub_efi_load_file2 +{ + grub_efi_status_t (*load_file)(struct grub_efi_load_file2 *this, + grub_efi_device_path_t *file_path, + grub_efi_boolean_t boot_policy, + grub_efi_uintn_t *buffer_size, + void *buffer); +}; +typedef struct grub_efi_load_file2 grub_efi_load_file2_t; + #if (GRUB_TARGET_SIZEOF_VOID_P == 4) || defined (__ia64__) \ || defined (__aarch64__) || defined (__MINGW64__) || defined (__CYGWIN__) \ || defined(__riscv) From patchwork Sun Oct 25 13:49:40 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 285502 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=-12.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS, 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 07D32C55178 for ; Sun, 25 Oct 2020 13:50:06 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B69662225E for ; Sun, 25 Oct 2020 13:50:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732354AbgJYNuF (ORCPT ); Sun, 25 Oct 2020 09:50:05 -0400 Received: from foss.arm.com ([217.140.110.172]:46350 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1416433AbgJYNuF (ORCPT ); Sun, 25 Oct 2020 09:50:05 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 556F2143B; Sun, 25 Oct 2020 06:50:04 -0700 (PDT) Received: from e123331-lin.nice.arm.com (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 391153F68F; Sun, 25 Oct 2020 06:50:03 -0700 (PDT) From: Ard Biesheuvel To: linux-efi@vger.kernel.org Cc: Ard Biesheuvel , grub-devel@gnu.org, daniel.kiper@oracle.com, leif@nuviainc.com Subject: [PATCH v2 7/8] efi: implement LoadFile2 initrd loading protocol for Linux Date: Sun, 25 Oct 2020 14:49:40 +0100 Message-Id: <20201025134941.4805-8-ard.biesheuvel@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201025134941.4805-1-ard.biesheuvel@arm.com> References: <20201025134941.4805-1-ard.biesheuvel@arm.com> Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org Recent Linux kernels will invoke the LoadFile2 protocol installed on a well-known vendor media devicepath to load the initrd if it is exposed by the firmware. Using this method is preferred for two reasons: - the Linux kernel is in charge of allocating the memory, and so it can implement any placement policy it wants (given that these tend to change between kernel versions), - it is no longer necessary to modify the device tree provided by the firmware. So let's install this protocol when handling the 'initrd' command if such a recent kernel was detected (based on the PE/COFF image version), and defer loading the initrd contents until the point where the kernel invokes the LoadFile2 protocol. Signed-off-by: Ard Biesheuvel --- grub-core/loader/arm64/linux.c | 109 +++++++++++++++++++- 1 file changed, 108 insertions(+), 1 deletion(-) diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c index 28ff8584a3b5..c6a95e1f0c43 100644 --- a/grub-core/loader/arm64/linux.c +++ b/grub-core/loader/arm64/linux.c @@ -48,6 +48,10 @@ static grub_uint32_t cmdline_size; static grub_addr_t initrd_start; static grub_addr_t initrd_end; +static struct grub_linux_initrd_context initrd_ctx = { 0, 0, 0 }; +static grub_efi_handle_t initrd_lf2_handle; +static int initrd_use_loadfile2; + grub_err_t grub_arch_efi_linux_load_image_header (grub_file_t file, struct linux_arch_kernel_header * lh) @@ -81,6 +85,18 @@ grub_arch_efi_linux_load_image_header (grub_file_t file, return grub_error(GRUB_ERR_FILE_READ_ERROR, "failed to read COFF image header"); } + /* + * Linux kernels built for any architecture are guaranteed to support the + * LoadFile2 based initrd loading protocol if the image version is >= 1. + */ + if (lh->coff_image_header.optional_header.major_image_version >= 1) + initrd_use_loadfile2 = 1; + else + initrd_use_loadfile2 = 0; + + grub_dprintf ("linux", "LoadFile2 initrd loading %sabled\n", + initrd_use_loadfile2 ? "en" : "dis"); + return GRUB_ERR_NONE; } @@ -250,13 +266,86 @@ allocate_initrd_mem (int initrd_pages) GRUB_EFI_LOADER_DATA); } +struct initrd_media_device_path { + grub_efi_vendor_media_device_path_t vendor; + grub_efi_device_path_t end; +} GRUB_PACKED; + +#define LINUX_EFI_INITRD_MEDIA_GUID \ + { 0x5568e427, 0x68fc, 0x4f3d, \ + { 0xac, 0x74, 0xca, 0x55, 0x52, 0x31, 0xcc, 0x68 } \ + } + +static struct initrd_media_device_path initrd_lf2_device_path = { + { + { + GRUB_EFI_MEDIA_DEVICE_PATH_TYPE, + GRUB_EFI_VENDOR_MEDIA_DEVICE_PATH_SUBTYPE, + sizeof(grub_efi_vendor_media_device_path_t), + }, + LINUX_EFI_INITRD_MEDIA_GUID + }, { + GRUB_EFI_END_DEVICE_PATH_TYPE, + GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE, + sizeof(grub_efi_device_path_t) + } +}; + +static grub_efi_status_t initrd_load_file2(grub_efi_load_file2_t *this, + grub_efi_device_path_t *device_path, + grub_efi_boolean_t boot_policy, + grub_efi_uintn_t *buffer_size, + void *buffer); + +static grub_efi_load_file2_t initrd_lf2 = { + initrd_load_file2 +}; + +static grub_efi_status_t initrd_load_file2(grub_efi_load_file2_t *this, + grub_efi_device_path_t *device_path, + grub_efi_boolean_t boot_policy, + grub_efi_uintn_t *buffer_size, + void *buffer) +{ + grub_efi_status_t status = GRUB_EFI_SUCCESS; + grub_efi_uintn_t initrd_size; + + if (!this || this != &initrd_lf2 || !buffer_size) + return GRUB_EFI_INVALID_PARAMETER; + + if (device_path->type != GRUB_EFI_END_DEVICE_PATH_TYPE || + device_path->subtype != GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE) + return GRUB_EFI_NOT_FOUND; + + if (boot_policy) + return GRUB_EFI_UNSUPPORTED; + + initrd_size = grub_get_initrd_size (&initrd_ctx); + if (!buffer || *buffer_size < initrd_size) + { + *buffer_size = initrd_size; + return GRUB_EFI_BUFFER_TOO_SMALL; + } + + grub_dprintf ("linux", "Loading initrd via LOAD_FILE2_PROTOCOL\n"); + + if (grub_initrd_load (&initrd_ctx, NULL, buffer)) + status = GRUB_EFI_LOAD_ERROR; + + grub_initrd_close (&initrd_ctx); + return status; +} + static grub_err_t grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), int argc, char *argv[]) { - struct grub_linux_initrd_context initrd_ctx = { 0, 0, 0 }; int initrd_size, initrd_pages; void *initrd_mem = NULL; + grub_efi_guid_t load_file2_guid = GRUB_EFI_LOAD_FILE2_PROTOCOL_GUID; + grub_efi_guid_t device_path_guid = GRUB_EFI_DEVICE_PATH_GUID; + grub_efi_boot_services_t *b; + grub_efi_status_t status; if (argc == 0) { @@ -274,6 +363,24 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), if (grub_initrd_init (argc, argv, &initrd_ctx)) goto fail; + if (initrd_use_loadfile2) + { + b = grub_efi_system_table->boot_services; + status = b->install_multiple_protocol_interfaces (&initrd_lf2_handle, + &load_file2_guid, + &initrd_lf2, + &device_path_guid, + &initrd_lf2_device_path, + NULL); + if (status == GRUB_EFI_OUT_OF_RESOURCES) + { + grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); + return grub_errno; + } + grub_dprintf ("linux", "LoadFile2 initrd loading protocol installed\n"); + return GRUB_ERR_NONE; + } + initrd_size = grub_get_initrd_size (&initrd_ctx); grub_dprintf ("linux", "Loading initrd\n"); From patchwork Sun Oct 25 13:49:41 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 293120 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=-12.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS, 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 3FCACC388F7 for ; Sun, 25 Oct 2020 13:50:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id F14012225E for ; Sun, 25 Oct 2020 13:50:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1416434AbgJYNuG (ORCPT ); Sun, 25 Oct 2020 09:50:06 -0400 Received: from foss.arm.com ([217.140.110.172]:46358 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1416433AbgJYNuG (ORCPT ); Sun, 25 Oct 2020 09:50:06 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id B428B12FC; Sun, 25 Oct 2020 06:50:05 -0700 (PDT) Received: from e123331-lin.nice.arm.com (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 9A0023F68F; Sun, 25 Oct 2020 06:50:04 -0700 (PDT) From: Ard Biesheuvel To: linux-efi@vger.kernel.org Cc: Ard Biesheuvel , grub-devel@gnu.org, daniel.kiper@oracle.com, leif@nuviainc.com Subject: [PATCH v2 8/8] linux: ignore FDT unless we need to modify it Date: Sun, 25 Oct 2020 14:49:41 +0100 Message-Id: <20201025134941.4805-9-ard.biesheuvel@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201025134941.4805-1-ard.biesheuvel@arm.com> References: <20201025134941.4805-1-ard.biesheuvel@arm.com> Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org Now that we implemented support for the LoadFile2 protocol for initrd loading, there is no longer a need to pass the initrd parameters via the device tree. This means there is no longer a reason to update the device tree in the first place, and so we can ignore it entirely. The only remaining reason to deal with the devicetree is if we are using the 'devicetree' command to load one from disk, so tweak the logic in grub_fdt_install() to take that into account. Signed-off-by: Ard Biesheuvel Reviewed-by: Leif Lindholm --- grub-core/loader/arm64/linux.c | 22 ++++++++++---------- grub-core/loader/efi/fdt.c | 7 +++++-- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c index c6a95e1f0c43..248277c753b6 100644 --- a/grub-core/loader/arm64/linux.c +++ b/grub-core/loader/arm64/linux.c @@ -107,21 +107,21 @@ finalize_params_linux (void) void *fdt; - fdt = grub_fdt_load (GRUB_EFI_LINUX_FDT_EXTRA_SPACE); + /* Set initrd info */ + if (initrd_start && initrd_end > initrd_start) + { + fdt = grub_fdt_load (GRUB_EFI_LINUX_FDT_EXTRA_SPACE); - if (!fdt) - goto failure; + if (!fdt) + goto failure; - node = grub_fdt_find_subnode (fdt, 0, "chosen"); - if (node < 0) - node = grub_fdt_add_subnode (fdt, 0, "chosen"); + node = grub_fdt_find_subnode (fdt, 0, "chosen"); + if (node < 0) + node = grub_fdt_add_subnode (fdt, 0, "chosen"); - if (node < 1) - goto failure; + if (node < 1) + goto failure; - /* Set initrd info */ - if (initrd_start && initrd_end > initrd_start) - { grub_dprintf ("linux", "Initrd @ %p-%p\n", (void *) initrd_start, (void *) initrd_end); diff --git a/grub-core/loader/efi/fdt.c b/grub-core/loader/efi/fdt.c index ee9c5592c700..ab900b27d927 100644 --- a/grub-core/loader/efi/fdt.c +++ b/grub-core/loader/efi/fdt.c @@ -85,13 +85,16 @@ grub_fdt_install (void) grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID; grub_efi_status_t status; + if (!fdt && !loaded_fdt) + return GRUB_ERR_NONE; + b = grub_efi_system_table->boot_services; - status = b->install_configuration_table (&fdt_guid, fdt); + status = b->install_configuration_table (&fdt_guid, fdt ?: loaded_fdt); if (status != GRUB_EFI_SUCCESS) return grub_error (GRUB_ERR_IO, "failed to install FDT"); grub_dprintf ("fdt", "Installed/updated FDT configuration table @ %p\n", - fdt); + fdt ?: loaded_fdt); return GRUB_ERR_NONE; }