57#include "libfdt_internal.h"
74overlay_get_target_phandle (
82 val = fdt_getprop (fdto, fragment,
"target", &len);
87 if ((len !=
sizeof (*val)) || (fdt32_to_cpu (*val) == (uint32_t)-1)) {
91 return fdt32_to_cpu (*val);
118 const char *path =
NULL;
119 int path_len = 0, ret;
122 phandle = overlay_get_target_phandle (fdto, fragment);
123 if (phandle == (uint32_t)-1) {
124 return -FDT_ERR_BADPHANDLE;
130 path = fdt_getprop (fdto, fragment,
"target-path", &path_len);
132 ret = fdt_path_offset (fdt, path);
137 ret = fdt_node_offset_by_phandle (fdt, phandle);
147 if ((ret < 0) && (path_len == -FDT_ERR_NOTFOUND)) {
148 ret = -FDT_ERR_BADOVERLAY;
158 *pathp = path ? path :
NULL;
179overlay_phandle_add_offset (
190 val = fdt_getprop (fdt, node, name, &len);
195 if (len !=
sizeof (*val)) {
196 return -FDT_ERR_BADPHANDLE;
199 adj_val = fdt32_to_cpu (*val);
200 if ((adj_val + delta) < adj_val) {
201 return -FDT_ERR_NOPHANDLES;
205 if (adj_val == (uint32_t)-1) {
206 return -FDT_ERR_NOPHANDLES;
209 return fdt_setprop_inplace_u32 (fdt, node, name, adj_val);
228overlay_adjust_node_phandles (
237 ret = overlay_phandle_add_offset (fdto, node,
"phandle", delta);
238 if (ret && (ret != -FDT_ERR_NOTFOUND)) {
242 ret = overlay_phandle_add_offset (fdto, node,
"linux,phandle", delta);
243 if (ret && (ret != -FDT_ERR_NOTFOUND)) {
247 fdt_for_each_subnode (child, fdto, node) {
248 ret = overlay_adjust_node_phandles (fdto, child, delta);
272overlay_adjust_local_phandles (
280 return overlay_adjust_node_phandles (fdto, 0, delta);
303overlay_update_local_node_references (
314 fdt_for_each_property_offset (fixup_prop, fdto, fixup_node) {
315 const fdt32_t *fixup_val;
316 const char *tree_val;
322 fixup_val = fdt_getprop_by_offset (
332 if (fixup_len %
sizeof (uint32_t)) {
333 return -FDT_ERR_BADOVERLAY;
336 tree_val = fdt_getprop (fdto, tree_node, name, &tree_len);
338 if (tree_len == -FDT_ERR_NOTFOUND) {
339 return -FDT_ERR_BADOVERLAY;
345 for (i = 0; i < (fixup_len /
sizeof (uint32_t)); i++) {
349 poffset = fdt32_to_cpu (fixup_val[i]);
357 memcpy (&adj_val, tree_val + poffset,
sizeof (adj_val));
359 adj_val = cpu_to_fdt32 (fdt32_to_cpu (adj_val) + delta);
361 ret = fdt_setprop_inplace_namelen_partial (
370 if (ret == -FDT_ERR_NOSPACE) {
371 return -FDT_ERR_BADOVERLAY;
380 fdt_for_each_subnode (fixup_child, fdto, fixup_node) {
381 const char *fixup_child_name = fdt_get_name (
388 tree_child = fdt_subnode_offset (
393 if (tree_child == -FDT_ERR_NOTFOUND) {
394 return -FDT_ERR_BADOVERLAY;
397 if (tree_child < 0) {
401 ret = overlay_update_local_node_references (
433overlay_update_local_references (
440 fixups = fdt_path_offset (fdto,
"/__local_fixups__");
443 if (fixups == -FDT_ERR_NOTFOUND) {
453 return overlay_update_local_node_references (
485overlay_fixup_one_phandle (
497 const char *symbol_path;
499 fdt32_t phandle_prop;
500 int symbol_off, fixup_off;
503 if (symbols_off < 0) {
507 symbol_path = fdt_getprop (
517 symbol_off = fdt_path_offset (fdt, symbol_path);
518 if (symbol_off < 0) {
522 phandle = fdt_get_phandle (fdt, symbol_off);
524 return -FDT_ERR_NOTFOUND;
527 fixup_off = fdt_path_offset_namelen (fdto, path, path_len);
528 if (fixup_off == -FDT_ERR_NOTFOUND) {
529 return -FDT_ERR_BADOVERLAY;
536 phandle_prop = cpu_to_fdt32 (phandle);
537 return fdt_setprop_inplace_namelen_partial (
544 sizeof (phandle_prop)
575overlay_fixup_phandle (
586 value = fdt_getprop_by_offset (
593 if (len == -FDT_ERR_NOTFOUND) {
594 return -FDT_ERR_INTERNAL;
601 const char *path, *name, *fixup_end;
602 const char *fixup_str = value;
603 uint32_t path_len, name_len;
608 fixup_end = memchr (value,
'\0', len);
610 return -FDT_ERR_BADOVERLAY;
613 fixup_len = fixup_end - fixup_str;
615 len -= fixup_len + 1;
616 value += fixup_len + 1;
619 sep = memchr (fixup_str,
':', fixup_len);
620 if (!sep || (*sep !=
':')) {
621 return -FDT_ERR_BADOVERLAY;
624 path_len = sep - path;
625 if (path_len == (fixup_len - 1)) {
626 return -FDT_ERR_BADOVERLAY;
629 fixup_len -= path_len + 1;
631 sep = memchr (name,
':', fixup_len);
632 if (!sep || (*sep !=
':')) {
633 return -FDT_ERR_BADOVERLAY;
636 name_len = sep - name;
638 return -FDT_ERR_BADOVERLAY;
641 poffset = strtoul (sep + 1, &endptr, 10);
642 if ((*endptr !=
'\0') || (endptr <= (sep + 1))) {
643 return -FDT_ERR_BADOVERLAY;
646 ret = overlay_fixup_one_phandle (
683overlay_fixup_phandles (
688 int fixups_off, symbols_off;
692 fixups_off = fdt_path_offset (fdto,
"/__fixups__");
693 if (fixups_off == -FDT_ERR_NOTFOUND) {
697 if (fixups_off < 0) {
702 symbols_off = fdt_path_offset (fdt,
"/__symbols__");
703 if (((symbols_off < 0) && (symbols_off != -FDT_ERR_NOTFOUND))) {
707 fdt_for_each_property_offset (property, fdto, fixups_off) {
710 ret = overlay_fixup_phandle (fdt, fdto, symbols_off, property);
749 fdt_for_each_property_offset (property, fdto, node) {
755 prop = fdt_getprop_by_offset (
761 if (prop_len == -FDT_ERR_NOTFOUND) {
762 return -FDT_ERR_INTERNAL;
769 ret = fdt_setprop (fdt, target, name, prop, prop_len);
775 fdt_for_each_subnode (subnode, fdto, node) {
776 const char *name = fdt_get_name (fdto, subnode,
NULL);
780 nnode = fdt_add_subnode (fdt, target, name);
781 if (nnode == -FDT_ERR_EXISTS) {
782 nnode = fdt_subnode_offset (fdt, target, name);
783 if (nnode == -FDT_ERR_NOTFOUND) {
784 return -FDT_ERR_INTERNAL;
792 ret = overlay_apply_node (fdt, nnode, fdto, subnode);
824 fdt_for_each_subnode (fragment, fdto, 0) {
833 overlay = fdt_subnode_offset (fdto, fragment,
"__overlay__");
834 if (overlay == -FDT_ERR_NOTFOUND) {
842 target = overlay_get_target (fdt, fdto, fragment,
NULL);
847 ret = overlay_apply_node (fdt, target, fdto, overlay);
862 int len = 0, namelen;
865 FDT_CHECK_HEADER (fdt);
868 name = fdt_get_name (fdt, nodeoffset, &namelen);
878 nodeoffset = fdt_parent_offset (fdt, nodeoffset);
879 if (nodeoffset < 0) {
911overlay_symbol_update (
916 int root_sym, ov_sym, prop, path_len, fragment, target;
917 int len, frag_name_len, ret, rel_path_len;
921 const char *frag_name;
922 const char *rel_path;
923 const char *target_path;
927 ov_sym = fdt_subnode_offset (fdto, 0,
"__symbols__");
934 root_sym = fdt_subnode_offset (fdt, 0,
"__symbols__");
937 if (root_sym == -FDT_ERR_NOTFOUND) {
938 root_sym = fdt_add_subnode (fdt, 0,
"__symbols__");
947 fdt_for_each_property_offset (prop, fdto, ov_sym) {
948 path = fdt_getprop_by_offset (fdto, prop, &name, &path_len);
954 if ((path_len < 1) || (memchr (path,
'\0', path_len) != &path[path_len - 1])) {
955 return -FDT_ERR_BADVALUE;
964 return -FDT_ERR_BADVALUE;
968 s = strchr (path + 1,
'/');
970 return -FDT_ERR_BADOVERLAY;
973 frag_name = path + 1;
974 frag_name_len = s - path - 1;
977 len =
sizeof (
"/__overlay__/") - 1;
978 if (((e - s) < len) || memcmp (s,
"/__overlay__/", len)) {
979 return -FDT_ERR_BADOVERLAY;
983 rel_path_len = e - rel_path;
986 ret = fdt_subnode_offset_namelen (
994 return -FDT_ERR_BADOVERLAY;
1000 ret = fdt_subnode_offset (fdto, fragment,
"__overlay__");
1002 return -FDT_ERR_BADOVERLAY;
1006 ret = overlay_get_target (fdt, fdto, fragment, &target_path);
1015 ret = get_path_len (fdt, target);
1022 len = strlen (target_path);
1025 ret = fdt_setprop_placeholder (
1029 len + (len > 1) + rel_path_len + 1,
1038 ret = overlay_get_target (fdt, fdto, fragment, &target_path);
1050 ret = fdt_get_path (fdt, target, buf, len + 1);
1055 memcpy (buf, target_path, len + 1);
1062 memcpy (buf + len + 1, rel_path, rel_path_len);
1063 buf[len + 1 + rel_path_len] =
'\0';
1075 uint32_t delta = fdt_get_max_phandle (fdt);
1078 FDT_CHECK_HEADER (fdt);
1079 FDT_CHECK_HEADER (fdto);
1081 ret = overlay_adjust_local_phandles (fdto, delta);
1086 ret = overlay_update_local_references (fdto, delta);
1091 ret = overlay_fixup_phandles (fdt, fdto);
1096 ret = overlay_merge (fdt, fdto);
1101 ret = overlay_symbol_update (fdt, fdto);
1109 fdt_set_magic (fdto, ~0);
1118 fdt_set_magic (fdto, ~0);
1124 fdt_set_magic (fdt, ~0);