<p>Patrick Rudolph has uploaded this change for <strong>review</strong>.</p><p><a href="https://review.coreboot.org/25019">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">[WIP]src/lib: Add uImage support<br><br>Add support for parsing and booting FIT uImage.<br>Copy loader code from depthcharge.<br>Add architecture code to boot a kernel on armv8.<br>Add payloadtype raw, as uImage is not executable.<br>Add Kconfig option to select image type:<br>* uImage<br>* bzImage<br><br>Tested on Cavium SoC: Parses and loads a kernel.<br><br>Change-Id: I0f27b92a5e074966f893399eb401eb97d784850d<br>Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com><br>---<br>M payloads/Kconfig<br>M payloads/external/Makefile.inc<br>M payloads/external/linux/Kconfig<br>M src/arch/arm64/boot.c<br>A src/include/device_tree.h<br>A src/include/fit.h<br>A src/include/list.h<br>A src/include/ranges.h<br>M src/include/string.h<br>M src/lib/Makefile.inc<br>A src/lib/device_tree.c<br>A src/lib/fit.c<br>A src/lib/list.c<br>M src/lib/prog_loaders.c<br>A src/lib/ranges.c<br>A src/lib/uImage.c<br>16 files changed, 2,459 insertions(+), 3 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://review.coreboot.org:29418/coreboot refs/changes/19/25019/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/payloads/Kconfig b/payloads/Kconfig</span><br><span>index 2a329ac..9e9a7cb 100644</span><br><span>--- a/payloads/Kconfig</span><br><span>+++ b/payloads/Kconfig</span><br><span>@@ -3,6 +3,9 @@</span><br><span> config NO_DEFAULT_PAYLOAD</span><br><span> bool</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+config PAYLOAD_TYPE_RAW</span><br><span style="color: hsl(120, 100%, 40%);">+ bool</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> choice</span><br><span> prompt "Add a payload"</span><br><span> default PAYLOAD_NONE if NO_DEFAULT_PAYLOAD || !ARCH_X86</span><br><span>diff --git a/payloads/external/Makefile.inc b/payloads/external/Makefile.inc</span><br><span>index ec7d9a8..e65d7e4 100644</span><br><span>--- a/payloads/external/Makefile.inc</span><br><span>+++ b/payloads/external/Makefile.inc</span><br><span>@@ -47,6 +47,8 @@</span><br><span> $(CONFIG_CBFS_PREFIX)/payload-file := $(CONFIG_PAYLOAD_FILE)</span><br><span> ifeq ($(CONFIG_PAYLOAD_IS_FLAT_BINARY),y)</span><br><span> $(CONFIG_CBFS_PREFIX)/payload-type := flat-binary</span><br><span style="color: hsl(120, 100%, 40%);">+else if ($(CONFIG_PAYLOAD_TYPE_RAW),y)</span><br><span style="color: hsl(120, 100%, 40%);">+$(CONFIG_CBFS_PREFIX)/payload-type := raw</span><br><span> else</span><br><span> $(CONFIG_CBFS_PREFIX)/payload-type := payload</span><br><span> endif</span><br><span>diff --git a/payloads/external/linux/Kconfig b/payloads/external/linux/Kconfig</span><br><span>index 8b15f99..13718a2 100644</span><br><span>--- a/payloads/external/linux/Kconfig</span><br><span>+++ b/payloads/external/linux/Kconfig</span><br><span>@@ -1,5 +1,23 @@</span><br><span> if PAYLOAD_LINUX</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+config PAYLOAD_SPECIFIC_OPTIONS # dummy</span><br><span style="color: hsl(120, 100%, 40%);">+ def_bool y</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+choice</span><br><span style="color: hsl(120, 100%, 40%);">+ prompt "Image type"</span><br><span style="color: hsl(120, 100%, 40%);">+ default PAYLOAD_LINUX_BZIMAGE if X86</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+config PAYLOAD_LINUX_BZIMAGE</span><br><span style="color: hsl(120, 100%, 40%);">+ bool "bzImage"</span><br><span style="color: hsl(120, 100%, 40%);">+ depends on ARCH_X86</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+config PAYLOAD_LINUX_UIMAGE</span><br><span style="color: hsl(120, 100%, 40%);">+ select PAYLOAD_TYPE_RAW</span><br><span style="color: hsl(120, 100%, 40%);">+ bool "uImage"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+endchoice</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> config PAYLOAD_FILE</span><br><span> string "Linux path and filename"</span><br><span> default "bzImage"</span><br><span>diff --git a/src/arch/arm64/boot.c b/src/arch/arm64/boot.c</span><br><span>index d498cd9..f49b66c 100644</span><br><span>--- a/src/arch/arm64/boot.c</span><br><span>+++ b/src/arch/arm64/boot.c</span><br><span>@@ -23,6 +23,13 @@</span><br><span> #include <program_loading.h></span><br><span> #include <rules.h></span><br><span> #include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <assert.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <console/console.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <boot/coreboot_tables.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <symbols.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define OVERLAPS(s,e,x) (((uintptr_t)_##x > (s) && (s) < (uintptr_t)_e##x) || \</span><br><span style="color: hsl(120, 100%, 40%);">+ ((uintptr_t)_##x > (e) && (e) < (uintptr_t)_e##x))</span><br><span> </span><br><span> static void run_payload(struct prog *prog)</span><br><span> {</span><br><span>@@ -82,3 +89,105 @@</span><br><span> {</span><br><span> main();</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int overlaps_coreboot(uintptr_t start, uintptr_t end)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return OVERLAPS(start, end, program) ||</span><br><span style="color: hsl(120, 100%, 40%);">+ OVERLAPS(start, end, stack) ||</span><br><span style="color: hsl(120, 100%, 40%);">+ OVERLAPS(start, end, ttb) ||</span><br><span style="color: hsl(120, 100%, 40%);">+ OVERLAPS(start, end, preram_cbfs_cache) ||</span><br><span style="color: hsl(120, 100%, 40%);">+ OVERLAPS(start, end, postram_cbfs_cache) ||</span><br><span style="color: hsl(120, 100%, 40%);">+ OVERLAPS(start, end, cbfs_cache);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct lb_memory *lb_memory(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct lb_header *head;</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct lb_record *rec;</span><br><span style="color: hsl(120, 100%, 40%);">+ size_t i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ head = cbmem_find(CBMEM_ID_CBTABLE);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!head)</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ i = head->table_entries;</span><br><span style="color: hsl(120, 100%, 40%);">+ rec = (struct lb_record *)(((uint8_t *)head) + head->header_bytes);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ while (i--) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rec->tag == LB_TAG_FORWARD) {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct lb_forward *forward = (struct lb_forward *)rec;</span><br><span style="color: hsl(120, 100%, 40%);">+ head = (void *)forward->forward;</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ rec = (struct lb_record *)(((uint8_t *)rec) + rec->size);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ i = head->table_entries;</span><br><span style="color: hsl(120, 100%, 40%);">+ rec = (struct lb_record *)(((uint8_t *)head) + head->header_bytes);</span><br><span style="color: hsl(120, 100%, 40%);">+ while (i--) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rec->tag == LB_TAG_MEMORY)</span><br><span style="color: hsl(120, 100%, 40%);">+ return (struct lb_memory *)rec;</span><br><span style="color: hsl(120, 100%, 40%);">+ rec = (struct lb_record *)(((uint8_t *)rec) + rec->size);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Override weak implementation for ARCH specific uImage load support.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Return kernel and fdt load address.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+size_t</span><br><span style="color: hsl(120, 100%, 40%);">+arch_get_kernel_fdt_load_addr(uint32_t load_offset,</span><br><span style="color: hsl(120, 100%, 40%);">+ size_t kernel_size,</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t fdt_size,</span><br><span style="color: hsl(120, 100%, 40%);">+ void **kernel_load_addr,</span><br><span style="color: hsl(120, 100%, 40%);">+ void **fdt_load_addr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct lb_memory *lb_mem = lb_memory();</span><br><span style="color: hsl(120, 100%, 40%);">+ size_t i, nentries;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ assert ((fdt_size > 0) && (fdt_size < 2 * MiB));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ nentries = (lb_mem->size - sizeof(*lb_mem)) / sizeof(lb_mem->map[0]);</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 0; i < nentries; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct lb_memory_range *range = &lb_mem->map[i];</span><br><span style="color: hsl(120, 100%, 40%);">+ uint64_t kstart, kend, fdtstart;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (range->type != LB_MEM_RAM)</span><br><span style="color: hsl(120, 100%, 40%);">+ continue;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ uint64_t start = unpack_lb64(range->start);</span><br><span style="color: hsl(120, 100%, 40%);">+ uint64_t end = start + unpack_lb64(range->size);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ do {</span><br><span style="color: hsl(120, 100%, 40%);">+ fdtstart = ALIGN_DOWN(start, 2*MiB) < start</span><br><span style="color: hsl(120, 100%, 40%);">+ ? ALIGN_UP(start, 2 * MiB)</span><br><span style="color: hsl(120, 100%, 40%);">+ : ALIGN_DOWN(start, 2 * MiB);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ kstart = fdtstart + load_offset;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (fdt_size > load_offset)</span><br><span style="color: hsl(120, 100%, 40%);">+ kstart += 2 * MiB;</span><br><span style="color: hsl(120, 100%, 40%);">+ kend = kstart + kernel_size;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!overlaps_coreboot(fdtstart, kend))</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ start += 2 * MiB;</span><br><span style="color: hsl(120, 100%, 40%);">+ } while (kend <= end);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (kend <= end) {</span><br><span style="color: hsl(120, 100%, 40%);">+ *fdt_load_addr = (void *)fdtstart;</span><br><span style="color: hsl(120, 100%, 40%);">+ *kernel_load_addr = (void *)kstart;</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ // Should be avoided in practice, that memory might be wasted.</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_WARNING,</span><br><span style="color: hsl(120, 100%, 40%);">+ "WARNING: Skipping low memory range [%p:%p]!\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ (void *)start, (void *)end);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_ERR,</span><br><span style="color: hsl(120, 100%, 40%);">+ "ERROR: Cannot find enough continuous memory for kernel!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/include/device_tree.h b/src/include/device_tree.h</span><br><span>new file mode 100644</span><br><span>index 0000000..03af77a</span><br><span>--- /dev/null</span><br><span>+++ b/src/include/device_tree.h</span><br><span>@@ -0,0 +1,219 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright 2013 Google Inc.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * See file CREDITS for list of people who contributed to this</span><br><span style="color: hsl(120, 100%, 40%);">+ * project.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or</span><br><span style="color: hsl(120, 100%, 40%);">+ * modify it under the terms of the GNU General Public License as</span><br><span style="color: hsl(120, 100%, 40%);">+ * published by the Free Software Foundation; either version 2 of</span><br><span style="color: hsl(120, 100%, 40%);">+ * the License, or (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but without any warranty; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef __BASE_DEVICE_TREE_H__</span><br><span style="color: hsl(120, 100%, 40%);">+#define __BASE_DEVICE_TREE_H__</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "list.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Flattened device tree structures/constants.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+typedef struct FdtHeader {</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t magic;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t totalsize;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t structure_offset;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t strings_offset;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t reserve_map_offset;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t version;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t last_compatible_version;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t boot_cpuid_phys;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t strings_size;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t structure_size;</span><br><span style="color: hsl(120, 100%, 40%);">+} FdtHeader;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static const uint32_t FdtMagic = 0xd00dfeed;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static const uint32_t TokenBeginNode = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+static const uint32_t TokenEndNode = 2;</span><br><span style="color: hsl(120, 100%, 40%);">+static const uint32_t TokenProperty = 3;</span><br><span style="color: hsl(120, 100%, 40%);">+static const uint32_t TokenEnd = 9;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+typedef struct FdtProperty</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *name;</span><br><span style="color: hsl(120, 100%, 40%);">+ void *data;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t size;</span><br><span style="color: hsl(120, 100%, 40%);">+} FdtProperty;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Unflattened device tree structures.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+typedef struct DeviceTreeProperty</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ FdtProperty prop;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ListNode list_node;</span><br><span style="color: hsl(120, 100%, 40%);">+} DeviceTreeProperty;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+typedef struct DeviceTreeNode</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *name;</span><br><span style="color: hsl(120, 100%, 40%);">+ // List of DeviceTreeProperty-s.</span><br><span style="color: hsl(120, 100%, 40%);">+ ListNode properties;</span><br><span style="color: hsl(120, 100%, 40%);">+ // List of DeviceTreeNodes.</span><br><span style="color: hsl(120, 100%, 40%);">+ ListNode children;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ListNode list_node;</span><br><span style="color: hsl(120, 100%, 40%);">+} DeviceTreeNode;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+typedef struct DeviceTreeReserveMapEntry</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ uint64_t start;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint64_t size;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ListNode list_node;</span><br><span style="color: hsl(120, 100%, 40%);">+} DeviceTreeReserveMapEntry;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+typedef struct DeviceTree</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ void *header;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t header_size;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ListNode reserve_map;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ DeviceTreeNode *root;</span><br><span style="color: hsl(120, 100%, 40%);">+} DeviceTree;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Flattened device tree functions. These generally return the number of bytes</span><br><span style="color: hsl(120, 100%, 40%);">+ * which were consumed reading the requested value.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+// Read the property, if any, at offset offset.</span><br><span style="color: hsl(120, 100%, 40%);">+int fdt_next_property(void *blob, uint32_t offset, FdtProperty *prop);</span><br><span style="color: hsl(120, 100%, 40%);">+// Read the name of the node, if any, at offset offset.</span><br><span style="color: hsl(120, 100%, 40%);">+int fdt_node_name(void *blob, uint32_t offset, const char **name);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void fdt_print_node(void *blob, uint32_t offset);</span><br><span style="color: hsl(120, 100%, 40%);">+int fdt_skip_node(void *blob, uint32_t offset);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+// Read a flattened device tree into a heirarchical structure which refers to</span><br><span style="color: hsl(120, 100%, 40%);">+// the contents of the flattened tree in place. Modifying the flat tree</span><br><span style="color: hsl(120, 100%, 40%);">+// invalidates the unflattened one.</span><br><span style="color: hsl(120, 100%, 40%);">+DeviceTree *fdt_unflatten(void *blob);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Unflattened device tree functions.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+// Figure out how big a device tree would be if it were flattened.</span><br><span style="color: hsl(120, 100%, 40%);">+uint32_t dt_flat_size(DeviceTree *tree);</span><br><span style="color: hsl(120, 100%, 40%);">+// Flatten a device tree into the buffer pointed to by dest.</span><br><span style="color: hsl(120, 100%, 40%);">+void dt_flatten(DeviceTree *tree, void *dest);</span><br><span style="color: hsl(120, 100%, 40%);">+void dt_print_node(DeviceTreeNode *node);</span><br><span style="color: hsl(120, 100%, 40%);">+// Read #address-cells and #size-cells properties from a node.</span><br><span style="color: hsl(120, 100%, 40%);">+void dt_read_cell_props(DeviceTreeNode *node, u32 *addrcp, u32 *sizecp);</span><br><span style="color: hsl(120, 100%, 40%);">+// Look up or create a node relative to a parent node, through its path</span><br><span style="color: hsl(120, 100%, 40%);">+// represented as an array of strings.</span><br><span style="color: hsl(120, 100%, 40%);">+DeviceTreeNode *dt_find_node(DeviceTreeNode *parent, const char **path,</span><br><span style="color: hsl(120, 100%, 40%);">+ u32 *addrcp, u32 *sizecp, int create);</span><br><span style="color: hsl(120, 100%, 40%);">+// Look up or create a node relative to a parent node, through its path</span><br><span style="color: hsl(120, 100%, 40%);">+// represented as a string of '/' separated node names.</span><br><span style="color: hsl(120, 100%, 40%);">+DeviceTreeNode *dt_find_node_by_path(DeviceTreeNode *parent, const char *path,</span><br><span style="color: hsl(120, 100%, 40%);">+ u32 *addrcp, u32 *sizecp, int create);</span><br><span style="color: hsl(120, 100%, 40%);">+// Look up a node relative to a parent node, through its compatible string.</span><br><span style="color: hsl(120, 100%, 40%);">+DeviceTreeNode *dt_find_compat(DeviceTreeNode *parent, const char *compatible);</span><br><span style="color: hsl(120, 100%, 40%);">+// Look up the next child of a parent node, through its compatible string. It</span><br><span style="color: hsl(120, 100%, 40%);">+// uses child pointer as the marker to find next.</span><br><span style="color: hsl(120, 100%, 40%);">+DeviceTreeNode *dt_find_next_compat_child(DeviceTreeNode *parent,</span><br><span style="color: hsl(120, 100%, 40%);">+ DeviceTreeNode *child,</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *compat);</span><br><span style="color: hsl(120, 100%, 40%);">+// Look up a node relative to a parent node, through its property value.</span><br><span style="color: hsl(120, 100%, 40%);">+DeviceTreeNode *dt_find_prop_value(DeviceTreeNode *parent, const char *name,</span><br><span style="color: hsl(120, 100%, 40%);">+ void *data, size_t size);</span><br><span style="color: hsl(120, 100%, 40%);">+// Write src into *dest as a 'length'-byte big-endian integer.</span><br><span style="color: hsl(120, 100%, 40%);">+void dt_write_int(u8 *dest, u64 src, size_t length);</span><br><span style="color: hsl(120, 100%, 40%);">+// Add different kinds of properties to a node, or update existing ones.</span><br><span style="color: hsl(120, 100%, 40%);">+void dt_add_bin_prop(DeviceTreeNode *node, char *name, void *data, size_t size);</span><br><span style="color: hsl(120, 100%, 40%);">+void dt_add_string_prop(DeviceTreeNode *node, char *name, char *str);</span><br><span style="color: hsl(120, 100%, 40%);">+void dt_add_u32_prop(DeviceTreeNode *node, char *name, u32 val);</span><br><span style="color: hsl(120, 100%, 40%);">+void dt_add_reg_prop(DeviceTreeNode *node, u64 *addrs, u64 *sizes,</span><br><span style="color: hsl(120, 100%, 40%);">+ int count, u32 addr_cells, u32 size_cells);</span><br><span style="color: hsl(120, 100%, 40%);">+int dt_set_bin_prop_by_path(DeviceTree *tree, const char *path,</span><br><span style="color: hsl(120, 100%, 40%);">+ void *data, size_t size, int create);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void dt_find_bin_prop(DeviceTreeNode *node, const char *name, void **data,</span><br><span style="color: hsl(120, 100%, 40%);">+ size_t *size);</span><br><span style="color: hsl(120, 100%, 40%);">+const char *dt_find_string_prop(DeviceTreeNode *node, const char *name);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Fixups to apply to a kernel's device tree before booting it.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+typedef struct DeviceTreeFixup</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ // The function which does the fixing.</span><br><span style="color: hsl(120, 100%, 40%);">+ int (*fixup)(struct DeviceTreeFixup *fixup, DeviceTree *tree);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ListNode list_node;</span><br><span style="color: hsl(120, 100%, 40%);">+} DeviceTreeFixup;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+extern ListNode device_tree_fixups;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int dt_apply_fixups(DeviceTree *tree);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Structure defining mapping between arbitrary objects and the device tree</span><br><span style="color: hsl(120, 100%, 40%);">+ * path to the property corresponding to the object.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+typedef struct {</span><br><span style="color: hsl(120, 100%, 40%);">+ int force_create; /* If false - do not create a new node. */</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *dt_path;</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *key;</span><br><span style="color: hsl(120, 100%, 40%);">+} DtPathMap;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copy mac addresses from sysinfo table into the device tree. The mapping</span><br><span style="color: hsl(120, 100%, 40%);">+ * between the dt_maps entries and sysinfo mac address table elements is</span><br><span style="color: hsl(120, 100%, 40%);">+ * implicit, i.e. the device tree node found in the maps entry, gets assinged</span><br><span style="color: hsl(120, 100%, 40%);">+ * the mac address found in the sysinfo table, in the same order.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int dt_set_mac_addresses(DeviceTree *tree, const DtPathMap *dt_maps);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copy WIFI calibration data from sysinfo table into the device tree. Each</span><br><span style="color: hsl(120, 100%, 40%);">+ * WIFI calibration blob stored the sysinfo table contains key and data. The</span><br><span style="color: hsl(120, 100%, 40%);">+ * key is used for mapping into the device tree path. The data becomes the</span><br><span style="color: hsl(120, 100%, 40%);">+ * contents of the device tree property at that path.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int dt_set_wifi_calibration(DeviceTree *tree, const DtPathMap *maps);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Retrieve Country Code data from VPD and add it into the device tree.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int dt_set_wifi_country_code(DeviceTree *tree, const DtPathMap *maps);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Init/retrieve the /reserved-memory/ node.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+DeviceTreeNode *dt_init_reserved_memory_node(DeviceTree *tree);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#endif /* __BASE_DEVICE_TREE_H__ */</span><br><span>diff --git a/src/include/fit.h b/src/include/fit.h</span><br><span>new file mode 100644</span><br><span>index 0000000..22939be</span><br><span>--- /dev/null</span><br><span>+++ b/src/include/fit.h</span><br><span>@@ -0,0 +1,78 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright 2013 Google Inc.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * See file CREDITS for list of people who contributed to this</span><br><span style="color: hsl(120, 100%, 40%);">+ * project.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or</span><br><span style="color: hsl(120, 100%, 40%);">+ * modify it under the terms of the GNU General Public License as</span><br><span style="color: hsl(120, 100%, 40%);">+ * published by the Free Software Foundation; either version 2 of</span><br><span style="color: hsl(120, 100%, 40%);">+ * the License, or (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but without any warranty; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef __BOOT_FIT_H__</span><br><span style="color: hsl(120, 100%, 40%);">+#define __BOOT_FIT_H__</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <stddef.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "device_tree.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "list.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct FitImageNode</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *name;</span><br><span style="color: hsl(120, 100%, 40%);">+ void *data;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t size;</span><br><span style="color: hsl(120, 100%, 40%);">+ int compression;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ListNode list_node;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct FitConfigNode</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *name;</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *kernel;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct FitImageNode *kernel_node;</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *fdt;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct FitImageNode *fdt_node;</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *ramdisk;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct FitImageNode *ramdisk_node;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct FdtProperty compat;</span><br><span style="color: hsl(120, 100%, 40%);">+ int compat_rank;</span><br><span style="color: hsl(120, 100%, 40%);">+ int compat_pos;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ListNode list_node;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Weak function to get the list of compat names.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Has to be implemented on every board, that wants to use uImage FIT.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void</span><br><span style="color: hsl(120, 100%, 40%);">+fit_get_compats_strings(char *fit_kernel_compat[10],</span><br><span style="color: hsl(120, 100%, 40%);">+ int *num_fit_kernel_compat);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Unpack a FIT image into memory, choosing the right configuration through the</span><br><span style="color: hsl(120, 100%, 40%);">+ * compatible string set by fit_add_compat() and unflattening the corresponding</span><br><span style="color: hsl(120, 100%, 40%);">+ * kernel device tree.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct FitImageNode *fit_load(void *fit, struct DeviceTree **dt);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Add a compatible string for the preferred kernel DT to the list for this</span><br><span style="color: hsl(120, 100%, 40%);">+ * platform. This should be called before the first fit_load() so it will be</span><br><span style="color: hsl(120, 100%, 40%);">+ * ranked as a better match than the default compatible strings. |compat| must</span><br><span style="color: hsl(120, 100%, 40%);">+ * stay accessible throughout depthcharge's runtime (i.e. not stack-allocated)!</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void fit_add_compat(const char *compat);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void fit_add_ramdisk(struct DeviceTree *tree, void *ramdisk_addr, size_t ramdisk_size);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#endif /* __BOOT_FIT_H__ */</span><br><span>diff --git a/src/include/list.h b/src/include/list.h</span><br><span>new file mode 100644</span><br><span>index 0000000..a541ce5</span><br><span>--- /dev/null</span><br><span>+++ b/src/include/list.h</span><br><span>@@ -0,0 +1,44 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright 2012 Google Inc.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * See file CREDITS for list of people who contributed to this</span><br><span style="color: hsl(120, 100%, 40%);">+ * project.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or</span><br><span style="color: hsl(120, 100%, 40%);">+ * modify it under the terms of the GNU General Public License as</span><br><span style="color: hsl(120, 100%, 40%);">+ * published by the Free Software Foundation; either version 2 of</span><br><span style="color: hsl(120, 100%, 40%);">+ * the License, or (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but without any warranty; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef __BASE_LIST_H__</span><br><span style="color: hsl(120, 100%, 40%);">+#define __BASE_LIST_H__</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <stddef.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+//#include "container_of.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+typedef struct ListNode {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ListNode *next;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ListNode *prev;</span><br><span style="color: hsl(120, 100%, 40%);">+} ListNode;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+// Remove ListNode node from the doubly linked list it's a part of.</span><br><span style="color: hsl(120, 100%, 40%);">+void list_remove(ListNode *node);</span><br><span style="color: hsl(120, 100%, 40%);">+// Insert ListNode node after ListNode after in a doubly linked list.</span><br><span style="color: hsl(120, 100%, 40%);">+void list_insert_after(ListNode *node, ListNode *after);</span><br><span style="color: hsl(120, 100%, 40%);">+// Insert ListNode node before ListNode before in a doubly linked list.</span><br><span style="color: hsl(120, 100%, 40%);">+void list_insert_before(ListNode *node, ListNode *before);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define list_for_each(ptr, head, member) \</span><br><span style="color: hsl(120, 100%, 40%);">+ for ((ptr) = container_of((head).next, typeof(*(ptr)), member); \</span><br><span style="color: hsl(120, 100%, 40%);">+ &((ptr)->member); \</span><br><span style="color: hsl(120, 100%, 40%);">+ (ptr) = container_of((ptr)->member.next, \</span><br><span style="color: hsl(120, 100%, 40%);">+ typeof(*(ptr)), member))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#endif /* __BASE_LIST_H__ */</span><br><span>diff --git a/src/include/ranges.h b/src/include/ranges.h</span><br><span>new file mode 100644</span><br><span>index 0000000..87b427d</span><br><span>--- /dev/null</span><br><span>+++ b/src/include/ranges.h</span><br><span>@@ -0,0 +1,79 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright 2012 Google Inc.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * See file CREDITS for list of people who contributed to this</span><br><span style="color: hsl(120, 100%, 40%);">+ * project.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or</span><br><span style="color: hsl(120, 100%, 40%);">+ * modify it under the terms of the GNU General Public License as</span><br><span style="color: hsl(120, 100%, 40%);">+ * published by the Free Software Foundation; either version 2 of</span><br><span style="color: hsl(120, 100%, 40%);">+ * the License, or (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but without any warranty; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef __BASE_RANGES_H__</span><br><span style="color: hsl(120, 100%, 40%);">+#define __BASE_RANGES_H__</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* A node in a linked list of edges, each at position "pos". */</span><br><span style="color: hsl(120, 100%, 40%);">+typedef struct RangesEdge {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct RangesEdge *next;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint64_t pos;</span><br><span style="color: hsl(120, 100%, 40%);">+} RangesEdge;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Data describing ranges. Contains a linked list of edges between the ranges</span><br><span style="color: hsl(120, 100%, 40%);">+ * and the empty space between them.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+typedef struct Ranges {</span><br><span style="color: hsl(120, 100%, 40%);">+ RangesEdge head;</span><br><span style="color: hsl(120, 100%, 40%);">+} Ranges;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Initializes the Ranges structure.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param ranges Ranges structure to initialize.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void ranges_init(Ranges *ranges);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Free memory associated with a Ranges structure, not including the structure</span><br><span style="color: hsl(120, 100%, 40%);">+ * itself.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param ranges Ranges structure to tear down.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void ranges_teardown(Ranges *ranges);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Adds a range to a collection of ranges.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param ranges Ranges structure to add the range to.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param start The start of the range.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param end The end of the range.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void ranges_add(Ranges *ranges, uint64_t start, uint64_t end);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Subtracts a range.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param ranges Ranges structure to subtract the range from.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param start The start of the region.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param end The end of the region.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void ranges_sub(Ranges *ranges, uint64_t start, uint64_t end);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+typedef void (*RangesForEachFunc)(uint64_t start, uint64_t end, void *data);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Runs a function on each range in Ranges.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param ranges Ranges structure to iterate over.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void ranges_for_each(Ranges *ranges, RangesForEachFunc func, void *data);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#endif /* __BASE_RANGES_H__ */</span><br><span>diff --git a/src/include/string.h b/src/include/string.h</span><br><span>index 7597323..2dd73a0 100644</span><br><span>--- a/src/include/string.h</span><br><span>+++ b/src/include/string.h</span><br><span>@@ -66,6 +66,26 @@</span><br><span> }</span><br><span> #endif</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * Find a character in a string.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param s The string.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param c The character.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @return A pointer to the last occurence of the character in the</span><br><span style="color: hsl(120, 100%, 40%);">+ * string, or NULL if the character was not encountered within the string.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static inline char *strrchr(const char *s, int c)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ char *p = (char *)s + strlen(s);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ for (; p >= s; p--) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (*p == c)</span><br><span style="color: hsl(120, 100%, 40%);">+ return p;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static inline char *strncpy(char *to, const char *from, int count)</span><br><span> {</span><br><span> register char *ret = to;</span><br><span>diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc</span><br><span>index 3ddf017..0bcef59 100644</span><br><span>--- a/src/lib/Makefile.inc</span><br><span>+++ b/src/lib/Makefile.inc</span><br><span>@@ -135,6 +135,13 @@</span><br><span> ramstage-y += b64_decode.c</span><br><span> ramstage-$(CONFIG_ACPI_NHLT) += nhlt.c</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ramstage-y += list.c</span><br><span style="color: hsl(120, 100%, 40%);">+ramstage-y += ranges.c</span><br><span style="color: hsl(120, 100%, 40%);">+ramstage-$(CONFIG_PAYLOAD_LINUX_UIMAGE) += device_tree.c</span><br><span style="color: hsl(120, 100%, 40%);">+ramstage-$(CONFIG_PAYLOAD_LINUX_UIMAGE) += fit.c</span><br><span style="color: hsl(120, 100%, 40%);">+ramstage-$(CONFIG_PAYLOAD_LINUX_UIMAGE) += uImage.c</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> romstage-y += cbmem_common.c</span><br><span> romstage-y += imd_cbmem.c</span><br><span> romstage-y += imd.c</span><br><span>diff --git a/src/lib/device_tree.c b/src/lib/device_tree.c</span><br><span>new file mode 100644</span><br><span>index 0000000..246d0f3</span><br><span>--- /dev/null</span><br><span>+++ b/src/lib/device_tree.c</span><br><span>@@ -0,0 +1,954 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright 2013 Google Inc.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * See file CREDITS for list of people who contributed to this</span><br><span style="color: hsl(120, 100%, 40%);">+ * project.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or</span><br><span style="color: hsl(120, 100%, 40%);">+ * modify it under the terms of the GNU General Public License as</span><br><span style="color: hsl(120, 100%, 40%);">+ * published by the Free Software Foundation; either version 2 of</span><br><span style="color: hsl(120, 100%, 40%);">+ * the License, or (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but without any warranty; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <assert.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <endian.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <console/console.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <endian.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stddef.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdlib.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "device_tree.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Functions for picking apart flattened trees.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static uint32_t size32(uint32_t val)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return (val + sizeof(uint32_t) - 1) / sizeof(uint32_t);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int fdt_next_property(void *blob, uint32_t offset, FdtProperty *prop)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ FdtHeader *header = (FdtHeader *)blob;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t *ptr = (uint32_t *)(((uint8_t *)blob) + offset);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ int index = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (be32toh(ptr[index++]) != TokenProperty)</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t size = be32toh(ptr[index++]);</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t name_offset = be32toh(ptr[index++]);</span><br><span style="color: hsl(120, 100%, 40%);">+ name_offset += be32toh(header->strings_offset);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (prop) {</span><br><span style="color: hsl(120, 100%, 40%);">+ prop->name = (char *)((uint8_t *)blob + name_offset);</span><br><span style="color: hsl(120, 100%, 40%);">+ prop->data = &ptr[index];</span><br><span style="color: hsl(120, 100%, 40%);">+ prop->size = size;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ index += size32(size);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return index * 4;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int fdt_node_name(void *blob, uint32_t offset, const char **name)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t *ptr = ((uint8_t *)blob) + offset;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (be32toh(*(uint32_t *)ptr) != TokenBeginNode)</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ptr += 4;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (name)</span><br><span style="color: hsl(120, 100%, 40%);">+ *name = (char *)ptr;</span><br><span style="color: hsl(120, 100%, 40%);">+ return size32(strlen((char *)ptr) + 1) * sizeof(uint32_t) + 4;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Functions for printing flattened trees.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void print_indent(int depth)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ while (depth--)</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_DEBUG, " ");</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void print_property(FdtProperty *prop, int depth)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ print_indent(depth);</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_DEBUG, "prop \"%s\" (%d bytes).\n", prop->name, prop->size);</span><br><span style="color: hsl(120, 100%, 40%);">+ print_indent(depth + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+ for (int i = 0; i < MIN(25, prop->size); i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_DEBUG, "%02x ", ((uint8_t *)prop->data)[i]);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (prop->size > 25)</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_DEBUG, "...");</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_DEBUG, "\n");</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int print_flat_node(void *blob, uint32_t start_offset, int depth)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int offset = start_offset;</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *name;</span><br><span style="color: hsl(120, 100%, 40%);">+ int size;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ size = fdt_node_name(blob, offset, &name);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!size)</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ offset += size;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ print_indent(depth);</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_DEBUG, "name = %s\n", name);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ FdtProperty prop;</span><br><span style="color: hsl(120, 100%, 40%);">+ while ((size = fdt_next_property(blob, offset, &prop))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ print_property(&prop, depth + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ offset += size;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ while ((size = print_flat_node(blob, offset, depth + 1)))</span><br><span style="color: hsl(120, 100%, 40%);">+ offset += size;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return offset - start_offset + sizeof(uint32_t);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void fdt_print_node(void *blob, uint32_t offset)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ print_flat_node(blob, offset, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * A utility function to skip past nodes in flattened trees.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int fdt_skip_node(void *blob, uint32_t start_offset)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int offset = start_offset;</span><br><span style="color: hsl(120, 100%, 40%);">+ int size;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *name;</span><br><span style="color: hsl(120, 100%, 40%);">+ size = fdt_node_name(blob, offset, &name);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!size)</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ offset += size;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ while ((size = fdt_next_property(blob, offset, NULL)))</span><br><span style="color: hsl(120, 100%, 40%);">+ offset += size;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ while ((size = fdt_skip_node(blob, offset)))</span><br><span style="color: hsl(120, 100%, 40%);">+ offset += size;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return offset - start_offset + sizeof(uint32_t);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Functions to turn a flattened tree into an unflattened one.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static DeviceTreeNode node_cache[1000];</span><br><span style="color: hsl(120, 100%, 40%);">+static int node_counter = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+static DeviceTreeProperty prop_cache[5000];</span><br><span style="color: hsl(120, 100%, 40%);">+static int prop_counter = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Libpayload's malloc() has linear allocation complexity and goes completely</span><br><span style="color: hsl(120, 100%, 40%);">+ * mental after a few thousand small requests. This little hack will absorb</span><br><span style="color: hsl(120, 100%, 40%);">+ * the worst of it to avoid increasing boot time for no reason.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static DeviceTreeNode *alloc_node(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (node_counter >= ARRAY_SIZE(node_cache)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ DeviceTreeNode *buf = malloc(sizeof(DeviceTreeNode));</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!buf)</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ memset(buf, 0, sizeof(*buf));</span><br><span style="color: hsl(120, 100%, 40%);">+ return buf;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ return &node_cache[node_counter++];</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static DeviceTreeProperty *alloc_prop(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (prop_counter >= ARRAY_SIZE(prop_cache)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ DeviceTreeProperty *buf = malloc(sizeof(DeviceTreeProperty));</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!buf)</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ memset(buf, 0, sizeof(*buf));</span><br><span style="color: hsl(120, 100%, 40%);">+ return buf;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ return &prop_cache[prop_counter++];</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int fdt_unflatten_node(void *blob, uint32_t start_offset,</span><br><span style="color: hsl(120, 100%, 40%);">+ DeviceTreeNode **new_node)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ ListNode *last;</span><br><span style="color: hsl(120, 100%, 40%);">+ int offset = start_offset;</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *name;</span><br><span style="color: hsl(120, 100%, 40%);">+ int size;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ size = fdt_node_name(blob, offset, &name);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!size)</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ offset += size;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ DeviceTreeNode *node = alloc_node();</span><br><span style="color: hsl(120, 100%, 40%);">+ *new_node = node;</span><br><span style="color: hsl(120, 100%, 40%);">+ node->name = name;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ FdtProperty fprop;</span><br><span style="color: hsl(120, 100%, 40%);">+ last = &node->properties;</span><br><span style="color: hsl(120, 100%, 40%);">+ while ((size = fdt_next_property(blob, offset, &fprop))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ DeviceTreeProperty *prop = alloc_prop();</span><br><span style="color: hsl(120, 100%, 40%);">+ prop->prop = fprop;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ list_insert_after(&prop->list_node, last);</span><br><span style="color: hsl(120, 100%, 40%);">+ last = &prop->list_node;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ offset += size;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ DeviceTreeNode *child;</span><br><span style="color: hsl(120, 100%, 40%);">+ last = &node->children;</span><br><span style="color: hsl(120, 100%, 40%);">+ while ((size = fdt_unflatten_node(blob, offset, &child))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ list_insert_after(&child->list_node, last);</span><br><span style="color: hsl(120, 100%, 40%);">+ last = &child->list_node;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ offset += size;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return offset - start_offset + sizeof(uint32_t);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int fdt_unflatten_map_entry(void *blob, uint32_t offset,</span><br><span style="color: hsl(120, 100%, 40%);">+ DeviceTreeReserveMapEntry **new_entry)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ uint64_t *ptr = (uint64_t *)(((uint8_t *)blob) + offset);</span><br><span style="color: hsl(120, 100%, 40%);">+ uint64_t start = be64toh(ptr[0]);</span><br><span style="color: hsl(120, 100%, 40%);">+ uint64_t size = be64toh(ptr[1]);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!size)</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ DeviceTreeReserveMapEntry *entry = malloc(sizeof(*entry));</span><br><span style="color: hsl(120, 100%, 40%);">+ memset(entry, 0, sizeof(*entry));</span><br><span style="color: hsl(120, 100%, 40%);">+ *new_entry = entry;</span><br><span style="color: hsl(120, 100%, 40%);">+ entry->start = start;</span><br><span style="color: hsl(120, 100%, 40%);">+ entry->size = size;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return sizeof(uint64_t) * 2;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+DeviceTree *fdt_unflatten(void *blob)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ DeviceTree *tree = malloc(sizeof(*tree));</span><br><span style="color: hsl(120, 100%, 40%);">+ FdtHeader *header = (FdtHeader *)blob;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ memset(tree, 0, sizeof(*tree));</span><br><span style="color: hsl(120, 100%, 40%);">+ tree->header = header;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t struct_offset = be32toh(header->structure_offset);</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t strings_offset = be32toh(header->strings_offset);</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t reserve_offset = be32toh(header->reserve_map_offset);</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t min_offset = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ min_offset = MIN(struct_offset, strings_offset);</span><br><span style="color: hsl(120, 100%, 40%);">+ min_offset = MIN(min_offset, reserve_offset);</span><br><span style="color: hsl(120, 100%, 40%);">+ // Assume everything up to the first non-header component is part of</span><br><span style="color: hsl(120, 100%, 40%);">+ // the header and needs to be preserved. This will protect us against</span><br><span style="color: hsl(120, 100%, 40%);">+ // new elements being added in the future.</span><br><span style="color: hsl(120, 100%, 40%);">+ tree->header_size = min_offset;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ DeviceTreeReserveMapEntry *entry;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t offset = reserve_offset;</span><br><span style="color: hsl(120, 100%, 40%);">+ int size;</span><br><span style="color: hsl(120, 100%, 40%);">+ ListNode *last = &tree->reserve_map;</span><br><span style="color: hsl(120, 100%, 40%);">+ while ((size = fdt_unflatten_map_entry(blob, offset, &entry))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ list_insert_after(&entry->list_node, last);</span><br><span style="color: hsl(120, 100%, 40%);">+ last = &entry->list_node;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ offset += size;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ fdt_unflatten_node(blob, struct_offset, &tree->root);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return tree;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Functions to find the size of device tree would take if it was flattened.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void dt_flat_prop_size(DeviceTreeProperty *prop, uint32_t *struct_size,</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t *strings_size)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ // Starting token.</span><br><span style="color: hsl(120, 100%, 40%);">+ *struct_size += sizeof(uint32_t);</span><br><span style="color: hsl(120, 100%, 40%);">+ // Size.</span><br><span style="color: hsl(120, 100%, 40%);">+ *struct_size += sizeof(uint32_t);</span><br><span style="color: hsl(120, 100%, 40%);">+ // Name offset.</span><br><span style="color: hsl(120, 100%, 40%);">+ *struct_size += sizeof(uint32_t);</span><br><span style="color: hsl(120, 100%, 40%);">+ // Property value.</span><br><span style="color: hsl(120, 100%, 40%);">+ *struct_size += size32(prop->prop.size) * sizeof(uint32_t);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ // Property name.</span><br><span style="color: hsl(120, 100%, 40%);">+ *strings_size += strlen(prop->prop.name) + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void dt_flat_node_size(DeviceTreeNode *node, uint32_t *struct_size,</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t *strings_size)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ // Starting token.</span><br><span style="color: hsl(120, 100%, 40%);">+ *struct_size += sizeof(uint32_t);</span><br><span style="color: hsl(120, 100%, 40%);">+ // Node name.</span><br><span style="color: hsl(120, 100%, 40%);">+ *struct_size += size32(strlen(node->name) + 1) * sizeof(uint32_t);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ DeviceTreeProperty *prop;</span><br><span style="color: hsl(120, 100%, 40%);">+ list_for_each(prop, node->properties, list_node)</span><br><span style="color: hsl(120, 100%, 40%);">+ dt_flat_prop_size(prop, struct_size, strings_size);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ DeviceTreeNode *child;</span><br><span style="color: hsl(120, 100%, 40%);">+ list_for_each(child, node->children, list_node)</span><br><span style="color: hsl(120, 100%, 40%);">+ dt_flat_node_size(child, struct_size, strings_size);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ // End token.</span><br><span style="color: hsl(120, 100%, 40%);">+ *struct_size += sizeof(uint32_t);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+uint32_t dt_flat_size(DeviceTree *tree)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t size = tree->header_size;</span><br><span style="color: hsl(120, 100%, 40%);">+ DeviceTreeReserveMapEntry *entry;</span><br><span style="color: hsl(120, 100%, 40%);">+ list_for_each(entry, tree->reserve_map, list_node)</span><br><span style="color: hsl(120, 100%, 40%);">+ size += sizeof(uint64_t) * 2;</span><br><span style="color: hsl(120, 100%, 40%);">+ size += sizeof(uint64_t) * 2;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t struct_size = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t strings_size = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ dt_flat_node_size(tree->root, &struct_size, &strings_size);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ size += struct_size;</span><br><span style="color: hsl(120, 100%, 40%);">+ // End token.</span><br><span style="color: hsl(120, 100%, 40%);">+ size += sizeof(uint32_t);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ size += strings_size;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return size;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Functions to flatten a device tree.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void dt_flatten_map_entry(DeviceTreeReserveMapEntry *entry,</span><br><span style="color: hsl(120, 100%, 40%);">+ void **map_start)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ ((uint64_t *)*map_start)[0] = htobe64(entry->start);</span><br><span style="color: hsl(120, 100%, 40%);">+ ((uint64_t *)*map_start)[1] = htobe64(entry->size);</span><br><span style="color: hsl(120, 100%, 40%);">+ *map_start = ((uint8_t *)*map_start) + sizeof(uint64_t) * 2;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void dt_flatten_prop(DeviceTreeProperty *prop, void **struct_start,</span><br><span style="color: hsl(120, 100%, 40%);">+ void *strings_base, void **strings_start)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t *dstruct = (uint8_t *)*struct_start;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t *dstrings = (uint8_t *)*strings_start;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ *((uint32_t *)dstruct) = htobe32(TokenProperty);</span><br><span style="color: hsl(120, 100%, 40%);">+ dstruct += sizeof(uint32_t);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ *((uint32_t *)dstruct) = htobe32(prop->prop.size);</span><br><span style="color: hsl(120, 100%, 40%);">+ dstruct += sizeof(uint32_t);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t name_offset = (uintptr_t)dstrings - (uintptr_t)strings_base;</span><br><span style="color: hsl(120, 100%, 40%);">+ *((uint32_t *)dstruct) = htobe32(name_offset);</span><br><span style="color: hsl(120, 100%, 40%);">+ dstruct += sizeof(uint32_t);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ strcpy((char *)dstrings, prop->prop.name);</span><br><span style="color: hsl(120, 100%, 40%);">+ dstrings += strlen(prop->prop.name) + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ memcpy(dstruct, prop->prop.data, prop->prop.size);</span><br><span style="color: hsl(120, 100%, 40%);">+ dstruct += size32(prop->prop.size) * 4;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ *struct_start = dstruct;</span><br><span style="color: hsl(120, 100%, 40%);">+ *strings_start = dstrings;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void dt_flatten_node(DeviceTreeNode *node, void **struct_start,</span><br><span style="color: hsl(120, 100%, 40%);">+ void *strings_base, void **strings_start)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t *dstruct = (uint8_t *)*struct_start;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t *dstrings = (uint8_t *)*strings_start;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ *((uint32_t *)dstruct) = htobe32(TokenBeginNode);</span><br><span style="color: hsl(120, 100%, 40%);">+ dstruct += sizeof(uint32_t);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ strcpy((char *)dstruct, node->name);</span><br><span style="color: hsl(120, 100%, 40%);">+ dstruct += size32(strlen(node->name) + 1) * 4;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ DeviceTreeProperty *prop;</span><br><span style="color: hsl(120, 100%, 40%);">+ list_for_each(prop, node->properties, list_node)</span><br><span style="color: hsl(120, 100%, 40%);">+ dt_flatten_prop(prop, (void **)&dstruct, strings_base,</span><br><span style="color: hsl(120, 100%, 40%);">+ (void **)&dstrings);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ DeviceTreeNode *child;</span><br><span style="color: hsl(120, 100%, 40%);">+ list_for_each(child, node->children, list_node)</span><br><span style="color: hsl(120, 100%, 40%);">+ dt_flatten_node(child, (void **)&dstruct, strings_base,</span><br><span style="color: hsl(120, 100%, 40%);">+ (void **)&dstrings);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ *((uint32_t *)dstruct) = htobe32(TokenEndNode);</span><br><span style="color: hsl(120, 100%, 40%);">+ dstruct += sizeof(uint32_t);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ *struct_start = dstruct;</span><br><span style="color: hsl(120, 100%, 40%);">+ *strings_start = dstrings;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void dt_flatten(DeviceTree *tree, void *start_dest)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t *dest = (uint8_t *)start_dest;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ memcpy(dest, tree->header, tree->header_size);</span><br><span style="color: hsl(120, 100%, 40%);">+ FdtHeader *header = (FdtHeader *)dest;</span><br><span style="color: hsl(120, 100%, 40%);">+ dest += tree->header_size;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ DeviceTreeReserveMapEntry *entry;</span><br><span style="color: hsl(120, 100%, 40%);">+ list_for_each(entry, tree->reserve_map, list_node)</span><br><span style="color: hsl(120, 100%, 40%);">+ dt_flatten_map_entry(entry, (void **)&dest);</span><br><span style="color: hsl(120, 100%, 40%);">+ ((uint64_t *)dest)[0] = ((uint64_t *)dest)[1] = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ dest += sizeof(uint64_t) * 2;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t struct_size = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t strings_size = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ dt_flat_node_size(tree->root, &struct_size, &strings_size);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t *struct_start = dest;</span><br><span style="color: hsl(120, 100%, 40%);">+ header->structure_offset = htobe32(dest - (uint8_t *)start_dest);</span><br><span style="color: hsl(120, 100%, 40%);">+ header->structure_size = htobe32(struct_size);</span><br><span style="color: hsl(120, 100%, 40%);">+ dest += struct_size;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ *((uint32_t *)dest) = htobe32(TokenEnd);</span><br><span style="color: hsl(120, 100%, 40%);">+ dest += sizeof(uint32_t);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t *strings_start = dest;</span><br><span style="color: hsl(120, 100%, 40%);">+ header->strings_offset = htobe32(dest - (uint8_t *)start_dest);</span><br><span style="color: hsl(120, 100%, 40%);">+ header->strings_size = htobe32(strings_size);</span><br><span style="color: hsl(120, 100%, 40%);">+ dest += strings_size;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ dt_flatten_node(tree->root, (void **)&struct_start, strings_start,</span><br><span style="color: hsl(120, 100%, 40%);">+ (void **)&strings_start);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ header->totalsize = htobe32(dest - (uint8_t *)start_dest);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Functions for printing a non-flattened device tree.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void print_node(DeviceTreeNode *node, int depth)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ print_indent(depth);</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_DEBUG, "name = %s\n", node->name);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ DeviceTreeProperty *prop;</span><br><span style="color: hsl(120, 100%, 40%);">+ list_for_each(prop, node->properties, list_node)</span><br><span style="color: hsl(120, 100%, 40%);">+ print_property(&prop->prop, depth + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ DeviceTreeNode *child;</span><br><span style="color: hsl(120, 100%, 40%);">+ list_for_each(child, node->children, list_node)</span><br><span style="color: hsl(120, 100%, 40%);">+ print_node(child, depth + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void dt_print_node(DeviceTreeNode *node)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ print_node(node, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Functions for reading and manipulating an unflattened device tree.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Read #address-cells and #size-cells properties from a node.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param node The device tree node to read from.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param addrcp Pointer to store #address-cells in, skipped if NULL.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param sizecp Pointer to store #size-cells in, skipped if NULL.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void dt_read_cell_props(DeviceTreeNode *node, u32 *addrcp, u32 *sizecp)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ DeviceTreeProperty *prop;</span><br><span style="color: hsl(120, 100%, 40%);">+ list_for_each(prop, node->properties, list_node) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (addrcp && !strcmp("#address-cells", prop->prop.name))</span><br><span style="color: hsl(120, 100%, 40%);">+ *addrcp = be32toh(*(u32 *)prop->prop.data);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (sizecp && !strcmp("#size-cells", prop->prop.name))</span><br><span style="color: hsl(120, 100%, 40%);">+ *sizecp = be32toh(*(u32 *)prop->prop.data);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Find a node from a device tree path, relative to a parent node.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param parent The node from which to start the relative path lookup.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param path An array of path component strings that will be looked</span><br><span style="color: hsl(120, 100%, 40%);">+ * up in order to find the node. Must be terminated with</span><br><span style="color: hsl(120, 100%, 40%);">+ * a NULL pointer. Example: {'firmware', 'coreboot', NULL}</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param addrcp Pointer that will be updated with any #address-cells</span><br><span style="color: hsl(120, 100%, 40%);">+ * value found in the path. May be NULL to ignore.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param sizecp Pointer that will be updated with any #size-cells</span><br><span style="color: hsl(120, 100%, 40%);">+ * value found in the path. May be NULL to ignore.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param create 1: Create node(s) if not found. 0: Return NULL instead.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @return The found/created node, or NULL.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+DeviceTreeNode *dt_find_node(DeviceTreeNode *parent, const char **path,</span><br><span style="color: hsl(120, 100%, 40%);">+ u32 *addrcp, u32 *sizecp, int create)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ DeviceTreeNode *node, *found = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ // Update #address-cells and #size-cells for this level.</span><br><span style="color: hsl(120, 100%, 40%);">+ dt_read_cell_props(parent, addrcp, sizecp);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!*path)</span><br><span style="color: hsl(120, 100%, 40%);">+ return parent;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ // Find the next node in the path, if it exists.</span><br><span style="color: hsl(120, 100%, 40%);">+ list_for_each(node, parent->children, list_node) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!strcmp(node->name, *path)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ found = node;</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ // Otherwise create it or return NULL.</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!found) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!create)</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ found = alloc_node();</span><br><span style="color: hsl(120, 100%, 40%);">+ found->name = strdup(*path);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!found->name)</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ list_insert_after(&found->list_node, &parent->children);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return dt_find_node(found, path + 1, addrcp, sizecp, create);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Find a node from a string device tree path, relative to a parent node.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param parent The node from which to start the relative path lookup.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param path A string representing a path in the device tree, with</span><br><span style="color: hsl(120, 100%, 40%);">+ * nodes separated by '/'. Example: "soc/firmware/coreboot"</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param addrcp Pointer that will be updated with any #address-cells</span><br><span style="color: hsl(120, 100%, 40%);">+ * value found in the path. May be NULL to ignore.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param sizecp Pointer that will be updated with any #size-cells</span><br><span style="color: hsl(120, 100%, 40%);">+ * value found in the path. May be NULL to ignore.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param create 1: Create node(s) if not found. 0: Return NULL instead.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @return The found/created node, or NULL.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * It is the caller responsibility to provide the correct path string, namely</span><br><span style="color: hsl(120, 100%, 40%);">+ * not starting or ending with a '/', and not having "//" anywhere in it.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+DeviceTreeNode *dt_find_node_by_path(DeviceTreeNode *parent, const char *path,</span><br><span style="color: hsl(120, 100%, 40%);">+ u32 *addrcp, u32 *sizecp, int create)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ char *dup_path = strdup(path);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Hopefully enough depth for any node. */</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *path_array[15];</span><br><span style="color: hsl(120, 100%, 40%);">+ int i;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *next_slash;</span><br><span style="color: hsl(120, 100%, 40%);">+ DeviceTreeNode *node = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!dup_path)</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ next_slash = dup_path;</span><br><span style="color: hsl(120, 100%, 40%);">+ path_array[0] = dup_path;</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 1; i < (ARRAY_SIZE(path_array) - 1); i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ next_slash = strchr(next_slash, '/');</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!next_slash)</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ *next_slash++ = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+ path_array[i] = next_slash;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!next_slash) {</span><br><span style="color: hsl(120, 100%, 40%);">+ path_array[i] = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ node = dt_find_node(parent, path_array,</span><br><span style="color: hsl(120, 100%, 40%);">+ addrcp, sizecp, create);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ free(dup_path);</span><br><span style="color: hsl(120, 100%, 40%);">+ return node;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Check if given node is compatible.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param node The node which is to be checked for compatible property.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param compat The compatible string to match.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @return 1 = compatible, 0 = not compatible.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static int dt_check_compat_match(DeviceTreeNode *node, const char *compat)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ DeviceTreeProperty *prop;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ list_for_each(prop, node->properties, list_node) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!strcmp("compatible", prop->prop.name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ size_t bytes = prop->prop.size;</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *str = prop->prop.data;</span><br><span style="color: hsl(120, 100%, 40%);">+ while (bytes > 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!strncmp(compat, str, bytes))</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ size_t len = strnlen(str, bytes) + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (bytes <= len)</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ str += len;</span><br><span style="color: hsl(120, 100%, 40%);">+ bytes -= len;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Find a node from a compatible string, in the subtree of a parent node.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param parent The parent node under which to look.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param compat The compatible string to find.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @return The found node, or NULL.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+DeviceTreeNode *dt_find_compat(DeviceTreeNode *parent, const char *compat)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ // Check if the parent node itself is compatible.</span><br><span style="color: hsl(120, 100%, 40%);">+ if (dt_check_compat_match(parent, compat))</span><br><span style="color: hsl(120, 100%, 40%);">+ return parent;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ DeviceTreeNode *child;</span><br><span style="color: hsl(120, 100%, 40%);">+ list_for_each(child, parent->children, list_node) {</span><br><span style="color: hsl(120, 100%, 40%);">+ DeviceTreeNode *found = dt_find_compat(child, compat);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (found)</span><br><span style="color: hsl(120, 100%, 40%);">+ return found;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Find the next compatible child of a given parent. All children upto the</span><br><span style="color: hsl(120, 100%, 40%);">+ * child passed in by caller are ignored. If child is NULL, it considers all the</span><br><span style="color: hsl(120, 100%, 40%);">+ * children to find the first child which is compatible.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param parent The parent node under which to look.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param child The child node to start search from (exclusive). If NULL</span><br><span style="color: hsl(120, 100%, 40%);">+ * consider all children.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param compat The compatible string to find.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @return The found node, or NULL.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+DeviceTreeNode *dt_find_next_compat_child(DeviceTreeNode *parent,</span><br><span style="color: hsl(120, 100%, 40%);">+ DeviceTreeNode *child,</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *compat)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ DeviceTreeNode *next;</span><br><span style="color: hsl(120, 100%, 40%);">+ int ignore = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (child)</span><br><span style="color: hsl(120, 100%, 40%);">+ ignore = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ list_for_each(next, parent->children, list_node) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ignore) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (child == next)</span><br><span style="color: hsl(120, 100%, 40%);">+ ignore = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ continue;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (dt_check_compat_match(next, compat))</span><br><span style="color: hsl(120, 100%, 40%);">+ return next;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Find a node with matching property value, in the subtree of a parent node.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param parent The parent node under which to look.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param name The property name to look for.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param data The property value to look for.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param size The property size.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+DeviceTreeNode *dt_find_prop_value(DeviceTreeNode *parent, const char *name,</span><br><span style="color: hsl(120, 100%, 40%);">+ void *data, size_t size)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ DeviceTreeProperty *prop;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Check if parent itself has the required property value. */</span><br><span style="color: hsl(120, 100%, 40%);">+ list_for_each(prop, parent->properties, list_node) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!strcmp(name, prop->prop.name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ size_t bytes = prop->prop.size;</span><br><span style="color: hsl(120, 100%, 40%);">+ void *prop_data = prop->prop.data;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (size != bytes)</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!memcmp(data, prop_data, size))</span><br><span style="color: hsl(120, 100%, 40%);">+ return parent;</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ DeviceTreeNode *child;</span><br><span style="color: hsl(120, 100%, 40%);">+ list_for_each(child, parent->children, list_node) {</span><br><span style="color: hsl(120, 100%, 40%);">+ DeviceTreeNode *found = dt_find_prop_value(child, name, data,</span><br><span style="color: hsl(120, 100%, 40%);">+ size);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (found)</span><br><span style="color: hsl(120, 100%, 40%);">+ return found;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Write an arbitrary sized big-endian integer into a pointer.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param dest Pointer to the DT property data buffer to write.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param src The integer to write (in CPU endianess).</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param length the length of the destination integer in bytes.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void dt_write_int(u8 *dest, u64 src, size_t length)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ while (length--) {</span><br><span style="color: hsl(120, 100%, 40%);">+ dest[length] = (u8)src;</span><br><span style="color: hsl(120, 100%, 40%);">+ src >>= 8;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Add an arbitrary property to a node, or update it if it already exists.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param node The device tree node to add to.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param name The name of the new property.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param data The raw data blob to be stored in the property.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param size The size of data in bytes.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void dt_add_bin_prop(DeviceTreeNode *node, char *name, void *data, size_t size)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ DeviceTreeProperty *prop;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ list_for_each(prop, node->properties, list_node) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!strcmp(prop->prop.name, name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ prop->prop.data = data;</span><br><span style="color: hsl(120, 100%, 40%);">+ prop->prop.size = size;</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ prop = alloc_prop();</span><br><span style="color: hsl(120, 100%, 40%);">+ list_insert_after(&prop->list_node, &node->properties);</span><br><span style="color: hsl(120, 100%, 40%);">+ prop->prop.name = name;</span><br><span style="color: hsl(120, 100%, 40%);">+ prop->prop.data = data;</span><br><span style="color: hsl(120, 100%, 40%);">+ prop->prop.size = size;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Find given string property in a node and return its content.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param node The device tree node to search.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param name The name of the property.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @return The found string, or NULL.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+const char *dt_find_string_prop(DeviceTreeNode *node, const char *name)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ void *content;</span><br><span style="color: hsl(120, 100%, 40%);">+ size_t size;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ dt_find_bin_prop(node, name, &content, &size);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return content;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Find given property in a node.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param node The device tree node to search.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param name The name of the property.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param data Pointer to return raw data blob in the property.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param size Pointer to return the size of data in bytes.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void dt_find_bin_prop(DeviceTreeNode *node, const char *name, void **data,</span><br><span style="color: hsl(120, 100%, 40%);">+ size_t *size)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ DeviceTreeProperty *prop;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ *data = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ *size = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ list_for_each(prop, node->properties, list_node) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!strcmp(prop->prop.name, name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ *data = prop->prop.data;</span><br><span style="color: hsl(120, 100%, 40%);">+ *size = prop->prop.size;</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Add a string property to a node, or update it if it already exists.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param node The device tree node to add to.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param name The name of the new property.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param str The zero-terminated string to be stored in the property.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void dt_add_string_prop(DeviceTreeNode *node, char *name, char *str)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ dt_add_bin_prop(node, name, str, strlen(str) + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Add a 32-bit integer property to a node, or update it if it already exists.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param node The device tree node to add to.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param name The name of the new property.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param val The integer to be stored in the property.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void dt_add_u32_prop(DeviceTreeNode *node, char *name, u32 val)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ u32 *val_ptr = malloc(sizeof(val));</span><br><span style="color: hsl(120, 100%, 40%);">+ *val_ptr = htobe32(val);</span><br><span style="color: hsl(120, 100%, 40%);">+ dt_add_bin_prop(node, name, val_ptr, sizeof(*val_ptr));</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Add a 'reg' address list property to a node, or update it if it exists.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param node The device tree node to add to.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param addrs Array of address values to be stored in the property.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param sizes Array of corresponding size values to 'addrs'.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param count Number of values in 'addrs' and 'sizes' (must be equal).</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param addr_cells Value of #address-cells property valid for this node.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param size_cells Value of #size-cells property valid for this node.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void dt_add_reg_prop(DeviceTreeNode *node, u64 *addrs, u64 *sizes,</span><br><span style="color: hsl(120, 100%, 40%);">+ int count, u32 addr_cells, u32 size_cells)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int i;</span><br><span style="color: hsl(120, 100%, 40%);">+ size_t length = (addr_cells + size_cells) * sizeof(u32) * count;</span><br><span style="color: hsl(120, 100%, 40%);">+ u8 *data = malloc(length);</span><br><span style="color: hsl(120, 100%, 40%);">+ u8 *cur = data;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 0; i < count; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ dt_write_int(cur, addrs[i], addr_cells * sizeof(u32));</span><br><span style="color: hsl(120, 100%, 40%);">+ cur += addr_cells * sizeof(u32);</span><br><span style="color: hsl(120, 100%, 40%);">+ dt_write_int(cur, sizes[i], size_cells * sizeof(u32));</span><br><span style="color: hsl(120, 100%, 40%);">+ cur += size_cells * sizeof(u32);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ dt_add_bin_prop(node, "reg", data, length);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Fixups to apply to a kernel's device tree before booting it.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ListNode device_tree_fixups;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int dt_apply_fixups(DeviceTree *tree)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ DeviceTreeFixup *fixup;</span><br><span style="color: hsl(120, 100%, 40%);">+ list_for_each(fixup, device_tree_fixups, list_node) {</span><br><span style="color: hsl(120, 100%, 40%);">+ assert(fixup->fixup);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (fixup->fixup(fixup, tree))</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int dt_set_bin_prop_by_path(DeviceTree *tree, const char *path,</span><br><span style="color: hsl(120, 100%, 40%);">+ void *data, size_t data_size, int create)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ char *path_copy, *prop_name;</span><br><span style="color: hsl(120, 100%, 40%);">+ DeviceTreeNode *dt_node;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ path_copy = strdup(path);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!path_copy) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_ERR, "Failed to allocate a copy of path %s\n", path);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ prop_name = strrchr(path_copy, '/');</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!prop_name) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_ERR, "Path %s does not include '/'\n", path);</span><br><span style="color: hsl(120, 100%, 40%);">+ free(path_copy);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ *prop_name++ = '\0'; /* Separate path from the property name. */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ dt_node = dt_find_node_by_path(tree->root, path_copy, NULL,</span><br><span style="color: hsl(120, 100%, 40%);">+ NULL, create);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!dt_node) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_ERR, "Failed to %s %s in the device tree\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ create ? "create" : "find", path_copy);</span><br><span style="color: hsl(120, 100%, 40%);">+ free(path_copy);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ dt_add_bin_prop(dt_node, prop_name, data, data_size);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Prepare the /reserved-memory/ node.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Technically, this can be called more than one time, to init and/or retrieve</span><br><span style="color: hsl(120, 100%, 40%);">+ * the node. But dt_add_u32_prop() may leak a bit of memory if you do.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @tree: Device tree to add/retrieve from.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @return: The /reserved-memory/ node (or NULL, if error).</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+DeviceTreeNode *dt_init_reserved_memory_node(DeviceTree *tree)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ DeviceTreeNode *reserved;</span><br><span style="color: hsl(120, 100%, 40%);">+ u32 addr = 0, size = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ reserved = dt_find_node_by_path(tree->root, "reserved-memory", &addr,</span><br><span style="color: hsl(120, 100%, 40%);">+ &size, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!reserved)</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ // Binding doc says this should have the same #{address,size}-cells as</span><br><span style="color: hsl(120, 100%, 40%);">+ // the root.</span><br><span style="color: hsl(120, 100%, 40%);">+ dt_add_u32_prop(reserved, "#address-cells", addr);</span><br><span style="color: hsl(120, 100%, 40%);">+ dt_add_u32_prop(reserved, "#size-cells", size);</span><br><span style="color: hsl(120, 100%, 40%);">+ // Binding doc says this should be empty (i.e., 1:1 mapping from root).</span><br><span style="color: hsl(120, 100%, 40%);">+ dt_add_bin_prop(reserved, "ranges", NULL, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return reserved;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/lib/fit.c b/src/lib/fit.c</span><br><span>new file mode 100644</span><br><span>index 0000000..9d8dee5</span><br><span>--- /dev/null</span><br><span>+++ b/src/lib/fit.c</span><br><span>@@ -0,0 +1,529 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright 2013 Google Inc.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * See file CREDITS for list of people who contributed to this</span><br><span style="color: hsl(120, 100%, 40%);">+ * project.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or</span><br><span style="color: hsl(120, 100%, 40%);">+ * modify it under the terms of the GNU General Public License as</span><br><span style="color: hsl(120, 100%, 40%);">+ * published by the Free Software Foundation; either version 2 of</span><br><span style="color: hsl(120, 100%, 40%);">+ * the License, or (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <assert.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <endian.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <cbmem.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <boot/coreboot_tables.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdlib.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <cbfs.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <program_loading.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <timestamp.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <ranges.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <fit.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static ListNode image_nodes;</span><br><span style="color: hsl(120, 100%, 40%);">+static ListNode config_nodes;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+__attribute__((weak)) void</span><br><span style="color: hsl(120, 100%, 40%);">+fit_get_compats_strings(char *fit_kernel_compat[10], int *num_fit_kernel_compat)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ *num_fit_kernel_compat = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void image_node(struct DeviceTreeNode *node)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct FitImageNode *image = malloc(sizeof(*image));</span><br><span style="color: hsl(120, 100%, 40%);">+ memset(image, 0, sizeof(*image));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ image->compression = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ image->name = node->name;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ struct DeviceTreeProperty *prop;</span><br><span style="color: hsl(120, 100%, 40%);">+ list_for_each(prop, node->properties, list_node) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!strcmp("data", prop->prop.name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ image->data = prop->prop.data;</span><br><span style="color: hsl(120, 100%, 40%);">+ image->size = prop->prop.size;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (!strcmp("compression", prop->prop.name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!strcmp("none", prop->prop.data))</span><br><span style="color: hsl(120, 100%, 40%);">+ image->compression = CBFS_COMPRESS_NONE;</span><br><span style="color: hsl(120, 100%, 40%);">+ else if (!strcmp("lzma", prop->prop.data))</span><br><span style="color: hsl(120, 100%, 40%);">+ image->compression = CBFS_COMPRESS_LZMA;</span><br><span style="color: hsl(120, 100%, 40%);">+ else if (!strcmp("lz4", prop->prop.data))</span><br><span style="color: hsl(120, 100%, 40%);">+ image->compression = CBFS_COMPRESS_LZ4;</span><br><span style="color: hsl(120, 100%, 40%);">+ else</span><br><span style="color: hsl(120, 100%, 40%);">+ image->compression = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ list_insert_after(&image->list_node, &image_nodes);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void config_node(struct DeviceTreeNode *node)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct FitConfigNode *config = malloc(sizeof(*config));</span><br><span style="color: hsl(120, 100%, 40%);">+ memset(config, 0, sizeof(*config));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ config->name = node->name;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ struct DeviceTreeProperty *prop;</span><br><span style="color: hsl(120, 100%, 40%);">+ list_for_each(prop, node->properties, list_node) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!strcmp("kernel", prop->prop.name))</span><br><span style="color: hsl(120, 100%, 40%);">+ config->kernel = prop->prop.data;</span><br><span style="color: hsl(120, 100%, 40%);">+ else if (!strcmp("fdt", prop->prop.name))</span><br><span style="color: hsl(120, 100%, 40%);">+ config->fdt = prop->prop.data;</span><br><span style="color: hsl(120, 100%, 40%);">+ else if (!strcmp("ramdisk", prop->prop.name))</span><br><span style="color: hsl(120, 100%, 40%);">+ config->ramdisk = prop->prop.data;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ list_insert_after(&config->list_node, &config_nodes);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void fit_unpack(struct DeviceTree *tree, const char **default_config)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ assert(tree && tree->root);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ struct DeviceTreeNode *top;</span><br><span style="color: hsl(120, 100%, 40%);">+ list_for_each(top, tree->root->children, list_node) {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct DeviceTreeNode *child;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!strcmp("images", top->name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ list_for_each(child, top->children, list_node)</span><br><span style="color: hsl(120, 100%, 40%);">+ image_node(child);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (!strcmp("configurations", top->name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ struct DeviceTreeProperty *prop;</span><br><span style="color: hsl(120, 100%, 40%);">+ list_for_each(prop, top->properties, list_node) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!strcmp("default", prop->prop.name) &&</span><br><span style="color: hsl(120, 100%, 40%);">+ default_config)</span><br><span style="color: hsl(120, 100%, 40%);">+ *default_config = prop->prop.data;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ list_for_each(child, top->children, list_node)</span><br><span style="color: hsl(120, 100%, 40%);">+ config_node(child);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct FitImageNode *find_image(const char *name)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct FitImageNode *image;</span><br><span style="color: hsl(120, 100%, 40%);">+ list_for_each(image, image_nodes, list_node) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!strcmp(image->name, name))</span><br><span style="color: hsl(120, 100%, 40%);">+ return image;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int fdt_find_compat(void *blob, uint32_t start_offset, struct FdtProperty *prop)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int offset = start_offset;</span><br><span style="color: hsl(120, 100%, 40%);">+ int size;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ size = fdt_node_name(blob, offset, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!size)</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ offset += size;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ while ((size = fdt_next_property(blob, offset, prop))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!strcmp("compatible", prop->name))</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ offset += size;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ prop->name = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int fit_check_compat(struct FdtProperty *compat_prop, const char *compat_name)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int bytes = compat_prop->size;</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *compat_str = compat_prop->data;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ for (int pos = 0; bytes && compat_str[0]; pos++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!strncmp(compat_str, compat_name, bytes))</span><br><span style="color: hsl(120, 100%, 40%);">+ return pos;</span><br><span style="color: hsl(120, 100%, 40%);">+ int len = strlen(compat_str) + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ compat_str += len;</span><br><span style="color: hsl(120, 100%, 40%);">+ bytes -= len;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void update_chosen(struct DeviceTree *tree, char *cmd_line)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *path[] = { "chosen", NULL };</span><br><span style="color: hsl(120, 100%, 40%);">+ struct DeviceTreeNode *node = dt_find_node(tree->root, path, NULL, NULL, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ dt_add_string_prop(node, "bootargs", cmd_line);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void fit_add_ramdisk(struct DeviceTree *tree, void *ramdisk_addr, size_t ramdisk_size)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *path[] = { "chosen", NULL };</span><br><span style="color: hsl(120, 100%, 40%);">+ struct DeviceTreeNode *node = dt_find_node(tree->root, path, NULL, NULL, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Warning: this assumes the ramdisk is currently located below 4GiB. */</span><br><span style="color: hsl(120, 100%, 40%);">+ u32 start = (uintptr_t)ramdisk_addr;</span><br><span style="color: hsl(120, 100%, 40%);">+ u32 end = start + ramdisk_size;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ dt_add_u32_prop(node, "linux,initrd-start", start);</span><br><span style="color: hsl(120, 100%, 40%);">+ dt_add_u32_prop(node, "linux,initrd-end", end);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void update_reserve_map(uint64_t start, uint64_t end, void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ DeviceTree *tree = (DeviceTree *)data;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ DeviceTreeReserveMapEntry *entry = malloc(sizeof(*entry));</span><br><span style="color: hsl(120, 100%, 40%);">+ memset(entry, 0, sizeof(*entry));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ entry->start = start;</span><br><span style="color: hsl(120, 100%, 40%);">+ entry->size = end - start;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ list_insert_after(&entry->list_node, &tree->reserve_map);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+typedef struct EntryParams</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned addr_cells;</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned size_cells;</span><br><span style="color: hsl(120, 100%, 40%);">+ void *data;</span><br><span style="color: hsl(120, 100%, 40%);">+} EntryParams;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static uint64_t max_range(unsigned size_cells)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ // Split up ranges who's sizes are too large to fit in #size-cells.</span><br><span style="color: hsl(120, 100%, 40%);">+ // The largest value we can store isn't a power of two, so we'll round</span><br><span style="color: hsl(120, 100%, 40%);">+ // down to make the math easier.</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0x1ULL << (size_cells * 32 - 1);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void count_entries(u64 start, u64 end, void *pdata)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ EntryParams *params = (EntryParams *)pdata;</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned *count = (unsigned *)params->data;</span><br><span style="color: hsl(120, 100%, 40%);">+ u64 size = end - start;</span><br><span style="color: hsl(120, 100%, 40%);">+ u64 max_size = max_range(params->size_cells);</span><br><span style="color: hsl(120, 100%, 40%);">+ *count += ALIGN_UP(size, max_size) / max_size;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void update_mem_property(u64 start, u64 end, void *pdata)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ EntryParams *params = (EntryParams *)pdata;</span><br><span style="color: hsl(120, 100%, 40%);">+ u8 *data = (u8 *)params->data;</span><br><span style="color: hsl(120, 100%, 40%);">+ u64 full_size = end - start;</span><br><span style="color: hsl(120, 100%, 40%);">+ while (full_size) {</span><br><span style="color: hsl(120, 100%, 40%);">+ const u64 max_size = max_range(params->size_cells);</span><br><span style="color: hsl(120, 100%, 40%);">+ const u64 size = MIN(max_size, full_size);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ dt_write_int(data, start, params->addr_cells * sizeof(u32));</span><br><span style="color: hsl(120, 100%, 40%);">+ data += params->addr_cells * sizeof(uint32_t);</span><br><span style="color: hsl(120, 100%, 40%);">+ start += size;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ dt_write_int(data, size, params->size_cells * sizeof(u32));</span><br><span style="color: hsl(120, 100%, 40%);">+ data += params->size_cells * sizeof(uint32_t);</span><br><span style="color: hsl(120, 100%, 40%);">+ full_size -= size;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ params->data = data;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct lb_memory *lb_memory(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct lb_header *head;</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct lb_record *rec;</span><br><span style="color: hsl(120, 100%, 40%);">+ size_t i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ head = cbmem_find(CBMEM_ID_CBTABLE);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!head)</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ i = head->table_entries;</span><br><span style="color: hsl(120, 100%, 40%);">+ rec = (struct lb_record *)(((uint8_t *)head) + head->header_bytes);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ while (i--) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rec->tag == LB_TAG_FORWARD) {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct lb_forward *forward = (struct lb_forward *)rec;</span><br><span style="color: hsl(120, 100%, 40%);">+ head = (void *)forward->forward;</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ rec = (struct lb_record *)(((uint8_t *)rec) + rec->size);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ i = head->table_entries;</span><br><span style="color: hsl(120, 100%, 40%);">+ rec = (struct lb_record *)(((uint8_t *)head) + head->header_bytes);</span><br><span style="color: hsl(120, 100%, 40%);">+ while (i--) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rec->tag == LB_TAG_MEMORY)</span><br><span style="color: hsl(120, 100%, 40%);">+ return (struct lb_memory *)rec;</span><br><span style="color: hsl(120, 100%, 40%);">+ rec = (struct lb_record *)(((uint8_t *)rec) + rec->size);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void update_memory(struct DeviceTree *tree)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct lb_memory *lb_mem;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct Ranges mem;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct Ranges reserved;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct DeviceTreeNode *node;</span><br><span style="color: hsl(120, 100%, 40%);">+ u32 addr_cells = 1, size_cells = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ size_t nentries;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_INFO, "Updating devicetree memory entries\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ dt_read_cell_props(tree->root, &addr_cells, &size_cells);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ // First remove all existing device_type="memory" nodes, then add ours.</span><br><span style="color: hsl(120, 100%, 40%);">+ list_for_each(node, tree->root->children, list_node) {</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *devtype = dt_find_string_prop(node, "device_type");</span><br><span style="color: hsl(120, 100%, 40%);">+ if (devtype && !strcmp(devtype, "memory"))</span><br><span style="color: hsl(120, 100%, 40%);">+ list_remove(&node->list_node);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ node = malloc(sizeof(*node));</span><br><span style="color: hsl(120, 100%, 40%);">+ memset(node, 0, sizeof(*node));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ node->name = "memory";</span><br><span style="color: hsl(120, 100%, 40%);">+ list_insert_after(&node->list_node, &tree->root->children);</span><br><span style="color: hsl(120, 100%, 40%);">+ dt_add_string_prop(node, "device_type", "memory");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ // Read memory info from coreboot (ranges are merged automatically).</span><br><span style="color: hsl(120, 100%, 40%);">+ ranges_init(&mem);</span><br><span style="color: hsl(120, 100%, 40%);">+ ranges_init(&reserved);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define MEMORY_ALIGNMENT (1 << 20)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ lb_mem = lb_memory();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (lb_mem)</span><br><span style="color: hsl(120, 100%, 40%);">+ nentries =</span><br><span style="color: hsl(120, 100%, 40%);">+ (lb_mem->size - sizeof(*lb_mem)) / sizeof(lb_mem->map[0]);</span><br><span style="color: hsl(120, 100%, 40%);">+ else</span><br><span style="color: hsl(120, 100%, 40%);">+ nentries = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ for (int i = 0; i < nentries; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct lb_memory_range *range = &lb_mem->map[i];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ uint64_t start = unpack_lb64(range->start);</span><br><span style="color: hsl(120, 100%, 40%);">+ uint64_t end = start + unpack_lb64(range->size);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Kernel likes its availabe memory areas at least 1MB</span><br><span style="color: hsl(120, 100%, 40%);">+ * aligned, let's trim the regions such that unaligned padding</span><br><span style="color: hsl(120, 100%, 40%);">+ * is added to reserved memory.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (range->type == LB_MEM_RAM) {</span><br><span style="color: hsl(120, 100%, 40%);">+ uint64_t new_start = ALIGN_UP(start, MEMORY_ALIGNMENT);</span><br><span style="color: hsl(120, 100%, 40%);">+ uint64_t new_end = ALIGN_DOWN(end, MEMORY_ALIGNMENT);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (new_start != start)</span><br><span style="color: hsl(120, 100%, 40%);">+ ranges_add(&reserved, start, new_start);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (new_start != new_end)</span><br><span style="color: hsl(120, 100%, 40%);">+ ranges_add(&mem, new_start, new_end);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (new_end != end)</span><br><span style="color: hsl(120, 100%, 40%);">+ ranges_add(&reserved, new_end, end);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ ranges_add(&reserved, start, end);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ // CBMEM regions are both carved out and explicitly reserved.</span><br><span style="color: hsl(120, 100%, 40%);">+ ranges_for_each(&reserved, &update_reserve_map, tree);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ // Count the amount of 'reg' entries we need (account for size limits).</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned count = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ EntryParams count_params = { addr_cells, size_cells, &count };</span><br><span style="color: hsl(120, 100%, 40%);">+ ranges_for_each(&mem, &count_entries, &count_params);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ // Allocate the right amount of space and fill up the entries.</span><br><span style="color: hsl(120, 100%, 40%);">+ size_t length = count * (addr_cells + size_cells) * sizeof(u32);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ void *data = malloc(length);</span><br><span style="color: hsl(120, 100%, 40%);">+ memset(data, 0, length);</span><br><span style="color: hsl(120, 100%, 40%);">+ EntryParams add_params = { addr_cells, size_cells, data };</span><br><span style="color: hsl(120, 100%, 40%);">+ ranges_for_each(&mem, &update_mem_property, &add_params);</span><br><span style="color: hsl(120, 100%, 40%);">+ assert(add_params.data - data == length);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ // Assemble the final property and add it to the device tree.</span><br><span style="color: hsl(120, 100%, 40%);">+ dt_add_bin_prop(node, "reg", data, length);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct FitImageNode *fit_load(void *fit, struct DeviceTree **dt)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct FdtHeader *header = (struct FdtHeader *)fit;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct FitImageNode *image;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct FitConfigNode *config;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *fit_kernel_compat[10] = { NULL };</span><br><span style="color: hsl(120, 100%, 40%);">+ int num_fit_kernel_compat = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_DEBUG, "Loading FIT.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (be32toh(header->magic) != FdtMagic) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_ERR, "Bad FIT header magic value 0x%08x.\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ be32toh(header->magic));</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_DEBUG, "Found FIT\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_DEBUG, " totalsize : %u\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ be32toh(header->totalsize));</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_DEBUG, " version : %u\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ be32toh(header->version));</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_DEBUG, " structure_size : %u\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ be32toh(header->structure_size));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ struct DeviceTree *tree = fdt_unflatten(fit);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *default_config_name = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct FitConfigNode *default_config = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct FitConfigNode *compat_config = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ fit_unpack(tree, &default_config_name);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ // List the images we found.</span><br><span style="color: hsl(120, 100%, 40%);">+ list_for_each(image, image_nodes, list_node)</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_DEBUG, "Image %s has %d bytes.\n", image->name,</span><br><span style="color: hsl(120, 100%, 40%);">+ image->size);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ fit_get_compats_strings(fit_kernel_compat, &num_fit_kernel_compat);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_DEBUG, "Compat preference:");</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 0; i < num_fit_kernel_compat; i++)</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_DEBUG, " %s", fit_kernel_compat[i]);</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_DEBUG, "\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ // Process and list the configs.</span><br><span style="color: hsl(120, 100%, 40%);">+ list_for_each(config, config_nodes, list_node) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (config->kernel)</span><br><span style="color: hsl(120, 100%, 40%);">+ config->kernel_node = find_image(config->kernel);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (config->fdt)</span><br><span style="color: hsl(120, 100%, 40%);">+ config->fdt_node = find_image(config->fdt);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (config->ramdisk)</span><br><span style="color: hsl(120, 100%, 40%);">+ config->ramdisk_node = find_image(config->ramdisk);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (config->ramdisk_node &&</span><br><span style="color: hsl(120, 100%, 40%);">+ config->ramdisk_node->compression < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_DEBUG, "Ramdisk compression not supported, "</span><br><span style="color: hsl(120, 100%, 40%);">+ "discarding config %s.\n", config->name);</span><br><span style="color: hsl(120, 100%, 40%);">+ list_remove(&config->list_node);</span><br><span style="color: hsl(120, 100%, 40%);">+ continue;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!config->kernel_node ||</span><br><span style="color: hsl(120, 100%, 40%);">+ (config->fdt && !config->fdt_node)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_DEBUG,</span><br><span style="color: hsl(120, 100%, 40%);">+ "Missing image, discarding config %s.\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ config->name);</span><br><span style="color: hsl(120, 100%, 40%);">+ list_remove(&config->list_node);</span><br><span style="color: hsl(120, 100%, 40%);">+ continue;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (config->fdt_node) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (config->fdt_node->compression < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_DEBUG,</span><br><span style="color: hsl(120, 100%, 40%);">+ "FDT compression not yet supported, "</span><br><span style="color: hsl(120, 100%, 40%);">+ "skipping config %s.\n", config->name);</span><br><span style="color: hsl(120, 100%, 40%);">+ list_remove(&config->list_node);</span><br><span style="color: hsl(120, 100%, 40%);">+ continue;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ void *fdt_blob = config->fdt_node->data;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct FdtHeader *fdt_header =</span><br><span style="color: hsl(120, 100%, 40%);">+ (struct FdtHeader *)fdt_blob;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t fdt_offset =</span><br><span style="color: hsl(120, 100%, 40%);">+ be32_to_cpu(fdt_header->structure_offset);</span><br><span style="color: hsl(120, 100%, 40%);">+ config->compat_pos = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ config->compat_rank = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!fdt_find_compat(fdt_blob, fdt_offset,</span><br><span style="color: hsl(120, 100%, 40%);">+ &config->compat)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 0; i < num_fit_kernel_compat; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ int pos = fit_check_compat(</span><br><span style="color: hsl(120, 100%, 40%);">+ &config->compat,</span><br><span style="color: hsl(120, 100%, 40%);">+ fit_kernel_compat[i]);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (pos >= 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ config->compat_pos = pos;</span><br><span style="color: hsl(120, 100%, 40%);">+ config->compat_rank = i;</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ //if (default_config_name &&</span><br><span style="color: hsl(120, 100%, 40%);">+ // !strcmp(config->name, default_config_name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ // printk(BIOS_DEBUG, " (default)");</span><br><span style="color: hsl(120, 100%, 40%);">+ default_config = config;</span><br><span style="color: hsl(120, 100%, 40%);">+ //}</span><br><span style="color: hsl(120, 100%, 40%);">+ if (config->fdt)</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_DEBUG, ", fdt %s", config->fdt);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (config->ramdisk)</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_DEBUG, ", ramdisk %s", config->ramdisk);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (config->compat.name) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_DEBUG, ", compat");</span><br><span style="color: hsl(120, 100%, 40%);">+ int bytes = config->compat.size;</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *compat_str = config->compat.data;</span><br><span style="color: hsl(120, 100%, 40%);">+ for (int pos = 0; bytes && compat_str[0]; pos++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_DEBUG, " %s", compat_str);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (pos == config->compat_pos)</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_DEBUG, " (match)");</span><br><span style="color: hsl(120, 100%, 40%);">+ int len = strlen(compat_str) + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ compat_str += len;</span><br><span style="color: hsl(120, 100%, 40%);">+ bytes -= len;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (config->compat_rank >= 0 && (!compat_config ||</span><br><span style="color: hsl(120, 100%, 40%);">+ config->compat_rank < compat_config->compat_rank))</span><br><span style="color: hsl(120, 100%, 40%);">+ compat_config = config;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_DEBUG, "\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ struct FitConfigNode *to_boot = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (compat_config) {</span><br><span style="color: hsl(120, 100%, 40%);">+ to_boot = compat_config;</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_ERR, "Choosing best match %s for compat %s.\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ to_boot->name, fit_kernel_compat[to_boot->compat_rank]);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (default_config) {</span><br><span style="color: hsl(120, 100%, 40%);">+ to_boot = default_config;</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_ERR, "No match, choosing default %s.\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ to_boot->name);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_ERR,</span><br><span style="color: hsl(120, 100%, 40%);">+ "No compatible or default configs. Giving up.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ // We're leaking memory here, but at this point we're beyond</span><br><span style="color: hsl(120, 100%, 40%);">+ // saving anyway.</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (to_boot->fdt_node) {</span><br><span style="color: hsl(120, 100%, 40%);">+ *dt = fdt_unflatten(to_boot->fdt_node->data);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!*dt) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_ERR,</span><br><span style="color: hsl(120, 100%, 40%);">+ "Failed to unflatten the kernel's fdt.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Update only if non-NULL cmd line */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (strlen(CONFIG_LINUX_COMMAND_LINE) > 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ update_chosen(*dt, CONFIG_LINUX_COMMAND_LINE);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ update_memory(*dt);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (to_boot->ramdisk_node)</span><br><span style="color: hsl(120, 100%, 40%);">+ fit_add_ramdisk(*dt, to_boot->ramdisk_node->data,</span><br><span style="color: hsl(120, 100%, 40%);">+ to_boot->ramdisk_node->size);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return to_boot->kernel_node;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/lib/list.c b/src/lib/list.c</span><br><span>new file mode 100644</span><br><span>index 0000000..581573e</span><br><span>--- /dev/null</span><br><span>+++ b/src/lib/list.c</span><br><span>@@ -0,0 +1,44 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright 2012 Google Inc.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * See file CREDITS for list of people who contributed to this</span><br><span style="color: hsl(120, 100%, 40%);">+ * project.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or</span><br><span style="color: hsl(120, 100%, 40%);">+ * modify it under the terms of the GNU General Public License as</span><br><span style="color: hsl(120, 100%, 40%);">+ * published by the Free Software Foundation; either version 2 of</span><br><span style="color: hsl(120, 100%, 40%);">+ * the License, or (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but without any warranty; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <list.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void list_remove(ListNode *node)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (node->prev)</span><br><span style="color: hsl(120, 100%, 40%);">+ node->prev->next = node->next;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (node->next)</span><br><span style="color: hsl(120, 100%, 40%);">+ node->next->prev = node->prev;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void list_insert_after(ListNode *node, ListNode *after)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ node->next = after->next;</span><br><span style="color: hsl(120, 100%, 40%);">+ node->prev = after;</span><br><span style="color: hsl(120, 100%, 40%);">+ after->next = node;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (node->next)</span><br><span style="color: hsl(120, 100%, 40%);">+ node->next->prev = node;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void list_insert_before(ListNode *node, ListNode *before)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ node->prev = before->prev;</span><br><span style="color: hsl(120, 100%, 40%);">+ node->next = before;</span><br><span style="color: hsl(120, 100%, 40%);">+ before->prev = node;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (node->prev)</span><br><span style="color: hsl(120, 100%, 40%);">+ node->prev->next = node;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/lib/prog_loaders.c b/src/lib/prog_loaders.c</span><br><span>index 128869b..cec9582 100644</span><br><span>--- a/src/lib/prog_loaders.c</span><br><span>+++ b/src/lib/prog_loaders.c</span><br><span>@@ -29,6 +29,7 @@</span><br><span> #include <stage_cache.h></span><br><span> #include <symbols.h></span><br><span> #include <timestamp.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <uImage.h></span><br><span> </span><br><span> /* Only can represent up to 1 byte less than size_t. */</span><br><span> const struct mem_region_device addrspace_32bit =</span><br><span>@@ -179,9 +180,14 @@</span><br><span> </span><br><span> mirror_payload(payload);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- /* Pass cbtables to payload if architecture desires it. */</span><br><span style="color: hsl(0, 100%, 40%);">- prog_set_entry(payload, selfload(payload, true),</span><br><span style="color: hsl(0, 100%, 40%);">- cbmem_find(CBMEM_ID_CBTABLE));</span><br><span style="color: hsl(120, 100%, 40%);">+ if (IS_ENABLED(CONFIG_PAYLOAD_LINUX_UIMAGE)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ uImageLoad(payload);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Entry and argument have already been set up */</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Pass cbtables to payload if architecture desires it. */</span><br><span style="color: hsl(120, 100%, 40%);">+ prog_set_entry(payload, selfload(payload, true),</span><br><span style="color: hsl(120, 100%, 40%);">+ cbmem_find(CBMEM_ID_CBTABLE));</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> </span><br><span> out:</span><br><span> if (prog_entry(payload) == NULL)</span><br><span>diff --git a/src/lib/ranges.c b/src/lib/ranges.c</span><br><span>new file mode 100644</span><br><span>index 0000000..c141f94</span><br><span>--- /dev/null</span><br><span>+++ b/src/lib/ranges.c</span><br><span>@@ -0,0 +1,133 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright 2012 Google Inc.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * See file CREDITS for list of people who contributed to this</span><br><span style="color: hsl(120, 100%, 40%);">+ * project.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or</span><br><span style="color: hsl(120, 100%, 40%);">+ * modify it under the terms of the GNU General Public License as</span><br><span style="color: hsl(120, 100%, 40%);">+ * published by the Free Software Foundation; either version 2 of</span><br><span style="color: hsl(120, 100%, 40%);">+ * the License, or (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but without any warranty; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <assert.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stddef.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <console/console.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <ranges.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * This implementation tracks a collection of ranges by keeping a linked list</span><br><span style="color: hsl(120, 100%, 40%);">+ * of the edges between ranges in the collection and the space between them.</span><br><span style="color: hsl(120, 100%, 40%);">+ * New ranges take precedence over older ranges they overlap with.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void ranges_insert_between(RangesEdge *before, RangesEdge *after,</span><br><span style="color: hsl(120, 100%, 40%);">+ uint64_t pos)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ RangesEdge *new_edge = malloc(sizeof(*new_edge));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ assert(before != after);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ new_edge->next = after;</span><br><span style="color: hsl(120, 100%, 40%);">+ new_edge->pos = pos;</span><br><span style="color: hsl(120, 100%, 40%);">+ before->next = new_edge;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void ranges_init(Ranges *ranges)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ ranges->head.next = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ ranges->head.pos = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void ranges_teardown(Ranges *ranges)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ RangesEdge *edge = ranges->head.next;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ while (edge) {</span><br><span style="color: hsl(120, 100%, 40%);">+ RangesEdge *next = edge->next;</span><br><span style="color: hsl(120, 100%, 40%);">+ free(edge);</span><br><span style="color: hsl(120, 100%, 40%);">+ edge = next;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ ranges->head.next = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void ranges_set_region_to(Ranges *ranges, uint64_t start,</span><br><span style="color: hsl(120, 100%, 40%);">+ uint64_t end, int new_included)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ /* whether the current region was originally going to be included. */</span><br><span style="color: hsl(120, 100%, 40%);">+ int included = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ assert(start != end);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* prev is never NULL, but cur might be. */</span><br><span style="color: hsl(120, 100%, 40%);">+ RangesEdge *prev = &ranges->head;</span><br><span style="color: hsl(120, 100%, 40%);">+ RangesEdge *cur = prev->next;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Find the start of the new region. After this loop, prev will be</span><br><span style="color: hsl(120, 100%, 40%);">+ * before the start of the new region, and cur will be after it or</span><br><span style="color: hsl(120, 100%, 40%);">+ * overlapping start. If they overlap, this ensures that the existing</span><br><span style="color: hsl(120, 100%, 40%);">+ * edge is deleted and we don't end up with two edges in the same spot.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+ while (cur && cur->pos < start) {</span><br><span style="color: hsl(120, 100%, 40%);">+ prev = cur;</span><br><span style="color: hsl(120, 100%, 40%);">+ cur = cur->next;</span><br><span style="color: hsl(120, 100%, 40%);">+ included = !included;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Add the "start" edge between prev and cur, if needed. */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (new_included != included) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ranges_insert_between(prev, cur, start);</span><br><span style="color: hsl(120, 100%, 40%);">+ prev = prev->next;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Delete any edges obscured by the new region. After this loop, prev</span><br><span style="color: hsl(120, 100%, 40%);">+ * will be before the end of the new region or overlapping it, and cur</span><br><span style="color: hsl(120, 100%, 40%);">+ * will be after if, if there is a edge after it. For the same</span><br><span style="color: hsl(120, 100%, 40%);">+ * reason as above, we want to ensure that we end up with one edge if</span><br><span style="color: hsl(120, 100%, 40%);">+ * there's an overlap.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+ while (cur && cur->pos <= end) {</span><br><span style="color: hsl(120, 100%, 40%);">+ cur = cur->next;</span><br><span style="color: hsl(120, 100%, 40%);">+ free(prev->next);</span><br><span style="color: hsl(120, 100%, 40%);">+ prev->next = cur;</span><br><span style="color: hsl(120, 100%, 40%);">+ included = !included;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Add the "end" edge between prev and cur, if needed. */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (included != new_included)</span><br><span style="color: hsl(120, 100%, 40%);">+ ranges_insert_between(prev, cur, end);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Add a range to a collection of ranges. */</span><br><span style="color: hsl(120, 100%, 40%);">+void ranges_add(Ranges *ranges, uint64_t start, uint64_t end)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ ranges_set_region_to(ranges, start, end, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Subtract a range. */</span><br><span style="color: hsl(120, 100%, 40%);">+void ranges_sub(Ranges *ranges, uint64_t start, uint64_t end)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ ranges_set_region_to(ranges, start, end, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Run a function on each range in Ranges. */</span><br><span style="color: hsl(120, 100%, 40%);">+void ranges_for_each(Ranges *ranges, RangesForEachFunc func, void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ for (RangesEdge *cur = ranges->head.next; cur; cur = cur->next->next) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!cur->next) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_ERR, "Odd number of range edges!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ func(cur->pos, cur->next->pos, data);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/lib/uImage.c b/src/lib/uImage.c</span><br><span>new file mode 100644</span><br><span>index 0000000..1717a96</span><br><span>--- /dev/null</span><br><span>+++ b/src/lib/uImage.c</span><br><span>@@ -0,0 +1,211 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * This file is part of the coreboot project.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (C) 2003-2004 Eric Biederman</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (C) 2005-2010 coresystems GmbH</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (C) 2014 Google Inc.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; version 2 of the License.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <console/console.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <bootmem.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <cbmem.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <device/resource.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdlib.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <uImage.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <commonlib/region.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <fit.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <program_loading.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <timestamp.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <cbfs.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <commonlib/compression.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <lib.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <uImage.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define MAX_KERNEL_SIZE (64*MiB)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+typedef struct {</span><br><span style="color: hsl(120, 100%, 40%);">+ u32 code0;</span><br><span style="color: hsl(120, 100%, 40%);">+ u32 code1;</span><br><span style="color: hsl(120, 100%, 40%);">+ u64 text_offset;</span><br><span style="color: hsl(120, 100%, 40%);">+ u64 image_size;</span><br><span style="color: hsl(120, 100%, 40%);">+ u64 flags;</span><br><span style="color: hsl(120, 100%, 40%);">+ u64 res2;</span><br><span style="color: hsl(120, 100%, 40%);">+ u64 res3;</span><br><span style="color: hsl(120, 100%, 40%);">+ u64 res4;</span><br><span style="color: hsl(120, 100%, 40%);">+ u32 magic;</span><br><span style="color: hsl(120, 100%, 40%);">+#define KERNEL_HEADER_MAGIC 0x644d5241</span><br><span style="color: hsl(120, 100%, 40%);">+ u32 res5;</span><br><span style="color: hsl(120, 100%, 40%);">+} Arm64KernelHeader;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct {</span><br><span style="color: hsl(120, 100%, 40%);">+ union {</span><br><span style="color: hsl(120, 100%, 40%);">+ Arm64KernelHeader header;</span><br><span style="color: hsl(120, 100%, 40%);">+ u8 raw[sizeof(Arm64KernelHeader) + 0x100];</span><br><span style="color: hsl(120, 100%, 40%);">+ };</span><br><span style="color: hsl(120, 100%, 40%);">+#define SCRATCH_CANARY_VALUE 0xdeadbeef</span><br><span style="color: hsl(120, 100%, 40%);">+ u32 canary;</span><br><span style="color: hsl(120, 100%, 40%);">+} scratch;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+__attribute__((weak)) size_t</span><br><span style="color: hsl(120, 100%, 40%);">+arch_get_kernel_fdt_load_addr(uint32_t load_offset,</span><br><span style="color: hsl(120, 100%, 40%);">+ size_t kernel_size,</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t fdt_size,</span><br><span style="color: hsl(120, 100%, 40%);">+ void **kernel_load_addr,</span><br><span style="color: hsl(120, 100%, 40%);">+ void **fdt_load_addr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_ERR, "ERROR: Unsupported ARCH\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static size_t extract_fit(struct prog *payload,</span><br><span style="color: hsl(120, 100%, 40%);">+ struct FitImageNode *kernel,</span><br><span style="color: hsl(120, 100%, 40%);">+ struct DeviceTree *dt)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ void *kernel_reloc, *fdt_reloc;</span><br><span style="color: hsl(120, 100%, 40%);">+ size_t kernel_max_size, dt_size;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_INFO, "%s: %p, %p, %p\n", __func__, payload, kernel, dt);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ // Partially decompress to get text_offset. Can't check for errors.</span><br><span style="color: hsl(120, 100%, 40%);">+ scratch.canary = SCRATCH_CANARY_VALUE;</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (kernel->compression) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case CBFS_COMPRESS_NONE:</span><br><span style="color: hsl(120, 100%, 40%);">+ memcpy(scratch.raw, kernel->data, sizeof(scratch.raw));</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case CBFS_COMPRESS_LZMA:</span><br><span style="color: hsl(120, 100%, 40%);">+ ulzman(kernel->data, kernel->size,</span><br><span style="color: hsl(120, 100%, 40%);">+ scratch.raw, sizeof(scratch.raw));</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case CBFS_COMPRESS_LZ4:</span><br><span style="color: hsl(120, 100%, 40%);">+ ulz4fn(kernel->data, kernel->size,</span><br><span style="color: hsl(120, 100%, 40%);">+ scratch.raw, sizeof(scratch.raw));</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ default:</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_ERR, "ERROR: Unsupported compression algorithm!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ // Should never happen, but if it does we'll want to know.</span><br><span style="color: hsl(120, 100%, 40%);">+ if (scratch.canary != SCRATCH_CANARY_VALUE) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_ERR,</span><br><span style="color: hsl(120, 100%, 40%);">+ "ERROR: Partial decompression ran over scratchbuf!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (scratch.header.magic != KERNEL_HEADER_MAGIC) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_ERR,</span><br><span style="color: hsl(120, 100%, 40%);">+ "ERROR: Invalid kernel magic: %#.8x\n != %#.8x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ scratch.header.magic, KERNEL_HEADER_MAGIC);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!scratch.header.image_size) {</span><br><span style="color: hsl(120, 100%, 40%);">+ kernel_max_size = MAX_KERNEL_SIZE;</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_WARNING, "Assuming %zd MiB kernel size\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ kernel_max_size >> 20);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else</span><br><span style="color: hsl(120, 100%, 40%);">+ kernel_max_size = scratch.header.image_size;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ dt_size = dt ? dt_flat_size(dt) : 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (arch_get_kernel_fdt_load_addr(scratch.header.text_offset,</span><br><span style="color: hsl(120, 100%, 40%);">+ kernel_max_size,</span><br><span style="color: hsl(120, 100%, 40%);">+ dt_size,</span><br><span style="color: hsl(120, 100%, 40%);">+ &kernel_reloc,</span><br><span style="color: hsl(120, 100%, 40%);">+ &fdt_reloc)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_ERR, "ERROR: Failed to find free memory region\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_DEBUG, "Kernel load address %p\n", kernel_reloc);</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_DEBUG, "FDT load address %p\n", fdt_reloc);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ // Flatten it.</span><br><span style="color: hsl(120, 100%, 40%);">+ if (dt) {</span><br><span style="color: hsl(120, 100%, 40%);">+ dt_flatten(dt, fdt_reloc);</span><br><span style="color: hsl(120, 100%, 40%);">+ prog_segment_loaded((uintptr_t)fdt_reloc, dt_size, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ timestamp_add_now(TS_KERNEL_DECOMPRESSION);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ size_t true_size = kernel->size;</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (kernel->compression) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case CBFS_COMPRESS_NONE:</span><br><span style="color: hsl(120, 100%, 40%);">+ if (kernel->size > kernel_max_size) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_ERR,</span><br><span style="color: hsl(120, 100%, 40%);">+ "ERROR: Cannot relocate a kernel this large!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_INFO, "Relocating kernel to %p\n", kernel_reloc);</span><br><span style="color: hsl(120, 100%, 40%);">+ memmove(kernel_reloc, kernel->data, kernel->size);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case CBFS_COMPRESS_LZMA:</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_INFO, "Decompressing LZMA kernel to %p\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ kernel_reloc);</span><br><span style="color: hsl(120, 100%, 40%);">+ timestamp_add_now(TS_START_ULZMA);</span><br><span style="color: hsl(120, 100%, 40%);">+ true_size = ulzman(kernel->data, kernel->size,</span><br><span style="color: hsl(120, 100%, 40%);">+ kernel_reloc, kernel_max_size);</span><br><span style="color: hsl(120, 100%, 40%);">+ timestamp_add_now(TS_END_ULZMA);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!true_size) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_ERR, "ERROR: LZMA decompression failed!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case CBFS_COMPRESS_LZ4:</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_INFO, "Decompressing LZ4 kernel to %p\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ kernel_reloc);</span><br><span style="color: hsl(120, 100%, 40%);">+ timestamp_add_now(TS_START_ULZ4F);</span><br><span style="color: hsl(120, 100%, 40%);">+ true_size = ulz4fn(kernel->data, kernel->size,</span><br><span style="color: hsl(120, 100%, 40%);">+ kernel_reloc, kernel_max_size);</span><br><span style="color: hsl(120, 100%, 40%);">+ timestamp_add_now(TS_END_ULZ4F);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!true_size) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_ERR, "ERROR: LZ4 decompression failed!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ default: // It's 2015 and GCC's reachability analyzer still sucks...</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ prog_segment_loaded((uintptr_t)kernel_reloc, true_size, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ timestamp_add_now(TS_START_KERNEL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_INFO, "Set kernel entry\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ prog_set_entry(payload, kernel_reloc, fdt_reloc);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Parse and load a kernel, devicetree and config from uImage payload.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void uImageLoad(struct prog *payload)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct DeviceTree *dt = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ void *data;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ data = rdev_mmap_full(prog_rdev(payload));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (data == NULL)</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ struct FitImageNode *fit = fit_load(data, &dt);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!fit)</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_ERR, "ERROR: Could not load FIT\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ else</span><br><span style="color: hsl(120, 100%, 40%);">+ extract_fit(payload, fit, dt);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ rdev_munmap(prog_rdev(payload), data);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span></span><br></pre><p>To view, visit <a href="https://review.coreboot.org/25019">change 25019</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://review.coreboot.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://review.coreboot.org/25019"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: coreboot </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I0f27b92a5e074966f893399eb401eb97d784850d </div>
<div style="display:none"> Gerrit-Change-Number: 25019 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Patrick Rudolph <patrick.rudolph@9elements.com> </div>