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