~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to dtc/libfdt/fdt_overlay.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "libfdt_env.h"
 
2
 
 
3
#include <fdt.h>
 
4
#include <libfdt.h>
 
5
 
 
6
#include "libfdt_internal.h"
 
7
 
 
8
/**
 
9
 * overlay_get_target_phandle - retrieves the target phandle of a fragment
 
10
 * @fdto: pointer to the device tree overlay blob
 
11
 * @fragment: node offset of the fragment in the overlay
 
12
 *
 
13
 * overlay_get_target_phandle() retrieves the target phandle of an
 
14
 * overlay fragment when that fragment uses a phandle (target
 
15
 * property) instead of a path (target-path property).
 
16
 *
 
17
 * returns:
 
18
 *      the phandle pointed by the target property
 
19
 *      0, if the phandle was not found
 
20
 *      -1, if the phandle was malformed
 
21
 */
 
22
static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
 
23
{
 
24
        const fdt32_t *val;
 
25
        int len;
 
26
 
 
27
        val = fdt_getprop(fdto, fragment, "target", &len);
 
28
        if (!val)
 
29
                return 0;
 
30
 
 
31
        if ((len != sizeof(*val)) || (fdt32_to_cpu(*val) == (uint32_t)-1))
 
32
                return (uint32_t)-1;
 
33
 
 
34
        return fdt32_to_cpu(*val);
 
35
}
 
36
 
 
37
/**
 
38
 * overlay_get_target - retrieves the offset of a fragment's target
 
39
 * @fdt: Base device tree blob
 
40
 * @fdto: Device tree overlay blob
 
41
 * @fragment: node offset of the fragment in the overlay
 
42
 *
 
43
 * overlay_get_target() retrieves the target offset in the base
 
44
 * device tree of a fragment, no matter how the actual targetting is
 
45
 * done (through a phandle or a path)
 
46
 *
 
47
 * returns:
 
48
 *      the targetted node offset in the base device tree
 
49
 *      Negative error code on error
 
50
 */
 
51
static int overlay_get_target(const void *fdt, const void *fdto,
 
52
                              int fragment)
 
53
{
 
54
        uint32_t phandle;
 
55
        const char *path;
 
56
        int path_len;
 
57
 
 
58
        /* Try first to do a phandle based lookup */
 
59
        phandle = overlay_get_target_phandle(fdto, fragment);
 
60
        if (phandle == (uint32_t)-1)
 
61
                return -FDT_ERR_BADPHANDLE;
 
62
 
 
63
        if (phandle)
 
64
                return fdt_node_offset_by_phandle(fdt, phandle);
 
65
 
 
66
        /* And then a path based lookup */
 
67
        path = fdt_getprop(fdto, fragment, "target-path", &path_len);
 
68
        if (!path) {
 
69
                /*
 
70
                 * If we haven't found either a target or a
 
71
                 * target-path property in a node that contains a
 
72
                 * __overlay__ subnode (we wouldn't be called
 
73
                 * otherwise), consider it a improperly written
 
74
                 * overlay
 
75
                 */
 
76
                if (path_len == -FDT_ERR_NOTFOUND)
 
77
                        return -FDT_ERR_BADOVERLAY;
 
78
 
 
79
                return path_len;
 
80
        }
 
81
 
 
82
        return fdt_path_offset(fdt, path);
 
83
}
 
84
 
 
85
/**
 
86
 * overlay_phandle_add_offset - Increases a phandle by an offset
 
87
 * @fdt: Base device tree blob
 
88
 * @node: Device tree overlay blob
 
89
 * @name: Name of the property to modify (phandle or linux,phandle)
 
90
 * @delta: offset to apply
 
91
 *
 
92
 * overlay_phandle_add_offset() increments a node phandle by a given
 
93
 * offset.
 
94
 *
 
95
 * returns:
 
96
 *      0 on success.
 
97
 *      Negative error code on error
 
98
 */
 
