<p>Patrick Rudolph has uploaded this change for <strong>review</strong>.</p><p><a href="https://review.coreboot.org/25632">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">lib: Raw import FDT devicetree from depthcharge<br><br>Import from https://chromium.googlesource.com/chromiumos/platform/depthcharge<br><br>Coding style and coreboot integration will be done in a separate commit.<br><br>Change-Id: Ida75d4786eae38d84bfc71bf53573dafca8eda40<br>Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com><br>---<br>A src/include/device_tree.h<br>A src/include/list.h<br>A src/lib/device_tree.c<br>A src/lib/list.c<br>4 files changed, 1,244 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://review.coreboot.org:29418/coreboot refs/changes/32/25632/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><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..7a2cfb2</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 "base/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/list.h b/src/include/list.h</span><br><span>new file mode 100644</span><br><span>index 0000000..084c8f0</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 "base/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/lib/device_tree.c b/src/lib/device_tree.c</span><br><span>new file mode 100644</span><br><span>index 0000000..5f77870</span><br><span>--- /dev/null</span><br><span>+++ b/src/lib/device_tree.c</span><br><span>@@ -0,0 +1,937 @@</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 <libpayload.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 "base/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 (betohl(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 = betohl(ptr[index++]);</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t name_offset = betohl(ptr[index++]);</span><br><span style="color: hsl(120, 100%, 40%);">+  name_offset += betohl(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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (betohl(*(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%);">+               printf("  ");</span><br><span 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%);">+  printf("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%);">+         printf("%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%);">+            printf("...");</span><br><span style="color: hsl(120, 100%, 40%);">+      printf("\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%);">+  printf("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%);">+                return xzalloc(sizeof(DeviceTreeNode));</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%);">+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%);">+                return xzalloc(sizeof(DeviceTreeProperty));</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 = betohll(ptr[0]);</span><br><span style="color: hsl(120, 100%, 40%);">+     uint64_t size = betohll(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 = xzalloc(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 = xzalloc(sizeof(*tree));</span><br><span style="color: hsl(120, 100%, 40%);">+    FdtHeader *header = (FdtHeader *)blob;</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 = betohl(header->structure_offset);</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t strings_offset = betohl(header->strings_offset);</span><br><span style="color: hsl(120, 100%, 40%);">+  uint32_t reserve_offset = betohl(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] = htobell(entry->start);</span><br><span style="color: hsl(120, 100%, 40%);">+       ((uint64_t *)*map_start)[1] = htobell(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) = htobel(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) = htobel(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) = htobel(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) = htobel(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) = htobel(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 = htobel(dest - (uint8_t *)start_dest);</span><br><span style="color: hsl(120, 100%, 40%);">+   header->structure_size = htobel(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) = htobel(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 = htobel(dest - (uint8_t *)start_dest);</span><br><span style="color: hsl(120, 100%, 40%);">+     header->strings_size = htobel(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 = htobel(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%);">+  printf("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 = betohl(*(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 = betohl(*(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 = xmalloc(sizeof(val));</span><br><span style="color: hsl(120, 100%, 40%);">+  *val_ptr = htobel(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 = xmalloc(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%);">+             printf("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%);">+             printf("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%);">+               printf("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/list.c b/src/lib/list.c</span><br><span>new file mode 100644</span><br><span>index 0000000..ea7eff4</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 "base/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></span><br></pre><p>To view, visit <a href="https://review.coreboot.org/25632">change 25632</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/25632"/><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: Ida75d4786eae38d84bfc71bf53573dafca8eda40 </div>
<div style="display:none"> Gerrit-Change-Number: 25632 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Patrick Rudolph <patrick.rudolph@9elements.com> </div>