From patchwork Wed Feb 5 17:04:00 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leif Lindholm X-Patchwork-Id: 24198 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-oa0-f69.google.com (mail-oa0-f69.google.com [209.85.219.69]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id BDCA720675 for ; Wed, 5 Feb 2014 17:05:48 +0000 (UTC) Received: by mail-oa0-f69.google.com with SMTP id h16sf3556604oag.0 for ; Wed, 05 Feb 2014 09:05:47 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :list-post:list-help:list-archive:list-unsubscribe; bh=no75gOso99ve3RUf61J1TyXA06+Q3FqVeFvP9+KUjP4=; b=ffYPGOcCEvV0B70ClhNw0vscwR0fakZyZ3iHGq1vOvubJTFUQQElmDDY+2pOsgQZn+ fE1xVb6xjamCtmIz7jTE/DyHUFPKcTx+uOa1z5qJ2ealkrdfII0RbXACrrQzJpBKXVCn LSkiJjJ/RVrm2h4KGnYtIN/K8u3TnNSFpvwpvnR5s3V4pqxYUAlaIxtx4DLj4HaxCdDa ycbB6Wb2Ox46jVk6DGNRnLWxGGQr46BofK22FmFmIs63bAiMVGBqOvCttQF28tBJ2zCL B9kdvcDoAT/2iRmmy7fmktBK2HaenW1IX4A0TNPyJqCpQUq7+hkynkw5JPdMO1nESn/9 i1LA== X-Gm-Message-State: ALoCoQk6ecTySpG8g3O3E/UrOc1HB4tHkc5OuxIC8858Ijfmelrg5ihXLc81fs4poXifeFKIAHPl X-Received: by 10.182.126.137 with SMTP id my9mr1034378obb.13.1391619947724; Wed, 05 Feb 2014 09:05:47 -0800 (PST) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.91.110 with SMTP id y101ls211232qgd.0.gmail; Wed, 05 Feb 2014 09:05:47 -0800 (PST) X-Received: by 10.52.98.232 with SMTP id el8mr131281vdb.74.1391619947629; Wed, 05 Feb 2014 09:05:47 -0800 (PST) Received: from mail-ve0-f180.google.com (mail-ve0-f180.google.com [209.85.128.180]) by mx.google.com with ESMTPS id dc20si9833995vec.42.2014.02.05.09.05.47 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 05 Feb 2014 09:05:47 -0800 (PST) Received-SPF: neutral (google.com: 209.85.128.180 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.128.180; Received: by mail-ve0-f180.google.com with SMTP id db12so538701veb.11 for ; Wed, 05 Feb 2014 09:05:47 -0800 (PST) X-Received: by 10.58.170.106 with SMTP id al10mr104584vec.61.1391619947521; Wed, 05 Feb 2014 09:05:47 -0800 (PST) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.220.174.196 with SMTP id u4csp64611vcz; Wed, 5 Feb 2014 09:05:40 -0800 (PST) X-Received: by 10.194.189.4 with SMTP id ge4mr376404wjc.92.1391619922577; Wed, 05 Feb 2014 09:05:22 -0800 (PST) Received: from mail-wg0-f43.google.com (mail-wg0-f43.google.com [74.125.82.43]) by mx.google.com with ESMTPS id l7si15460890wjz.113.2014.02.05.09.05.21 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 05 Feb 2014 09:05:22 -0800 (PST) Received-SPF: neutral (google.com: 74.125.82.43 is neither permitted nor denied by best guess record for domain of leif.lindholm@linaro.org) client-ip=74.125.82.43; Received: by mail-wg0-f43.google.com with SMTP id y10so503291wgg.10 for ; Wed, 05 Feb 2014 09:05:21 -0800 (PST) X-Received: by 10.180.219.66 with SMTP id pm2mr17204379wic.60.1391619921867; Wed, 05 Feb 2014 09:05:21 -0800 (PST) Received: from mohikan.mushroom.smurfnet.nu (cpc4-cmbg17-2-0-cust71.5-4.cable.virginm.net. [86.14.224.72]) by mx.google.com with ESMTPSA id p1sm47427211wie.1.2014.02.05.09.05.20 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 05 Feb 2014 09:05:21 -0800 (PST) From: Leif Lindholm To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-efi@vger.kernel.org Cc: patches@linaro.org, Roy Franz , Leif Lindholm Subject: [PATCH 09/22] Add shared arm/arm64 EFI stub Date: Wed, 5 Feb 2014 17:04:00 +0000 Message-Id: <1391619853-10601-10-git-send-email-leif.lindholm@linaro.org> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1391619853-10601-1-git-send-email-leif.lindholm@linaro.org> References: <1391619853-10601-1-git-send-email-leif.lindholm@linaro.org> X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: leif.lindholm@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.128.180 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , From: Roy Franz This patch adds the EFI stub entry point that is shared by the arm/arm64 architectures. Each arch will implement the handle_kernel_image() function that handles the arch specific load address and boot protocol requirements. Signed-off-by: Roy Franz Signed-off-by: Leif Lindholm --- drivers/firmware/efi/arm-stub.c | 145 +++++++++++++++++++++++++++++++++++++++ drivers/firmware/efi/fdt.c | 31 +++++++-- 2 files changed, 171 insertions(+), 5 deletions(-) create mode 100644 drivers/firmware/efi/arm-stub.c diff --git a/drivers/firmware/efi/arm-stub.c b/drivers/firmware/efi/arm-stub.c new file mode 100644 index 0000000..aefe963 --- /dev/null +++ b/drivers/firmware/efi/arm-stub.c @@ -0,0 +1,145 @@ +/* + * EFI stub implementation that is shared by arm and arm64 architectures. + * This should be #included by the EFI stub implementation files. + * + * Copyright (C) 2013,2014 Linaro Limited + * Roy Franz + * + * This file is part of the Linux kernel, and is made available under the + * terms of the GNU General Public License version 2. + * + */ + +/* + * This function handles the architcture specific differences between arm and + * arm64 regarding where the kernel image must be loaded and any memory that + * must be reserved. On failure it is required to free all + * all allocations it has made. + */ +static efi_status_t handle_kernel_image(efi_system_table_t *sys_table, + unsigned long *image_addr, + unsigned long *image_size, + unsigned long *reserve_addr, + unsigned long *reserve_size, + unsigned long dram_base, + efi_loaded_image_t *image); +/* + * EFI entry point for the arm/arm64 EFI stubs. This is the entrypoint + * that is described in the PE/COFF header. Most of the code is the same + * for both archictectures, with the arch-specific code provided in the + * handle_kernel_image() function. + */ +unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, + unsigned long *image_addr) +{ + efi_loaded_image_t *image; + efi_status_t status; + unsigned long image_size = 0; + unsigned long dram_base; + /* addr/point and size pairs for memory management*/ + unsigned long initrd_addr; + u64 initrd_size = 0; + unsigned long fdt_addr; /* Original DTB */ + u64 fdt_size = 0; /* We don't get size from configuration table */ + char *cmdline_ptr = NULL; + int cmdline_size = 0; + unsigned long new_fdt_addr; + efi_guid_t loaded_image_proto = LOADED_IMAGE_PROTOCOL_GUID; + unsigned long reserve_addr = 0; + unsigned long reserve_size = 0; + + /* Check if we were booted by the EFI firmware */ + if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) + goto fail; + + pr_efi(sys_table, "Booting Linux Kernel...\n"); + + /* + * Get a handle to the loaded image protocol. This is used to get + * information about the running image, such as size and the command + * line. + */ + status = efi_call_phys3(sys_table->boottime->handle_protocol, + handle, &loaded_image_proto, (void *)&image); + if (status != EFI_SUCCESS) { + pr_efi_err(sys_table, "Failed to get loaded image protocol\n"); + goto fail; + } + + dram_base = get_dram_base(sys_table); + if (dram_base == EFI_ERROR) { + pr_efi_err(sys_table, "Failed to find DRAM base\n"); + goto fail; + } + status = handle_kernel_image(sys_table, image_addr, &image_size, + &reserve_addr, + &reserve_size, + dram_base, image); + if (status != EFI_SUCCESS) { + pr_efi_err(sys_table, "Failed to relocate kernel\n"); + goto fail; + } + + /* + * Get the command line from EFI, using the LOADED_IMAGE + * protocol. We are going to copy the command line into the + * device tree, so this can be allocated anywhere. + */ + cmdline_ptr = efi_convert_cmdline_to_ascii(sys_table, image, + &cmdline_size); + if (!cmdline_ptr) { + pr_efi_err(sys_table, "getting command line via LOADED_IMAGE_PROTOCOL\n"); + goto fail_free_image; + } + + /* Load a device tree from the configuration table, if present. */ + fdt_addr = (uintptr_t)get_fdt(sys_table); + if (!fdt_addr) { + status = handle_cmdline_files(sys_table, image, cmdline_ptr, + "dtb=", + ~0UL, (unsigned long *)&fdt_addr, + (unsigned long *)&fdt_size); + + if (status != EFI_SUCCESS) { + pr_efi_err(sys_table, "Failed to load device tree!\n"); + goto fail_free_cmdline; + } + } + + status = handle_cmdline_files(sys_table, image, cmdline_ptr, + "initrd=", dram_base + SZ_512M, + (unsigned long *)&initrd_addr, + (unsigned long *)&initrd_size); + if (status != EFI_SUCCESS) + pr_efi_err(sys_table, "Failed initrd from command line!\n"); + + new_fdt_addr = fdt_addr; + status = allocate_new_fdt_and_exit_boot(sys_table, handle, + &new_fdt_addr, dram_base + MAX_FDT_OFFSET, + initrd_addr, initrd_size, cmdline_ptr, + fdt_addr, fdt_size); + + /* + * If all went well, we need to return the FDT address to the + * calling function so it can be passed to kernel as part of + * the kernel boot protocol. + */ + if (status == EFI_SUCCESS) + return new_fdt_addr; + + pr_efi_err(sys_table, "Failed to update FDT and exit boot services\n"); + + efi_free(sys_table, initrd_size, initrd_addr); + efi_free(sys_table, fdt_size, fdt_addr); + +fail_free_cmdline: + efi_free(sys_table, cmdline_size, (unsigned long)cmdline_ptr); + +fail_free_image: + efi_free(sys_table, image_size, *image_addr); + efi_free(sys_table, reserve_size, reserve_addr); +fail: + return EFI_ERROR; +} diff --git a/drivers/firmware/efi/fdt.c b/drivers/firmware/efi/fdt.c index a602b0a..4510f97 100644 --- a/drivers/firmware/efi/fdt.c +++ b/drivers/firmware/efi/fdt.c @@ -11,6 +11,7 @@ */ static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt, + unsigned long orig_fdt_size, void *fdt, int new_fdt_size, char *cmdline_ptr, u64 initrd_addr, u64 initrd_size, efi_memory_desc_t *memory_map, @@ -32,7 +33,27 @@ static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt, "Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n"; - status = fdt_open_into(orig_fdt, fdt, new_fdt_size); + /* Do some checks on provided FDT, if it exists*/ + if (orig_fdt) { + if (fdt_check_header(orig_fdt)) { + pr_efi_err(sys_table, "Device Tree header not valid!\n"); + return EFI_LOAD_ERROR; + } + /* + * We don't get the size of the FDT if we get if from a + * configuration table. + */ + if (orig_fdt_size && fdt_totalsize(orig_fdt) > orig_fdt_size) { + pr_efi_err(sys_table, "Truncated device tree! foo!\n"); + return EFI_LOAD_ERROR; + } + } + + if (orig_fdt) + status = fdt_open_into(orig_fdt, fdt, new_fdt_size); + else + status = fdt_create_empty_tree(fdt, new_fdt_size); + if (status != 0) goto fdt_set_fail; @@ -180,10 +201,10 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table, goto fail_free_new_fdt; status = update_fdt(sys_table, - (void *)fdt_addr, (void *)*new_fdt_addr, - new_fdt_size, cmdline_ptr, initrd_addr, - initrd_size, memory_map, map_size, - desc_size, desc_ver); + (void *)fdt_addr, fdt_size, + (void *)*new_fdt_addr, new_fdt_size, + cmdline_ptr, initrd_addr, initrd_size, + memory_map, map_size, desc_size, desc_ver); /* Succeeding the first time is the expected case. */ if (status == EFI_SUCCESS)