99
static int overlay_phandle_add_offset(void *fdt, int node,
 
100
                                      const char *name, uint32_t delta)
 
101
{
 
102
        const fdt32_t *val;
 
103
        uint32_t adj_val;
 
104
        int len;
 
105
 
 
106
        val = fdt_getprop(fdt, node, name, &len);
 
107
        if (!val)
 
108
                return len;
 
109
 
 
110
        if (len != sizeof(*val))
 
111
                return -FDT_ERR_BADPHANDLE;
 
112
 
 
113
        adj_val = fdt32_to_cpu(*val);
 
114
        if ((adj_val + delta) < adj_val)
 
115
                return -FDT_ERR_NOPHANDLES;
 
116
 
 
117
        adj_val += delta;
 
118
        if (adj_val == (uint32_t)-1)
 
119
                return -FDT_ERR_NOPHANDLES;
 
120
 
 
121
        return fdt_setprop_inplace_u32(fdt, node, name, adj_val);
 
122
}
 
123
 
 
124
/**
 
125
 * overlay_adjust_node_phandles - Offsets the phandles of a node
 
126
 * @fdto: Device tree overlay blob
 
127
 * @node: Offset of the node we want to adjust
 
128
 * @delta: Offset to shift the phandles of
 
129
 *
 
130
 * overlay_adjust_node_phandles() adds a constant to all the phandles
 
131
 * of a given node. This is mainly use as part of the overlay
 
132
 * application process, when we want to update all the overlay
 
133
 * phandles to not conflict with the overlays of the base device tree.
 
134
 *
 
135
 * returns:
 
136
 *      0 on success
 
137
 *      Negative error code on failure
 
138
 */
 
139
static int overlay_adjust_node_phandles(void *fdto, int node,
 
140
                                        uint32_t delta)
 
141
{
 
142
        int child;
 
143
        int ret;
 
144
 
 
145
        ret = overlay_phandle_add_offset(fdto, node, "phandle", delta);
 
146
        if (ret && ret != -FDT_ERR_NOTFOUND)
 
147
                return ret;
 
148
 
 
149
        ret = overlay_phandle_add_offset(fdto, node, "linux,phandle", delta);
 
150
        if (ret && ret != -FDT_ERR_NOTFOUND)
 
151
                return ret;
 
152
 
 
153
        fdt_for_each_subnode(child, fdto, node) {
 
154
                ret = overlay_adjust_node_phandles(fdto, child, delta);
 
155
                if (ret)
 
156
                        return ret;
 
157
        }
 
158
 
 
159
        return 0;
 
160
}
 
161
 
 
162
/**
 
163
 * overlay_adjust_local_phandles - Adjust the phandles of a whole overlay
 
164
 * @fdto: Device tree overlay blob
 
165
 * @delta: Offset to shift the phandles of
 
166
 *
 
167
 * overlay_adjust_local_phandles() adds a constant to all the
 
168
 * phandles of an overlay. This is mainly use as part of the overlay
 
169
 * application process, when we want to update all the overlay
 
170
 * phandles to not conflict with the overlays of the base device tree.
 
171
 *
 
172
 * returns:
 
173
 *      0 on success
 
174
 *      Negative error code on failure
 
175
 */
 
176
static int overlay_adjust_local_phandles(void *fdto, uint32_t delta)
 
177
{
 
178
        /*
 
179
         * Start adjusting the phandles from the overlay root
 
180
         */
 
181
        return overlay_adjust_node_phandles(fdto, 0, delta);
 
182
}
 
