From patchwork Mon Feb 10 16:02:31 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 206596 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 7EA57C352A3 for ; Mon, 10 Feb 2020 16:03:03 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 573B9208C3 for ; Mon, 10 Feb 2020 16:03:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1581350583; bh=R7q80aWwvv5LOMlcAX4Y2uWOdpki+5GAuOG1bTRQdxg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=0wvhQutytwUu0G+ECnAPB/09SP1drIAvcz5tv0ZM7XSYfsKcGFZTzERrSP5SMHAsl Jbs2NEsAx66Hhlg2W8ZzlbRF3gShjMNQLaO2/PqND2cEUpnbndlaS1p+AXSKNzrJuI evV8G605x2nNziW+wfWSqZqjdOEJb5Z7osUJ/LSU= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727773AbgBJQDD (ORCPT ); Mon, 10 Feb 2020 11:03:03 -0500 Received: from mail.kernel.org ([198.145.29.99]:52592 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727435AbgBJQDC (ORCPT ); Mon, 10 Feb 2020 11:03:02 -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 6895120842; Mon, 10 Feb 2020 16:03:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1581350581; bh=R7q80aWwvv5LOMlcAX4Y2uWOdpki+5GAuOG1bTRQdxg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BGJdxe+i+6TyO1fAEWnFN6JYegR+KHyCzV3yE/XKWINfJKbF6S9LBdEgGLG9SZz8m Zd12oru6xSsCIgVi42NgmPiHJNESywktUqnmbMtfP0pt7a31TlMsVacDgbL1RE6hck URXUxPi2FYllM1JrXfD0yBFntDJ5w7DFjPp5GBn0= From: Ard Biesheuvel To: linux-efi@vger.kernel.org Cc: Ard Biesheuvel , nivedita@alum.mit.edu, mingo@kernel.org, lukas@wunner.de, atish.patra@wdc.com Subject: [PATCH 02/19] efi/libstub/x86: Avoid overflowing code32_start on PE entry Date: Mon, 10 Feb 2020 17:02:31 +0100 Message-Id: <20200210160248.4889-3-ardb@kernel.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200210160248.4889-1-ardb@kernel.org> References: <20200210160248.4889-1-ardb@kernel.org> Sender: linux-efi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org When using the native PE entry point (as opposed to the EFI handover protocol entry point that is used more widely), we set code32_start, which is a 32-bit wide field, to the effective symbol address of startup_32, which could overflow given that the EFI loader may have located the running image anywhere in memory, and we haven't reached the point yet where we relocate ourselves. Since we relocate ourselves if code32_start != pref_address, this isn't likely to lead to problems in practice, given how unlikely it is that the truncated effective address of startup_32 happens to equal pref_address. But it is better to defer the assignment of code32_start to after the relocation, when it is guaranteed to fit. While at it, move the call to efi_relocate_kernel() to an earlier stage so it is more likely that our preferred offset in memory has not been occupied by other memory allocations done in the mean time. Signed-off-by: Ard Biesheuvel --- arch/x86/boot/compressed/eboot.c | 40 +++++++++----------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index 4745a1ee7953..55637135b50c 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c @@ -439,8 +439,6 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle, boot_params->ext_ramdisk_image = (u64)ramdisk_addr >> 32; boot_params->ext_ramdisk_size = (u64)ramdisk_size >> 32; - hdr->code32_start = (u32)(unsigned long)startup_32; - efi_stub_entry(handle, sys_table, boot_params); /* not reached */ @@ -707,6 +705,7 @@ struct boot_params *efi_main(efi_handle_t handle, efi_system_table_t *sys_table_arg, struct boot_params *boot_params) { + unsigned long bzimage_addr = (unsigned long)startup_32; struct setup_header *hdr = &boot_params->hdr; efi_status_t status; unsigned long cmdline_paddr; @@ -717,6 +716,23 @@ struct boot_params *efi_main(efi_handle_t handle, if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) goto fail; + /* + * If the kernel isn't already loaded at the preferred load + * address, relocate it. + */ + if (bzimage_addr != hdr->pref_address) { + status = efi_relocate_kernel(&bzimage_addr, + hdr->init_size, hdr->init_size, + hdr->pref_address, + hdr->kernel_alignment, + LOAD_PHYSICAL_ADDR); + if (status != EFI_SUCCESS) { + efi_printk("efi_relocate_kernel() failed!\n"); + goto fail; + } + } + hdr->code32_start = (u32)bzimage_addr; + /* * make_boot_params() may have been called before efi_main(), in which * case this is the second time we parse the cmdline. This is ok, @@ -746,26 +762,6 @@ struct boot_params *efi_main(efi_handle_t handle, setup_quirks(boot_params); - /* - * If the kernel isn't already loaded at the preferred load - * address, relocate it. - */ - if (hdr->pref_address != hdr->code32_start) { - unsigned long bzimage_addr = hdr->code32_start; - status = efi_relocate_kernel(&bzimage_addr, - hdr->init_size, hdr->init_size, - hdr->pref_address, - hdr->kernel_alignment, - LOAD_PHYSICAL_ADDR); - if (status != EFI_SUCCESS) { - efi_printk("efi_relocate_kernel() failed!\n"); - goto fail; - } - - hdr->pref_address = hdr->code32_start; - hdr->code32_start = bzimage_addr; - } - status = exit_boot(boot_params, handle); if (status != EFI_SUCCESS) { efi_printk("exit_boot() failed!\n"); From patchwork Mon Feb 10 16:02:33 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 206595 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 0BC5CC352A4 for ; Mon, 10 Feb 2020 16:03:06 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id D03B5214DB for ; Mon, 10 Feb 2020 16:03:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1581350585; bh=ASaLrT97USRIvRi+4ltHkPhd6CrnQ6CT2Qgaf827Oqg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=uvOiv8fDIIHN/5+HCrbVi9a2lzYeBOnyAlYEvexqzploq9NhWpSwZKghYFXixtayq UDBZ1W8xaNJqBrdPRHoCsZ6TZft05UtHMi0YK0316jdhccM2GGmgk9BcKVoZh87dVH +vazW+nPODEfxsANNpofQVSlDeOxJImk5fsb441Q= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727778AbgBJQDF (ORCPT ); Mon, 10 Feb 2020 11:03:05 -0500 Received: from mail.kernel.org ([198.145.29.99]:52668 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727435AbgBJQDF (ORCPT ); Mon, 10 Feb 2020 11:03:05 -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 C13F320873; Mon, 10 Feb 2020 16:03:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1581350585; bh=ASaLrT97USRIvRi+4ltHkPhd6CrnQ6CT2Qgaf827Oqg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=CbjrOzaWP4EfffJbC7QmlpEzAYa+rFP5ut4n20teI9ym5GIIvTGxMM7Jzf94UZNij XbuLMp22hSINgBY0vGgmg5NeJ3iwJVMEVs1nOFZE39YWE2tROLUtiGuTT9QkudZ+Sw Jzi9yBHkT5M9Nb1UEsrCu6jNdyQKwwpEZK8fPpGY= From: Ard Biesheuvel To: linux-efi@vger.kernel.org Cc: Ard Biesheuvel , nivedita@alum.mit.edu, mingo@kernel.org, lukas@wunner.de, atish.patra@wdc.com Subject: [PATCH 04/19] efi/libstub/arm: Relax FDT alignment requirement Date: Mon, 10 Feb 2020 17:02:33 +0100 Message-Id: <20200210160248.4889-5-ardb@kernel.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200210160248.4889-1-ardb@kernel.org> References: <20200210160248.4889-1-ardb@kernel.org> Sender: linux-efi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org The arm64 kernel no longer requires the FDT blob to fit inside a naturally aligned 2 MB memory block, so remove the code that aligns the allocation to 2 MB. Signed-off-by: Ard Biesheuvel --- arch/arm64/include/asm/efi.h | 7 ------- drivers/firmware/efi/libstub/fdt.c | 6 +----- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h index 56ae87401a26..45e821222774 100644 --- a/arch/arm64/include/asm/efi.h +++ b/arch/arm64/include/asm/efi.h @@ -57,13 +57,6 @@ efi_status_t __efi_rt_asm_wrapper(void *, const char *, ...); /* arch specific definitions used by the stub code */ -/* - * AArch64 requires the DTB to be 8-byte aligned in the first 512MiB from - * start of kernel and may not cross a 2MiB boundary. We set alignment to - * 2MiB so we know it won't cross a 2MiB boundary. - */ -#define EFI_FDT_ALIGN SZ_2M /* used by allocate_new_fdt_and_exit_boot() */ - /* * In some configurations (e.g. VMAP_STACK && 64K pages), stacks built into the * kernel need greater alignment than we require the segments to be padded to. diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c index 0a91e5232127..f71cd54823b7 100644 --- a/drivers/firmware/efi/libstub/fdt.c +++ b/drivers/firmware/efi/libstub/fdt.c @@ -199,10 +199,6 @@ static efi_status_t update_fdt_memmap(void *fdt, struct efi_boot_memmap *map) return EFI_SUCCESS; } -#ifndef EFI_FDT_ALIGN -# define EFI_FDT_ALIGN EFI_PAGE_SIZE -#endif - struct exit_boot_struct { efi_memory_desc_t *runtime_map; int *runtime_entry_count; @@ -281,7 +277,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(void *handle, pr_efi("Exiting boot services and installing virtual address map...\n"); map.map = &memory_map; - status = efi_high_alloc(MAX_FDT_SIZE, EFI_FDT_ALIGN, + status = efi_high_alloc(MAX_FDT_SIZE, EFI_PAGE_SIZE, new_fdt_addr, max_addr); if (status != EFI_SUCCESS) { pr_efi_err("Unable to allocate memory for new device tree.\n"); From patchwork Mon Feb 10 16:02: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: 206594 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 2FABAC352A3 for ; Mon, 10 Feb 2020 16:03:10 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id F0BF92168B for ; Mon, 10 Feb 2020 16:03:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1581350590; bh=S2eliISg/+Q+9Odm/AMeFO2bH+WSNeQKwKkfIiZJxIc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=vpJ6K5w5fWPa1bsiRT7fxQN/hbZIE+AcpUM9ms64+L7pj7KpNxva/FQkceGvW6lUi +wKFIphLWkbq+jDnBvO6pUYePYYvI3s2HEd2MahEpEwGf8j6FmDhllZ47lDn0t92HV zCy4Yg/nB1hsjFyWzuT2AFjwylAn29iC4cZqaTzc= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727779AbgBJQDJ (ORCPT ); Mon, 10 Feb 2020 11:03:09 -0500 Received: from mail.kernel.org ([198.145.29.99]:52714 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727435AbgBJQDJ (ORCPT ); Mon, 10 Feb 2020 11:03:09 -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 2789621569; Mon, 10 Feb 2020 16:03:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1581350588; bh=S2eliISg/+Q+9Odm/AMeFO2bH+WSNeQKwKkfIiZJxIc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qyOYqEJZ6ldsKflV0QszkOeloTe0vXpup47Df3ncZ/mTIuzuhkNyhLVLx/V8HOEKx eV3/6QErcouGjC6Xqt+5cn+7oGvudGu+b2ResdNCUTSosj06iYFYiyzPme8DgcnxbJ ry6TxCE8HivuHkr8un0nJ+6ws50FWQefdvw9z10c= From: Ard Biesheuvel To: linux-efi@vger.kernel.org Cc: Ard Biesheuvel , nivedita@alum.mit.edu, mingo@kernel.org, lukas@wunner.de, atish.patra@wdc.com Subject: [PATCH 06/19] efi/libstub: Simplify efi_high_alloc() and rename to efi_allocate_pages() Date: Mon, 10 Feb 2020 17:02:35 +0100 Message-Id: <20200210160248.4889-7-ardb@kernel.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200210160248.4889-1-ardb@kernel.org> References: <20200210160248.4889-1-ardb@kernel.org> Sender: linux-efi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org The implementation of efi_high_alloc() uses a complicated way of traversing the memory map to find an available region that is located as close as possible to the provided upper limit, and calls AllocatePages subsequently to create the allocation at that exact address. This is precisely what the EFI_ALLOCATE_MAX_ADDRESS allocation type argument to AllocatePages() does, and considering that EFI_ALLOC_ALIGN only exceeds EFI_PAGE_SIZE on arm64, let's use AllocatePages() directly and implement the alignment using code that the compiler can remove if it does not exceed EFI_PAGE_SIZE. Signed-off-by: Ard Biesheuvel --- drivers/firmware/efi/libstub/efi-stub-helper.c | 5 +- drivers/firmware/efi/libstub/fdt.c | 3 +- drivers/firmware/efi/libstub/mem.c | 102 ++++---------------- include/linux/efi.h | 4 +- 4 files changed, 23 insertions(+), 91 deletions(-) diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c index 60d13c7a2e92..7afe31357df3 100644 --- a/drivers/firmware/efi/libstub/efi-stub-helper.c +++ b/drivers/firmware/efi/libstub/efi-stub-helper.c @@ -385,8 +385,7 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image, * so allocate enough memory for all the files. This is used * for loading multiple files. */ - status = efi_high_alloc(file_size_total, 0x1000, &file_addr, - max_addr); + status = efi_allocate_pages(file_size_total, &file_addr, max_addr); if (status != EFI_SUCCESS) { pr_efi_err("Failed to alloc highmem for files\n"); goto close_handles; @@ -536,7 +535,7 @@ char *efi_convert_cmdline(efi_loaded_image_t *image, options_bytes++; /* NUL termination */ - status = efi_high_alloc(options_bytes, 0, &cmdline_addr, + status = efi_allocate_pages(options_bytes, &cmdline_addr, MAX_CMDLINE_ADDRESS); if (status != EFI_SUCCESS) return NULL; diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c index f71cd54823b7..46cffac7a5f1 100644 --- a/drivers/firmware/efi/libstub/fdt.c +++ b/drivers/firmware/efi/libstub/fdt.c @@ -277,8 +277,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(void *handle, pr_efi("Exiting boot services and installing virtual address map...\n"); map.map = &memory_map; - status = efi_high_alloc(MAX_FDT_SIZE, EFI_PAGE_SIZE, - new_fdt_addr, max_addr); + status = efi_allocate_pages(MAX_FDT_SIZE, new_fdt_addr, max_addr); if (status != EFI_SUCCESS) { pr_efi_err("Unable to allocate memory for new device tree.\n"); goto fail; diff --git a/drivers/firmware/efi/libstub/mem.c b/drivers/firmware/efi/libstub/mem.c index 690648a7ca1e..5808c8764e64 100644 --- a/drivers/firmware/efi/libstub/mem.c +++ b/drivers/firmware/efi/libstub/mem.c @@ -68,100 +68,34 @@ efi_status_t efi_get_memory_map(struct efi_boot_memmap *map) /* * Allocate at the highest possible address that is not above 'max'. */ -efi_status_t efi_high_alloc(unsigned long size, unsigned long align, - unsigned long *addr, unsigned long max) +efi_status_t efi_allocate_pages(unsigned long size, unsigned long *addr, + unsigned long max) { - unsigned long map_size, desc_size, buff_size; - efi_memory_desc_t *map; + efi_physical_addr_t alloc_addr = ALIGN_DOWN(max + 1, EFI_ALLOC_ALIGN) - 1; + int slack = EFI_ALLOC_ALIGN / EFI_PAGE_SIZE - 1; efi_status_t status; - unsigned long nr_pages; - u64 max_addr = 0; - int i; - struct efi_boot_memmap boot_map; - - boot_map.map = ↦ - boot_map.map_size = &map_size; - boot_map.desc_size = &desc_size; - boot_map.desc_ver = NULL; - boot_map.key_ptr = NULL; - boot_map.buff_size = &buff_size; - - status = efi_get_memory_map(&boot_map); - if (status != EFI_SUCCESS) - goto fail; - - /* - * Enforce minimum alignment that EFI or Linux requires when - * requesting a specific address. We are doing page-based (or - * larger) allocations, and both the address and size must meet - * alignment constraints. - */ - if (align < EFI_ALLOC_ALIGN) - align = EFI_ALLOC_ALIGN; size = round_up(size, EFI_ALLOC_ALIGN); - nr_pages = size / EFI_PAGE_SIZE; -again: - for (i = 0; i < map_size / desc_size; i++) { - efi_memory_desc_t *desc; - unsigned long m = (unsigned long)map; - u64 start, end; - - desc = efi_early_memdesc_ptr(m, desc_size, i); - if (desc->type != EFI_CONVENTIONAL_MEMORY) - continue; - - if (efi_soft_reserve_enabled() && - (desc->attribute & EFI_MEMORY_SP)) - continue; - - if (desc->num_pages < nr_pages) - continue; - - start = desc->phys_addr; - end = start + desc->num_pages * EFI_PAGE_SIZE; - - if (end > max) - end = max; - - if ((start + size) > end) - continue; - - if (round_down(end - size, align) < start) - continue; - - start = round_down(end - size, align); + status = efi_bs_call(allocate_pages, EFI_ALLOCATE_MAX_ADDRESS, + EFI_LOADER_DATA, size / EFI_PAGE_SIZE + slack, + &alloc_addr); + if (status != EFI_SUCCESS) + return status; - /* - * Don't allocate at 0x0. It will confuse code that - * checks pointers against NULL. - */ - if (start == 0x0) - continue; + *addr = ALIGN((unsigned long)alloc_addr, EFI_ALLOC_ALIGN); - if (start > max_addr) - max_addr = start; - } + if (slack > 0) { + int l = (alloc_addr % EFI_ALLOC_ALIGN) / EFI_PAGE_SIZE; - if (!max_addr) - status = EFI_NOT_FOUND; - else { - status = efi_bs_call(allocate_pages, EFI_ALLOCATE_ADDRESS, - EFI_LOADER_DATA, nr_pages, &max_addr); - if (status != EFI_SUCCESS) { - max = max_addr; - max_addr = 0; - goto again; + if (l) { + efi_bs_call(free_pages, alloc_addr, slack - l + 1); + slack = l - 1; } - - *addr = max_addr; + if (slack) + efi_bs_call(free_pages, *addr + size, slack); } - - efi_bs_call(free_pool, map); -fail: - return status; + return EFI_SUCCESS; } - /* * Allocate at the lowest possible address that is not below 'min'. */ diff --git a/include/linux/efi.h b/include/linux/efi.h index 7efd7072cca5..7e231c3cfb6f 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -1508,8 +1508,8 @@ efi_status_t efi_low_alloc(unsigned long size, unsigned long align, return efi_low_alloc_above(size, align, addr, 0x8); } -efi_status_t efi_high_alloc(unsigned long size, unsigned long align, - unsigned long *addr, unsigned long max); +efi_status_t efi_allocate_pages(unsigned long size, unsigned long *addr, + unsigned long max); efi_status_t efi_relocate_kernel(unsigned long *image_addr, unsigned long image_size, From patchwork Mon Feb 10 16:02: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: 206593 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 8AAB7C352A3 for ; Mon, 10 Feb 2020 16:03:13 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 5CA6024649 for ; Mon, 10 Feb 2020 16:03:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1581350593; bh=fR1MLajy12VAkBQ+CZ5rb2XrJWUYT3T4nVepKlgAaIQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=XwaLqLE05RPeJkDaLg+Y44GNCh5HVCV/YkT74r9l+sQbWWSp5mPztkMrjt6T10E4l YcMYV5rqPmTRNtBEz1jNSYSkXnbdPPqf9SsN2bLxlCmF83a4EuOVaPir4/YRghRrP/ MBdL183qSYIhTrbFri7bF6ZierENhD4zItqyXpcA= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727782AbgBJQDN (ORCPT ); Mon, 10 Feb 2020 11:03:13 -0500 Received: from mail.kernel.org ([198.145.29.99]:52754 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727435AbgBJQDN (ORCPT ); Mon, 10 Feb 2020 11:03:13 -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 813DF2168B; Mon, 10 Feb 2020 16:03:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1581350591; bh=fR1MLajy12VAkBQ+CZ5rb2XrJWUYT3T4nVepKlgAaIQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=2B3baBq5taQgHkKNPC/MMqcamQZVjTrqBbkQOVzocSvYSUc8ugahQyD0fhd7MwRze 98iRdwAj90RQ9TkgvEUQLruo7nUQgm0six4LpfX/3GfOOLsZ/koQurDDLUOgk2MY9d DdHLFnZgsFuZdD4TKxrGuFhulqtxh/ZzwstJDauY= From: Ard Biesheuvel To: linux-efi@vger.kernel.org Cc: Ard Biesheuvel , nivedita@alum.mit.edu, mingo@kernel.org, lukas@wunner.de, atish.patra@wdc.com Subject: [PATCH 08/19] efi/libstub: Use consistent type names for file I/O protocols Date: Mon, 10 Feb 2020 17:02:37 +0100 Message-Id: <20200210160248.4889-9-ardb@kernel.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200210160248.4889-1-ardb@kernel.org> References: <20200210160248.4889-1-ardb@kernel.org> Sender: linux-efi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org Align the naming of efi_file_io_interface_t and efi_file_handle_t with the UEFI spec, and call them efi_simple_file_system_protocol_t and efi_file_protocol_t, respectively, using the same convention we use for all other type definitions that originate in the UEFI spec. While at it, move the definitions to efistub.h, so they are only seen by code that needs them. Signed-off-by: Ard Biesheuvel --- drivers/firmware/efi/libstub/efi-stub-helper.c | 16 ++--- drivers/firmware/efi/libstub/efistub.h | 63 ++++++++++++++++++++ include/linux/efi.h | 60 +------------------ 3 files changed, 72 insertions(+), 67 deletions(-) diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c index 7afe31357df3..6db91655c743 100644 --- a/drivers/firmware/efi/libstub/efi-stub-helper.c +++ b/drivers/firmware/efi/libstub/efi-stub-helper.c @@ -54,7 +54,7 @@ bool __pure __efi_soft_reserve_enabled(void) } struct file_info { - efi_file_handle_t *handle; + efi_file_protocol_t *handle; u64 size; }; @@ -113,7 +113,7 @@ unsigned long get_dram_base(void) static efi_status_t efi_file_size(void *__fh, efi_char16_t *filename_16, void **handle, u64 *file_sz) { - efi_file_handle_t *h, *fh = __fh; + efi_file_protocol_t *h, *fh = __fh; efi_file_info_t *info; efi_status_t status; efi_guid_t info_guid = EFI_FILE_INFO_ID; @@ -159,22 +159,22 @@ static efi_status_t efi_file_size(void *__fh, efi_char16_t *filename_16, return status; } -static efi_status_t efi_file_read(efi_file_handle_t *handle, +static efi_status_t efi_file_read(efi_file_protocol_t *handle, unsigned long *size, void *addr) { return handle->read(handle, size, addr); } -static efi_status_t efi_file_close(efi_file_handle_t *handle) +static efi_status_t efi_file_close(efi_file_protocol_t *handle) { return handle->close(handle); } static efi_status_t efi_open_volume(efi_loaded_image_t *image, - efi_file_handle_t **__fh) + efi_file_protocol_t **__fh) { - efi_file_io_interface_t *io; - efi_file_handle_t *fh; + efi_simple_file_system_protocol_t *io; + efi_file_protocol_t *fh; efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID; efi_status_t status; efi_handle_t handle = image->device_handle; @@ -282,7 +282,7 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image, struct file_info *files; unsigned long file_addr; u64 file_size_total; - efi_file_handle_t *fh = NULL; + efi_file_protocol_t *fh = NULL; efi_status_t status; int nr_files; char *str; diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h index 55de118e8267..79cdb219f439 100644 --- a/drivers/firmware/efi/libstub/efistub.h +++ b/drivers/firmware/efi/libstub/efistub.h @@ -106,4 +106,67 @@ union efi_uga_draw_protocol { } mixed_mode; }; +typedef struct efi_loaded_image { + u32 revision; + efi_handle_t parent_handle; + efi_system_table_t *system_table; + efi_handle_t device_handle; + void *file_path; + void *reserved; + u32 load_options_size; + void *load_options; + void *image_base; + __aligned_u64 image_size; + unsigned int image_code_type; + unsigned int image_data_type; + efi_status_t (__efiapi *unload)(efi_handle_t image_handle); +} efi_loaded_image_t; + +typedef struct { + u64 size; + u64 file_size; + u64 phys_size; + efi_time_t create_time; + efi_time_t last_access_time; + efi_time_t modification_time; + __aligned_u64 attribute; + efi_char16_t filename[1]; +} efi_file_info_t; + +typedef struct efi_file_protocol efi_file_protocol_t; + +struct efi_file_protocol { + u64 revision; + efi_status_t (__efiapi *open) (efi_file_protocol_t *, + efi_file_protocol_t **, + efi_char16_t *, u64, u64); + efi_status_t (__efiapi *close) (efi_file_protocol_t *); + efi_status_t (__efiapi *delete) (efi_file_protocol_t *); + efi_status_t (__efiapi *read) (efi_file_protocol_t *, + unsigned long *, void *); + efi_status_t (__efiapi *write) (efi_file_protocol_t *, + unsigned long, void *); + efi_status_t (__efiapi *get_position)(efi_file_protocol_t *, u64 *); + efi_status_t (__efiapi *set_position)(efi_file_protocol_t *, u64); + efi_status_t (__efiapi *get_info) (efi_file_protocol_t *, + efi_guid_t *, unsigned long *, + void *); + efi_status_t (__efiapi *set_info) (efi_file_protocol_t *, + efi_guid_t *, unsigned long, + void *); + efi_status_t (__efiapi *flush) (efi_file_protocol_t *); +}; + +typedef struct efi_simple_file_system_protocol efi_simple_file_system_protocol_t; + +struct efi_simple_file_system_protocol { + u64 revision; + int (__efiapi *open_volume)(efi_simple_file_system_protocol_t *, + efi_file_protocol_t **); +}; + +#define EFI_FILE_MODE_READ 0x0000000000000001 +#define EFI_FILE_MODE_WRITE 0x0000000000000002 +#define EFI_FILE_MODE_CREATE 0x8000000000000000 + #endif diff --git a/include/linux/efi.h b/include/linux/efi.h index 7e231c3cfb6f..2b228df18407 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -796,65 +796,7 @@ struct efi_fdt_params { u32 desc_ver; }; -typedef struct { - u32 revision; - efi_handle_t parent_handle; - efi_system_table_t *system_table; - efi_handle_t device_handle; - void *file_path; - void *reserved; - u32 load_options_size; - void *load_options; - void *image_base; - __aligned_u64 image_size; - unsigned int image_code_type; - unsigned int image_data_type; - efi_status_t ( __efiapi *unload)(efi_handle_t image_handle); -} efi_loaded_image_t; - -typedef struct { - u64 size; - u64 file_size; - u64 phys_size; - efi_time_t create_time; - efi_time_t last_access_time; - efi_time_t modification_time; - __aligned_u64 attribute; - efi_char16_t filename[1]; -} efi_file_info_t; - -typedef struct efi_file_handle efi_file_handle_t; - -struct efi_file_handle { - u64 revision; - efi_status_t (__efiapi *open)(efi_file_handle_t *, - efi_file_handle_t **, - efi_char16_t *, u64, u64); - efi_status_t (__efiapi *close)(efi_file_handle_t *); - void *delete; - efi_status_t (__efiapi *read)(efi_file_handle_t *, - unsigned long *, void *); - void *write; - void *get_position; - void *set_position; - efi_status_t (__efiapi *get_info)(efi_file_handle_t *, - efi_guid_t *, unsigned long *, - void *); - void *set_info; - void *flush; -}; - -typedef struct efi_file_io_interface efi_file_io_interface_t; - -struct efi_file_io_interface { - u64 revision; - int (__efiapi *open_volume)(efi_file_io_interface_t *, - efi_file_handle_t **); -}; - -#define EFI_FILE_MODE_READ 0x0000000000000001 -#define EFI_FILE_MODE_WRITE 0x0000000000000002 -#define EFI_FILE_MODE_CREATE 0x8000000000000000 +typedef struct efi_loaded_image efi_loaded_image_t; typedef struct { u32 version; From patchwork Mon Feb 10 16:02: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: 206592 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 1EE94C352A3 for ; Mon, 10 Feb 2020 16:03:16 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id BE5EE24649 for ; Mon, 10 Feb 2020 16:03:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1581350596; bh=tBA84jqUd9JPhq4w/iyU/aSbYVNefx2pxgv2vfXYgeo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=qiFXsLoiOalsDsefbPsu957UP8unb9C8ZU8275wo+dgzrkONiM5UvyzV0JIT35Qsu M92bS79kdy1BXkrnIs9hIHJxh7wJq9XkxBxsam3yuBUEpuUQeY05O7dwrt/U1SKEWp v8TtR63WxXfm3Zx383LAIjOgA2eErCh4Vpry+qV4= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727786AbgBJQDP (ORCPT ); Mon, 10 Feb 2020 11:03:15 -0500 Received: from mail.kernel.org ([198.145.29.99]:52770 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727435AbgBJQDP (ORCPT ); Mon, 10 Feb 2020 11:03:15 -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 3357924650; Mon, 10 Feb 2020 16:03:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1581350593; bh=tBA84jqUd9JPhq4w/iyU/aSbYVNefx2pxgv2vfXYgeo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=J7Dx4JVb8jJ57gFr9lDzqFt1bgiYxwraRyHfDN3iEWMibq/Fabdex1jQ1faNzZq0f N2pKvLeRTGnrAsEF+WElC2ekwe7z4YB6CZqRSU+zo2yZCNzuSKsj7S4alPJYIQcd/q Q4Fg8tPPb5wFItaHLxfdA0PfoP8fHwfJb8N4T/yA= From: Ard Biesheuvel To: linux-efi@vger.kernel.org Cc: Ard Biesheuvel , nivedita@alum.mit.edu, mingo@kernel.org, lukas@wunner.de, atish.patra@wdc.com Subject: [PATCH 09/19] efi/libstub: Move stub specific declarations into efistub.h Date: Mon, 10 Feb 2020 17:02:38 +0100 Message-Id: <20200210160248.4889-10-ardb@kernel.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200210160248.4889-1-ardb@kernel.org> References: <20200210160248.4889-1-ardb@kernel.org> Sender: linux-efi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org Move all the declarations that are only used in stub code from linux/efi.h to efistub.h which is only included locally. Signed-off-by: Ard Biesheuvel --- drivers/firmware/efi/libstub/efistub.h | 507 ++++++++++++++++++-- include/linux/efi.h | 456 +----------------- 2 files changed, 479 insertions(+), 484 deletions(-) diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h index 79cdb219f439..8bb46c1fd2cd 100644 --- a/drivers/firmware/efi/libstub/efistub.h +++ b/drivers/firmware/efi/libstub/efistub.h @@ -43,34 +43,6 @@ extern __pure efi_system_table_t *efi_system_table(void); #define pr_efi_err(msg) efi_printk("EFI stub: ERROR: "msg) -void efi_char16_printk(efi_char16_t *); -void efi_char16_printk(efi_char16_t *); - -unsigned long get_dram_base(void); - -efi_status_t allocate_new_fdt_and_exit_boot(void *handle, - unsigned long *new_fdt_addr, - unsigned long max_addr, - u64 initrd_addr, u64 initrd_size, - char *cmdline_ptr, - unsigned long fdt_addr, - unsigned long fdt_size); - -void *get_fdt(unsigned long *fdt_size); - -void efi_get_virtmap(efi_memory_desc_t *memory_map, unsigned long map_size, - unsigned long desc_size, efi_memory_desc_t *runtime_map, - int *count); - -efi_status_t efi_get_random_bytes(unsigned long size, u8 *out); - -efi_status_t efi_random_alloc(unsigned long size, unsigned long align, - unsigned long *addr, unsigned long random_seed); - -efi_status_t check_platform_features(void); - -void *get_efi_config_table(efi_guid_t guid); - /* Helper macros for the usual case of using simple C variables: */ #ifndef fdt_setprop_inplace_var #define fdt_setprop_inplace_var(fdt, node_offset, name, var) \ @@ -90,6 +62,156 @@ void *get_efi_config_table(efi_guid_t guid); efi_rt_call(set_variable, (efi_char16_t *)(name), \ (efi_guid_t *)(vendor), __VA_ARGS__) +#define efi_get_handle_at(array, idx) \ + (efi_is_native() ? (array)[idx] \ + : (efi_handle_t)(unsigned long)((u32 *)(array))[idx]) + +#define efi_get_handle_num(size) \ + ((size) / (efi_is_native() ? sizeof(efi_handle_t) : sizeof(u32))) + +#define for_each_efi_handle(handle, array, size, i) \ + for (i = 0; \ + i < efi_get_handle_num(size) && \ + ((handle = efi_get_handle_at((array), i)) || true); \ + i++) + +/* + * Allocation types for calls to boottime->allocate_pages. + */ +#define EFI_ALLOCATE_ANY_PAGES 0 +#define EFI_ALLOCATE_MAX_ADDRESS 1 +#define EFI_ALLOCATE_ADDRESS 2 +#define EFI_MAX_ALLOCATE_TYPE 3 + +/* + * The type of search to perform when calling boottime->locate_handle + */ +#define EFI_LOCATE_ALL_HANDLES 0 +#define EFI_LOCATE_BY_REGISTER_NOTIFY 1 +#define EFI_LOCATE_BY_PROTOCOL 2 + +struct efi_boot_memmap { + efi_memory_desc_t **map; + unsigned long *map_size; + unsigned long *desc_size; + u32 *desc_ver; + unsigned long *key_ptr; + unsigned long *buff_size; +}; + +/* + * EFI Boot Services table + */ +union efi_boot_services { + struct { + efi_table_hdr_t hdr; + void *raise_tpl; + void *restore_tpl; + efi_status_t (__efiapi *allocate_pages)(int, int, unsigned long, + efi_physical_addr_t *); + efi_status_t (__efiapi *free_pages)(efi_physical_addr_t, + unsigned long); + efi_status_t (__efiapi *get_memory_map)(unsigned long *, void *, + unsigned long *, + unsigned long *, u32 *); + efi_status_t (__efiapi *allocate_pool)(int, unsigned long, + void **); + efi_status_t (__efiapi *free_pool)(void *); + void *create_event; + void *set_timer; + void *wait_for_event; + void *signal_event; + void *close_event; + void *check_event; + void *install_protocol_interface; + void *reinstall_protocol_interface; + void *uninstall_protocol_interface; + efi_status_t (__efiapi *handle_protocol)(efi_handle_t, + efi_guid_t *, void **); + void *__reserved; + void *register_protocol_notify; + efi_status_t (__efiapi *locate_handle)(int, efi_guid_t *, + void *, unsigned long *, + efi_handle_t *); + void *locate_device_path; + efi_status_t (__efiapi *install_configuration_table)(efi_guid_t *, + void *); + void *load_image; + void *start_image; + void *exit; + void *unload_image; + efi_status_t (__efiapi *exit_boot_services)(efi_handle_t, + unsigned long); + void *get_next_monotonic_count; + void *stall; + void *set_watchdog_timer; + void *connect_controller; + efi_status_t (__efiapi *disconnect_controller)(efi_handle_t, + efi_handle_t, + efi_handle_t); + void *open_protocol; + void *close_protocol; + void *open_protocol_information; + void *protocols_per_handle; + void *locate_handle_buffer; + efi_status_t (__efiapi *locate_protocol)(efi_guid_t *, void *, + void **); + void *install_multiple_protocol_interfaces; + void *uninstall_multiple_protocol_interfaces; + void *calculate_crc32; + void *copy_mem; + void *set_mem; + void *create_event_ex; + }; + struct { + efi_table_hdr_t hdr; + u32 raise_tpl; + u32 restore_tpl; + u32 allocate_pages; + u32 free_pages; + u32 get_memory_map; + u32 allocate_pool; + u32 free_pool; + u32 create_event; + u32 set_timer; + u32 wait_for_event; + u32 signal_event; + u32 close_event; + u32 check_event; + u32 install_protocol_interface; + u32 reinstall_protocol_interface; + u32 uninstall_protocol_interface; + u32 handle_protocol; + u32 __reserved; + u32 register_protocol_notify; + u32 locate_handle; + u32 locate_device_path; + u32 install_configuration_table; + u32 load_image; + u32 start_image; + u32 exit; + u32 unload_image; + u32 exit_boot_services; + u32 get_next_monotonic_count; + u32 stall; + u32 set_watchdog_timer; + u32 connect_controller; + u32 disconnect_controller; + u32 open_protocol; + u32 close_protocol; + u32 open_protocol_information; + u32 protocols_per_handle; + u32 locate_handle_buffer; + u32 locate_protocol; + u32 install_multiple_protocol_interfaces; + u32 uninstall_multiple_protocol_interfaces; + u32 calculate_crc32; + u32 copy_mem; + u32 set_mem; + u32 create_event_ex; + } mixed_mode; +}; + typedef union efi_uga_draw_protocol efi_uga_draw_protocol_t; union efi_uga_draw_protocol { @@ -106,7 +228,81 @@ union efi_uga_draw_protocol { } mixed_mode; }; -typedef struct efi_loaded_image { +union efi_simple_text_output_protocol { + struct { + void *reset; + efi_status_t (__efiapi *output_string)(efi_simple_text_output_protocol_t *, + efi_char16_t *); + void *test_string; + }; + struct { + u32 reset; + u32 output_string; + u32 test_string; + } mixed_mode; +}; + +#define PIXEL_RGB_RESERVED_8BIT_PER_COLOR 0 +#define PIXEL_BGR_RESERVED_8BIT_PER_COLOR 1 +#define PIXEL_BIT_MASK 2 +#define PIXEL_BLT_ONLY 3 +#define PIXEL_FORMAT_MAX 4 + +typedef struct { + u32 red_mask; + u32 green_mask; + u32 blue_mask; + u32 reserved_mask; +} efi_pixel_bitmask_t; + +typedef struct { + u32 version; + u32 horizontal_resolution; + u32 vertical_resolution; + int pixel_format; + efi_pixel_bitmask_t pixel_information; + u32 pixels_per_scan_line; +} efi_graphics_output_mode_info_t; + +typedef union efi_graphics_output_protocol_mode efi_graphics_output_protocol_mode_t; + +union efi_graphics_output_protocol_mode { + struct { + u32 max_mode; + u32 mode; + efi_graphics_output_mode_info_t *info; + unsigned long size_of_info; + efi_physical_addr_t frame_buffer_base; + unsigned long frame_buffer_size; + }; + struct { + u32 max_mode; + u32 mode; + u32 info; + u32 size_of_info; + u64 frame_buffer_base; + u32 frame_buffer_size; + } mixed_mode; +}; + +typedef union efi_graphics_output_protocol efi_graphics_output_protocol_t; + +union efi_graphics_output_protocol { + struct { + void *query_mode; + void *set_mode; + void *blt; + efi_graphics_output_protocol_mode_t *mode; + }; + struct { + u32 query_mode; + u32 set_mode; + u32 blt; + u32 mode; + } mixed_mode; +}; + +typedef struct { u32 revision; efi_handle_t parent_handle; efi_system_table_t *system_table; @@ -169,4 +365,257 @@ struct efi_simple_file_system_protocol { #define EFI_FILE_MODE_WRITE 0x0000000000000002 #define EFI_FILE_MODE_CREATE 0x8000000000000000 +typedef enum { + EfiPciIoWidthUint8, + EfiPciIoWidthUint16, + EfiPciIoWidthUint32, + EfiPciIoWidthUint64, + EfiPciIoWidthFifoUint8, + EfiPciIoWidthFifoUint16, + EfiPciIoWidthFifoUint32, + EfiPciIoWidthFifoUint64, + EfiPciIoWidthFillUint8, + EfiPciIoWidthFillUint16, + EfiPciIoWidthFillUint32, + EfiPciIoWidthFillUint64, + EfiPciIoWidthMaximum +} EFI_PCI_IO_PROTOCOL_WIDTH; + +typedef enum { + EfiPciIoAttributeOperationGet, + EfiPciIoAttributeOperationSet, + EfiPciIoAttributeOperationEnable, + EfiPciIoAttributeOperationDisable, + EfiPciIoAttributeOperationSupported, + EfiPciIoAttributeOperationMaximum +} EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION; + +typedef struct { + u32 read; + u32 write; +} efi_pci_io_protocol_access_32_t; + +typedef union efi_pci_io_protocol efi_pci_io_protocol_t; + +typedef +efi_status_t (__efiapi *efi_pci_io_protocol_cfg_t)(efi_pci_io_protocol_t *, + EFI_PCI_IO_PROTOCOL_WIDTH, + u32 offset, + unsigned long count, + void *buffer); + +typedef struct { + void *read; + void *write; +} efi_pci_io_protocol_access_t; + +typedef struct { + efi_pci_io_protocol_cfg_t read; + efi_pci_io_protocol_cfg_t write; +} efi_pci_io_protocol_config_access_t; + +union efi_pci_io_protocol { + struct { + void *poll_mem; + void *poll_io; + efi_pci_io_protocol_access_t mem; + efi_pci_io_protocol_access_t io; + efi_pci_io_protocol_config_access_t pci; + void *copy_mem; + void *map; + void *unmap; + void *allocate_buffer; + void *free_buffer; + void *flush; + efi_status_t (__efiapi *get_location)(efi_pci_io_protocol_t *, + unsigned long *segment_nr, + unsigned long *bus_nr, + unsigned long *device_nr, + unsigned long *func_nr); + void *attributes; + void *get_bar_attributes; + void *set_bar_attributes; + uint64_t romsize; + void *romimage; + }; + struct { + u32 poll_mem; + u32 poll_io; + efi_pci_io_protocol_access_32_t mem; + efi_pci_io_protocol_access_32_t io; + efi_pci_io_protocol_access_32_t pci; + u32 copy_mem; + u32 map; + u32 unmap; + u32 allocate_buffer; + u32 free_buffer; + u32 flush; + u32 get_location; + u32 attributes; + u32 get_bar_attributes; + u32 set_bar_attributes; + u64 romsize; + u32 romimage; + } mixed_mode; +}; + +#define EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO 0x0001 +#define EFI_PCI_IO_ATTRIBUTE_ISA_IO 0x0002 +#define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO 0x0004 +#define EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY 0x0008 +#define EFI_PCI_IO_ATTRIBUTE_VGA_IO 0x0010 +#define EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO 0x0020 +#define EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO 0x0040 +#define EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE 0x0080 +#define EFI_PCI_IO_ATTRIBUTE_IO 0x0100 +#define EFI_PCI_IO_ATTRIBUTE_MEMORY 0x0200 +#define EFI_PCI_IO_ATTRIBUTE_BUS_MASTER 0x0400 +#define EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED 0x0800 +#define EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE 0x1000 +#define EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE 0x2000 +#define EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM 0x4000 +#define EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE 0x8000 +#define EFI_PCI_IO_ATTRIBUTE_ISA_IO_16 0x10000 +#define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16 0x20000 +#define EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 0x40000 + +struct efi_dev_path; + +typedef union apple_properties_protocol apple_properties_protocol_t; + +union apple_properties_protocol { + struct { + unsigned long version; + efi_status_t (__efiapi *get)(apple_properties_protocol_t *, + struct efi_dev_path *, + efi_char16_t *, void *, u32 *); + efi_status_t (__efiapi *set)(apple_properties_protocol_t *, + struct efi_dev_path *, + efi_char16_t *, void *, u32); + efi_status_t (__efiapi *del)(apple_properties_protocol_t *, + struct efi_dev_path *, + efi_char16_t *); + efi_status_t (__efiapi *get_all)(apple_properties_protocol_t *, + void *buffer, u32 *); + }; + struct { + u32 version; + u32 get; + u32 set; + u32 del; + u32 get_all; + } mixed_mode; +}; + +typedef u32 efi_tcg2_event_log_format; + +typedef union efi_tcg2_protocol efi_tcg2_protocol_t; + +union efi_tcg2_protocol { + struct { + void *get_capability; + efi_status_t (__efiapi *get_event_log)(efi_handle_t, + efi_tcg2_event_log_format, + efi_physical_addr_t *, + efi_physical_addr_t *, + efi_bool_t *); + void *hash_log_extend_event; + void *submit_command; + void *get_active_pcr_banks; + void *set_active_pcr_banks; + void *get_result_of_set_active_pcr_banks; + }; + struct { + u32 get_capability; + u32 get_event_log; + u32 hash_log_extend_event; + u32 submit_command; + u32 get_active_pcr_banks; + u32 set_active_pcr_banks; + u32 get_result_of_set_active_pcr_banks; + } mixed_mode; +}; + +void efi_pci_disable_bridge_busmaster(void); + +typedef efi_status_t (*efi_exit_boot_map_processing)( + struct efi_boot_memmap *map, + void *priv); + +efi_status_t efi_exit_boot_services(void *handle, + struct efi_boot_memmap *map, + void *priv, + efi_exit_boot_map_processing priv_func); + +void efi_char16_printk(efi_char16_t *); + +unsigned long get_dram_base(void); + +efi_status_t allocate_new_fdt_and_exit_boot(void *handle, + unsigned long *new_fdt_addr, + unsigned long max_addr, + u64 initrd_addr, u64 initrd_size, + char *cmdline_ptr, + unsigned long fdt_addr, + unsigned long fdt_size); + +void *get_fdt(unsigned long *fdt_size); + +void efi_get_virtmap(efi_memory_desc_t *memory_map, unsigned long map_size, + unsigned long desc_size, efi_memory_desc_t *runtime_map, + int *count); + +efi_status_t efi_get_random_bytes(unsigned long size, u8 *out); + +efi_status_t efi_random_alloc(unsigned long size, unsigned long align, + unsigned long *addr, unsigned long random_seed); + +efi_status_t check_platform_features(void); + +void *get_efi_config_table(efi_guid_t guid); + +void efi_printk(char *str); + +void efi_free(unsigned long size, unsigned long addr); + +char *efi_convert_cmdline(efi_loaded_image_t *image, int *cmd_line_len); + +efi_status_t efi_get_memory_map(struct efi_boot_memmap *map); + +efi_status_t efi_low_alloc_above(unsigned long size, unsigned long align, + unsigned long *addr, unsigned long min); + +static inline +efi_status_t efi_low_alloc(unsigned long size, unsigned long align, + unsigned long *addr) +{ + /* + * Don't allocate at 0x0. It will confuse code that + * checks pointers against NULL. Skip the first 8 + * bytes so we start at a nice even number. + */ + return efi_low_alloc_above(size, align, addr, 0x8); +} + +efi_status_t efi_allocate_pages(unsigned long size, unsigned long *addr, + unsigned long max); + +efi_status_t efi_relocate_kernel(unsigned long *image_addr, + unsigned long image_size, + unsigned long alloc_size, + unsigned long preferred_addr, + unsigned long alignment, + unsigned long min_addr); + +efi_status_t handle_cmdline_files(efi_loaded_image_t *image, + char *cmd_line, char *option_string, + unsigned long max_addr, + unsigned long *load_addr, + unsigned long *load_size); + +efi_status_t efi_parse_options(char const *cmdline); + +efi_status_t efi_setup_gop(struct screen_info *si, efi_guid_t *proto, + unsigned long size); + #endif diff --git a/include/linux/efi.h b/include/linux/efi.h index 2b228df18407..0e047d2738cd 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -56,19 +56,6 @@ typedef void *efi_handle_t; #define __efiapi #endif -#define efi_get_handle_at(array, idx) \ - (efi_is_native() ? (array)[idx] \ - : (efi_handle_t)(unsigned long)((u32 *)(array))[idx]) - -#define efi_get_handle_num(size) \ - ((size) / (efi_is_native() ? sizeof(efi_handle_t) : sizeof(u32))) - -#define for_each_efi_handle(handle, array, size, i) \ - for (i = 0; \ - i < efi_get_handle_num(size) && \ - ((handle = efi_get_handle_at((array), i)) || true); \ - i++) - /* * The UEFI spec and EDK2 reference implementation both define EFI_GUID as * struct { u32 a; u16; b; u16 c; u8 d[8]; }; and so the implied alignment @@ -157,15 +144,6 @@ typedef struct { u32 imagesize; } efi_capsule_header_t; -struct efi_boot_memmap { - efi_memory_desc_t **map; - unsigned long *map_size; - unsigned long *desc_size; - u32 *desc_ver; - unsigned long *key_ptr; - unsigned long *buff_size; -}; - /* * EFI capsule flags */ @@ -187,14 +165,6 @@ struct capsule_info { int __efi_capsule_setup_info(struct capsule_info *cap_info); -/* - * Allocation types for calls to boottime->allocate_pages. - */ -#define EFI_ALLOCATE_ANY_PAGES 0 -#define EFI_ALLOCATE_MAX_ADDRESS 1 -#define EFI_ALLOCATE_ADDRESS 2 -#define EFI_MAX_ALLOCATE_TYPE 3 - typedef int (*efi_freemem_callback_t) (u64 start, u64 end, void *arg); /* @@ -224,291 +194,7 @@ typedef struct { u8 sets_to_zero; } efi_time_cap_t; -typedef struct { - efi_table_hdr_t hdr; - u32 raise_tpl; - u32 restore_tpl; - u32 allocate_pages; - u32 free_pages; - u32 get_memory_map; - u32 allocate_pool; - u32 free_pool; - u32 create_event; - u32 set_timer; - u32 wait_for_event; - u32 signal_event; - u32 close_event; - u32 check_event; - u32 install_protocol_interface; - u32 reinstall_protocol_interface; - u32 uninstall_protocol_interface; - u32 handle_protocol; - u32 __reserved; - u32 register_protocol_notify; - u32 locate_handle; - u32 locate_device_path; - u32 install_configuration_table; - u32 load_image; - u32 start_image; - u32 exit; - u32 unload_image; - u32 exit_boot_services; - u32 get_next_monotonic_count; - u32 stall; - u32 set_watchdog_timer; - u32 connect_controller; - u32 disconnect_controller; - u32 open_protocol; - u32 close_protocol; - u32 open_protocol_information; - u32 protocols_per_handle; - u32 locate_handle_buffer; - u32 locate_protocol; - u32 install_multiple_protocol_interfaces; - u32 uninstall_multiple_protocol_interfaces; - u32 calculate_crc32; - u32 copy_mem; - u32 set_mem; - u32 create_event_ex; -} __packed efi_boot_services_32_t; - -/* - * EFI Boot Services table - */ -typedef union { - struct { - efi_table_hdr_t hdr; - void *raise_tpl; - void *restore_tpl; - efi_status_t (__efiapi *allocate_pages)(int, int, unsigned long, - efi_physical_addr_t *); - efi_status_t (__efiapi *free_pages)(efi_physical_addr_t, - unsigned long); - efi_status_t (__efiapi *get_memory_map)(unsigned long *, void *, - unsigned long *, - unsigned long *, u32 *); - efi_status_t (__efiapi *allocate_pool)(int, unsigned long, - void **); - efi_status_t (__efiapi *free_pool)(void *); - void *create_event; - void *set_timer; - void *wait_for_event; - void *signal_event; - void *close_event; - void *check_event; - void *install_protocol_interface; - void *reinstall_protocol_interface; - void *uninstall_protocol_interface; - efi_status_t (__efiapi *handle_protocol)(efi_handle_t, - efi_guid_t *, void **); - void *__reserved; - void *register_protocol_notify; - efi_status_t (__efiapi *locate_handle)(int, efi_guid_t *, - void *, unsigned long *, - efi_handle_t *); - void *locate_device_path; - efi_status_t (__efiapi *install_configuration_table)(efi_guid_t *, - void *); - void *load_image; - void *start_image; - void *exit; - void *unload_image; - efi_status_t (__efiapi *exit_boot_services)(efi_handle_t, - unsigned long); - void *get_next_monotonic_count; - void *stall; - void *set_watchdog_timer; - void *connect_controller; - efi_status_t (__efiapi *disconnect_controller)(efi_handle_t, - efi_handle_t, - efi_handle_t); - void *open_protocol; - void *close_protocol; - void *open_protocol_information; - void *protocols_per_handle; - void *locate_handle_buffer; - efi_status_t (__efiapi *locate_protocol)(efi_guid_t *, void *, - void **); - void *install_multiple_protocol_interfaces; - void *uninstall_multiple_protocol_interfaces; - void *calculate_crc32; - void *copy_mem; - void *set_mem; - void *create_event_ex; - }; - efi_boot_services_32_t mixed_mode; -} efi_boot_services_t; - -typedef enum { - EfiPciIoWidthUint8, - EfiPciIoWidthUint16, - EfiPciIoWidthUint32, - EfiPciIoWidthUint64, - EfiPciIoWidthFifoUint8, - EfiPciIoWidthFifoUint16, - EfiPciIoWidthFifoUint32, - EfiPciIoWidthFifoUint64, - EfiPciIoWidthFillUint8, - EfiPciIoWidthFillUint16, - EfiPciIoWidthFillUint32, - EfiPciIoWidthFillUint64, - EfiPciIoWidthMaximum -} EFI_PCI_IO_PROTOCOL_WIDTH; - -typedef enum { - EfiPciIoAttributeOperationGet, - EfiPciIoAttributeOperationSet, - EfiPciIoAttributeOperationEnable, - EfiPciIoAttributeOperationDisable, - EfiPciIoAttributeOperationSupported, - EfiPciIoAttributeOperationMaximum -} EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION; - -typedef struct { - u32 read; - u32 write; -} efi_pci_io_protocol_access_32_t; - -typedef union efi_pci_io_protocol efi_pci_io_protocol_t; - -typedef -efi_status_t (__efiapi *efi_pci_io_protocol_cfg_t)(efi_pci_io_protocol_t *, - EFI_PCI_IO_PROTOCOL_WIDTH, - u32 offset, - unsigned long count, - void *buffer); - -typedef struct { - void *read; - void *write; -} efi_pci_io_protocol_access_t; - -typedef struct { - efi_pci_io_protocol_cfg_t read; - efi_pci_io_protocol_cfg_t write; -} efi_pci_io_protocol_config_access_t; - -union efi_pci_io_protocol { - struct { - void *poll_mem; - void *poll_io; - efi_pci_io_protocol_access_t mem; - efi_pci_io_protocol_access_t io; - efi_pci_io_protocol_config_access_t pci; - void *copy_mem; - void *map; - void *unmap; - void *allocate_buffer; - void *free_buffer; - void *flush; - efi_status_t (__efiapi *get_location)(efi_pci_io_protocol_t *, - unsigned long *segment_nr, - unsigned long *bus_nr, - unsigned long *device_nr, - unsigned long *func_nr); - void *attributes; - void *get_bar_attributes; - void *set_bar_attributes; - uint64_t romsize; - void *romimage; - }; - struct { - u32 poll_mem; - u32 poll_io; - efi_pci_io_protocol_access_32_t mem; - efi_pci_io_protocol_access_32_t io; - efi_pci_io_protocol_access_32_t pci; - u32 copy_mem; - u32 map; - u32 unmap; - u32 allocate_buffer; - u32 free_buffer; - u32 flush; - u32 get_location; - u32 attributes; - u32 get_bar_attributes; - u32 set_bar_attributes; - u64 romsize; - u32 romimage; - } mixed_mode; -}; - -#define EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO 0x0001 -#define EFI_PCI_IO_ATTRIBUTE_ISA_IO 0x0002 -#define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO 0x0004 -#define EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY 0x0008 -#define EFI_PCI_IO_ATTRIBUTE_VGA_IO 0x0010 -#define EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO 0x0020 -#define EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO 0x0040 -#define EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE 0x0080 -#define EFI_PCI_IO_ATTRIBUTE_IO 0x0100 -#define EFI_PCI_IO_ATTRIBUTE_MEMORY 0x0200 -#define EFI_PCI_IO_ATTRIBUTE_BUS_MASTER 0x0400 -#define EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED 0x0800 -#define EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE 0x1000 -#define EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE 0x2000 -#define EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM 0x4000 -#define EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE 0x8000 -#define EFI_PCI_IO_ATTRIBUTE_ISA_IO_16 0x10000 -#define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16 0x20000 -#define EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 0x40000 - -struct efi_dev_path; - -typedef union apple_properties_protocol apple_properties_protocol_t; - -union apple_properties_protocol { - struct { - unsigned long version; - efi_status_t (__efiapi *get)(apple_properties_protocol_t *, - struct efi_dev_path *, - efi_char16_t *, void *, u32 *); - efi_status_t (__efiapi *set)(apple_properties_protocol_t *, - struct efi_dev_path *, - efi_char16_t *, void *, u32); - efi_status_t (__efiapi *del)(apple_properties_protocol_t *, - struct efi_dev_path *, - efi_char16_t *); - efi_status_t (__efiapi *get_all)(apple_properties_protocol_t *, - void *buffer, u32 *); - }; - struct { - u32 version; - u32 get; - u32 set; - u32 del; - u32 get_all; - } mixed_mode; -}; - -typedef u32 efi_tcg2_event_log_format; - -typedef union efi_tcg2_protocol efi_tcg2_protocol_t; - -union efi_tcg2_protocol { - struct { - void *get_capability; - efi_status_t (__efiapi *get_event_log)(efi_handle_t, - efi_tcg2_event_log_format, - efi_physical_addr_t *, - efi_physical_addr_t *, - efi_bool_t *); - void *hash_log_extend_event; - void *submit_command; - void *get_active_pcr_banks; - void *set_active_pcr_banks; - void *get_result_of_set_active_pcr_banks; - }; - struct { - u32 get_capability; - u32 get_event_log; - u32 hash_log_extend_event; - u32 submit_command; - u32 get_active_pcr_banks; - u32 set_active_pcr_banks; - u32 get_result_of_set_active_pcr_banks; - } mixed_mode; -}; +typedef union efi_boot_services efi_boot_services_t; /* * Types and defines for EFI ResetSystem @@ -796,8 +482,6 @@ struct efi_fdt_params { u32 desc_ver; }; -typedef struct efi_loaded_image efi_loaded_image_t; - typedef struct { u32 version; u32 length; @@ -1130,13 +814,6 @@ extern int efi_status_to_err(efi_status_t status); */ #define EFI_VARIABLE_GUID_LEN UUID_STRING_LEN -/* - * The type of search to perform when calling boottime->locate_handle - */ -#define EFI_LOCATE_ALL_HANDLES 0 -#define EFI_LOCATE_BY_REGISTER_NOTIFY 1 -#define EFI_LOCATE_BY_PROTOCOL 2 - /* * EFI Device Path information */ @@ -1254,80 +931,6 @@ struct efivar_entry { bool deleting; }; -union efi_simple_text_output_protocol { - struct { - void *reset; - efi_status_t (__efiapi *output_string)(efi_simple_text_output_protocol_t *, - efi_char16_t *); - void *test_string; - }; - struct { - u32 reset; - u32 output_string; - u32 test_string; - } mixed_mode; -}; - -#define PIXEL_RGB_RESERVED_8BIT_PER_COLOR 0 -#define PIXEL_BGR_RESERVED_8BIT_PER_COLOR 1 -#define PIXEL_BIT_MASK 2 -#define PIXEL_BLT_ONLY 3 -#define PIXEL_FORMAT_MAX 4 - -typedef struct { - u32 red_mask; - u32 green_mask; - u32 blue_mask; - u32 reserved_mask; -} efi_pixel_bitmask_t; - -typedef struct { - u32 version; - u32 horizontal_resolution; - u32 vertical_resolution; - int pixel_format; - efi_pixel_bitmask_t pixel_information; - u32 pixels_per_scan_line; -} efi_graphics_output_mode_info_t; - -typedef union efi_graphics_output_protocol_mode efi_graphics_output_protocol_mode_t; - -union efi_graphics_output_protocol_mode { - struct { - u32 max_mode; - u32 mode; - efi_graphics_output_mode_info_t *info; - unsigned long size_of_info; - efi_physical_addr_t frame_buffer_base; - unsigned long frame_buffer_size; - }; - struct { - u32 max_mode; - u32 mode; - u32 info; - u32 size_of_info; - u64 frame_buffer_base; - u32 frame_buffer_size; - } mixed_mode; -}; - -typedef union efi_graphics_output_protocol efi_graphics_output_protocol_t; - -union efi_graphics_output_protocol { - struct { - void *query_mode; - void *set_mode; - void *blt; - efi_graphics_output_protocol_mode_t *mode; - }; - struct { - u32 query_mode; - u32 set_mode; - u32 blt; - u32 mode; - } mixed_mode; -}; - extern struct list_head efivar_sysfs_list; static inline void @@ -1425,52 +1028,6 @@ static inline int efi_runtime_map_copy(void *buf, size_t bufsz) #endif -/* prototypes shared between arch specific and generic stub code */ - -void efi_printk(char *str); - -void efi_free(unsigned long size, unsigned long addr); - -char *efi_convert_cmdline(efi_loaded_image_t *image, int *cmd_line_len); - -efi_status_t efi_get_memory_map(struct efi_boot_memmap *map); - -efi_status_t efi_low_alloc_above(unsigned long size, unsigned long align, - unsigned long *addr, unsigned long min); - -static inline -efi_status_t efi_low_alloc(unsigned long size, unsigned long align, - unsigned long *addr) -{ - /* - * Don't allocate at 0x0. It will confuse code that - * checks pointers against NULL. Skip the first 8 - * bytes so we start at a nice even number. - */ - return efi_low_alloc_above(size, align, addr, 0x8); -} - -efi_status_t efi_allocate_pages(unsigned long size, unsigned long *addr, - unsigned long max); - -efi_status_t efi_relocate_kernel(unsigned long *image_addr, - unsigned long image_size, - unsigned long alloc_size, - unsigned long preferred_addr, - unsigned long alignment, - unsigned long min_addr); - -efi_status_t handle_cmdline_files(efi_loaded_image_t *image, - char *cmd_line, char *option_string, - unsigned long max_addr, - unsigned long *load_addr, - unsigned long *load_size); - -efi_status_t efi_parse_options(char const *cmdline); - -efi_status_t efi_setup_gop(struct screen_info *si, efi_guid_t *proto, - unsigned long size); - #ifdef CONFIG_EFI extern bool efi_runtime_disabled(void); #else @@ -1548,15 +1105,6 @@ void efi_retrieve_tpm2_eventlog(void); arch_efi_call_virt_teardown(); \ }) -typedef efi_status_t (*efi_exit_boot_map_processing)( - struct efi_boot_memmap *map, - void *priv); - -efi_status_t efi_exit_boot_services(void *handle, - struct efi_boot_memmap *map, - void *priv, - efi_exit_boot_map_processing priv_func); - #define EFI_RANDOM_SEED_SIZE 64U struct linux_efi_random_seed { @@ -1643,6 +1191,4 @@ struct linux_efi_memreserve { #define EFI_MEMRESERVE_COUNT(size) (((size) - sizeof(struct linux_efi_memreserve)) \ / sizeof(((struct linux_efi_memreserve *)0)->entry[0])) -void efi_pci_disable_bridge_busmaster(void); - #endif /* _LINUX_EFI_H */ From patchwork Mon Feb 10 16:02: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: 206591 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 E26AEC352A3 for ; Mon, 10 Feb 2020 16:03:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id B3A2524676 for ; Mon, 10 Feb 2020 16:03:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1581350599; bh=xDY5ywegpIQfMf5Jxe7n7RKZXAOGf2hdpZjQZmUp8Qo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=WyTItReJm9FP46K6VM77v43nrKb5qSMiZvDGoxgqifKbEB00OryJLdB/manxZ8/vc 2aACPOyvM3QlCcjoht78Mu7sjTBvqfgIgdkXSblgGw734MaKUsrD/3iJWD/ViGejDZ 62twX21l5iao3k+G3arzWsl4AhXDAdZr1zBvtNyk= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727798AbgBJQDT (ORCPT ); Mon, 10 Feb 2020 11:03:19 -0500 Received: from mail.kernel.org ([198.145.29.99]:52842 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727697AbgBJQDT (ORCPT ); Mon, 10 Feb 2020 11:03:19 -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 64BB52467A; Mon, 10 Feb 2020 16:03:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1581350598; bh=xDY5ywegpIQfMf5Jxe7n7RKZXAOGf2hdpZjQZmUp8Qo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=1oEJNCawnyNBAXNM+SvTCwxDrvzIHxM3p5vZEW94L3xOLBN8JhmJfQXwMJ3VW5EUS qup5b9A/tGXfYAl4X2SS20FBDMjQNZK83rUmwxKcuISe6jXIxIw5Gr+BjHNBDKJud7 /WjU3sHHzFp5SZRm18KdK4glZ+j4qdon73oMkcto= From: Ard Biesheuvel To: linux-efi@vger.kernel.org Cc: Ard Biesheuvel , nivedita@alum.mit.edu, mingo@kernel.org, lukas@wunner.de, atish.patra@wdc.com Subject: [PATCH 12/19] efi/libstub: Move efi_random_alloc() into separate source file Date: Mon, 10 Feb 2020 17:02:41 +0100 Message-Id: <20200210160248.4889-13-ardb@kernel.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200210160248.4889-1-ardb@kernel.org> References: <20200210160248.4889-1-ardb@kernel.org> Sender: linux-efi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org efi_random_alloc() is only used on arm64, but as it shares a source file with efi_random_get_seed(), the latter will pull in the former on other architectures as well. Let's take advantage of the fact that libstub is a static library, and so the linker will only incorporate objects that are needed to satisfy dependencies in other objects. This means we can move the random alloc code to a separate source file that gets built unconditionally, but only used when needed. Signed-off-by: Ard Biesheuvel --- drivers/firmware/efi/libstub/Makefile | 2 +- drivers/firmware/efi/libstub/random.c | 114 ------------------ drivers/firmware/efi/libstub/randomalloc.c | 124 ++++++++++++++++++++ 3 files changed, 125 insertions(+), 115 deletions(-) diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile index 8e15634fa929..ac0d0e1ef32d 100644 --- a/drivers/firmware/efi/libstub/Makefile +++ b/drivers/firmware/efi/libstub/Makefile @@ -39,7 +39,7 @@ OBJECT_FILES_NON_STANDARD := y KCOV_INSTRUMENT := n lib-y := efi-stub-helper.o gop.o secureboot.o tpm.o \ - mem.o random.o pci.o + mem.o random.o randomalloc.o pci.o # include the stub's generic dependencies from lib/ when building for ARM/arm64 arm-deps-y := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c diff --git a/drivers/firmware/efi/libstub/random.c b/drivers/firmware/efi/libstub/random.c index 316ce9ff0193..21e7e9325219 100644 --- a/drivers/firmware/efi/libstub/random.c +++ b/drivers/firmware/efi/libstub/random.c @@ -4,7 +4,6 @@ */ #include -#include #include #include "efistub.h" @@ -39,119 +38,6 @@ efi_status_t efi_get_random_bytes(unsigned long size, u8 *out) return efi_call_proto(rng, get_rng, NULL, size, out); } -/* - * Return the number of slots covered by this entry, i.e., the number of - * addresses it covers that are suitably aligned and supply enough room - * for the allocation. - */ -static unsigned long get_entry_num_slots(efi_memory_desc_t *md, - unsigned long size, - unsigned long align_shift) -{ - unsigned long align = 1UL << align_shift; - u64 first_slot, last_slot, region_end; - - if (md->type != EFI_CONVENTIONAL_MEMORY) - return 0; - - if (efi_soft_reserve_enabled() && - (md->attribute & EFI_MEMORY_SP)) - return 0; - - region_end = min((u64)ULONG_MAX, md->phys_addr + md->num_pages*EFI_PAGE_SIZE - 1); - - first_slot = round_up(md->phys_addr, align); - last_slot = round_down(region_end - size + 1, align); - - if (first_slot > last_slot) - return 0; - - return ((unsigned long)(last_slot - first_slot) >> align_shift) + 1; -} - -/* - * The UEFI memory descriptors have a virtual address field that is only used - * when installing the virtual mapping using SetVirtualAddressMap(). Since it - * is unused here, we can reuse it to keep track of each descriptor's slot - * count. - */ -#define MD_NUM_SLOTS(md) ((md)->virt_addr) - -efi_status_t efi_random_alloc(unsigned long size, - unsigned long align, - unsigned long *addr, - unsigned long random_seed) -{ - unsigned long map_size, desc_size, total_slots = 0, target_slot; - unsigned long buff_size; - efi_status_t status; - efi_memory_desc_t *memory_map; - int map_offset; - struct efi_boot_memmap map; - - map.map = &memory_map; - map.map_size = &map_size; - map.desc_size = &desc_size; - map.desc_ver = NULL; - map.key_ptr = NULL; - map.buff_size = &buff_size; - - status = efi_get_memory_map(&map); - if (status != EFI_SUCCESS) - return status; - - if (align < EFI_ALLOC_ALIGN) - align = EFI_ALLOC_ALIGN; - - /* count the suitable slots in each memory map entry */ - for (map_offset = 0; map_offset < map_size; map_offset += desc_size) { - efi_memory_desc_t *md = (void *)memory_map + map_offset; - unsigned long slots; - - slots = get_entry_num_slots(md, size, ilog2(align)); - MD_NUM_SLOTS(md) = slots; - total_slots += slots; - } - - /* find a random number between 0 and total_slots */ - target_slot = (total_slots * (u16)random_seed) >> 16; - - /* - * target_slot is now a value in the range [0, total_slots), and so - * it corresponds with exactly one of the suitable slots we recorded - * when iterating over the memory map the first time around. - * - * So iterate over the memory map again, subtracting the number of - * slots of each entry at each iteration, until we have found the entry - * that covers our chosen slot. Use the residual value of target_slot - * to calculate the randomly chosen address, and allocate it directly - * using EFI_ALLOCATE_ADDRESS. - */ - for (map_offset = 0; map_offset < map_size; map_offset += desc_size) { - efi_memory_desc_t *md = (void *)memory_map + map_offset; - efi_physical_addr_t target; - unsigned long pages; - - if (target_slot >= MD_NUM_SLOTS(md)) { - target_slot -= MD_NUM_SLOTS(md); - continue; - } - - target = round_up(md->phys_addr, align) + target_slot * align; - pages = round_up(size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE; - - status = efi_bs_call(allocate_pages, EFI_ALLOCATE_ADDRESS, - EFI_LOADER_DATA, pages, &target); - if (status == EFI_SUCCESS) - *addr = target; - break; - } - - efi_bs_call(free_pool, memory_map); - - return status; -} - efi_status_t efi_random_get_seed(void) { efi_guid_t rng_proto = EFI_RNG_PROTOCOL_GUID; diff --git a/drivers/firmware/efi/libstub/randomalloc.c b/drivers/firmware/efi/libstub/randomalloc.c new file mode 100644 index 000000000000..4578f59e160c --- /dev/null +++ b/drivers/firmware/efi/libstub/randomalloc.c @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2016 Linaro Ltd; + */ + +#include +#include +#include + +#include "efistub.h" + +/* + * Return the number of slots covered by this entry, i.e., the number of + * addresses it covers that are suitably aligned and supply enough room + * for the allocation. + */ +static unsigned long get_entry_num_slots(efi_memory_desc_t *md, + unsigned long size, + unsigned long align_shift) +{ + unsigned long align = 1UL << align_shift; + u64 first_slot, last_slot, region_end; + + if (md->type != EFI_CONVENTIONAL_MEMORY) + return 0; + + if (efi_soft_reserve_enabled() && + (md->attribute & EFI_MEMORY_SP)) + return 0; + + region_end = min(md->phys_addr + md->num_pages * EFI_PAGE_SIZE - 1, + (u64)ULONG_MAX); + + first_slot = round_up(md->phys_addr, align); + last_slot = round_down(region_end - size + 1, align); + + if (first_slot > last_slot) + return 0; + + return ((unsigned long)(last_slot - first_slot) >> align_shift) + 1; +} + +/* + * The UEFI memory descriptors have a virtual address field that is only used + * when installing the virtual mapping using SetVirtualAddressMap(). Since it + * is unused here, we can reuse it to keep track of each descriptor's slot + * count. + */ +#define MD_NUM_SLOTS(md) ((md)->virt_addr) + +efi_status_t efi_random_alloc(unsigned long size, + unsigned long align, + unsigned long *addr, + unsigned long random_seed) +{ + unsigned long map_size, desc_size, total_slots = 0, target_slot; + unsigned long buff_size; + efi_status_t status; + efi_memory_desc_t *memory_map; + int map_offset; + struct efi_boot_memmap map; + + map.map = &memory_map; + map.map_size = &map_size; + map.desc_size = &desc_size; + map.desc_ver = NULL; + map.key_ptr = NULL; + map.buff_size = &buff_size; + + status = efi_get_memory_map(&map); + if (status != EFI_SUCCESS) + return status; + + if (align < EFI_ALLOC_ALIGN) + align = EFI_ALLOC_ALIGN; + + /* count the suitable slots in each memory map entry */ + for (map_offset = 0; map_offset < map_size; map_offset += desc_size) { + efi_memory_desc_t *md = (void *)memory_map + map_offset; + unsigned long slots; + + slots = get_entry_num_slots(md, size, ilog2(align)); + MD_NUM_SLOTS(md) = slots; + total_slots += slots; + } + + /* find a random number between 0 and total_slots */ + target_slot = (total_slots * (u16)random_seed) >> 16; + + /* + * target_slot is now a value in the range [0, total_slots), and so + * it corresponds with exactly one of the suitable slots we recorded + * when iterating over the memory map the first time around. + * + * So iterate over the memory map again, subtracting the number of + * slots of each entry at each iteration, until we have found the entry + * that covers our chosen slot. Use the residual value of target_slot + * to calculate the randomly chosen address, and allocate it directly + * using EFI_ALLOCATE_ADDRESS. + */ + for (map_offset = 0; map_offset < map_size; map_offset += desc_size) { + efi_memory_desc_t *md = (void *)memory_map + map_offset; + efi_physical_addr_t target; + unsigned long pages; + + if (target_slot >= MD_NUM_SLOTS(md)) { + target_slot -= MD_NUM_SLOTS(md); + continue; + } + + target = round_up(md->phys_addr, align) + target_slot * align; + pages = round_up(size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE; + + status = efi_bs_call(allocate_pages, EFI_ALLOCATE_ADDRESS, + EFI_LOADER_DATA, pages, &target); + if (status == EFI_SUCCESS) + *addr = target; + break; + } + + efi_bs_call(free_pool, memory_map); + + return status; +} From patchwork Mon Feb 10 16:02:43 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 206590 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 0154EC352A3 for ; Mon, 10 Feb 2020 16:03:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id BE1C92467B for ; Mon, 10 Feb 2020 16:03:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1581350603; bh=Wv2epy5uJDKaPUyO5YZkE/QUitwk/0ZiVw7rVBrfAMA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=QT3Hu5rxwjxGCie9J0wnSGz15hr5yvDsbHFHNki/3BFY9uM4427mrx58/n+GvmYoy Nz2h6mK5n/GG/2Lf0UWZsqHT64nN6wvWLZv+zEArspV6c7OvRIYVZHHiZaMpO3I5Ym AlZoqLpR4qe8+/EPaimizKRVU3TmdVH38YYP+4DI= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727804AbgBJQDX (ORCPT ); Mon, 10 Feb 2020 11:03:23 -0500 Received: from mail.kernel.org ([198.145.29.99]:52880 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727800AbgBJQDX (ORCPT ); Mon, 10 Feb 2020 11:03:23 -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 BAF032467D; Mon, 10 Feb 2020 16:03:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1581350602; bh=Wv2epy5uJDKaPUyO5YZkE/QUitwk/0ZiVw7rVBrfAMA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=aJGuV9wyXAhOpUx9IedobC2X5F80g3WY5uLu3onprBUfWJOssv/F04t5wDJPC67eT +1l/0NRBeu5YoDNCmA34Paw16edUj64/dn06H6IxtIiP9Ftg8exFaGQ9J5T8QeyH4s oNRFsdHcfH73Y4n5jxW2PpunQQJrF9iKS+18Oxds= From: Ard Biesheuvel To: linux-efi@vger.kernel.org Cc: Ard Biesheuvel , nivedita@alum.mit.edu, mingo@kernel.org, lukas@wunner.de, atish.patra@wdc.com Subject: [PATCH 14/19] efi/libstub: Move file I/O support code into separate file Date: Mon, 10 Feb 2020 17:02:43 +0100 Message-Id: <20200210160248.4889-15-ardb@kernel.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200210160248.4889-1-ardb@kernel.org> References: <20200210160248.4889-1-ardb@kernel.org> Sender: linux-efi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org Split off the file I/O support code into a separate source file so it ends up in a separate object file in the static library, allowing the linker to omit it if the routines are not used. Signed-off-by: Ard Biesheuvel --- drivers/firmware/efi/libstub/Makefile | 2 +- drivers/firmware/efi/libstub/efi-stub-helper.c | 294 +------------------ drivers/firmware/efi/libstub/efistub.h | 1 + drivers/firmware/efi/libstub/file.c | 303 ++++++++++++++++++++ 4 files changed, 311 insertions(+), 289 deletions(-) diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile index ac0d0e1ef32d..74a097ef1780 100644 --- a/drivers/firmware/efi/libstub/Makefile +++ b/drivers/firmware/efi/libstub/Makefile @@ -39,7 +39,7 @@ OBJECT_FILES_NON_STANDARD := y KCOV_INSTRUMENT := n lib-y := efi-stub-helper.o gop.o secureboot.o tpm.o \ - mem.o random.o randomalloc.o pci.o + file.o mem.o random.o randomalloc.o pci.o # include the stub's generic dependencies from lib/ when building for ARM/arm64 arm-deps-y := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c index 1a8f2cf5a2bd..db23be5dc69b 100644 --- a/drivers/firmware/efi/libstub/efi-stub-helper.c +++ b/drivers/firmware/efi/libstub/efi-stub-helper.c @@ -12,23 +12,7 @@ #include "efistub.h" -/* - * Some firmware implementations have problems reading files in one go. - * A read chunk size of 1MB seems to work for most platforms. - * - * Unfortunately, reading files in chunks triggers *other* bugs on some - * platforms, so we provide a way to disable this workaround, which can - * be done by passing "efi=nochunk" on the EFI boot stub command line. - * - * If you experience issues with initrd images being corrupt it's worth - * trying efi=nochunk, but chunking is enabled by default because there - * are far more machines that require the workaround than those that - * break with it enabled. - */ -#define EFI_READ_CHUNK_SIZE (1024 * 1024) - -static unsigned long efi_chunk_size = EFI_READ_CHUNK_SIZE; - +static bool __efistub_global efi_nochunk; static bool __efistub_global efi_nokaslr; static bool __efistub_global efi_quiet; static bool __efistub_global efi_novamap; @@ -36,6 +20,10 @@ static bool __efistub_global efi_nosoftreserve; static bool __efistub_global efi_disable_pci_dma = IS_ENABLED(CONFIG_EFI_DISABLE_PCI_DMA); +bool __pure nochunk(void) +{ + return efi_nochunk; +} bool __pure nokaslr(void) { return efi_nokaslr; @@ -53,11 +41,6 @@ bool __pure __efi_soft_reserve_enabled(void) return !efi_nosoftreserve; } -struct file_info { - efi_file_protocol_t *handle; - u64 size; -}; - void efi_printk(char *str) { char *s8; @@ -75,90 +58,6 @@ void efi_printk(char *str) } } -static efi_status_t efi_file_size(void *__fh, efi_char16_t *filename_16, - void **handle, u64 *file_sz) -{ - efi_file_protocol_t *h, *fh = __fh; - efi_file_info_t *info; - efi_status_t status; - efi_guid_t info_guid = EFI_FILE_INFO_ID; - unsigned long info_sz; - - status = fh->open(fh, &h, filename_16, EFI_FILE_MODE_READ, 0); - if (status != EFI_SUCCESS) { - efi_printk("Failed to open file: "); - efi_char16_printk(filename_16); - efi_printk("\n"); - return status; - } - - *handle = h; - - info_sz = 0; - status = h->get_info(h, &info_guid, &info_sz, NULL); - if (status != EFI_BUFFER_TOO_SMALL) { - efi_printk("Failed to get file info size\n"); - return status; - } - -grow: - status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, info_sz, - (void **)&info); - if (status != EFI_SUCCESS) { - efi_printk("Failed to alloc mem for file info\n"); - return status; - } - - status = h->get_info(h, &info_guid, &info_sz, info); - if (status == EFI_BUFFER_TOO_SMALL) { - efi_bs_call(free_pool, info); - goto grow; - } - - *file_sz = info->file_size; - efi_bs_call(free_pool, info); - - if (status != EFI_SUCCESS) - efi_printk("Failed to get initrd info\n"); - - return status; -} - -static efi_status_t efi_file_read(efi_file_protocol_t *handle, - unsigned long *size, void *addr) -{ - return handle->read(handle, size, addr); -} - -static efi_status_t efi_file_close(efi_file_protocol_t *handle) -{ - return handle->close(handle); -} - -static efi_status_t efi_open_volume(efi_loaded_image_t *image, - efi_file_protocol_t **__fh) -{ - efi_simple_file_system_protocol_t *io; - efi_file_protocol_t *fh; - efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID; - efi_status_t status; - efi_handle_t handle = image->device_handle; - - status = efi_bs_call(handle_protocol, handle, &fs_proto, (void **)&io); - if (status != EFI_SUCCESS) { - efi_printk("Failed to handle fs_proto\n"); - return status; - } - - status = io->open_volume(io, &fh); - if (status != EFI_SUCCESS) - efi_printk("Failed to open volume\n"); - else - *__fh = fh; - - return status; -} - /* * Parse the ASCII string 'cmdline' for EFI options, denoted by the efi= * option, e.g. efi=nochunk. @@ -197,7 +96,7 @@ efi_status_t efi_parse_options(char const *cmdline) while (*str && *str != ' ') { if (!strncmp(str, "nochunk", 7)) { str += strlen("nochunk"); - efi_chunk_size = -1UL; + efi_nochunk = true; } if (!strncmp(str, "novamap", 7)) { @@ -232,187 +131,6 @@ efi_status_t efi_parse_options(char const *cmdline) return EFI_SUCCESS; } -/* - * Check the cmdline for a LILO-style file= arguments. - * - * We only support loading a file from the same filesystem as - * the kernel image. - */ -efi_status_t handle_cmdline_files(efi_loaded_image_t *image, - char *cmd_line, char *option_string, - unsigned long max_addr, - unsigned long *load_addr, - unsigned long *load_size) -{ - struct file_info *files; - unsigned long file_addr; - u64 file_size_total; - efi_file_protocol_t *fh = NULL; - efi_status_t status; - int nr_files; - char *str; - int i, j, k; - - file_addr = 0; - file_size_total = 0; - - str = cmd_line; - - j = 0; /* See close_handles */ - - if (!load_addr || !load_size) - return EFI_INVALID_PARAMETER; - - *load_addr = 0; - *load_size = 0; - - if (!str || !*str) - return EFI_SUCCESS; - - for (nr_files = 0; *str; nr_files++) { - str = strstr(str, option_string); - if (!str) - break; - - str += strlen(option_string); - - /* Skip any leading slashes */ - while (*str == '/' || *str == '\\') - str++; - - while (*str && *str != ' ' && *str != '\n') - str++; - } - - if (!nr_files) - return EFI_SUCCESS; - - status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, - nr_files * sizeof(*files), (void **)&files); - if (status != EFI_SUCCESS) { - pr_efi_err("Failed to alloc mem for file handle list\n"); - goto fail; - } - - str = cmd_line; - for (i = 0; i < nr_files; i++) { - struct file_info *file; - efi_char16_t filename_16[256]; - efi_char16_t *p; - - str = strstr(str, option_string); - if (!str) - break; - - str += strlen(option_string); - - file = &files[i]; - p = filename_16; - - /* Skip any leading slashes */ - while (*str == '/' || *str == '\\') - str++; - - while (*str && *str != ' ' && *str != '\n') { - if ((u8 *)p >= (u8 *)filename_16 + sizeof(filename_16)) - break; - - if (*str == '/') { - *p++ = '\\'; - str++; - } else { - *p++ = *str++; - } - } - - *p = '\0'; - - /* Only open the volume once. */ - if (!i) { - status = efi_open_volume(image, &fh); - if (status != EFI_SUCCESS) - goto free_files; - } - - status = efi_file_size(fh, filename_16, (void **)&file->handle, - &file->size); - if (status != EFI_SUCCESS) - goto close_handles; - - file_size_total += file->size; - } - - if (file_size_total) { - unsigned long addr; - - /* - * Multiple files need to be at consecutive addresses in memory, - * so allocate enough memory for all the files. This is used - * for loading multiple files. - */ - status = efi_allocate_pages(file_size_total, &file_addr, max_addr); - if (status != EFI_SUCCESS) { - pr_efi_err("Failed to alloc highmem for files\n"); - goto close_handles; - } - - /* We've run out of free low memory. */ - if (file_addr > max_addr) { - pr_efi_err("We've run out of free low memory\n"); - status = EFI_INVALID_PARAMETER; - goto free_file_total; - } - - addr = file_addr; - for (j = 0; j < nr_files; j++) { - unsigned long size; - - size = files[j].size; - while (size) { - unsigned long chunksize; - - if (IS_ENABLED(CONFIG_X86) && size > efi_chunk_size) - chunksize = efi_chunk_size; - else - chunksize = size; - - status = efi_file_read(files[j].handle, - &chunksize, - (void *)addr); - if (status != EFI_SUCCESS) { - pr_efi_err("Failed to read file\n"); - goto free_file_total; - } - addr += chunksize; - size -= chunksize; - } - - efi_file_close(files[j].handle); - } - - } - - efi_bs_call(free_pool, files); - - *load_addr = file_addr; - *load_size = file_size_total; - - return status; - -free_file_total: - efi_free(file_size_total, file_addr); - -close_handles: - for (k = j; k < i; k++) - efi_file_close(files[k].handle); -free_files: - efi_bs_call(free_pool, files); -fail: - *load_addr = 0; - *load_size = 0; - - return status; -} /* * Get the number of UTF-8 bytes corresponding to an UTF-16 character. * This overestimates for surrogates, but that is okay. diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h index 5123def761e9..e057d509d5d8 100644 --- a/drivers/firmware/efi/libstub/efistub.h +++ b/drivers/firmware/efi/libstub/efistub.h @@ -31,6 +31,7 @@ #define __efistub_global #endif +extern bool __pure nochunk(void); extern bool __pure nokaslr(void); extern bool __pure is_quiet(void); extern bool __pure novamap(void); diff --git a/drivers/firmware/efi/libstub/file.c b/drivers/firmware/efi/libstub/file.c new file mode 100644 index 000000000000..e0302f340962 --- /dev/null +++ b/drivers/firmware/efi/libstub/file.c @@ -0,0 +1,303 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Helper functions used by the EFI stub on multiple + * architectures. This should be #included by the EFI stub + * implementation files. + * + * Copyright 2011 Intel Corporation; author Matt Fleming + */ + +#include +#include + +#include "efistub.h" + +/* + * Some firmware implementations have problems reading files in one go. + * A read chunk size of 1MB seems to work for most platforms. + * + * Unfortunately, reading files in chunks triggers *other* bugs on some + * platforms, so we provide a way to disable this workaround, which can + * be done by passing "efi=nochunk" on the EFI boot stub command line. + * + * If you experience issues with initrd images being corrupt it's worth + * trying efi=nochunk, but chunking is enabled by default on x86 because + * there are far more machines that require the workaround than those that + * break with it enabled. + */ +#define EFI_READ_CHUNK_SIZE SZ_1M + +struct file_info { + efi_file_protocol_t *handle; + u64 size; +}; + +static efi_status_t efi_file_size(void *__fh, efi_char16_t *filename_16, + void **handle, u64 *file_sz) +{ + efi_file_protocol_t *h, *fh = __fh; + efi_file_info_t *info; + efi_status_t status; + efi_guid_t info_guid = EFI_FILE_INFO_ID; + unsigned long info_sz; + + status = fh->open(fh, &h, filename_16, EFI_FILE_MODE_READ, 0); + if (status != EFI_SUCCESS) { + efi_printk("Failed to open file: "); + efi_char16_printk(filename_16); + efi_printk("\n"); + return status; + } + + *handle = h; + + info_sz = 0; + status = h->get_info(h, &info_guid, &info_sz, NULL); + if (status != EFI_BUFFER_TOO_SMALL) { + efi_printk("Failed to get file info size\n"); + return status; + } + +grow: + status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, info_sz, + (void **)&info); + if (status != EFI_SUCCESS) { + efi_printk("Failed to alloc mem for file info\n"); + return status; + } + + status = h->get_info(h, &info_guid, &info_sz, info); + if (status == EFI_BUFFER_TOO_SMALL) { + efi_bs_call(free_pool, info); + goto grow; + } + + *file_sz = info->file_size; + efi_bs_call(free_pool, info); + + if (status != EFI_SUCCESS) + efi_printk("Failed to get initrd info\n"); + + return status; +} + +static efi_status_t efi_file_read(efi_file_protocol_t *handle, + unsigned long *size, void *addr) +{ + return handle->read(handle, size, addr); +} + +static efi_status_t efi_file_close(efi_file_protocol_t *handle) +{ + return handle->close(handle); +} + +static efi_status_t efi_open_volume(efi_loaded_image_t *image, + efi_file_protocol_t **__fh) +{ + efi_simple_file_system_protocol_t *io; + efi_file_protocol_t *fh; + efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID; + efi_status_t status; + efi_handle_t handle = image->device_handle; + + status = efi_bs_call(handle_protocol, handle, &fs_proto, (void **)&io); + if (status != EFI_SUCCESS) { + efi_printk("Failed to handle fs_proto\n"); + return status; + } + + status = io->open_volume(io, &fh); + if (status != EFI_SUCCESS) + efi_printk("Failed to open volume\n"); + else + *__fh = fh; + + return status; +} + +/* + * Check the cmdline for a LILO-style file= arguments. + * + * We only support loading a file from the same filesystem as + * the kernel image. + */ +efi_status_t handle_cmdline_files(efi_loaded_image_t *image, + char *cmd_line, char *option_string, + unsigned long max_addr, + unsigned long *load_addr, + unsigned long *load_size) +{ + unsigned long efi_chunk_size = ULONG_MAX; + struct file_info *files; + unsigned long file_addr; + u64 file_size_total; + efi_file_protocol_t *fh = NULL; + efi_status_t status; + int nr_files; + char *str; + int i, j, k; + + if (IS_ENABLED(CONFIG_X86) && !nochunk()) + efi_chunk_size = EFI_READ_CHUNK_SIZE; + + file_addr = 0; + file_size_total = 0; + + str = cmd_line; + + j = 0; /* See close_handles */ + + if (!load_addr || !load_size) + return EFI_INVALID_PARAMETER; + + *load_addr = 0; + *load_size = 0; + + if (!str || !*str) + return EFI_SUCCESS; + + for (nr_files = 0; *str; nr_files++) { + str = strstr(str, option_string); + if (!str) + break; + + str += strlen(option_string); + + /* Skip any leading slashes */ + while (*str == '/' || *str == '\\') + str++; + + while (*str && *str != ' ' && *str != '\n') + str++; + } + + if (!nr_files) + return EFI_SUCCESS; + + status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, + nr_files * sizeof(*files), (void **)&files); + if (status != EFI_SUCCESS) { + pr_efi_err("Failed to alloc mem for file handle list\n"); + goto fail; + } + + str = cmd_line; + for (i = 0; i < nr_files; i++) { + struct file_info *file; + efi_char16_t filename_16[256]; + efi_char16_t *p; + + str = strstr(str, option_string); + if (!str) + break; + + str += strlen(option_string); + + file = &files[i]; + p = filename_16; + + /* Skip any leading slashes */ + while (*str == '/' || *str == '\\') + str++; + + while (*str && *str != ' ' && *str != '\n') { + if ((u8 *)p >= (u8 *)filename_16 + sizeof(filename_16)) + break; + + if (*str == '/') { + *p++ = '\\'; + str++; + } else { + *p++ = *str++; + } + } + + *p = '\0'; + + /* Only open the volume once. */ + if (!i) { + status = efi_open_volume(image, &fh); + if (status != EFI_SUCCESS) + goto free_files; + } + + status = efi_file_size(fh, filename_16, (void **)&file->handle, + &file->size); + if (status != EFI_SUCCESS) + goto close_handles; + + file_size_total += file->size; + } + + if (file_size_total) { + unsigned long addr; + + /* + * Multiple files need to be at consecutive addresses in memory, + * so allocate enough memory for all the files. This is used + * for loading multiple files. + */ + status = efi_allocate_pages(file_size_total, &file_addr, max_addr); + if (status != EFI_SUCCESS) { + pr_efi_err("Failed to alloc highmem for files\n"); + goto close_handles; + } + + /* We've run out of free low memory. */ + if (file_addr > max_addr) { + pr_efi_err("We've run out of free low memory\n"); + status = EFI_INVALID_PARAMETER; + goto free_file_total; + } + + addr = file_addr; + for (j = 0; j < nr_files; j++) { + unsigned long size; + + size = files[j].size; + while (size) { + unsigned long chunksize; + + if (size > efi_chunk_size) + chunksize = efi_chunk_size; + else + chunksize = size; + + status = efi_file_read(files[j].handle, + &chunksize, + (void *)addr); + if (status != EFI_SUCCESS) { + pr_efi_err("Failed to read file\n"); + goto free_file_total; + } + addr += chunksize; + size -= chunksize; + } + + efi_file_close(files[j].handle); + } + + } + + efi_bs_call(free_pool, files); + + *load_addr = file_addr; + *load_size = file_size_total; + + return status; + +free_file_total: + efi_free(file_size_total, file_addr); + +close_handles: + for (k = j; k < i; k++) + efi_file_close(files[k].handle); +free_files: + efi_bs_call(free_pool, files); +fail: + *load_addr = 0; + *load_size = 0; + + return status; +} From patchwork Mon Feb 10 16:02:45 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 206589 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 049C7C352A3 for ; Mon, 10 Feb 2020 16:03:27 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id CEFE024680 for ; Mon, 10 Feb 2020 16:03:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1581350606; bh=JmxN+QByh25YY+an/+C8asdfGCNNoif4mUIvCTyf8Hc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=bWnnN+kc3ub3SsEvzVjIkBSEQEmLnqs206BSlxd8Yvp8Pb34fC3zEBgDHiZypPAOV +y15Dw6mWZuZBICzIKyMoOyvRrqj29kSnJB4eyOQa1mosPKn9lEKvy6ZM8LF1sMFoA w/IhNtWksoqHDTcGc02OhKdv1x4Wr2GWK7DYivVQ= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727810AbgBJQD0 (ORCPT ); Mon, 10 Feb 2020 11:03:26 -0500 Received: from mail.kernel.org ([198.145.29.99]:52918 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727800AbgBJQD0 (ORCPT ); Mon, 10 Feb 2020 11:03:26 -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 1CC3F2467B; Mon, 10 Feb 2020 16:03:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1581350605; bh=JmxN+QByh25YY+an/+C8asdfGCNNoif4mUIvCTyf8Hc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=rZHK4ypjCnjLbYNABZnl3XGunqU88zbBcSabD1qhOsuS4CNf/JQsJTeUCZmSQp3S5 /Cop5/7Tu82t2QOpFcJWIXTS9ctel6iPFqp+h34kYEqp2Hlo7htj0BCm3TGa7juKwI XB+Xe478sTE+ACYrZHcOj4bDPVvxg+LVe4MJvXj0= From: Ard Biesheuvel To: linux-efi@vger.kernel.org Cc: Ard Biesheuvel , nivedita@alum.mit.edu, mingo@kernel.org, lukas@wunner.de, atish.patra@wdc.com Subject: [PATCH 16/19] efi/libstub: Take soft and hard memory limits into account for initrd loading Date: Mon, 10 Feb 2020 17:02:45 +0100 Message-Id: <20200210160248.4889-17-ardb@kernel.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200210160248.4889-1-ardb@kernel.org> References: <20200210160248.4889-1-ardb@kernel.org> Sender: linux-efi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org On x86, the preferred load address of the initrd is still below 4 GB, even though in some cases, we can cope with an initrd that is loaded above that. To simplify the code, and to make it more straightforward to introduce other ways to load the initrd, pass the soft and hard memory limits at the same time, and let the code handling the initrd= command line option deal with this. Signed-off-by: Ard Biesheuvel --- drivers/firmware/efi/libstub/arm-stub.c | 2 +- drivers/firmware/efi/libstub/efistub.h | 3 ++- drivers/firmware/efi/libstub/file.c | 21 ++++++++++++++------ drivers/firmware/efi/libstub/x86-stub.c | 11 ++-------- 4 files changed, 20 insertions(+), 17 deletions(-) diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c index 9b12f9b19533..2edc673ea06c 100644 --- a/drivers/firmware/efi/libstub/arm-stub.c +++ b/drivers/firmware/efi/libstub/arm-stub.c @@ -258,7 +258,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table_arg, if (!fdt_addr) pr_efi("Generating empty DTB\n"); - status = efi_load_initrd(image, &initrd_addr, &initrd_size, + status = efi_load_initrd(image, &initrd_addr, &initrd_size, ULONG_MAX, efi_get_max_initrd_addr(dram_base, *image_addr)); if (status != EFI_SUCCESS) pr_efi_err("Failed initrd from command line!\n"); diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h index 60d929469b8b..d282d907cd33 100644 --- a/drivers/firmware/efi/libstub/efistub.h +++ b/drivers/firmware/efi/libstub/efistub.h @@ -619,6 +619,7 @@ efi_status_t efi_load_dtb(efi_loaded_image_t *image, efi_status_t efi_load_initrd(efi_loaded_image_t *image, unsigned long *load_addr, unsigned long *load_size, - unsigned long max_addr); + unsigned long soft_limit, + unsigned long hard_limit); #endif diff --git a/drivers/firmware/efi/libstub/file.c b/drivers/firmware/efi/libstub/file.c index 0d67432ed067..be78f64f8d80 100644 --- a/drivers/firmware/efi/libstub/file.c +++ b/drivers/firmware/efi/libstub/file.c @@ -123,7 +123,8 @@ static int find_file_option(const efi_char16_t *cmdline, int cmdline_len, static efi_status_t handle_cmdline_files(efi_loaded_image_t *image, const efi_char16_t *optstr, int optstr_size, - unsigned long max_addr, + unsigned long soft_limit, + unsigned long hard_limit, unsigned long *load_addr, unsigned long *load_size) { @@ -179,8 +180,15 @@ static efi_status_t handle_cmdline_files(efi_loaded_image_t *image, round_up(alloc_size, EFI_ALLOC_ALIGN)) { unsigned long old_addr = alloc_addr; - status = efi_allocate_pages(alloc_size + size, &alloc_addr, - max_addr); + status = EFI_OUT_OF_RESOURCES; + if (soft_limit < hard_limit) + status = efi_allocate_pages(alloc_size + size, + &alloc_addr, + soft_limit); + if (status == EFI_OUT_OF_RESOURCES) + status = efi_allocate_pages(alloc_size + size, + &alloc_addr, + hard_limit); if (status != EFI_SUCCESS) { pr_efi_err("Failed to reallocate memory for files\n"); goto err_close_file; @@ -236,14 +244,15 @@ efi_status_t efi_load_dtb(efi_loaded_image_t *image, unsigned long *load_size) { return handle_cmdline_files(image, L"dtb=", sizeof(L"dtb=") - 2, - ULONG_MAX, load_addr, load_size); + ULONG_MAX, ULONG_MAX, load_addr, load_size); } efi_status_t efi_load_initrd(efi_loaded_image_t *image, unsigned long *load_addr, unsigned long *load_size, - unsigned long max_addr) + unsigned long soft_limit, + unsigned long hard_limit) { return handle_cmdline_files(image, L"initrd=", sizeof(L"initrd=") - 2, - max_addr, load_addr, load_size); + soft_limit, hard_limit, load_addr, load_size); } diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c index 39d04735f1c5..52a1a2df2071 100644 --- a/drivers/firmware/efi/libstub/x86-stub.c +++ b/drivers/firmware/efi/libstub/x86-stub.c @@ -422,15 +422,8 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle, goto fail2; status = efi_load_initrd(image, &ramdisk_addr, &ramdisk_size, - hdr->initrd_addr_max); - - if (status != EFI_SUCCESS && - hdr->xloadflags & XLF_CAN_BE_LOADED_ABOVE_4G) { - efi_printk("Trying to load files to higher address\n"); - status = efi_load_initrd(image, &ramdisk_addr, &ramdisk_size, - ULONG_MAX); - } - + hdr->initrd_addr_max, + above4g ? ULONG_MAX : hdr->initrd_addr_max); if (status != EFI_SUCCESS) goto fail2; hdr->ramdisk_image = ramdisk_addr & 0xffffffff; From patchwork Mon Feb 10 16:02:47 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 206588 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 BB9B0C352A5 for ; Mon, 10 Feb 2020 16:03:29 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 961F420863 for ; Mon, 10 Feb 2020 16:03:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1581350609; bh=1jCLSpuxWNvqDDktboTcTA462Gp+IJGKbFelxV2ZYVE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=CGp5Vl9c2cZTjrMKsJXAjk82cBMyS+fiATWjuUhKNi+fDHm8QCiqqMDtwJaGRyHYl wofJnqGjmhcdIHDKyd1b0rkkhtpwLWs+zvzbTVGc3Jagy9bq579rjnKBj+IdhUMxP+ 4vBe57iRlfr6hR1vS6QRP49yY7612bbFr4H3llWk= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727821AbgBJQD3 (ORCPT ); Mon, 10 Feb 2020 11:03:29 -0500 Received: from mail.kernel.org ([198.145.29.99]:52952 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727800AbgBJQD3 (ORCPT ); Mon, 10 Feb 2020 11:03:29 -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 76FD824683; Mon, 10 Feb 2020 16:03:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1581350608; bh=1jCLSpuxWNvqDDktboTcTA462Gp+IJGKbFelxV2ZYVE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=03ux1Q+Vm+C2tBAUwfCPQasLYb2lOqUR20UipexcqE6i9is+wueJrEE6eQ0u9Y3/m pz4Z+FxKzkjKnkq6SFcTt6O60jVqo5RA+gPPGBJaw+7wbpgNSJtkpKFp1gEU73pgJL mkSFccEbdObwCxmOqA1yYlBVRDmgWqfTKjvkOIBo= From: Ard Biesheuvel To: linux-efi@vger.kernel.org Cc: Ard Biesheuvel , nivedita@alum.mit.edu, mingo@kernel.org, lukas@wunner.de, atish.patra@wdc.com Subject: [PATCH 18/19] efi/libstub: Expose LocateDevicePath boot service Date: Mon, 10 Feb 2020 17:02:47 +0100 Message-Id: <20200210160248.4889-19-ardb@kernel.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200210160248.4889-1-ardb@kernel.org> References: <20200210160248.4889-1-ardb@kernel.org> Sender: linux-efi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org We will be adding support for loading the initrd from a GUIDed device path in a subsequent patch, so update the prototype of the LocateDevicePath() boot service to make it callable from our code. Signed-off-by: Ard Biesheuvel --- arch/x86/include/asm/efi.h | 3 +++ drivers/firmware/efi/libstub/efistub.h | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index 85f79accd3f8..9ced980b123b 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h @@ -283,6 +283,9 @@ static inline void *efi64_zero_upper(void *p) #define __efi64_argmap_locate_protocol(protocol, reg, interface) \ ((protocol), (reg), efi64_zero_upper(interface)) +#define __efi64_argmap_locate_device_path(protocol, path, handle) \ + ((protocol), (path), efi64_zero_upper(handle)) + /* 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 d282d907cd33..afa774a312f5 100644 --- a/drivers/firmware/efi/libstub/efistub.h +++ b/drivers/firmware/efi/libstub/efistub.h @@ -100,6 +100,8 @@ struct efi_boot_memmap { unsigned long *buff_size; }; +typedef struct efi_generic_dev_path efi_device_path_protocol_t; + /* * EFI Boot Services table */ @@ -134,7 +136,9 @@ union efi_boot_services { efi_status_t (__efiapi *locate_handle)(int, efi_guid_t *, void *, unsigned long *, efi_handle_t *); - void *locate_device_path; + efi_status_t (__efiapi *locate_device_path)(efi_guid_t *, + efi_device_path_protocol_t **, + efi_handle_t *); efi_status_t (__efiapi *install_configuration_table)(efi_guid_t *, void *); void *load_image;