treewide: replace GPLv2 long form headers with SPDX header
[coreboot.git] / src / lib / device_tree.c
blobcb81d3248c50e1c692fb0093cd7ab3e2d3511e7e
1 /* Taken from depthcharge: src/base/device_tree.c */
2 /* SPDX-License-Identifier: GPL-2.0-or-later */
4 #include <assert.h>
5 #include <commonlib/stdlib.h>
6 #include <console/console.h>
7 #include <ctype.h>
8 #include <device_tree.h>
9 #include <endian.h>
10 #include <stdint.h>
11 #include <string.h>
12 #include <stddef.h>
13 #include <stdlib.h>
16 * Functions for picking apart flattened trees.
19 int fdt_next_property(const void *blob, uint32_t offset,
20 struct fdt_property *prop)
22 struct fdt_header *header = (struct fdt_header *)blob;
23 uint32_t *ptr = (uint32_t *)(((uint8_t *)blob) + offset);
25 int index = 0;
26 if (be32toh(ptr[index++]) != FDT_TOKEN_PROPERTY)
27 return 0;
29 uint32_t size = be32toh(ptr[index++]);
30 uint32_t name_offset = be32toh(ptr[index++]);
31 name_offset += be32toh(header->strings_offset);
33 if (prop) {
34 prop->name = (char *)((uint8_t *)blob + name_offset);
35 prop->data = &ptr[index];
36 prop->size = size;
39 index += DIV_ROUND_UP(size, sizeof(uint32_t));
41 return index * sizeof(uint32_t);
44 int fdt_node_name(const void *blob, uint32_t offset, const char **name)
46 uint8_t *ptr = ((uint8_t *)blob) + offset;
47 if (be32dec(ptr) != FDT_TOKEN_BEGIN_NODE)
48 return 0;
50 ptr += 4;
51 if (name)
52 *name = (char *)ptr;
53 return ALIGN_UP(strlen((char *)ptr) + 1, sizeof(uint32_t)) + 4;
56 static int dt_prop_is_phandle(struct device_tree_property *prop)
58 return !(strcmp("phandle", prop->prop.name) &&
59 strcmp("linux,phandle", prop->prop.name));
65 * Functions for printing flattened trees.
68 static void print_indent(int depth)
70 printk(BIOS_DEBUG, "%*s", depth * 8, "");
73 static void print_property(const struct fdt_property *prop, int depth)
75 int is_string = prop->size > 0 &&
76 ((char *)prop->data)[prop->size - 1] == '\0';
78 if (is_string)
79 for (const char *c = prop->data; *c != '\0'; c++)
80 if (!isprint(*c))
81 is_string = 0;
83 print_indent(depth);
84 if (is_string) {
85 printk(BIOS_DEBUG, "%s = \"%s\";\n",
86 prop->name, (const char *)prop->data);
87 } else {
88 printk(BIOS_DEBUG, "%s = < ", prop->name);
89 for (int i = 0; i < MIN(128, prop->size); i += 4) {
90 uint32_t val = 0;
91 for (int j = 0; j < MIN(4, prop->size - i); j++)
92 val |= ((uint8_t *)prop->data)[i + j] <<
93 (24 - j * 8);
94 printk(BIOS_DEBUG, "%#.2x ", val);
96 if (prop->size > 128)
97 printk(BIOS_DEBUG, "...");
98 printk(BIOS_DEBUG, ">;\n");
102 static int print_flat_node(const void *blob, uint32_t start_offset, int depth)
104 int offset = start_offset;
105 const char *name;
106 int size;
108 size = fdt_node_name(blob, offset, &name);
109 if (!size)
110 return 0;
111 offset += size;
113 print_indent(depth);
114 printk(BIOS_DEBUG, "%s {\n", name);
116 struct fdt_property prop;
117 while ((size = fdt_next_property(blob, offset, &prop))) {
118 print_property(&prop, depth + 1);
120 offset += size;
123 printk(BIOS_DEBUG, "\n"); /* empty line between props and nodes */
125 while ((size = print_flat_node(blob, offset, depth + 1)))
126 offset += size;
128 print_indent(depth);
129 printk(BIOS_DEBUG, "}\n");
131 return offset - start_offset + sizeof(uint32_t);
134 void fdt_print_node(const void *blob, uint32_t offset)
136 print_flat_node(blob, offset, 0);
142 * A utility function to skip past nodes in flattened trees.
145 int fdt_skip_node(const void *blob, uint32_t start_offset)
147 int offset = start_offset;
148 int size;
150 const char *name;
151 size = fdt_node_name(blob, offset, &name);
152 if (!size)
153 return 0;
154 offset += size;
156 while ((size = fdt_next_property(blob, offset, NULL)))
157 offset += size;
159 while ((size = fdt_skip_node(blob, offset)))
160 offset += size;
162 return offset - start_offset + sizeof(uint32_t);
168 * Functions to turn a flattened tree into an unflattened one.
171 static int fdt_unflatten_node(const void *blob, uint32_t start_offset,
172 struct device_tree *tree,
173 struct device_tree_node **new_node)
175 struct list_node *last;
176 int offset = start_offset;
177 const char *name;
178 int size;
180 size = fdt_node_name(blob, offset, &name);
181 if (!size)
182 return 0;
183 offset += size;
185 struct device_tree_node *node = xzalloc(sizeof(*node));
186 *new_node = node;
187 node->name = name;
189 struct fdt_property fprop;
190 last = &node->properties;
191 while ((size = fdt_next_property(blob, offset, &fprop))) {
192 struct device_tree_property *prop = xzalloc(sizeof(*prop));
193 prop->prop = fprop;
195 if (dt_prop_is_phandle(prop)) {
196 node->phandle = be32dec(prop->prop.data);
197 if (node->phandle > tree->max_phandle)
198 tree->max_phandle = node->phandle;
201 list_insert_after(&prop->list_node, last);
202 last = &prop->list_node;
204 offset += size;
207 struct device_tree_node *child;
208 last = &node->children;
209 while ((size = fdt_unflatten_node(blob, offset, tree, &child))) {
210 list_insert_after(&child->list_node, last);
211 last = &child->list_node;
213 offset += size;
216 return offset - start_offset + sizeof(uint32_t);
219 static int fdt_unflatten_map_entry(const void *blob, uint32_t offset,
220 struct device_tree_reserve_map_entry **new)
222 const uint64_t *ptr = (const uint64_t *)(((uint8_t *)blob) + offset);
223 const uint64_t start = be64toh(ptr[0]);
224 const uint64_t size = be64toh(ptr[1]);
226 if (!size)
227 return 0;
229 struct device_tree_reserve_map_entry *entry = xzalloc(sizeof(*entry));
230 *new = entry;
231 entry->start = start;
232 entry->size = size;
234 return sizeof(uint64_t) * 2;
237 struct device_tree *fdt_unflatten(const void *blob)
239 struct device_tree *tree = xzalloc(sizeof(*tree));
240 const struct fdt_header *header = (const struct fdt_header *)blob;
241 tree->header = header;
243 uint32_t magic = be32toh(header->magic);
244 uint32_t version = be32toh(header->version);
245 uint32_t last_comp_version = be32toh(header->last_comp_version);
247 if (magic != FDT_HEADER_MAGIC) {
248 printk(BIOS_DEBUG, "Invalid device tree magic %#.8x!\n", magic);
249 free(tree);
250 return NULL;
252 if (last_comp_version > FDT_SUPPORTED_VERSION) {
253 printk(BIOS_DEBUG, "Unsupported device tree version %u(>=%u)\n",
254 version, last_comp_version);
255 free(tree);
256 return NULL;
258 if (version > FDT_SUPPORTED_VERSION)
259 printk(BIOS_DEBUG,
260 "NOTE: FDT version %u too new, should add support!\n",
261 version);
263 uint32_t struct_offset = be32toh(header->structure_offset);
264 uint32_t strings_offset = be32toh(header->strings_offset);
265 uint32_t reserve_offset = be32toh(header->reserve_map_offset);
266 uint32_t min_offset = 0;
267 min_offset = MIN(struct_offset, strings_offset);
268 min_offset = MIN(min_offset, reserve_offset);
269 /* Assume everything up to the first non-header component is part of
270 the header and needs to be preserved. This will protect us against
271 new elements being added in the future. */
272 tree->header_size = min_offset;
274 struct device_tree_reserve_map_entry *entry;
275 uint32_t offset = reserve_offset;
276 int size;
277 struct list_node *last = &tree->reserve_map;
278 while ((size = fdt_unflatten_map_entry(blob, offset, &entry))) {
279 list_insert_after(&entry->list_node, last);
280 last = &entry->list_node;
282 offset += size;
285 fdt_unflatten_node(blob, struct_offset, tree, &tree->root);
287 return tree;
293 * Functions to find the size of the device tree if it was flattened.
296 static void dt_flat_prop_size(struct device_tree_property *prop,
297 uint32_t *struct_size, uint32_t *strings_size)
299 /* Starting token. */
300 *struct_size += sizeof(uint32_t);
301 /* Size. */
302 *struct_size += sizeof(uint32_t);
303 /* Name offset. */
304 *struct_size += sizeof(uint32_t);
305 /* Property value. */
306 *struct_size += ALIGN_UP(prop->prop.size, sizeof(uint32_t));
308 /* Property name. */
309 *strings_size += strlen(prop->prop.name) + 1;
312 static void dt_flat_node_size(struct device_tree_node *node,
313 uint32_t *struct_size, uint32_t *strings_size)
315 /* Starting token. */
316 *struct_size += sizeof(uint32_t);
317 /* Node name. */
318 *struct_size += ALIGN_UP(strlen(node->name) + 1, sizeof(uint32_t));
320 struct device_tree_property *prop;
321 list_for_each(prop, node->properties, list_node)
322 dt_flat_prop_size(prop, struct_size, strings_size);
324 struct device_tree_node *child;
325 list_for_each(child, node->children, list_node)
326 dt_flat_node_size(child, struct_size, strings_size);
328 /* End token. */
329 *struct_size += sizeof(uint32_t);
332 uint32_t dt_flat_size(const struct device_tree *tree)
334 uint32_t size = tree->header_size;
335 struct device_tree_reserve_map_entry *entry;
336 list_for_each(entry, tree->reserve_map, list_node)
337 size += sizeof(uint64_t) * 2;
338 size += sizeof(uint64_t) * 2;
340 uint32_t struct_size = 0;
341 uint32_t strings_size = 0;
342 dt_flat_node_size(tree->root, &struct_size, &strings_size);
344 size += struct_size;
345 /* End token. */
346 size += sizeof(uint32_t);
348 size += strings_size;
350 return size;
356 * Functions to flatten a device tree.
359 static void dt_flatten_map_entry(struct device_tree_reserve_map_entry *entry,
360 void **map_start)
362 ((uint64_t *)*map_start)[0] = htobe64(entry->start);
363 ((uint64_t *)*map_start)[1] = htobe64(entry->size);
364 *map_start = ((uint8_t *)*map_start) + sizeof(uint64_t) * 2;
367 static void dt_flatten_prop(struct device_tree_property *prop,
368 void **struct_start, void *strings_base,
369 void **strings_start)
371 uint8_t *dstruct = (uint8_t *)*struct_start;
372 uint8_t *dstrings = (uint8_t *)*strings_start;
374 be32enc(dstruct, FDT_TOKEN_PROPERTY);
375 dstruct += sizeof(uint32_t);
377 be32enc(dstruct, prop->prop.size);
378 dstruct += sizeof(uint32_t);
380 uint32_t name_offset = (uintptr_t)dstrings - (uintptr_t)strings_base;
381 be32enc(dstruct, name_offset);
382 dstruct += sizeof(uint32_t);
384 strcpy((char *)dstrings, prop->prop.name);
385 dstrings += strlen(prop->prop.name) + 1;
387 memcpy(dstruct, prop->prop.data, prop->prop.size);
388 dstruct += ALIGN_UP(prop->prop.size, sizeof(uint32_t));
390 *struct_start = dstruct;
391 *strings_start = dstrings;
394 static void dt_flatten_node(const struct device_tree_node *node,
395 void **struct_start, void *strings_base,
396 void **strings_start)
398 uint8_t *dstruct = (uint8_t *)*struct_start;
399 uint8_t *dstrings = (uint8_t *)*strings_start;
401 be32enc(dstruct, FDT_TOKEN_BEGIN_NODE);
402 dstruct += sizeof(uint32_t);
404 strcpy((char *)dstruct, node->name);
405 dstruct += ALIGN_UP(strlen(node->name) + 1, sizeof(uint32_t));
407 struct device_tree_property *prop;
408 list_for_each(prop, node->properties, list_node)
409 dt_flatten_prop(prop, (void **)&dstruct, strings_base,
410 (void **)&dstrings);
412 struct device_tree_node *child;
413 list_for_each(child, node->children, list_node)
414 dt_flatten_node(child, (void **)&dstruct, strings_base,
415 (void **)&dstrings);
417 be32enc(dstruct, FDT_TOKEN_END_NODE);
418 dstruct += sizeof(uint32_t);
420 *struct_start = dstruct;
421 *strings_start = dstrings;
424 void dt_flatten(const struct device_tree *tree, void *start_dest)
426 uint8_t *dest = (uint8_t *)start_dest;
428 memcpy(dest, tree->header, tree->header_size);
429 struct fdt_header *header = (struct fdt_header *)dest;
430 dest += tree->header_size;
432 struct device_tree_reserve_map_entry *entry;
433 list_for_each(entry, tree->reserve_map, list_node)
434 dt_flatten_map_entry(entry, (void **)&dest);
435 ((uint64_t *)dest)[0] = ((uint64_t *)dest)[1] = 0;
436 dest += sizeof(uint64_t) * 2;
438 uint32_t struct_size = 0;
439 uint32_t strings_size = 0;
440 dt_flat_node_size(tree->root, &struct_size, &strings_size);
442 uint8_t *struct_start = dest;
443 header->structure_offset = htobe32(dest - (uint8_t *)start_dest);
444 header->structure_size = htobe32(struct_size);
445 dest += struct_size;
447 *((uint32_t *)dest) = htobe32(FDT_TOKEN_END);
448 dest += sizeof(uint32_t);
450 uint8_t *strings_start = dest;
451 header->strings_offset = htobe32(dest - (uint8_t *)start_dest);
452 header->strings_size = htobe32(strings_size);
453 dest += strings_size;
455 dt_flatten_node(tree->root, (void **)&struct_start, strings_start,
456 (void **)&strings_start);
458 header->totalsize = htobe32(dest - (uint8_t *)start_dest);
464 * Functions for printing a non-flattened device tree.
467 static void print_node(const struct device_tree_node *node, int depth)
469 print_indent(depth);
470 if (depth == 0) /* root node has no name, print a starting slash */
471 printk(BIOS_DEBUG, "/");
472 printk(BIOS_DEBUG, "%s {\n", node->name);
474 struct device_tree_property *prop;
475 list_for_each(prop, node->properties, list_node)
476 print_property(&prop->prop, depth + 1);
478 printk(BIOS_DEBUG, "\n"); /* empty line between props and nodes */
480 struct device_tree_node *child;
481 list_for_each(child, node->children, list_node)
482 print_node(child, depth + 1);
484 print_indent(depth);
485 printk(BIOS_DEBUG, "};\n");
488 void dt_print_node(const struct device_tree_node *node)
490 print_node(node, 0);
496 * Functions for reading and manipulating an unflattened device tree.
500 * Read #address-cells and #size-cells properties from a node.
502 * @param node The device tree node to read from.
503 * @param addrcp Pointer to store #address-cells in, skipped if NULL.
504 * @param sizecp Pointer to store #size-cells in, skipped if NULL.
506 void dt_read_cell_props(const struct device_tree_node *node, u32 *addrcp,
507 u32 *sizecp)
509 struct device_tree_property *prop;
510 list_for_each(prop, node->properties, list_node) {
511 if (addrcp && !strcmp("#address-cells", prop->prop.name))
512 *addrcp = be32dec(prop->prop.data);
513 if (sizecp && !strcmp("#size-cells", prop->prop.name))
514 *sizecp = be32dec(prop->prop.data);
519 * Find a node from a device tree path, relative to a parent node.
521 * @param parent The node from which to start the relative path lookup.
522 * @param path An array of path component strings that will be looked
523 * up in order to find the node. Must be terminated with
524 * a NULL pointer. Example: {'firmware', 'coreboot', NULL}
525 * @param addrcp Pointer that will be updated with any #address-cells
526 * value found in the path. May be NULL to ignore.
527 * @param sizecp Pointer that will be updated with any #size-cells
528 * value found in the path. May be NULL to ignore.
529 * @param create 1: Create node(s) if not found. 0: Return NULL instead.
530 * @return The found/created node, or NULL.
532 struct device_tree_node *dt_find_node(struct device_tree_node *parent,
533 const char **path, u32 *addrcp,
534 u32 *sizecp, int create)
536 struct device_tree_node *node, *found = NULL;
538 /* Update #address-cells and #size-cells for this level. */
539 dt_read_cell_props(parent, addrcp, sizecp);
541 if (!*path)
542 return parent;
544 /* Find the next node in the path, if it exists. */
545 list_for_each(node, parent->children, list_node) {
546 if (!strcmp(node->name, *path)) {
547 found = node;
548 break;
552 /* Otherwise create it or return NULL. */
553 if (!found) {
554 if (!create)
555 return NULL;
557 found = malloc(sizeof(*found));
558 if (!found)
559 return NULL;
560 found->name = strdup(*path);
561 if (!found->name)
562 return NULL;
564 list_insert_after(&found->list_node, &parent->children);
567 return dt_find_node(found, path + 1, addrcp, sizecp, create);
571 * Find a node in the tree from a string device tree path.
573 * @param tree The device tree to search.
574 * @param path A string representing a path in the device tree, with
575 * nodes separated by '/'. Example: "/firmware/coreboot"
576 * @param addrcp Pointer that will be updated with any #address-cells
577 * value found in the path. May be NULL to ignore.
578 * @param sizecp Pointer that will be updated with any #size-cells
579 * value found in the path. May be NULL to ignore.
580 * @param create 1: Create node(s) if not found. 0: Return NULL instead.
581 * @return The found/created node, or NULL.
583 * It is the caller responsibility to provide a path string that doesn't end
584 * with a '/' and doesn't contain any "//". If the path does not start with a
585 * '/', the first segment is interpreted as an alias. */
586 struct device_tree_node *dt_find_node_by_path(struct device_tree *tree,
587 const char *path, u32 *addrcp,
588 u32 *sizecp, int create)
590 char *sub_path;
591 char *duped_str;
592 struct device_tree_node *parent;
593 char *next_slash;
594 /* Hopefully enough depth for any node. */
595 const char *path_array[15];
596 int i;
597 struct device_tree_node *node = NULL;
599 if (path[0] == '/') { /* regular path */
600 if (path[1] == '\0') { /* special case: "/" is root node */
601 dt_read_cell_props(tree->root, addrcp, sizecp);
602 return tree->root;
605 sub_path = duped_str = strdup(&path[1]);
606 if (!sub_path)
607 return NULL;
609 parent = tree->root;
610 } else { /* alias */
611 char *alias;
613 alias = duped_str = strdup(path);
614 if (!alias)
615 return NULL;
617 sub_path = strchr(alias, '/');
618 if (sub_path)
619 *sub_path = '\0';
621 parent = dt_find_node_by_alias(tree, alias);
622 if (!parent) {
623 printk(BIOS_DEBUG,
624 "Could not find node '%s', alias '%s' does not exist\n",
625 path, alias);
626 free(duped_str);
627 return NULL;
630 if (!sub_path) {
631 /* it's just the alias, no sub-path */
632 free(duped_str);
633 return parent;
636 sub_path++;
639 next_slash = sub_path;
640 path_array[0] = sub_path;
641 for (i = 1; i < (ARRAY_SIZE(path_array) - 1); i++) {
642 next_slash = strchr(next_slash, '/');
643 if (!next_slash)
644 break;
646 *next_slash++ = '\0';
647 path_array[i] = next_slash;
650 if (!next_slash) {
651 path_array[i] = NULL;
652 node = dt_find_node(parent, path_array,
653 addrcp, sizecp, create);
656 free(duped_str);
657 return node;
661 * Find a node from an alias
663 * @param tree The device tree.
664 * @param alias The alias name.
665 * @return The found node, or NULL.
667 struct device_tree_node *dt_find_node_by_alias(struct device_tree *tree,
668 const char *alias)
670 struct device_tree_node *node;
671 const char *alias_path;
673 node = dt_find_node_by_path(tree, "/aliases", NULL, NULL, 0);
674 if (!node)
675 return NULL;
677 alias_path = dt_find_string_prop(node, alias);
678 if (!alias_path)
679 return NULL;
681 return dt_find_node_by_path(tree, alias_path, NULL, NULL, 0);
684 struct device_tree_node *dt_find_node_by_phandle(struct device_tree_node *root,
685 uint32_t phandle)
687 if (!root)
688 return NULL;
690 if (root->phandle == phandle)
691 return root;
693 struct device_tree_node *node;
694 struct device_tree_node *result;
695 list_for_each(node, root->children, list_node) {
696 result = dt_find_node_by_phandle(node, phandle);
697 if (result)
698 return result;
701 return NULL;
705 * Check if given node is compatible.
707 * @param node The node which is to be checked for compatible property.
708 * @param compat The compatible string to match.
709 * @return 1 = compatible, 0 = not compatible.
711 static int dt_check_compat_match(struct device_tree_node *node,
712 const char *compat)
714 struct device_tree_property *prop;
716 list_for_each(prop, node->properties, list_node) {
717 if (!strcmp("compatible", prop->prop.name)) {
718 size_t bytes = prop->prop.size;
719 const char *str = prop->prop.data;
720 while (bytes > 0) {
721 if (!strncmp(compat, str, bytes))
722 return 1;
723 size_t len = strnlen(str, bytes) + 1;
724 if (bytes <= len)
725 break;
726 str += len;
727 bytes -= len;
729 break;
733 return 0;
737 * Find a node from a compatible string, in the subtree of a parent node.
739 * @param parent The parent node under which to look.
740 * @param compat The compatible string to find.
741 * @return The found node, or NULL.
743 struct device_tree_node *dt_find_compat(struct device_tree_node *parent,
744 const char *compat)
746 /* Check if the parent node itself is compatible. */
747 if (dt_check_compat_match(parent, compat))
748 return parent;
750 struct device_tree_node *child;
751 list_for_each(child, parent->children, list_node) {
752 struct device_tree_node *found = dt_find_compat(child, compat);
753 if (found)
754 return found;
757 return NULL;
761 * Find the next compatible child of a given parent. All children upto the
762 * child passed in by caller are ignored. If child is NULL, it considers all the
763 * children to find the first child which is compatible.
765 * @param parent The parent node under which to look.
766 * @param child The child node to start search from (exclusive). If NULL
767 * consider all children.
768 * @param compat The compatible string to find.
769 * @return The found node, or NULL.
771 struct device_tree_node *
772 dt_find_next_compat_child(struct device_tree_node *parent,
773 struct device_tree_node *child,
774 const char *compat)
776 struct device_tree_node *next;
777 int ignore = 0;
779 if (child)
780 ignore = 1;
782 list_for_each(next, parent->children, list_node) {
783 if (ignore) {
784 if (child == next)
785 ignore = 0;
786 continue;
789 if (dt_check_compat_match(next, compat))
790 return next;
793 return NULL;
797 * Find a node with matching property value, in the subtree of a parent node.
799 * @param parent The parent node under which to look.
800 * @param name The property name to look for.
801 * @param data The property value to look for.
802 * @param size The property size.
804 struct device_tree_node *dt_find_prop_value(struct device_tree_node *parent,
805 const char *name, void *data,
806 size_t size)
808 struct device_tree_property *prop;
810 /* Check if parent itself has the required property value. */
811 list_for_each(prop, parent->properties, list_node) {
812 if (!strcmp(name, prop->prop.name)) {
813 size_t bytes = prop->prop.size;
814 const void *prop_data = prop->prop.data;
815 if (size != bytes)
816 break;
817 if (!memcmp(data, prop_data, size))
818 return parent;
819 break;
823 struct device_tree_node *child;
824 list_for_each(child, parent->children, list_node) {
825 struct device_tree_node *found = dt_find_prop_value(child, name,
826 data, size);
827 if (found)
828 return found;
830 return NULL;
834 * Write an arbitrary sized big-endian integer into a pointer.
836 * @param dest Pointer to the DT property data buffer to write.
837 * @param src The integer to write (in CPU endianness).
838 * @param length the length of the destination integer in bytes.
840 void dt_write_int(u8 *dest, u64 src, size_t length)
842 while (length--) {
843 dest[length] = (u8)src;
844 src >>= 8;
849 * Delete a property by name in a given node if it exists.
851 * @param node The device tree node to operate on.
852 * @param name The name of the property to delete.
854 void dt_delete_prop(struct device_tree_node *node, const char *name)
856 struct device_tree_property *prop;
858 list_for_each(prop, node->properties, list_node) {
859 if (!strcmp(prop->prop.name, name)) {
860 list_remove(&prop->list_node);
861 return;
867 * Add an arbitrary property to a node, or update it if it already exists.
869 * @param node The device tree node to add to.
870 * @param name The name of the new property.
871 * @param data The raw data blob to be stored in the property.
872 * @param size The size of data in bytes.
874 void dt_add_bin_prop(struct device_tree_node *node, const char *name,
875 void *data, size_t size)
877 struct device_tree_property *prop;
879 list_for_each(prop, node->properties, list_node) {
880 if (!strcmp(prop->prop.name, name)) {
881 prop->prop.data = data;
882 prop->prop.size = size;
883 return;
887 prop = xzalloc(sizeof(*prop));
888 list_insert_after(&prop->list_node, &node->properties);
889 prop->prop.name = name;
890 prop->prop.data = data;
891 prop->prop.size = size;
895 * Find given string property in a node and return its content.
897 * @param node The device tree node to search.
898 * @param name The name of the property.
899 * @return The found string, or NULL.
901 const char *dt_find_string_prop(const struct device_tree_node *node,
902 const char *name)
904 const void *content;
905 size_t size;
907 dt_find_bin_prop(node, name, &content, &size);
909 return content;
913 * Find given property in a node.
915 * @param node The device tree node to search.
916 * @param name The name of the property.
917 * @param data Pointer to return raw data blob in the property.
918 * @param size Pointer to return the size of data in bytes.
920 void dt_find_bin_prop(const struct device_tree_node *node, const char *name,
921 const void **data, size_t *size)
923 struct device_tree_property *prop;
925 *data = NULL;
926 *size = 0;
928 list_for_each(prop, node->properties, list_node) {
929 if (!strcmp(prop->prop.name, name)) {
930 *data = prop->prop.data;
931 *size = prop->prop.size;
932 return;
938 * Add a string property to a node, or update it if it already exists.
940 * @param node The device tree node to add to.
941 * @param name The name of the new property.
942 * @param str The zero-terminated string to be stored in the property.
944 void dt_add_string_prop(struct device_tree_node *node, const char *name,
945 const char *str)
947 dt_add_bin_prop(node, name, (char *)str, strlen(str) + 1);
951 * Add a 32-bit integer property to a node, or update it if it already exists.
953 * @param node The device tree node to add to.
954 * @param name The name of the new property.
955 * @param val The integer to be stored in the property.
957 void dt_add_u32_prop(struct device_tree_node *node, const char *name, u32 val)
959 u32 *val_ptr = xmalloc(sizeof(val));
960 *val_ptr = htobe32(val);
961 dt_add_bin_prop(node, name, val_ptr, sizeof(*val_ptr));
965 * Add a 64-bit integer property to a node, or update it if it already exists.
967 * @param node The device tree node to add to.
968 * @param name The name of the new property.
969 * @param val The integer to be stored in the property.
971 void dt_add_u64_prop(struct device_tree_node *node, const char *name, u64 val)
973 u64 *val_ptr = xmalloc(sizeof(val));
974 *val_ptr = htobe64(val);
975 dt_add_bin_prop(node, name, val_ptr, sizeof(*val_ptr));
979 * Add a 'reg' address list property to a node, or update it if it exists.
981 * @param node The device tree node to add to.
982 * @param addrs Array of address values to be stored in the property.
983 * @param sizes Array of corresponding size values to 'addrs'.
984 * @param count Number of values in 'addrs' and 'sizes' (must be equal).
985 * @param addr_cells Value of #address-cells property valid for this node.
986 * @param size_cells Value of #size-cells property valid for this node.
988 void dt_add_reg_prop(struct device_tree_node *node, u64 *addrs, u64 *sizes,
989 int count, u32 addr_cells, u32 size_cells)
991 int i;
992 size_t length = (addr_cells + size_cells) * sizeof(u32) * count;
993 u8 *data = xmalloc(length);
994 u8 *cur = data;
996 for (i = 0; i < count; i++) {
997 dt_write_int(cur, addrs[i], addr_cells * sizeof(u32));
998 cur += addr_cells * sizeof(u32);
999 dt_write_int(cur, sizes[i], size_cells * sizeof(u32));
1000 cur += size_cells * sizeof(u32);
1003 dt_add_bin_prop(node, "reg", data, length);
1007 * Fixups to apply to a kernel's device tree before booting it.
1010 struct list_node device_tree_fixups;
1012 int dt_apply_fixups(struct device_tree *tree)
1014 struct device_tree_fixup *fixup;
1015 list_for_each(fixup, device_tree_fixups, list_node) {
1016 assert(fixup->fixup);
1017 if (fixup->fixup(fixup, tree))
1018 return 1;
1020 return 0;
1023 int dt_set_bin_prop_by_path(struct device_tree *tree, const char *path,
1024 void *data, size_t data_size, int create)
1026 char *path_copy, *prop_name;
1027 struct device_tree_node *dt_node;
1029 path_copy = strdup(path);
1031 if (!path_copy) {
1032 printk(BIOS_ERR, "Failed to allocate a copy of path %s\n",
1033 path);
1034 return 1;
1037 prop_name = strrchr(path_copy, '/');
1038 if (!prop_name) {
1039 free(path_copy);
1040 printk(BIOS_ERR, "Path %s does not include '/'\n", path);
1041 return 1;
1044 *prop_name++ = '\0'; /* Separate path from the property name. */
1046 dt_node = dt_find_node_by_path(tree, path_copy, NULL,
1047 NULL, create);
1049 if (!dt_node) {
1050 printk(BIOS_ERR, "Failed to %s %s in the device tree\n",
1051 create ? "create" : "find", path_copy);
1052 free(path_copy);
1053 return 1;
1056 dt_add_bin_prop(dt_node, prop_name, data, data_size);
1057 free(path_copy);
1059 return 0;
1063 * Prepare the /reserved-memory/ node.
1065 * Technically, this can be called more than one time, to init and/or retrieve
1066 * the node. But dt_add_u32_prop() may leak a bit of memory if you do.
1068 * @tree: Device tree to add/retrieve from.
1069 * @return: The /reserved-memory/ node (or NULL, if error).
1071 struct device_tree_node *dt_init_reserved_memory_node(struct device_tree *tree)
1073 struct device_tree_node *reserved;
1074 u32 addr = 0, size = 0;
1076 reserved = dt_find_node_by_path(tree, "/reserved-memory", &addr,
1077 &size, 1);
1078 if (!reserved)
1079 return NULL;
1081 /* Binding doc says this should have the same #{address,size}-cells as
1082 the root. */
1083 dt_add_u32_prop(reserved, "#address-cells", addr);
1084 dt_add_u32_prop(reserved, "#size-cells", size);
1085 /* Binding doc says this should be empty (1:1 mapping from root). */
1086 dt_add_bin_prop(reserved, "ranges", NULL, 0);
1088 return reserved;
1092 * Increment a single phandle in prop at a given offset by a given adjustment.
1094 * @param prop Property whose phandle should be adjusted.
1095 * @param adjustment Value that should be added to the existing phandle.
1096 * @param offset Byte offset of the phandle in the property data.
1098 * @return New phandle value, or 0 on error.
1100 static uint32_t dt_adjust_phandle(struct device_tree_property *prop,
1101 uint32_t adjustment, uint32_t offset)
1103 if (offset + 4 > prop->prop.size)
1104 return 0;
1106 uint32_t phandle = be32dec(prop->prop.data + offset);
1107 if (phandle == 0 ||
1108 phandle == FDT_PHANDLE_ILLEGAL ||
1109 phandle == 0xffffffff)
1110 return 0;
1112 phandle += adjustment;
1113 if (phandle >= FDT_PHANDLE_ILLEGAL)
1114 return 0;
1116 be32enc(prop->prop.data + offset, phandle);
1117 return phandle;
1121 * Adjust all phandles in subtree by adding a new base offset.
1123 * @param node Root node of the subtree to work on.
1124 * @param base New phandle base to be added to all phandles.
1126 * @return New highest phandle in the subtree, or 0 on error.
1128 static uint32_t dt_adjust_all_phandles(struct device_tree_node *node,
1129 uint32_t base)
1131 uint32_t new_max = MAX(base, 1); /* make sure we don't return 0 */
1132 struct device_tree_property *prop;
1133 struct device_tree_node *child;
1135 if (!node)
1136 return new_max;
1138 list_for_each(prop, node->properties, list_node)
1139 if (dt_prop_is_phandle(prop)) {
1140 node->phandle = dt_adjust_phandle(prop, base, 0);
1141 if (!node->phandle)
1142 return 0;
1143 new_max = MAX(new_max, node->phandle);
1144 } /* no break -- can have more than one phandle prop */
1146 list_for_each(child, node->children, list_node)
1147 new_max = MAX(new_max, dt_adjust_all_phandles(child, base));
1149 return new_max;
1153 * Apply a /__local_fixup__ subtree to the corresponding overlay subtree.
1155 * @param node Root node of the overlay subtree to fix up.
1156 * @param node Root node of the /__local_fixup__ subtree.
1157 * @param base Adjustment that was added to phandles in the overlay.
1159 * @return 0 on success, -1 on error.
1161 static int dt_fixup_locals(struct device_tree_node *node,
1162 struct device_tree_node *fixup, uint32_t base)
1164 struct device_tree_property *prop;
1165 struct device_tree_property *fixup_prop;
1166 struct device_tree_node *child;
1167 struct device_tree_node *fixup_child;
1168 int i;
1171 * For local fixups the /__local_fixup__ subtree contains the same node
1172 * hierarchy as the main tree we're fixing up. Each property contains
1173 * the fixup offsets for the respective property in the main tree. For
1174 * each property in the fixup node, find the corresponding property in
1175 * the base node and apply fixups to all offsets it specifies.
1177 list_for_each(fixup_prop, fixup->properties, list_node) {
1178 struct device_tree_property *base_prop = NULL;
1179 list_for_each(prop, node->properties, list_node)
1180 if (!strcmp(prop->prop.name, fixup_prop->prop.name)) {
1181 base_prop = prop;
1182 break;
1185 /* We should always find a corresponding base prop for a fixup,
1186 and fixup props contain a list of 32-bit fixup offsets. */
1187 if (!base_prop || fixup_prop->prop.size % sizeof(uint32_t))
1188 return -1;
1190 for (i = 0; i < fixup_prop->prop.size; i += sizeof(uint32_t))
1191 if (!dt_adjust_phandle(base_prop, base, be32dec(
1192 fixup_prop->prop.data + i)))
1193 return -1;
1196 /* Now recursively descend both the base tree and the /__local_fixups__
1197 subtree in sync to apply all fixups. */
1198 list_for_each(fixup_child, fixup->children, list_node) {
1199 struct device_tree_node *base_child = NULL;
1200 list_for_each(child, node->children, list_node)
1201 if (!strcmp(child->name, fixup_child->name)) {
1202 base_child = child;
1203 break;
1206 /* All fixup nodes should have a corresponding base node. */
1207 if (!base_child)
1208 return -1;
1210 if (dt_fixup_locals(base_child, fixup_child, base) < 0)
1211 return -1;
1214 return 0;
1218 * Update all /__symbols__ properties in an overlay that start with
1219 * "/fragment@X/__overlay__" with corresponding path prefix in the base tree.
1221 * @param symbols /__symbols__ done to update.
1222 * @param fragment /fragment@X node that references to should be updated.
1223 * @param base_path Path of base tree node that the fragment overlaid.
1225 static void dt_fix_symbols(struct device_tree_node *symbols,
1226 struct device_tree_node *fragment,
1227 const char *base_path)
1229 struct device_tree_property *prop;
1230 char buf[512]; /* Should be enough for maximum DT path length? */
1231 char node_path[64]; /* easily enough for /fragment@XXXX/__overlay__ */
1233 if (!symbols) /* If the overlay has no /__symbols__ node, we're done! */
1234 return;
1236 int len = snprintf(node_path, sizeof(node_path), "/%s/__overlay__",
1237 fragment->name);
1239 list_for_each(prop, symbols->properties, list_node)
1240 if (!strncmp(prop->prop.data, node_path, len)) {
1241 prop->prop.size = snprintf(buf, sizeof(buf), "%s%s",
1242 base_path, (char *)prop->prop.data + len) + 1;
1243 free(prop->prop.data);
1244 prop->prop.data = strdup(buf);
1249 * Fix up overlay according to a property in /__fixup__. If the fixed property
1250 * is a /fragment@X:target, also update /__symbols__ references to fragment.
1252 * @params overlay Overlay to fix up.
1253 * @params fixup /__fixup__ property.
1254 * @params phandle phandle value to insert where the fixup points to.
1255 * @params base_path Path to the base DT node that the fixup points to.
1256 * @params overlay_symbols /__symbols__ node of the overlay.
1258 * @return 0 on success, -1 on error.
1260 static int dt_fixup_external(struct device_tree *overlay,
1261 struct device_tree_property *fixup,
1262 uint32_t phandle, const char *base_path,
1263 struct device_tree_node *overlay_symbols)
1265 struct device_tree_property *prop;
1267 /* External fixup properties are encoded as "<path>:<prop>:<offset>". */
1268 char *entry = fixup->prop.data;
1269 while ((void *)entry < fixup->prop.data + fixup->prop.size) {
1270 /* okay to destroy fixup property value, won't need it again */
1271 char *node_path = entry;
1272 entry = strchr(node_path, ':');
1273 if (!entry)
1274 return -1;
1275 *entry++ = '\0';
1277 char *prop_name = entry;
1278 entry = strchr(prop_name, ':');
1279 if (!entry)
1280 return -1;
1281 *entry++ = '\0';
1283 struct device_tree_node *ovl_node = dt_find_node_by_path(
1284 overlay, node_path, NULL, NULL, 0);
1285 if (!ovl_node || !isdigit(*entry))
1286 return -1;
1288 struct device_tree_property *ovl_prop = NULL;
1289 list_for_each(prop, ovl_node->properties, list_node)
1290 if (!strcmp(prop->prop.name, prop_name)) {
1291 ovl_prop = prop;
1292 break;
1295 /* Move entry to first char after number, must be a '\0'. */
1296 uint32_t offset = skip_atoi(&entry);
1297 if (!ovl_prop || offset + 4 > ovl_prop->prop.size || entry[0])
1298 return -1;
1299 entry++; /* jump over '\0' to potential next fixup */
1301 be32enc(ovl_prop->prop.data + offset, phandle);
1303 /* If this is a /fragment@X:target property, update references
1304 to this fragment in the overlay __symbols__ now. */
1305 if (offset == 0 && !strcmp(prop_name, "target") &&
1306 !strchr(node_path + 1, '/')) /* only toplevel nodes */
1307 dt_fix_symbols(overlay_symbols, ovl_node, base_path);
1310 return 0;
1314 * Apply all /__fixup__ properties in the overlay. This will destroy the
1315 * property data in /__fixup__ and it should not be accessed again.
1317 * @params tree Base device tree that the overlay updates.
1318 * @params symbols /__symbols__ node of the base device tree.
1319 * @params overlay Overlay to fix up.
1320 * @params fixups /__fixup__ node in the overlay.
1321 * @params overlay_symbols /__symbols__ node of the overlay.
1323 * @return 0 on success, -1 on error.
1325 static int dt_fixup_all_externals(struct device_tree *tree,
1326 struct device_tree_node *symbols,
1327 struct device_tree *overlay,
1328 struct device_tree_node *fixups,
1329 struct device_tree_node *overlay_symbols)
1331 struct device_tree_property *fix;
1333 /* If we have any external fixups, base tree must have /__symbols__. */
1334 if (!symbols)
1335 return -1;
1338 * Unlike /__local_fixups__, /__fixups__ is not a whole subtree that
1339 * mirrors the node hierarchy. It's just a directory of fixup properties
1340 * that each directly contain all information necessary to apply them.
1342 list_for_each(fix, fixups->properties, list_node) {
1343 /* The name of a fixup property is the label of the node we want
1344 a property to phandle-reference. Look up in /__symbols__. */
1345 const char *path = dt_find_string_prop(symbols, fix->prop.name);
1346 if (!path)
1347 return -1;
1349 /* Find node the label pointed to to figure out its phandle. */
1350 struct device_tree_node *node = dt_find_node_by_path(tree, path,
1351 NULL, NULL, 0);
1352 if (!node)
1353 return -1;
1355 /* Write into the overlay property(s) pointing to that node. */
1356 if (dt_fixup_external(overlay, fix, node->phandle,
1357 path, overlay_symbols) < 0)
1358 return -1;
1361 return 0;
1365 * Copy all nodes and properties from one DT subtree into another. This is a
1366 * shallow copy so both trees will point to the same property data afterwards.
1368 * @params dst Destination subtree to copy into.
1369 * @params src Source subtree to copy from.
1370 * @params upd 1 to overwrite same-name properties, 0 to discard them.
1372 static void dt_copy_subtree(struct device_tree_node *dst,
1373 struct device_tree_node *src, int upd)
1375 struct device_tree_property *prop;
1376 struct device_tree_property *src_prop;
1377 list_for_each(src_prop, src->properties, list_node) {
1378 if (dt_prop_is_phandle(src_prop) ||
1379 !strcmp(src_prop->prop.name, "name")) {
1380 printk(BIOS_DEBUG,
1381 "WARNING: ignoring illegal overlay prop '%s'\n",
1382 src_prop->prop.name);
1383 continue;
1386 struct device_tree_property *dst_prop = NULL;
1387 list_for_each(prop, dst->properties, list_node)
1388 if (!strcmp(prop->prop.name, src_prop->prop.name)) {
1389 dst_prop = prop;
1390 break;
1393 if (dst_prop) {
1394 if (!upd) {
1395 printk(BIOS_DEBUG,
1396 "WARNING: ignoring prop update '%s'\n",
1397 src_prop->prop.name);
1398 continue;
1400 } else {
1401 dst_prop = xzalloc(sizeof(*dst_prop));
1402 list_insert_after(&dst_prop->list_node,
1403 &dst->properties);
1406 dst_prop->prop = src_prop->prop;
1409 struct device_tree_node *node;
1410 struct device_tree_node *src_node;
1411 list_for_each(src_node, src->children, list_node) {
1412 struct device_tree_node *dst_node = NULL;
1413 list_for_each(node, dst->children, list_node)
1414 if (!strcmp(node->name, src_node->name)) {
1415 dst_node = node;
1416 break;
1419 if (!dst_node) {
1420 dst_node = xzalloc(sizeof(*dst_node));
1421 *dst_node = *src_node;
1422 list_insert_after(&dst_node->list_node, &dst->children);
1423 } else {
1424 dt_copy_subtree(dst_node, src_node, upd);
1430 * Apply an overlay /fragment@X node to a base device tree.
1432 * @param tree Base device tree.
1433 * @param fragment /fragment@X node.
1434 * @params overlay_symbols /__symbols__ node of the overlay.
1436 * @return 0 on success, -1 on error.
1438 static int dt_import_fragment(struct device_tree *tree,
1439 struct device_tree_node *fragment,
1440 struct device_tree_node *overlay_symbols)
1442 /* The actual overlaid nodes/props are in an __overlay__ child node. */
1443 static const char *overlay_path[] = { "__overlay__", NULL };
1444 struct device_tree_node *overlay = dt_find_node(fragment, overlay_path,
1445 NULL, NULL, 0);
1447 /* If it doesn't have an __overlay__ child, it's not a fragment. */
1448 if (!overlay)
1449 return 0;
1451 /* Target node of the fragment can be given by path or by phandle. */
1452 struct device_tree_property *prop;
1453 struct device_tree_property *phandle = NULL;
1454 struct device_tree_property *path = NULL;
1455 list_for_each(prop, fragment->properties, list_node) {
1456 if (!strcmp(prop->prop.name, "target")) {
1457 phandle = prop;
1458 break; /* phandle target has priority, stop looking */
1460 if (!strcmp(prop->prop.name, "target-path"))
1461 path = prop;
1464 struct device_tree_node *target = NULL;
1465 if (phandle) {
1466 if (phandle->prop.size != sizeof(uint32_t))
1467 return -1;
1468 target = dt_find_node_by_phandle(tree->root,
1469 be32dec(phandle->prop.data));
1470 /* Symbols already updated as part of dt_fixup_external(). */
1471 } else if (path) {
1472 target = dt_find_node_by_path(tree, path->prop.data,
1473 NULL, NULL, 0);
1474 dt_fix_symbols(overlay_symbols, fragment, path->prop.data);
1476 if (!target)
1477 return -1;
1479 dt_copy_subtree(target, overlay, 1);
1480 return 0;
1484 * Apply a device tree overlay to a base device tree. This will
1485 * destroy/incorporate the overlay data, so it should not be freed or reused.
1486 * See dtc.git/Documentation/dt-object-internal.txt for overlay format details.
1488 * @param tree Unflattened base device tree to add the overlay into.
1489 * @param overlay Unflattened overlay device tree to apply to the base.
1491 * @return 0 on success, -1 on error.
1493 int dt_apply_overlay(struct device_tree *tree, struct device_tree *overlay)
1496 * First, we need to make sure phandles inside the overlay don't clash
1497 * with those in the base tree. We just define the highest phandle value
1498 * in the base tree as the "phandle offset" for this overlay and
1499 * increment all phandles in it by that value.
1501 uint32_t phandle_base = tree->max_phandle;
1502 uint32_t new_max = dt_adjust_all_phandles(overlay->root, phandle_base);
1503 if (!new_max) {
1504 printk(BIOS_DEBUG, "ERROR: invalid phandles in overlay\n");
1505 return -1;
1507 tree->max_phandle = new_max;
1509 /* Now that we changed phandles in the overlay, we need to update any
1510 nodes referring to them. Those are listed in /__local_fixups__. */
1511 struct device_tree_node *local_fixups = dt_find_node_by_path(overlay,
1512 "/__local_fixups__", NULL, NULL, 0);
1513 if (local_fixups && dt_fixup_locals(overlay->root, local_fixups,
1514 phandle_base) < 0) {
1515 printk(BIOS_DEBUG, "ERROR: invalid local fixups in overlay\n");
1516 return -1;
1520 * Besides local phandle references (from nodes within the overlay to
1521 * other nodes within the overlay), the overlay may also contain phandle
1522 * references to the base tree. These are stored with invalid values and
1523 * must be updated now. /__symbols__ contains a list of all labels in
1524 * the base tree, and /__fixups__ describes all nodes in the overlay
1525 * that contain external phandle references.
1526 * We also take this opportunity to update all /fragment@X/__overlay__/
1527 * prefixes in the overlay's /__symbols__ node to the correct path that
1528 * the fragment will be placed in later, since this is the only step
1529 * where we have all necessary information for that easily available.
1531 struct device_tree_node *symbols = dt_find_node_by_path(tree,
1532 "/__symbols__", NULL, NULL, 0);
1533 struct device_tree_node *fixups = dt_find_node_by_path(overlay,
1534 "/__fixups__", NULL, NULL, 0);
1535 struct device_tree_node *overlay_symbols = dt_find_node_by_path(overlay,
1536 "/__symbols__", NULL, NULL, 0);
1537 if (fixups && dt_fixup_all_externals(tree, symbols, overlay,
1538 fixups, overlay_symbols) < 0) {
1539 printk(BIOS_DEBUG,
1540 "ERROR: cannot match external fixups from overlay\n");
1541 return -1;
1544 /* After all this fixing up, we can finally merge overlay into the tree
1545 (one fragment at a time, because for some reason it's split up). */
1546 struct device_tree_node *fragment;
1547 list_for_each(fragment, overlay->root->children, list_node)
1548 if (dt_import_fragment(tree, fragment, overlay_symbols) < 0) {
1549 printk(BIOS_DEBUG, "ERROR: bad DT fragment '%s'\n",
1550 fragment->name);
1551 return -1;
1555 * We need to also update /__symbols__ to include labels from this
1556 * overlay, in case we want to load further overlays with external
1557 * phandle references to it. If the base tree already has a /__symbols__
1558 * we merge them together, otherwise we just insert the overlay's
1559 * /__symbols__ node into the base tree root.
1561 if (overlay_symbols) {
1562 if (symbols)
1563 dt_copy_subtree(symbols, overlay_symbols, 0);
1564 else
1565 list_insert_after(&overlay_symbols->list_node,
1566 &tree->root->children);
1569 return 0;