183
 
 
184
/**
 
185
 * overlay_update_local_node_references - Adjust the overlay references
 
186
 * @fdto: Device tree overlay blob
 
187
 * @tree_node: Node offset of the node to operate on
 
188
 * @fixup_node: Node offset of the matching local fixups node
 
189
 * @delta: Offset to shift the phandles of
 
190
 *
 
191
 * overlay_update_local_nodes_references() update the phandles
 
192
 * pointing to a node within the device tree overlay by adding a
 
193
 * constant delta.
 
194
 *
 
195
 * This is mainly used as part of a device tree application process,
 
196
 * where you want the device tree overlays phandles to not conflict
 
197
 * with the ones from the base device tree before merging them.
 
198
 *
 
199
 * returns:
 
200
 *      0 on success
 
201
 *      Negative error code on failure
 
202
 */
 
203
static int overlay_update_local_node_references(void *fdto,
 
204
                                                int tree_node,
 
205
                                                int fixup_node,
 
206
                                                uint32_t delta)
 
207
{
 
208
        int fixup_prop;
 
209
        int fixup_child;
 
210
        int ret;
 
211
 
 
212
        fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) {
 
213
                const fdt32_t *fixup_val;
 
214
                const char *tree_val;
 
215
                const char *name;
 
216
                int fixup_len;
 
217
                int tree_len;
 
218
                int i;
 
219
 
 
220
                fixup_val = fdt_getprop_by_offset(fdto, fixup_prop,
 
221
                                                  &name, &fixup_len);
 
222
                if (!fixup_val)
 
223
                        return fixup_len;
 
224
 
 
225
                if (fixup_len % sizeof(uint32_t))
 
226
                        return -FDT_ERR_BADOVERLAY;
 
227
 
 
228
                tree_val = fdt_getprop(fdto, tree_node, name, &tree_len);
 
229
                if (!tree_val) {
 
230
                        if (tree_len == -FDT_ERR_NOTFOUND)
 
231
                                return -FDT_ERR_BADOVERLAY;
 
232
 
 
233
                        return tree_len;
 
234
                }
 
235
 
 
236
                for (i = 0; i < (fixup_len / sizeof(uint32_t)); i++) {
 
237
                        fdt32_t adj_val;
 
238
                        uint32_t poffset;
 
239
 
 
240
                        poffset = fdt32_to_cpu(fixup_val[i]);
 
241
 
 
242
                        /*
 
243
                         * phandles to fixup can be unaligned.
 
244
                         *
 
245
                         * Use a memcpy for the architectures that do
 
246
                         * not support unaligned accesses.
 
247
                         */
 
248
                        memcpy(&adj_val, tree_val + poffset, sizeof(adj_val));
 
249
 
 
250
                        adj_val = cpu_to_fdt32(fdt32_to_cpu(adj_val) + delta);
 
251
 
 
252
                        ret = fdt_setprop_inplace_namelen_partial(fdto,
 
253
                                                                  tree_node,
 
254
                                                                  name,
 
255
                                                                  strlen(name),
 
256
                                                                  poffset,
 
257
                                                                  &adj_val,
 
258
                                                                  sizeof(adj_val));
 
259
                        if (ret == -FDT_ERR_NOSPACE)
 
260
                                return -FDT_ERR_BADOVERLAY;
 
261
 
 
262
                        if (ret)
 
263
                                return ret;
 
264
                }
 
265
        }
 
266
 
 
267
        fdt_for_each_subnode(fixup_child, fdto, fixup_node) {
 
268
                const char *fixup_child_name = fdt_get_name(fdto, fixup_child,
 
269
                                                            NULL);
 
270
                int tree_child;
 
271
 
 
272
                tree_child = fdt_subnode_offset(fdto, tree_node,
 
273
                                                fixup_child_name);
 
274
                if (tree_child == -FDT_ERR_NOTFOUND)
 
275
                        return -FDT_ERR_BADOVERLAY;
 
276
                if (tree_child < 0)
 
277
                        return tree_child;
 
278
 
 
279
                ret = overlay_update_local_node_references(fdto,
 
280
                                                           tree_child,
 
281
                                                           fixup_child,
 
282
                                                           delta);
 
283
                if (ret)
 
284
                        return ret;
 
285
        }
 
