<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>