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