286
 
 
287
        return 0;
 
288
}
 
289
 
 
290
/**
 
291
 * overlay_update_local_references - Adjust the overlay references
 
292
 * @fdto: Device tree overlay blob
 
293
 * @delta: Offset to shift the phandles of
 
294
 *
 
295
 * overlay_update_local_references() update all the phandles pointing
 
296
 * to a node within the device tree overlay by adding a constant
 
297
 * delta to not conflict with the base overlay.
 
298
 *
 
299
 * This is mainly used as part of a device tree application process,
 
300
 * where you want the device tree overlays phandles to not conflict
 
301
 * with the ones from the base device tree before merging them.
 
302
 *
 
303
 * returns:
 
304
 *      0 on success
 
305
 *      Negative error code on failure
 
306
 */
 
307
static int overlay_update_local_references(void *fdto, uint32_t delta)
 
308
{
 
309
        int fixups;
 
310
 
 
311
        fixups = fdt_path_offset(fdto, "/__local_fixups__");
 
312
        if (fixups < 0) {
 
313
                /* There's no local phandles to adjust, bail out */
 
314
                if (fixups == -FDT_ERR_NOTFOUND)
 
315
                        return 0;
 
316
 
 
317
                return fixups;
 
318
        }
 
319
 
 
320
        /*
 
321
         * Update our local references from the root of the tree
 
322
         */
 
323
        return overlay_update_local_node_references(fdto, 0, fixups,
 
324
                                                    delta);
 
325
}
 
326
 
 
327
/**
 
328
 * overlay_fixup_one_phandle - Set an overlay phandle to the base one
 
329
 * @fdt: Base Device Tree blob
 
330
 * @fdto: Device tree overlay blob
 
331
 * @symbols_off: Node offset of the symbols node in the base device tree
 
332
 * @path: Path to a node holding a phandle in the overlay
 
333
 * @path_len: number of path characters to consider
 
334
 * @name: Name of the property holding the phandle reference in the overlay
 
335
 * @name_len: number of name characters to consider
 
336
 * @poffset: Offset within the overlay property where the phandle is stored
 
337
 * @label: Label of the node referenced by the phandle
 
338
 *
 
339
 * overlay_fixup_one_phandle() resolves an overlay phandle pointing to
 
340
 * a node in the base device tree.
 
341
 *
 
342
 * This is part of the device tree overlay application process, when
 
343
 * you want all the phandles in the overlay to point to the actual
 
344
 * base dt nodes.
 
345
 *
 
346
 * returns:
 
347
 *      0 on success
 
348
 *      Negative error code on failure
 
349
 */
 
350
static int overlay_fixup_one_phandle(void *fdt, void *fdto,
 
351
                                     int symbols_off,
 
352
                                     const char *path, uint32_t path_len,
 
353
                                     const char *name, uint32_t name_len,
 
354
                                     int poffset, const char *label)
 
355
{
 
356
        const char *symbol_path;
 
357
        uint32_t phandle;
 
358
        fdt32_t phandle_prop;
 
359
        int symbol_off, fixup_off;
 
360
        int prop_len;
 
361
 
 
362
        if (symbols_off < 0)
 
363
                return symbols_off;
 
364
 
 
365
        symbol_path = fdt_getprop(fdt, symbols_off, label,
 
366
                                  &prop_len);
 
367
        if (!symbol_path)
 
368
                return prop_len;
 
369
 
 
370
        symbol_off = fdt_path_offset(fdt, symbol_path);
 
371
        if (symbol_off < 0)
 
372
                return symbol_off;
 
373
 
 
374
        phandle = fdt_get_phandle(fdt, symbol_off);
 
375
        if (!phandle)
 
376
                return -FDT_ERR_NOTFOUND;
 
377
 
 
378
        fixup_off = fdt_path_offset_namelen(fdto, path, path_len);
 
379
        if (fixup_off == -FDT_ERR_NOTFOUND)
 
380
                return -FDT_ERR_BADOVERLAY;
 
381
        if (fixup_off < 0)
 
382
                return fixup_off;
 
383
 
 
384
        phandle_prop = cpu_to_fdt32(phandle);
 
385
        return fdt_setprop_inplace_namelen_partial(fdto, fixup_off,
 
386
                                                   name, name_len, poffset,
 
387
                                                   &phandle_prop,
 
388
                                                   sizeof(phandle_prop));
 
389
};
 
