From: Leif Lindholm <leif.lindholm@linaro.org>
To: linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, linux-efi@vger.kernel.org
Cc: patches@linaro.org, Roy Franz <roy.franz@linaro.org>,
Leif Lindholm <leif.lindholm@linaro.org>
Subject: [PATCH 07/22] Add shared FDT related functions for ARM/ARM64
Date: Wed, 5 Feb 2014 17:03:58 +0000 [thread overview]
Message-ID: <1391619853-10601-8-git-send-email-leif.lindholm@linaro.org> (raw)
In-Reply-To: <1391619853-10601-1-git-send-email-leif.lindholm@linaro.org>
From: Roy Franz <roy.franz@linaro.org>
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 <roy.franz@linaro.org>
Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
Acked-by: Grant Likely <grant.likely@linaro.org>
---
drivers/firmware/efi/fdt.c | 247 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/efi.h | 3 +
2 files changed, 250 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..a602b0a
--- /dev/null
+++ b/drivers/firmware/efi/fdt.c
@@ -0,0 +1,247 @@
+/*
+ * 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.
+ *
+ */
+
+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;
+
+ /* Delete any memory nodes present */
+ while ((node = fdt_subnode_offset(fdt, 0, "memory")) >= 0)
+ fdt_del_node(fdt, node);
+
+ 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;
+}
+
+static void *get_fdt(efi_system_table_t *sys_table)
+{
+ efi_guid_t fdt_guid = EFI_DEVICE_TREE_GUID;
+ efi_config_table_t *tables;
+ void *fdt;
+ int i;
+
+ tables = (efi_config_table_t *) sys_table->tables;
+ fdt = NULL;
+
+ for (i = 0; i < sys_table->nr_tables; i++)
+ if (efi_guidcmp(tables[i].guid, fdt_guid) == 0) {
+ fdt = (void *) tables[i].table;
+ break;
+ }
+
+ return fdt;
+}
diff --git a/include/linux/efi.h b/include/linux/efi.h
index d450673..cd112bb 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -394,6 +394,9 @@ typedef efi_status_t efi_query_variable_store_t(u32 attributes, unsigned long si
#define EFI_FILE_SYSTEM_GUID \
EFI_GUID( 0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b )
+#define EFI_DEVICE_TREE_GUID \
+ EFI_GUID( 0xb1b621d5, 0xf19c, 0x41a5, 0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0 )
+
typedef struct {
efi_guid_t guid;
u64 table;
--
1.7.10.4
next prev parent reply other threads:[~2014-02-05 17:03 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-02-05 17:03 [PATCH 00/22] arm/arm64: UEFI stubs + runtime services Leif Lindholm
2014-02-05 17:03 ` [PATCH 01/22] arm: break part of __soft_restart out into separate function Leif Lindholm
2014-02-05 17:03 ` [PATCH 02/22] arm: add new asm macro update_sctlr Leif Lindholm
[not found] ` <1391619853-10601-3-git-send-email-leif.lindholm-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2014-02-05 18:01 ` Will Deacon
2014-02-05 17:03 ` [PATCH 03/22] efi: add helper function to get UEFI params from FDT Leif Lindholm
[not found] ` <1391619853-10601-4-git-send-email-leif.lindholm-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2014-02-13 11:17 ` Matt Fleming
[not found] ` <20140213111637.GE20717-HNK1S37rvNbeXh+fF434Mdi2O/JbrIOy@public.gmane.org>
2014-02-13 14:56 ` Mark Salter
2014-02-05 17:03 ` [PATCH 04/22] efi-stub.txt updates for ARM Leif Lindholm
2014-02-05 17:03 ` [PATCH 05/22] Add shared printk wrapper for consistent prefixing Leif Lindholm
[not found] ` <1391619853-10601-6-git-send-email-leif.lindholm-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2014-02-05 17:34 ` Joe Perches
2014-02-05 17:03 ` [PATCH 06/22] Add helper functions used by arm/arm64 Leif Lindholm
[not found] ` <1391619853-10601-7-git-send-email-leif.lindholm-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2014-02-13 11:26 ` Matt Fleming
[not found] ` <20140213112606.GF20717-HNK1S37rvNbeXh+fF434Mdi2O/JbrIOy@public.gmane.org>
2014-02-14 19:02 ` Roy Franz
[not found] ` <CAFECyb_wUphr4XOyW9tC-Rw5Py3m39e6GQorCtFGtSXTUTBnFQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2014-03-03 14:08 ` Matt Fleming
[not found] ` <20140303140811.GA18828-HNK1S37rvNbeXh+fF434Mdi2O/JbrIOy@public.gmane.org>
2014-03-04 7:48 ` Roy Franz
2014-02-05 17:03 ` Leif Lindholm [this message]
2014-02-05 17:03 ` [PATCH 08/22] Add strstr to compressed string.c for ARM Leif Lindholm
[not found] ` <1391619853-10601-1-git-send-email-leif.lindholm-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2014-02-05 17:04 ` [PATCH 09/22] Add shared arm/arm64 EFI stub Leif Lindholm
2014-02-05 17:04 ` [PATCH 18/22] doc: arm64: add description of EFI stub support Leif Lindholm
2014-02-05 17:04 ` [PATCH 19/22] arm64: add EFI runtime services Leif Lindholm
2014-02-05 17:04 ` [PATCH 20/22] Improve cmdline conversion Leif Lindholm
2014-02-05 17:04 ` [PATCH 10/22] Add EFI stub for ARM Leif Lindholm
2014-02-05 17:04 ` [PATCH 11/22] Disable stack protection for decompressor/stub Leif Lindholm
2014-02-05 17:04 ` [PATCH 12/22] Documentation: arm: add UEFI support documentation Leif Lindholm
2014-02-05 17:04 ` [PATCH 13/22] arm: Add [U]EFI runtime services support Leif Lindholm
2014-02-05 17:04 ` [PATCH 14/22] init: efi: arm: enable (U)EFI runtime services on arm Leif Lindholm
2014-02-05 17:04 ` [PATCH 15/22] lib: add fdt_empty_tree.c Leif Lindholm
2014-02-05 17:04 ` [PATCH 16/22] arm64: Add function to create identity mappings Leif Lindholm
2014-02-14 17:42 ` Catalin Marinas
[not found] ` <20140214174256.GC12304-5wv7dgnIgG8@public.gmane.org>
2014-02-17 13:29 ` Mark Salter
2014-02-05 17:04 ` [PATCH 17/22] arm64: add EFI stub Leif Lindholm
2014-02-05 17:04 ` [PATCH 21/22] arm: efistub: ignore dtb= when UEFI SecureBoot is enabled Leif Lindholm
[not found] ` <1391619853-10601-22-git-send-email-leif.lindholm-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2014-02-05 18:09 ` Ard Biesheuvel
2014-02-05 17:04 ` [PATCH 22/22] arm: update boot/compressed/.gitignore Leif Lindholm
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1391619853-10601-8-git-send-email-leif.lindholm@linaro.org \
--to=leif.lindholm@linaro.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-efi@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=patches@linaro.org \
--cc=roy.franz@linaro.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).