Merge https://gitlab.denx.de/u-boot/custodians/u-boot-spi into next
[platform/kernel/u-boot.git] / scripts / dtc / libfdt / fdt_overlay.c
1 // SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
2 /*
3  * libfdt - Flat Device Tree manipulation
4  * Copyright (C) 2016 Free Electrons
5  * Copyright (C) 2016 NextThing Co.
6  */
7 #include "libfdt_env.h"
8
9 #include <fdt.h>
10 #include <libfdt.h>
11
12 #include "libfdt_internal.h"
13
14 /**
15  * overlay_get_target_phandle - retrieves the target phandle of a fragment
16  * @fdto: pointer to the device tree overlay blob
17  * @fragment: node offset of the fragment in the overlay
18  *
19  * overlay_get_target_phandle() retrieves the target phandle of an
20  * overlay fragment when that fragment uses a phandle (target
21  * property) instead of a path (target-path property).
22  *
23  * returns:
24  *      the phandle pointed by the target property
25  *      0, if the phandle was not found
26  *      -1, if the phandle was malformed
27  */
28 static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
29 {
30         const fdt32_t *val;
31         int len;
32
33         val = fdt_getprop(fdto, fragment, "target", &len);
34         if (!val)
35                 return 0;
36
37         if ((len != sizeof(*val)) || (fdt32_to_cpu(*val) == (uint32_t)-1))
38                 return (uint32_t)-1;
39
40         return fdt32_to_cpu(*val);
41 }
42
43 /**
44  * overlay_get_target - retrieves the offset of a fragment's target
45  * @fdt: Base device tree blob
46  * @fdto: Device tree overlay blob
47  * @fragment: node offset of the fragment in the overlay
48  * @pathp: pointer which receives the path of the target (or NULL)
49  *
50  * overlay_get_target() retrieves the target offset in the base
51  * device tree of a fragment, no matter how the actual targeting is
52  * done (through a phandle or a path)
53  *
54  * returns:
55  *      the targeted node offset in the base device tree
56  *      Negative error code on error
57  */
58 static int overlay_get_target(const void *fdt, const void *fdto,
59                               int fragment, char const **pathp)
60 {
61         uint32_t phandle;
62         const char *path = NULL;
63         int path_len = 0, ret;
64
65         /* Try first to do a phandle based lookup */
66         phandle = overlay_get_target_phandle(fdto, fragment);
67         if (phandle == (uint32_t)-1)
68                 return -FDT_ERR_BADPHANDLE;
69
70         /* no phandle, try path */
71         if (!phandle) {
72                 /* And then a path based lookup */
73                 path = fdt_getprop(fdto, fragment, "target-path", &path_len);
74                 if (path)
75                         ret = fdt_path_offset(fdt, path);
76                 else
77                         ret = path_len;
78         } else
79                 ret = fdt_node_offset_by_phandle(fdt, phandle);
80
81         /*
82         * If we haven't found either a target or a
83         * target-path property in a node that contains a
84         * __overlay__ subnode (we wouldn't be called
85         * otherwise), consider it a improperly written
86         * overlay
87         */
88         if (ret < 0 && path_len == -FDT_ERR_NOTFOUND)
89                 ret = -FDT_ERR_BADOVERLAY;
90
91         /* return on error */
92         if (ret < 0)
93                 return ret;
94
95         /* return pointer to path (if available) */
96         if (pathp)
97                 *pathp = path ? path : NULL;
98
99         return ret;
100 }
101
102 /**
103  * overlay_phandle_add_offset - Increases a phandle by an offset
104  * @fdt: Base device tree blob
105  * @node: Device tree overlay blob
106  * @name: Name of the property to modify (phandle or linux,phandle)
107  * @delta: offset to apply
108  *
109  * overlay_phandle_add_offset() increments a node phandle by a given
110  * offset.
111  *
112  * returns:
113  *      0 on success.
114  *      Negative error code on error
115  */
116 static int overlay_phandle_add_offset(void *fdt, int node,
117                                       const char *name, uint32_t delta)
118 {
119         const fdt32_t *val;
120         uint32_t adj_val;
121         int len;
122
123         val = fdt_getprop(fdt, node, name, &len);
124         if (!val)
125                 return len;
126
127         if (len != sizeof(*val))
128                 return -FDT_ERR_BADPHANDLE;
129
130         adj_val = fdt32_to_cpu(*val);
131         if ((adj_val + delta) < adj_val)
132                 return -FDT_ERR_NOPHANDLES;
133
134         adj_val += delta;
135         if (adj_val == (uint32_t)-1)
136                 return -FDT_ERR_NOPHANDLES;
137
138         return fdt_setprop_inplace_u32(fdt, node, name, adj_val);
139 }
140
141 /**
142  * overlay_adjust_node_phandles - Offsets the phandles of a node
143  * @fdto: Device tree overlay blob
144  * @node: Offset of the node we want to adjust
145  * @delta: Offset to shift the phandles of
146  *
147  * overlay_adjust_node_phandles() adds a constant to all the phandles
148  * of a given node. This is mainly use as part of the overlay
149  * application process, when we want to update all the overlay
150  * phandles to not conflict with the overlays of the base device tree.
151  *
152  * returns:
153  *      0 on success
154  *      Negative error code on failure
155  */
156 static int overlay_adjust_node_phandles(void *fdto, int node,
157                                         uint32_t delta)
158 {
159         int child;
160         int ret;
161
162         ret = overlay_phandle_add_offset(fdto, node, "phandle", delta);
163         if (ret && ret != -FDT_ERR_NOTFOUND)
164                 return ret;
165
166         ret = overlay_phandle_add_offset(fdto, node, "linux,phandle", delta);
167         if (ret && ret != -FDT_ERR_NOTFOUND)
168                 return ret;
169
170         fdt_for_each_subnode(child, fdto, node) {
171                 ret = overlay_adjust_node_phandles(fdto, child, delta);
172                 if (ret)
173                         return ret;
174         }
175
176         return 0;
177 }
178
179 /**
180  * overlay_adjust_local_phandles - Adjust the phandles of a whole overlay
181  * @fdto: Device tree overlay blob
182  * @delta: Offset to shift the phandles of
183  *
184  * overlay_adjust_local_phandles() adds a constant to all the
185  * phandles of an overlay. This is mainly use as part of the overlay
186  * application process, when we want to update all the overlay
187  * phandles to not conflict with the overlays of the base device tree.
188  *
189  * returns:
190  *      0 on success
191  *      Negative error code on failure
192  */
193 static int overlay_adjust_local_phandles(void *fdto, uint32_t delta)
194 {
195         /*
196          * Start adjusting the phandles from the overlay root
197          */
198         return overlay_adjust_node_phandles(fdto, 0, delta);
199 }
200
201 /**
202  * overlay_update_local_node_references - Adjust the overlay references
203  * @fdto: Device tree overlay blob
204  * @tree_node: Node offset of the node to operate on
205  * @fixup_node: Node offset of the matching local fixups node
206  * @delta: Offset to shift the phandles of
207  *
208  * overlay_update_local_nodes_references() update the phandles
209  * pointing to a node within the device tree overlay by adding a
210  * constant delta.
211  *
212  * This is mainly used as part of a device tree application process,
213  * where you want the device tree overlays phandles to not conflict
214  * with the ones from the base device tree before merging them.
215  *
216  * returns:
217  *      0 on success
218  *      Negative error code on failure
219  */
220 static int overlay_update_local_node_references(void *fdto,
221                                                 int tree_node,
222                                                 int fixup_node,
223                                                 uint32_t delta)
224 {
225         int fixup_prop;
226         int fixup_child;
227         int ret;
228
229         fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) {
230                 const fdt32_t *fixup_val;
231                 const char *tree_val;
232                 const char *name;
233                 int fixup_len;
234                 int tree_len;
235                 int i;
236
237                 fixup_val = fdt_getprop_by_offset(fdto, fixup_prop,
238                                                   &name, &fixup_len);
239                 if (!fixup_val)
240                         return fixup_len;
241
242                 if (fixup_len % sizeof(uint32_t))
243                         return -FDT_ERR_BADOVERLAY;
244
245                 tree_val = fdt_getprop(fdto, tree_node, name, &tree_len);
246                 if (!tree_val) {
247                         if (tree_len == -FDT_ERR_NOTFOUND)
248                                 return -FDT_ERR_BADOVERLAY;
249
250                         return tree_len;
251                 }
252
253                 for (i = 0; i < (fixup_len / sizeof(uint32_t)); i++) {
254                         fdt32_t adj_val;
255                         uint32_t poffset;
256
257                         poffset = fdt32_to_cpu(fixup_val[i]);
258
259                         /*
260                          * phandles to fixup can be unaligned.
261                          *
262                          * Use a memcpy for the architectures that do
263                          * not support unaligned accesses.
264                          */
265                         memcpy(&adj_val, tree_val + poffset, sizeof(adj_val));
266
267                         adj_val = cpu_to_fdt32(fdt32_to_cpu(adj_val) + delta);
268
269                         ret = fdt_setprop_inplace_namelen_partial(fdto,
270                                                                   tree_node,
271                                                                   name,
272                                                                   strlen(name),
273                                                                   poffset,
274                                                                   &adj_val,
275                                                                   sizeof(adj_val));
276                         if (ret == -FDT_ERR_NOSPACE)
277                                 return -FDT_ERR_BADOVERLAY;
278
279                         if (ret)
280                                 return ret;
281                 }
282         }
283
284         fdt_for_each_subnode(fixup_child, fdto, fixup_node) {
285                 const char *fixup_child_name = fdt_get_name(fdto, fixup_child,
286                                                             NULL);
287                 int tree_child;
288
289                 tree_child = fdt_subnode_offset(fdto, tree_node,
290                                                 fixup_child_name);
291                 if (tree_child == -FDT_ERR_NOTFOUND)
292                         return -FDT_ERR_BADOVERLAY;
293                 if (tree_child < 0)
294                         return tree_child;
295
296                 ret = overlay_update_local_node_references(fdto,
297                                                            tree_child,
298                                                            fixup_child,
299                                                            delta);
300                 if (ret)
301                         return ret;
302         }
303
304         return 0;
305 }
306
307 /**
308  * overlay_update_local_references - Adjust the overlay references
309  * @fdto: Device tree overlay blob
310  * @delta: Offset to shift the phandles of
311  *
312  * overlay_update_local_references() update all the phandles pointing
313  * to a node within the device tree overlay by adding a constant
314  * delta to not conflict with the base overlay.
315  *
316  * This is mainly used as part of a device tree application process,
317  * where you want the device tree overlays phandles to not conflict
318  * with the ones from the base device tree before merging them.
319  *
320  * returns:
321  *      0 on success
322  *      Negative error code on failure
323  */
324 static int overlay_update_local_references(void *fdto, uint32_t delta)
325 {
326         int fixups;
327
328         fixups = fdt_path_offset(fdto, "/__local_fixups__");
329         if (fixups < 0) {
330                 /* There's no local phandles to adjust, bail out */
331                 if (fixups == -FDT_ERR_NOTFOUND)
332                         return 0;
333
334                 return fixups;
335         }
336
337         /*
338          * Update our local references from the root of the tree
339          */
340         return overlay_update_local_node_references(fdto, 0, fixups,
341                                                     delta);
342 }
343
344 /**
345  * overlay_fixup_one_phandle - Set an overlay phandle to the base one
346  * @fdt: Base Device Tree blob
347  * @fdto: Device tree overlay blob
348  * @symbols_off: Node offset of the symbols node in the base device tree
349  * @path: Path to a node holding a phandle in the overlay
350  * @path_len: number of path characters to consider
351  * @name: Name of the property holding the phandle reference in the overlay
352  * @name_len: number of name characters to consider
353  * @poffset: Offset within the overlay property where the phandle is stored
354  * @label: Label of the node referenced by the phandle
355  *
356  * overlay_fixup_one_phandle() resolves an overlay phandle pointing to
357  * a node in the base device tree.
358  *
359  * This is part of the device tree overlay application process, when
360  * you want all the phandles in the overlay to point to the actual
361  * base dt nodes.
362  *
363  * returns:
364  *      0 on success
365  *      Negative error code on failure
366  */
367 static int overlay_fixup_one_phandle(void *fdt, void *fdto,
368                                      int symbols_off,
369                                      const char *path, uint32_t path_len,
370                                      const char *name, uint32_t name_len,
371                                      int poffset, const char *label)
372 {
373         const char *symbol_path;
374         uint32_t phandle;
375         fdt32_t phandle_prop;
376         int symbol_off, fixup_off;
377         int prop_len;
378
379         if (symbols_off < 0)
380                 return symbols_off;
381
382         symbol_path = fdt_getprop(fdt, symbols_off, label,
383                                   &prop_len);
384         if (!symbol_path)
385                 return prop_len;
386
387         symbol_off = fdt_path_offset(fdt, symbol_path);
388         if (symbol_off < 0)
389                 return symbol_off;
390
391         phandle = fdt_get_phandle(fdt, symbol_off);
392         if (!phandle)
393                 return -FDT_ERR_NOTFOUND;
394
395         fixup_off = fdt_path_offset_namelen(fdto, path, path_len);
396         if (fixup_off == -FDT_ERR_NOTFOUND)
397                 return -FDT_ERR_BADOVERLAY;
398         if (fixup_off < 0)
399                 return fixup_off;
400
401         phandle_prop = cpu_to_fdt32(phandle);
402         return fdt_setprop_inplace_namelen_partial(fdto, fixup_off,
403                                                    name, name_len, poffset,
404                                                    &phandle_prop,
405                                                    sizeof(phandle_prop));
406 };
407
408 /**
409  * overlay_fixup_phandle - Set an overlay phandle to the base one
410  * @fdt: Base Device Tree blob
411  * @fdto: Device tree overlay blob
412  * @symbols_off: Node offset of the symbols node in the base device tree
413  * @property: Property offset in the overlay holding the list of fixups
414  *
415  * overlay_fixup_phandle() resolves all the overlay phandles pointed
416  * to in a __fixups__ property, and updates them to match the phandles
417  * in use in the base device tree.
418  *
419  * This is part of the device tree overlay application process, when
420  * you want all the phandles in the overlay to point to the actual
421  * base dt nodes.
422  *
423  * returns:
424  *      0 on success
425  *      Negative error code on failure
426  */
427 static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
428                                  int property)
429 {
430         const char *value;
431         const char *label;
432         int len;
433
434         value = fdt_getprop_by_offset(fdto, property,
435                                       &label, &len);
436         if (!value) {
437                 if (len == -FDT_ERR_NOTFOUND)
438                         return -FDT_ERR_INTERNAL;
439
440                 return len;
441         }
442
443         do {
444                 const char *path, *name, *fixup_end;
445                 const char *fixup_str = value;
446                 uint32_t path_len, name_len;
447                 uint32_t fixup_len;
448                 char *sep, *endptr;
449                 int poffset, ret;
450
451                 fixup_end = memchr(value, '\0', len);
452                 if (!fixup_end)
453                         return -FDT_ERR_BADOVERLAY;
454                 fixup_len = fixup_end - fixup_str;
455
456                 len -= fixup_len + 1;
457                 value += fixup_len + 1;
458
459                 path = fixup_str;
460                 sep = memchr(fixup_str, ':', fixup_len);
461                 if (!sep || *sep != ':')
462                         return -FDT_ERR_BADOVERLAY;
463
464                 path_len = sep - path;
465                 if (path_len == (fixup_len - 1))
466                         return -FDT_ERR_BADOVERLAY;
467
468                 fixup_len -= path_len + 1;
469                 name = sep + 1;
470                 sep = memchr(name, ':', fixup_len);
471                 if (!sep || *sep != ':')
472                         return -FDT_ERR_BADOVERLAY;
473
474                 name_len = sep - name;
475                 if (!name_len)
476                         return -FDT_ERR_BADOVERLAY;
477
478                 poffset = strtoul(sep + 1, &endptr, 10);
479                 if ((*endptr != '\0') || (endptr <= (sep + 1)))
480                         return -FDT_ERR_BADOVERLAY;
481
482                 ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off,
483                                                 path, path_len, name, name_len,
484                                                 poffset, label);
485                 if (ret)
486                         return ret;
487         } while (len > 0);
488
489         return 0;
490 }
491
492 /**
493  * overlay_fixup_phandles - Resolve the overlay phandles to the base
494  *                          device tree
495  * @fdt: Base Device Tree blob
496  * @fdto: Device tree overlay blob
497  *
498  * overlay_fixup_phandles() resolves all the overlay phandles pointing
499  * to nodes in the base device tree.
500  *
501  * This is one of the steps of the device tree overlay application
502  * process, when you want all the phandles in the overlay to point to
503  * the actual base dt nodes.
504  *
505  * returns:
506  *      0 on success
507  *      Negative error code on failure
508  */
509 static int overlay_fixup_phandles(void *fdt, void *fdto)
510 {
511         int fixups_off, symbols_off;
512         int property;
513
514         /* We can have overlays without any fixups */
515         fixups_off = fdt_path_offset(fdto, "/__fixups__");
516         if (fixups_off == -FDT_ERR_NOTFOUND)
517                 return 0; /* nothing to do */
518         if (fixups_off < 0)
519                 return fixups_off;
520
521         /* And base DTs without symbols */
522         symbols_off = fdt_path_offset(fdt, "/__symbols__");
523         if ((symbols_off < 0 && (symbols_off != -FDT_ERR_NOTFOUND)))
524                 return symbols_off;
525
526         fdt_for_each_property_offset(property, fdto, fixups_off) {
527                 int ret;
528
529                 ret = overlay_fixup_phandle(fdt, fdto, symbols_off, property);
530                 if (ret)
531                         return ret;
532         }
533
534         return 0;
535 }
536
537 /**
538  * overlay_apply_node - Merges a node into the base device tree
539  * @fdt: Base Device Tree blob
540  * @target: Node offset in the base device tree to apply the fragment to
541  * @fdto: Device tree overlay blob
542  * @node: Node offset in the overlay holding the changes to merge
543  *
544  * overlay_apply_node() merges a node into a target base device tree
545  * node pointed.
546  *
547  * This is part of the final step in the device tree overlay
548  * application process, when all the phandles have been adjusted and
549  * resolved and you just have to merge overlay into the base device
550  * tree.
551  *
552  * returns:
553  *      0 on success
554  *      Negative error code on failure
555  */
556 static int overlay_apply_node(void *fdt, int target,
557                               void *fdto, int node)
558 {
559         int property;
560         int subnode;
561
562         fdt_for_each_property_offset(property, fdto, node) {
563                 const char *name;
564                 const void *prop;
565                 int prop_len;
566                 int ret;
567
568                 prop = fdt_getprop_by_offset(fdto, property, &name,
569                                              &prop_len);
570                 if (prop_len == -FDT_ERR_NOTFOUND)
571                         return -FDT_ERR_INTERNAL;
572                 if (prop_len < 0)
573                         return prop_len;
574
575                 ret = fdt_setprop(fdt, target, name, prop, prop_len);
576                 if (ret)
577                         return ret;
578         }
579
580         fdt_for_each_subnode(subnode, fdto, node) {
581                 const char *name = fdt_get_name(fdto, subnode, NULL);
582                 int nnode;
583                 int ret;
584
585                 nnode = fdt_add_subnode(fdt, target, name);
586                 if (nnode == -FDT_ERR_EXISTS) {
587                         nnode = fdt_subnode_offset(fdt, target, name);
588                         if (nnode == -FDT_ERR_NOTFOUND)
589                                 return -FDT_ERR_INTERNAL;
590                 }
591
592                 if (nnode < 0)
593                         return nnode;
594
595                 ret = overlay_apply_node(fdt, nnode, fdto, subnode);
596                 if (ret)
597                         return ret;
598         }
599
600         return 0;
601 }
602
603 /**
604  * overlay_merge - Merge an overlay into its base device tree
605  * @fdt: Base Device Tree blob
606  * @fdto: Device tree overlay blob
607  *
608  * overlay_merge() merges an overlay into its base device tree.
609  *
610  * This is the next to last step in the device tree overlay application
611  * process, when all the phandles have been adjusted and resolved and
612  * you just have to merge overlay into the base device tree.
613  *
614  * returns:
615  *      0 on success
616  *      Negative error code on failure
617  */
618 static int overlay_merge(void *fdt, void *fdto)
619 {
620         int fragment;
621
622         fdt_for_each_subnode(fragment, fdto, 0) {
623                 int overlay;
624                 int target;
625                 int ret;
626
627                 /*
628                  * Each fragments will have an __overlay__ node. If
629                  * they don't, it's not supposed to be merged
630                  */
631                 overlay = fdt_subnode_offset(fdto, fragment, "__overlay__");
632                 if (overlay == -FDT_ERR_NOTFOUND)
633                         continue;
634
635                 if (overlay < 0)
636                         return overlay;
637
638                 target = overlay_get_target(fdt, fdto, fragment, NULL);
639                 if (target < 0)
640                         return target;
641
642                 ret = overlay_apply_node(fdt, target, fdto, overlay);
643                 if (ret)
644                         return ret;
645         }
646
647         return 0;
648 }
649
650 static int get_path_len(const void *fdt, int nodeoffset)
651 {
652         int len = 0, namelen;
653         const char *name;
654
655         FDT_RO_PROBE(fdt);
656
657         for (;;) {
658                 name = fdt_get_name(fdt, nodeoffset, &namelen);
659                 if (!name)
660                         return namelen;
661
662                 /* root? we're done */
663                 if (namelen == 0)
664                         break;
665
666                 nodeoffset = fdt_parent_offset(fdt, nodeoffset);
667                 if (nodeoffset < 0)
668                         return nodeoffset;
669                 len += namelen + 1;
670         }
671
672         /* in case of root pretend it's "/" */
673         if (len == 0)
674                 len++;
675         return len;
676 }
677
678 /**
679  * overlay_symbol_update - Update the symbols of base tree after a merge
680  * @fdt: Base Device Tree blob
681  * @fdto: Device tree overlay blob
682  *
683  * overlay_symbol_update() updates the symbols of the base tree with the
684  * symbols of the applied overlay
685  *
686  * This is the last step in the device tree overlay application
687  * process, allowing the reference of overlay symbols by subsequent
688  * overlay operations.
689  *
690  * returns:
691  *      0 on success
692  *      Negative error code on failure
693  */
694 static int overlay_symbol_update(void *fdt, void *fdto)
695 {
696         int root_sym, ov_sym, prop, path_len, fragment, target;
697         int len, frag_name_len, ret, rel_path_len;
698         const char *s, *e;
699         const char *path;
700         const char *name;
701         const char *frag_name;
702         const char *rel_path;
703         const char *target_path;
704         char *buf;
705         void *p;
706
707         ov_sym = fdt_subnode_offset(fdto, 0, "__symbols__");
708
709         /* if no overlay symbols exist no problem */
710         if (ov_sym < 0)
711                 return 0;
712
713         root_sym = fdt_subnode_offset(fdt, 0, "__symbols__");
714
715         /* it no root symbols exist we should create them */
716         if (root_sym == -FDT_ERR_NOTFOUND)
717                 root_sym = fdt_add_subnode(fdt, 0, "__symbols__");
718
719         /* any error is fatal now */
720         if (root_sym < 0)
721                 return root_sym;
722
723         /* iterate over each overlay symbol */
724         fdt_for_each_property_offset(prop, fdto, ov_sym) {
725                 path = fdt_getprop_by_offset(fdto, prop, &name, &path_len);
726                 if (!path)
727                         return path_len;
728
729                 /* verify it's a string property (terminated by a single \0) */
730                 if (path_len < 1 || memchr(path, '\0', path_len) != &path[path_len - 1])
731                         return -FDT_ERR_BADVALUE;
732
733                 /* keep end marker to avoid strlen() */
734                 e = path + path_len;
735
736                 if (*path != '/')
737                         return -FDT_ERR_BADVALUE;
738
739                 /* get fragment name first */
740                 s = strchr(path + 1, '/');
741                 if (!s) {
742                         /* Symbol refers to something that won't end
743                          * up in the target tree */
744                         continue;
745                 }
746
747                 frag_name = path + 1;
748                 frag_name_len = s - path - 1;
749
750                 /* verify format; safe since "s" lies in \0 terminated prop */
751                 len = sizeof("/__overlay__/") - 1;
752                 if ((e - s) > len && (memcmp(s, "/__overlay__/", len) == 0)) {
753                         /* /<fragment-name>/__overlay__/<relative-subnode-path> */
754                         rel_path = s + len;
755                         rel_path_len = e - rel_path;
756                 } else if ((e - s) == len
757                            && (memcmp(s, "/__overlay__", len - 1) == 0)) {
758                         /* /<fragment-name>/__overlay__ */
759                         rel_path = "";
760                         rel_path_len = 1; /* Include NUL character */
761                 } else {
762                         /* Symbol refers to something that won't end
763                          * up in the target tree */
764                         continue;
765                 }
766
767                 /* find the fragment index in which the symbol lies */
768                 ret = fdt_subnode_offset_namelen(fdto, 0, frag_name,
769                                                frag_name_len);
770                 /* not found? */
771                 if (ret < 0)
772                         return -FDT_ERR_BADOVERLAY;
773                 fragment = ret;
774
775                 /* an __overlay__ subnode must exist */
776                 ret = fdt_subnode_offset(fdto, fragment, "__overlay__");
777                 if (ret < 0)
778                         return -FDT_ERR_BADOVERLAY;
779
780                 /* get the target of the fragment */
781                 ret = overlay_get_target(fdt, fdto, fragment, &target_path);
782                 if (ret < 0)
783                         return ret;
784                 target = ret;
785
786                 /* if we have a target path use */
787                 if (!target_path) {
788                         ret = get_path_len(fdt, target);
789                         if (ret < 0)
790                                 return ret;
791                         len = ret;
792                 } else {
793                         len = strlen(target_path);
794                 }
795
796                 ret = fdt_setprop_placeholder(fdt, root_sym, name,
797                                 len + (len > 1) + rel_path_len, &p);
798                 if (ret < 0)
799                         return ret;
800
801                 if (!target_path) {
802                         /* again in case setprop_placeholder changed it */
803                         ret = overlay_get_target(fdt, fdto, fragment, &target_path);
804                         if (ret < 0)
805                                 return ret;
806                         target = ret;
807                 }
808
809                 buf = p;
810                 if (len > 1) { /* target is not root */
811                         if (!target_path) {
812                                 ret = fdt_get_path(fdt, target, buf, len + 1);
813                                 if (ret < 0)
814                                         return ret;
815                         } else
816                                 memcpy(buf, target_path, len + 1);
817
818                 } else
819                         len--;
820
821                 buf[len] = '/';
822                 memcpy(buf + len + 1, rel_path, rel_path_len);
823         }
824
825         return 0;
826 }
827
828 int fdt_overlay_apply(void *fdt, void *fdto)
829 {
830         uint32_t delta;
831         int ret;
832
833         FDT_RO_PROBE(fdt);
834         FDT_RO_PROBE(fdto);
835
836         ret = fdt_find_max_phandle(fdt, &delta);
837         if (ret)
838                 goto err;
839
840         ret = overlay_adjust_local_phandles(fdto, delta);
841         if (ret)
842                 goto err;
843
844         ret = overlay_update_local_references(fdto, delta);
845         if (ret)
846                 goto err;
847
848         ret = overlay_fixup_phandles(fdt, fdto);
849         if (ret)
850                 goto err;
851
852         ret = overlay_merge(fdt, fdto);
853         if (ret)
854                 goto err;
855
856         ret = overlay_symbol_update(fdt, fdto);
857         if (ret)
858                 goto err;
859
860         /*
861          * The overlay has been damaged, erase its magic.
862          */
863         fdt_set_magic(fdto, ~0);
864
865         return 0;
866
867 err:
868         /*
869          * The overlay might have been damaged, erase its magic.
870          */
871         fdt_set_magic(fdto, ~0);
872
873         /*
874          * The base device tree might have been damaged, erase its
875          * magic.
876          */
877         fdt_set_magic(fdt, ~0);
878
879         return ret;
880 }
881
882 int fdt_overlay_apply_node(void *fdt, int target, void *fdto, int node)
883 {
884         return overlay_apply_node(fdt, target, fdto, node);
885 }