390
 
 
391
/**
 
392
 * overlay_fixup_phandle - Set an overlay phandle to the base one
 
393
 * @fdt: Base Device Tree blob
 
394
 * @fdto: Device tree overlay blob
 
395
 * @symbols_off: Node offset of the symbols node in the base device tree
 
396
 * @property: Property offset in the overlay holding the list of fixups
 
397
 *
 
398
 * overlay_fixup_phandle() resolves all the overlay phandles pointed
 
399
 * to in a __fixups__ property, and updates them to match the phandles
 
400
 * in use in the base device tree.
 
401
 *
 
402
 * This is part of the device tree overlay application process, when
 
403
 * you want all the phandles in the overlay to point to the actual
 
404
 * base dt nodes.
 
405
 *
 
406
 * returns:
 
407
 *      0 on success
 
408
 *      Negative error code on failure
 
409
 */
 
410
static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
 
411
                                 int property)
 
412
{
 
413
        const char *value;
 
414
        const char *label;
 
415
        int len;
 
416
 
 
417
        value = fdt_getprop_by_offset(fdto, property,
 
418
                                      &label, &len);
 
419
        if (!value) {
 
420
                if (len == -FDT_ERR_NOTFOUND)
 
421
                        return -FDT_ERR_INTERNAL;
 
422
 
 
423
                return len;
 
424
        }
 
425
 
 
426
        do {
 
427
                const char *path, *name, *fixup_end;
 
428
                const char *fixup_str = value;
 
429
                uint32_t path_len, name_len;
 
430
                uint32_t fixup_len;
 
431
                char *sep, *endptr;
 
432
                int poffset, ret;
 
433
 
 
434
                fixup_end = memchr(value, '\0', len);
 
435
                if (!fixup_end)
 
436
                        return -FDT_ERR_BADOVERLAY;
 
437
                fixup_len = fixup_end - fixup_str;
 
438
 
 
439
                len -= fixup_len + 1;
 
440
                value += fixup_len + 1;
 
441
 
 
442
                path = fixup_str;
 
443
                sep = memchr(fixup_str, ':', fixup_len);
 
444
                if (!sep || *sep != ':')
 
445
                        return -FDT_ERR_BADOVERLAY;
 
446
 
 
447
                path_len = sep - path;
 
448
                if (path_len == (fixup_len - 1))
 
449
                        return -FDT_ERR_BADOVERLAY;
 
450
 
 
451
                fixup_len -= path_len + 1;
 
452
                name = sep + 1;
 
453
                sep = memchr(name, ':', fixup_len);
 
454
                if (!sep || *sep != ':')
 
455
                        return -FDT_ERR_BADOVERLAY;
 
456
 
 
457
                name_len = sep - name;
 
458
                if (!name_len)
 
459
                        return -FDT_ERR_BADOVERLAY;
 
460
 
 
461
                poffset = strtoul(sep + 1, &endptr, 10);
 
462
                if ((*endptr != '\0') || (endptr <= (sep + 1)))
 
463
                        return -FDT_ERR_BADOVERLAY;
 
464
 
 
465
                ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off,
 
466
                                                path, path_len, name, name_len,
 
467
                                                poffset, label);
 
468
                if (ret)
 
469
                        return ret;
 
470
        } while (len > 0);
 
