From patchwork Fri Jan 10 16:30:13 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roy Franz X-Patchwork-Id: 23093 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-gg0-f200.google.com (mail-gg0-f200.google.com [209.85.161.200]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 2681F216DB for ; Fri, 10 Jan 2014 16:30:38 +0000 (UTC) Received: by mail-gg0-f200.google.com with SMTP id q4sf5769858ggn.3 for ; Fri, 10 Jan 2014 08:30:37 -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=Brsa7jGhjUp1LE03K8jiFYNGT8eiViHZXpptFd9oAFU=; b=CWpxEZXYq6572Q4IiCJuc7sqC0tMOPCzjMnRPn8xcxDUoli7jbbSHdqkBw8d4VsJFK 240KenQFA+j1UmVrIe5oK/NzeLP4HFDoTKCeN/hpJh5wf0ODrMTAgayq0h6sCrRiEuhT 1uD9MqQzjLxWqhqAK+9Cqn/fNNPGUPJWKc9LdmzvFA6vkPpbQgiAeecm4+tegGFuPhmU SJ8G4TclqiAf15/5h90iyAQr+JQpw6PWuKrhboGjue2Ji0jaRPdUHJ81YOZdU9scxQ7I wKPBl6JUu3HJ99Va6G+YvjhNKejxVA+8jOTSSNgerlAkkniTjBZCGDl/DTkHczC8FVnW WU3A== X-Gm-Message-State: ALoCoQnN7DPGUYZVoFG9pu79xytGlm8bJMIqcxM1RffL/I6PINKJgapzy9pbr9kI96Hh8N50jsKI X-Received: by 10.236.93.230 with SMTP id l66mr3194854yhf.10.1389371437331; Fri, 10 Jan 2014 08:30:37 -0800 (PST) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.95.229 with SMTP id dn5ls1573898qeb.48.gmail; Fri, 10 Jan 2014 08:30:37 -0800 (PST) X-Received: by 10.53.5.230 with SMTP id cp6mr1336111vdd.65.1389371437146; Fri, 10 Jan 2014 08:30:37 -0800 (PST) Received: from mail-ve0-f171.google.com (mail-ve0-f171.google.com [209.85.128.171]) by mx.google.com with ESMTPS id vy2si5241064vec.115.2014.01.10.08.30.37 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 10 Jan 2014 08:30:37 -0800 (PST) Received-SPF: neutral (google.com: 209.85.128.171 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.171; Received: by mail-ve0-f171.google.com with SMTP id cz12so603141veb.2 for ; Fri, 10 Jan 2014 08:30:37 -0800 (PST) X-Received: by 10.58.152.130 with SMTP id uy2mr320639veb.71.1389371437019; Fri, 10 Jan 2014 08:30:37 -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.59.13.131 with SMTP id ey3csp100823ved; Fri, 10 Jan 2014 08:30:34 -0800 (PST) X-Received: by 10.66.119.136 with SMTP id ku8mr12531114pab.121.1389371433886; Fri, 10 Jan 2014 08:30:33 -0800 (PST) Received: from mail-pa0-f44.google.com (mail-pa0-f44.google.com [209.85.220.44]) by mx.google.com with ESMTPS id yd9si7653063pab.60.2014.01.10.08.30.33 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 10 Jan 2014 08:30:33 -0800 (PST) Received-SPF: neutral (google.com: 209.85.220.44 is neither permitted nor denied by best guess record for domain of roy.franz@linaro.org) client-ip=209.85.220.44; Received: by mail-pa0-f44.google.com with SMTP id fa1so4957323pad.17 for ; Fri, 10 Jan 2014 08:30:33 -0800 (PST) X-Received: by 10.68.44.106 with SMTP id d10mr917778pbm.114.1389371433318; Fri, 10 Jan 2014 08:30:33 -0800 (PST) Received: from rfranz-i7.local (c-24-10-97-91.hsd1.ca.comcast.net. [24.10.97.91]) by mx.google.com with ESMTPSA id nw11sm23388124pab.13.2014.01.10.08.30.31 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 10 Jan 2014 08:30:32 -0800 (PST) From: Roy Franz To: linux-kernel@vger.kernel.org, linux-efi@vger.kernel.org, linux-arm-kernel@lists.infradead.org, matt.fleming@intel.com, linux@arm.linux.org.uk Cc: leif.lindholm@linaro.org, grant.likely@linaro.org, dave.martin@arm.com, msalter@redhat.com, patches@linaro.org, Roy Franz Subject: [PATCH V6 4/8] Add shared FDT related functions for ARM/ARM64 Date: Fri, 10 Jan 2014 08:30:13 -0800 Message-Id: <1389371417-379-5-git-send-email-roy.franz@linaro.org> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1389371417-379-1-git-send-email-roy.franz@linaro.org> References: <1389371417-379-1-git-send-email-roy.franz@linaro.org> X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: roy.franz@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.128.171 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: , Both ARM and ARM64 stubs will update the device tree that they pass to the kernel. In both cases they primarily need to add the same UEFI related information, so the function can be shared. Create a new FDT related file for this to avoid use of architecture #ifdefs in efi-stub-helper.c. Signed-off-by: Roy Franz Acked-by: Grant Likely --- drivers/firmware/efi/fdt.c | 225 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 225 insertions(+) create mode 100644 drivers/firmware/efi/fdt.c diff --git a/drivers/firmware/efi/fdt.c b/drivers/firmware/efi/fdt.c new file mode 100644 index 0000000..e38f330 --- /dev/null +++ b/drivers/firmware/efi/fdt.c @@ -0,0 +1,225 @@ +/* + * FDT related Helper functions used by the EFI stub on multiple + * architectures. This should be #included by the EFI stub + * implementation files. + * + * Copyright 2013 Linaro Limited; author 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. + * + */ + +struct fdt_region { + u64 base; + u64 size; +}; + +static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt, + void *fdt, int new_fdt_size, char *cmdline_ptr, + u64 initrd_addr, u64 initrd_size, + efi_memory_desc_t *memory_map, + unsigned long map_size, unsigned long desc_size, + u32 desc_ver) +{ + int node; + int status; + u32 fdt_val32; + u64 fdt_val64; + + /* + * Copy definition of linux_banner here. Since this code is + * built as part of the decompressor for ARM v7, pulling + * in version.c where linux_banner is defined for the + * kernel brings other kernel dependencies with it. + */ + const char linux_banner[] = + "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); + if (status != 0) + goto fdt_set_fail; + + node = fdt_subnode_offset(fdt, 0, "chosen"); + if (node < 0) { + node = fdt_add_subnode(fdt, 0, "chosen"); + if (node < 0) { + status = node; /* node is error code when negative */ + goto fdt_set_fail; + } + } + + if ((cmdline_ptr != NULL) && (strlen(cmdline_ptr) > 0)) { + status = fdt_setprop(fdt, node, "bootargs", cmdline_ptr, + strlen(cmdline_ptr) + 1); + if (status) + goto fdt_set_fail; + } + + /* Set initrd address/end in device tree, if present */ + if (initrd_size != 0) { + u64 initrd_image_end; + u64 initrd_image_start = cpu_to_fdt64(initrd_addr); + status = fdt_setprop(fdt, node, "linux,initrd-start", + &initrd_image_start, sizeof(u64)); + if (status) + goto fdt_set_fail; + initrd_image_end = cpu_to_fdt64(initrd_addr + initrd_size); + status = fdt_setprop(fdt, node, "linux,initrd-end", + &initrd_image_end, sizeof(u64)); + if (status) + goto fdt_set_fail; + } + + /* Add FDT entries for EFI runtime services in chosen node. */ + node = fdt_subnode_offset(fdt, 0, "chosen"); + fdt_val64 = cpu_to_fdt64((u64)(unsigned long)sys_table); + status = fdt_setprop(fdt, node, "linux,uefi-system-table", + &fdt_val64, sizeof(fdt_val64)); + if (status) + goto fdt_set_fail; + + fdt_val64 = cpu_to_fdt64((u64)(unsigned long)memory_map); + status = fdt_setprop(fdt, node, "linux,uefi-mmap-start", + &fdt_val64, sizeof(fdt_val64)); + if (status) + goto fdt_set_fail; + + fdt_val32 = cpu_to_fdt32(map_size); + status = fdt_setprop(fdt, node, "linux,uefi-mmap-size", + &fdt_val32, sizeof(fdt_val32)); + if (status) + goto fdt_set_fail; + + fdt_val32 = cpu_to_fdt32(desc_size); + status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-size", + &fdt_val32, sizeof(fdt_val32)); + if (status) + goto fdt_set_fail; + + fdt_val32 = cpu_to_fdt32(desc_ver); + status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-ver", + &fdt_val32, sizeof(fdt_val32)); + if (status) + goto fdt_set_fail; + + /* + * Add kernel version banner so stub/kernel match can be + * verified. + */ + status = fdt_setprop_string(fdt, node, "linux,uefi-stub-kern-ver", + linux_banner); + if (status) + goto fdt_set_fail; + + return EFI_SUCCESS; + +fdt_set_fail: + if (status == -FDT_ERR_NOSPACE) + return EFI_BUFFER_TOO_SMALL; + + return EFI_LOAD_ERROR; +} + +#ifndef EFI_FDT_ALIGN +#define EFI_FDT_ALIGN EFI_PAGE_SIZE +#endif + +/* + * Allocate memory for a new FDT, then add EFI, commandline, and + * initrd related fields to the FDT. This routine increases the + * FDT allocation size until the allocated memory is large + * enough. EFI allocations are in EFI_PAGE_SIZE granules, + * which are fixed at 4K bytes, so in most cases the first + * allocation should succeed. + * EFI boot services are exited at the end of this function. + * There must be no allocations between the get_memory_map() + * call and the exit_boot_services() call, so the exiting of + * boot services is very tightly tied to the creation of the FDT + * with the final memory map in it. + */ + +efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table, + 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) +{ + unsigned long map_size, desc_size; + u32 desc_ver; + unsigned long mmap_key; + efi_memory_desc_t *memory_map; + unsigned long new_fdt_size; + efi_status_t status; + + /* Estimate size of new FDT, and allocate memory for it. We + * will allocate a bigger buffer if this ends up being too + * small, so a rough guess is OK here.*/ + new_fdt_size = fdt_size + EFI_PAGE_SIZE; + while (1) { + status = efi_high_alloc(sys_table, new_fdt_size, EFI_FDT_ALIGN, + new_fdt_addr, max_addr); + if (status != EFI_SUCCESS) { + pr_efi_err(sys_table, "Unable to allocate memory for new device tree.\n"); + goto fail; + } + + /* Now that we have done our final memory allocation (and free) + * we can get the memory map key needed for + * exit_boot_services(). + */ + status = efi_get_memory_map(sys_table, &memory_map, &map_size, + &desc_size, &desc_ver, &mmap_key); + if (status != EFI_SUCCESS) + 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); + + /* Succeeding the first time is the expected case. */ + if (status == EFI_SUCCESS) + break; + + if (status == EFI_BUFFER_TOO_SMALL) { + /* We need to allocate more space for the new + * device tree, so free existing buffer that is + * too small. Also free memory map, as we will need + * to get new one that reflects the free/alloc we do + * on the device tree buffer. */ + efi_free(sys_table, new_fdt_size, *new_fdt_addr); + efi_call_phys1(sys_table->boottime->free_pool, + memory_map); + new_fdt_size += EFI_PAGE_SIZE; + } else { + pr_efi_err(sys_table, "Unable to constuct new device tree.\n"); + goto fail_free_mmap; + } + } + + /* Now we are ready to exit_boot_services.*/ + status = efi_call_phys2(sys_table->boottime->exit_boot_services, + handle, mmap_key); + + + if (status == EFI_SUCCESS) + return status; + + pr_efi_err(sys_table, "Exit boot services failed.\n"); + +fail_free_mmap: + efi_call_phys1(sys_table->boottime->free_pool, memory_map); + +fail_free_new_fdt: + efi_free(sys_table, new_fdt_size, *new_fdt_addr); + +fail: + return EFI_LOAD_ERROR; +} +