471
 
 
472
        return 0;
 
473
}
 
474
 
 
475
/**
 
476
 * overlay_fixup_phandles - Resolve the overlay phandles to the base
 
477
 *                          device tree
 
478
 * @fdt: Base Device Tree blob
 
479
 * @fdto: Device tree overlay blob
 
480
 *
 
481
 * overlay_fixup_phandles() resolves all the overlay phandles pointing
 
482
 * to nodes in the base device tree.
 
483
 *
 
484
 * This is one of the steps of the device tree overlay application
 
485
 * process, when you want all the phandles in the overlay to point to
 
486
 * the actual base dt nodes.
 
487
 *
 
488
 * returns:
 
489
 *      0 on success
 
490
 *      Negative error code on failure
 
491
 */
 
492
static int overlay_fixup_phandles(void *fdt, void *fdto)
 
493
{
 
494
        int fixups_off, symbols_off;
 
495
        int property;
 
496
 
 
497
        /* We can have overlays without any fixups */
 
498
        fixups_off = fdt_path_offset(fdto, "/__fixups__");
 
499
        if (fixups_off == -FDT_ERR_NOTFOUND)
 
500
                return 0; /* nothing to do */
 
501
        if (fixups_off < 0)
 
502
                return fixups_off;
 
503
 
 
504
        /* And base DTs without symbols */
 
505
        symbols_off = fdt_path_offset(fdt, "/__symbols__");
 
506
        if ((symbols_off < 0 && (symbols_off != -FDT_ERR_NOTFOUND)))
 
507
                return symbols_off;
 
508
 
 
509
        fdt_for_each_property_offset(property, fdto, fixups_off) {
 
510
                int ret;
 
511
 
 
512
                ret = overlay_fixup_phandle(fdt, fdto, symbols_off, property);
 
513
                if (ret)
 
514
                        return ret;
 
515
        }
 
516
 
 
517
        return 0;
 
518
}
 
519
 
 
520
/**
 
521
 * overlay_apply_node - Merges a node into the base device tree
 
522
 * @fdt: Base Device Tree blob
 
523
 * @target: Node offset in the base device tree to apply the fragment to
 
524
 * @fdto: Device tree overlay blob
 
525
 * @node: Node offset in the overlay holding the changes to merge
 
526
 *
 
527
 * overlay_apply_node() merges a node into a target base device tree
 
528
 * node pointed.
 
529
 *
 
530
 * This is part of the final step in the device tree overlay
 
531
 * application process, when all the phandles have been adjusted and
 
532
 * resolved and you just have to merge overlay into the base device
 
533
 * tree.
 
534
 *
 
535
 * returns:
 
536
 *      0 on success
 
537
 *      Negative error code on failure
 
538
 */
 
539
static int overlay_apply_node(void *fdt, int target,
 
540
                              void *fdto, int node)
 
541
{
 
542
        int property;
 
543
        int subnode;
 
544
 
 
545
        fdt_for_each_property_offset(property, fdto, node) {
 
546
                const char *name;
 
547
                const void *prop;
 
548
                int prop_len;
 
549
                int ret;
 
550
 
 
551
                prop = fdt_getprop_by_offset(fdto, property, &name,
 
552
                                             &prop_len);
 
553
                if (prop_len == -FDT_ERR_NOTFOUND)
 
554
                        return -FDT_ERR_INTERNAL;
 
555
                if (prop_len < 0)
 
556
                        return prop_len;
 
557
 
 
558
                ret = fdt_setprop(fdt, target, name, prop, prop_len);
 
559
                if (ret)
 
560
                        return ret;
 
561
        }
 
562
 
 
563
        fdt_for_each_subnode(subnode, fdto, node) {
 
564
                const char *name = fdt_get_name(fdto, subnode, NULL);
 
565
                int nnode;
 
566
                int ret;
 
567
 
 
568
                nnode = fdt_add_subnode(fdt, target, name);
 
569
                if (nnode == -FDT_ERR_EXISTS) {
 
570
                        nnode = fdt_subnode_offset(fdt, target, name);
 
571
                        if (nnode == -FDT_ERR_NOTFOUND)
 
572
                                return -FDT_ERR_INTERNAL;
 
573
                }
 
574
 
 
575
                if (nnode < 0)
 
576
                        return nnode;
 
577
 
 
578
                ret = overlay_apply_node(fdt, nnode, fdto, subnode);
 
579
                if (ret)
 
580
                        return ret;
 
581
        }
 
582
 
 
583
        return 0;
 
584
}
 
585
 
 
586
/**
 
587
 * overlay_merge - Merge an overlay into its base device tree
 
588
 * @fdt: Base Device Tree blob
 
589
 * @fdto: Device tree overlay blob
 
590
 *
 
591
 * overlay_merge() merges an overlay into its base device tree.
 
592
 *
 
593
 * This is the final step in the device tree overlay application
 
594
 * process, when all the phandles have been adjusted and resolved and
 
595
 * you just have to merge overlay into the base device tree.
 
596
 *
 
597
 * returns:
 
598
 *      0 on success
 
599
 *      Negative error code on failure
 
600
 */
 
601
static int overlay_merge(void *fdt, void *fdto)
 
602
{
 
603
        int fragment;
 
604
 
 
605
        fdt_for_each_subnode(fragment, fdto, 0) {
 
606
                int overlay;
 
607
                int target;
 
608
                int ret;
 
609
 
 
610
                /*
 
611
                 * Each fragments will have an __overlay__ node. If
 
612
                 * they don't, it's not supposed to be merged
 
613
                 */
 
614
                overlay = fdt_subnode_offset(fdto, fragment, "__overlay__");
 
615
                if (overlay == -FDT_ERR_NOTFOUND)
 
616
                        continue;
 
617
 
 
618
                if (overlay < 0)
 
619
                        return overlay;
 
620
 
 
621
                target = overlay_get_target(fdt, fdto, fragment);
 
622
                if (target < 0)
 
623
                        return target;
 
624
 
 
625
                ret = overlay_apply_node(fdt, target, fdto, overlay);
 
626
                if (ret)
 
627
                        return ret;
 
628
        }
 
629
 
 
630
        return 0;
 
631
}
 
632
 
 
633
int fdt_overlay_apply(void *fdt, void *fdto)
 
634
{
 
635
        uint32_t delta = fdt_get_max_phandle(fdt);
 
636
        int ret;
 
637
 
 
638
        FDT_CHECK_HEADER(fdt);
 
639
        FDT_CHECK_HEADER(fdto);
 
640
 
 
641
        ret = overlay_adjust_local_phandles(fdto, delta);
 
642
        if (ret)
 
643
                goto err;
 
644
 
 
645
        ret = overlay_update_local_references(fdto, delta);
 
646
        if (ret)
 
647
                goto err;
 
648
 
 
649
        ret = overlay_fixup_phandles(fdt, fdto);
 
650
        if (ret)
 
651
                goto err;
 
652
 
 
653
        ret = overlay_merge(fdt, fdto);
 
654
        if (ret)
 
655
                goto err;
 
656
 
 
657
        /*
 
658
         * The overlay has been damaged, erase its magic.
 
659
         */
 
660
        fdt_set_magic(fdto, ~0);
 
661
 
 
662
        return 0;
 
663
 
 
664
err:
 
665
        /*
 
666
         * The overlay might have been damaged, erase its magic.
 
667
         */
 
668
        fdt_set_magic(fdto, ~0);
 
669
 
 
670
        /*
 
671
         * The base device tree might have been damaged, erase its
 
672
         * magic.
 
673
         */
 
674
        fdt_set_magic(fdt, ~0);
 
675
 
 
676
        return ret;
 
677
}