xref: /openbmc/linux/scripts/dtc/libfdt/fdt_overlay.c (revision ea3723a5)
112869ecdSRob Herring // SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
29130ba88SRob Herring /*
39130ba88SRob Herring  * libfdt - Flat Device Tree manipulation
49130ba88SRob Herring  * Copyright (C) 2016 Free Electrons
59130ba88SRob Herring  * Copyright (C) 2016 NextThing Co.
69130ba88SRob Herring  */
74201d057SRob Herring #include "libfdt_env.h"
84201d057SRob Herring 
94201d057SRob Herring #include <fdt.h>
104201d057SRob Herring #include <libfdt.h>
114201d057SRob Herring 
124201d057SRob Herring #include "libfdt_internal.h"
134201d057SRob Herring 
144201d057SRob Herring /**
154201d057SRob Herring  * overlay_get_target_phandle - retrieves the target phandle of a fragment
164201d057SRob Herring  * @fdto: pointer to the device tree overlay blob
174201d057SRob Herring  * @fragment: node offset of the fragment in the overlay
184201d057SRob Herring  *
194201d057SRob Herring  * overlay_get_target_phandle() retrieves the target phandle of an
204201d057SRob Herring  * overlay fragment when that fragment uses a phandle (target
214201d057SRob Herring  * property) instead of a path (target-path property).
224201d057SRob Herring  *
234201d057SRob Herring  * returns:
244201d057SRob Herring  *      the phandle pointed by the target property
254201d057SRob Herring  *      0, if the phandle was not found
264201d057SRob Herring  *	-1, if the phandle was malformed
274201d057SRob Herring  */
overlay_get_target_phandle(const void * fdto,int fragment)284201d057SRob Herring static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
294201d057SRob Herring {
304201d057SRob Herring 	const fdt32_t *val;
314201d057SRob Herring 	int len;
324201d057SRob Herring 
334201d057SRob Herring 	val = fdt_getprop(fdto, fragment, "target", &len);
344201d057SRob Herring 	if (!val)
354201d057SRob Herring 		return 0;
364201d057SRob Herring 
374201d057SRob Herring 	if ((len != sizeof(*val)) || (fdt32_to_cpu(*val) == (uint32_t)-1))
384201d057SRob Herring 		return (uint32_t)-1;
394201d057SRob Herring 
404201d057SRob Herring 	return fdt32_to_cpu(*val);
414201d057SRob Herring }
424201d057SRob Herring 
fdt_overlay_target_offset(const void * fdt,const void * fdto,int fragment_offset,char const ** pathp)43*ea3723a5SRob Herring int fdt_overlay_target_offset(const void *fdt, const void *fdto,
44*ea3723a5SRob Herring 			      int fragment_offset, char const **pathp)
454201d057SRob Herring {
464201d057SRob Herring 	uint32_t phandle;
474201d057SRob Herring 	const char *path = NULL;
484201d057SRob Herring 	int path_len = 0, ret;
494201d057SRob Herring 
504201d057SRob Herring 	/* Try first to do a phandle based lookup */
51*ea3723a5SRob Herring 	phandle = overlay_get_target_phandle(fdto, fragment_offset);
524201d057SRob Herring 	if (phandle == (uint32_t)-1)
534201d057SRob Herring 		return -FDT_ERR_BADPHANDLE;
544201d057SRob Herring 
554201d057SRob Herring 	/* no phandle, try path */
564201d057SRob Herring 	if (!phandle) {
574201d057SRob Herring 		/* And then a path based lookup */
58*ea3723a5SRob Herring 		path = fdt_getprop(fdto, fragment_offset, "target-path", &path_len);
594201d057SRob Herring 		if (path)
604201d057SRob Herring 			ret = fdt_path_offset(fdt, path);
614201d057SRob Herring 		else
624201d057SRob Herring 			ret = path_len;
634201d057SRob Herring 	} else
644201d057SRob Herring 		ret = fdt_node_offset_by_phandle(fdt, phandle);
654201d057SRob Herring 
664201d057SRob Herring 	/*
674201d057SRob Herring 	* If we haven't found either a target or a
684201d057SRob Herring 	* target-path property in a node that contains a
694201d057SRob Herring 	* __overlay__ subnode (we wouldn't be called
704201d057SRob Herring 	* otherwise), consider it a improperly written
714201d057SRob Herring 	* overlay
724201d057SRob Herring 	*/
734201d057SRob Herring 	if (ret < 0 && path_len == -FDT_ERR_NOTFOUND)
744201d057SRob Herring 		ret = -FDT_ERR_BADOVERLAY;
754201d057SRob Herring 
764201d057SRob Herring 	/* return on error */
774201d057SRob Herring 	if (ret < 0)
784201d057SRob Herring 		return ret;
794201d057SRob Herring 
804201d057SRob Herring 	/* return pointer to path (if available) */
814201d057SRob Herring 	if (pathp)
824201d057SRob Herring 		*pathp = path ? path : NULL;
834201d057SRob Herring 
844201d057SRob Herring 	return ret;
854201d057SRob Herring }
864201d057SRob Herring 
874201d057SRob Herring /**
884201d057SRob Herring  * overlay_phandle_add_offset - Increases a phandle by an offset
894201d057SRob Herring  * @fdt: Base device tree blob
904201d057SRob Herring  * @node: Device tree overlay blob
914201d057SRob Herring  * @name: Name of the property to modify (phandle or linux,phandle)
924201d057SRob Herring  * @delta: offset to apply
934201d057SRob Herring  *
944201d057SRob Herring  * overlay_phandle_add_offset() increments a node phandle by a given
954201d057SRob Herring  * offset.
964201d057SRob Herring  *
974201d057SRob Herring  * returns:
984201d057SRob Herring  *      0 on success.
994201d057SRob Herring  *      Negative error code on error
1004201d057SRob Herring  */
overlay_phandle_add_offset(void * fdt,int node,const char * name,uint32_t delta)1014201d057SRob Herring static int overlay_phandle_add_offset(void *fdt, int node,
1024201d057SRob Herring 				      const char *name, uint32_t delta)
1034201d057SRob Herring {
1044201d057SRob Herring 	const fdt32_t *val;
1054201d057SRob Herring 	uint32_t adj_val;
1064201d057SRob Herring 	int len;
1074201d057SRob Herring 
1084201d057SRob Herring 	val = fdt_getprop(fdt, node, name, &len);
1094201d057SRob Herring 	if (!val)
1104201d057SRob Herring 		return len;
1114201d057SRob Herring 
1124201d057SRob Herring 	if (len != sizeof(*val))
1134201d057SRob Herring 		return -FDT_ERR_BADPHANDLE;
1144201d057SRob Herring 
1154201d057SRob Herring 	adj_val = fdt32_to_cpu(*val);
1164201d057SRob Herring 	if ((adj_val + delta) < adj_val)
1174201d057SRob Herring 		return -FDT_ERR_NOPHANDLES;
1184201d057SRob Herring 
1194201d057SRob Herring 	adj_val += delta;
1204201d057SRob Herring 	if (adj_val == (uint32_t)-1)
1214201d057SRob Herring 		return -FDT_ERR_NOPHANDLES;
1224201d057SRob Herring 
1234201d057SRob Herring 	return fdt_setprop_inplace_u32(fdt, node, name, adj_val);
1244201d057SRob Herring }
1254201d057SRob Herring 
1264201d057SRob Herring /**
1274201d057SRob Herring  * overlay_adjust_node_phandles - Offsets the phandles of a node
1284201d057SRob Herring  * @fdto: Device tree overlay blob
1294201d057SRob Herring  * @node: Offset of the node we want to adjust
1304201d057SRob Herring  * @delta: Offset to shift the phandles of
1314201d057SRob Herring  *
1324201d057SRob Herring  * overlay_adjust_node_phandles() adds a constant to all the phandles
1334201d057SRob Herring  * of a given node. This is mainly use as part of the overlay
1344201d057SRob Herring  * application process, when we want to update all the overlay
1354201d057SRob Herring  * phandles to not conflict with the overlays of the base device tree.
1364201d057SRob Herring  *
1374201d057SRob Herring  * returns:
1384201d057SRob Herring  *      0 on success
1394201d057SRob Herring  *      Negative error code on failure
1404201d057SRob Herring  */
overlay_adjust_node_phandles(void * fdto,int node,uint32_t delta)1414201d057SRob Herring static int overlay_adjust_node_phandles(void *fdto, int node,
1424201d057SRob Herring 					uint32_t delta)
1434201d057SRob Herring {
1444201d057SRob Herring 	int child;
1454201d057SRob Herring 	int ret;
1464201d057SRob Herring 
1474201d057SRob Herring 	ret = overlay_phandle_add_offset(fdto, node, "phandle", delta);
1484201d057SRob Herring 	if (ret && ret != -FDT_ERR_NOTFOUND)
1494201d057SRob Herring 		return ret;
1504201d057SRob Herring 
1514201d057SRob Herring 	ret = overlay_phandle_add_offset(fdto, node, "linux,phandle", delta);
1524201d057SRob Herring 	if (ret && ret != -FDT_ERR_NOTFOUND)
1534201d057SRob Herring 		return ret;
1544201d057SRob Herring 
1554201d057SRob Herring 	fdt_for_each_subnode(child, fdto, node) {
1564201d057SRob Herring 		ret = overlay_adjust_node_phandles(fdto, child, delta);
1574201d057SRob Herring 		if (ret)
1584201d057SRob Herring 			return ret;
1594201d057SRob Herring 	}
1604201d057SRob Herring 
1614201d057SRob Herring 	return 0;
1624201d057SRob Herring }
1634201d057SRob Herring 
1644201d057SRob Herring /**
1654201d057SRob Herring  * overlay_adjust_local_phandles - Adjust the phandles of a whole overlay
1664201d057SRob Herring  * @fdto: Device tree overlay blob
1674201d057SRob Herring  * @delta: Offset to shift the phandles of
1684201d057SRob Herring  *
1694201d057SRob Herring  * overlay_adjust_local_phandles() adds a constant to all the
1704201d057SRob Herring  * phandles of an overlay. This is mainly use as part of the overlay
1714201d057SRob Herring  * application process, when we want to update all the overlay
1724201d057SRob Herring  * phandles to not conflict with the overlays of the base device tree.
1734201d057SRob Herring  *
1744201d057SRob Herring  * returns:
1754201d057SRob Herring  *      0 on success
1764201d057SRob Herring  *      Negative error code on failure
1774201d057SRob Herring  */
overlay_adjust_local_phandles(void * fdto,uint32_t delta)1784201d057SRob Herring static int overlay_adjust_local_phandles(void *fdto, uint32_t delta)
1794201d057SRob Herring {
1804201d057SRob Herring 	/*
1814201d057SRob Herring 	 * Start adjusting the phandles from the overlay root
1824201d057SRob Herring 	 */
1834201d057SRob Herring 	return overlay_adjust_node_phandles(fdto, 0, delta);
1844201d057SRob Herring }
1854201d057SRob Herring 
1864201d057SRob Herring /**
1874201d057SRob Herring  * overlay_update_local_node_references - Adjust the overlay references
1884201d057SRob Herring  * @fdto: Device tree overlay blob
1894201d057SRob Herring  * @tree_node: Node offset of the node to operate on
1904201d057SRob Herring  * @fixup_node: Node offset of the matching local fixups node
1914201d057SRob Herring  * @delta: Offset to shift the phandles of
1924201d057SRob Herring  *
1934201d057SRob Herring  * overlay_update_local_nodes_references() update the phandles
1944201d057SRob Herring  * pointing to a node within the device tree overlay by adding a
1954201d057SRob Herring  * constant delta.
1964201d057SRob Herring  *
1974201d057SRob Herring  * This is mainly used as part of a device tree application process,
1984201d057SRob Herring  * where you want the device tree overlays phandles to not conflict
1994201d057SRob Herring  * with the ones from the base device tree before merging them.
2004201d057SRob Herring  *
2014201d057SRob Herring  * returns:
2024201d057SRob Herring  *      0 on success
2034201d057SRob Herring  *      Negative error code on failure
2044201d057SRob Herring  */
overlay_update_local_node_references(void * fdto,int tree_node,int fixup_node,uint32_t delta)2054201d057SRob Herring static int overlay_update_local_node_references(void *fdto,
2064201d057SRob Herring 						int tree_node,
2074201d057SRob Herring 						int fixup_node,
2084201d057SRob Herring 						uint32_t delta)
2094201d057SRob Herring {
2104201d057SRob Herring 	int fixup_prop;
2114201d057SRob Herring 	int fixup_child;
2124201d057SRob Herring 	int ret;
2134201d057SRob Herring 
2144201d057SRob Herring 	fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) {
2154201d057SRob Herring 		const fdt32_t *fixup_val;
2164201d057SRob Herring 		const char *tree_val;
2174201d057SRob Herring 		const char *name;
2184201d057SRob Herring 		int fixup_len;
2194201d057SRob Herring 		int tree_len;
2204201d057SRob Herring 		int i;
2214201d057SRob Herring 
2224201d057SRob Herring 		fixup_val = fdt_getprop_by_offset(fdto, fixup_prop,
2234201d057SRob Herring 						  &name, &fixup_len);
2244201d057SRob Herring 		if (!fixup_val)
2254201d057SRob Herring 			return fixup_len;
2264201d057SRob Herring 
2274201d057SRob Herring 		if (fixup_len % sizeof(uint32_t))
2284201d057SRob Herring 			return -FDT_ERR_BADOVERLAY;
2296e9c9686SRob Herring 		fixup_len /= sizeof(uint32_t);
2304201d057SRob Herring 
2314201d057SRob Herring 		tree_val = fdt_getprop(fdto, tree_node, name, &tree_len);
2324201d057SRob Herring 		if (!tree_val) {
2334201d057SRob Herring 			if (tree_len == -FDT_ERR_NOTFOUND)
2344201d057SRob Herring 				return -FDT_ERR_BADOVERLAY;
2354201d057SRob Herring 
2364201d057SRob Herring 			return tree_len;
2374201d057SRob Herring 		}
2384201d057SRob Herring 
2396e9c9686SRob Herring 		for (i = 0; i < fixup_len; i++) {
2404201d057SRob Herring 			fdt32_t adj_val;
2414201d057SRob Herring 			uint32_t poffset;
2424201d057SRob Herring 
2434201d057SRob Herring 			poffset = fdt32_to_cpu(fixup_val[i]);
2444201d057SRob Herring 
2454201d057SRob Herring 			/*
2464201d057SRob Herring 			 * phandles to fixup can be unaligned.
2474201d057SRob Herring 			 *
2484201d057SRob Herring 			 * Use a memcpy for the architectures that do
2494201d057SRob Herring 			 * not support unaligned accesses.
2504201d057SRob Herring 			 */
2514201d057SRob Herring 			memcpy(&adj_val, tree_val + poffset, sizeof(adj_val));
2524201d057SRob Herring 
2534201d057SRob Herring 			adj_val = cpu_to_fdt32(fdt32_to_cpu(adj_val) + delta);
2544201d057SRob Herring 
2554201d057SRob Herring 			ret = fdt_setprop_inplace_namelen_partial(fdto,
2564201d057SRob Herring 								  tree_node,
2574201d057SRob Herring 								  name,
2584201d057SRob Herring 								  strlen(name),
2594201d057SRob Herring 								  poffset,
2604201d057SRob Herring 								  &adj_val,
2614201d057SRob Herring 								  sizeof(adj_val));
2624201d057SRob Herring 			if (ret == -FDT_ERR_NOSPACE)
2634201d057SRob Herring 				return -FDT_ERR_BADOVERLAY;
2644201d057SRob Herring 
2654201d057SRob Herring 			if (ret)
2664201d057SRob Herring 				return ret;
2674201d057SRob Herring 		}
2684201d057SRob Herring 	}
2694201d057SRob Herring 
2704201d057SRob Herring 	fdt_for_each_subnode(fixup_child, fdto, fixup_node) {
2714201d057SRob Herring 		const char *fixup_child_name = fdt_get_name(fdto, fixup_child,
2724201d057SRob Herring 							    NULL);
2734201d057SRob Herring 		int tree_child;
2744201d057SRob Herring 
2754201d057SRob Herring 		tree_child = fdt_subnode_offset(fdto, tree_node,
2764201d057SRob Herring 						fixup_child_name);
2774201d057SRob Herring 		if (tree_child == -FDT_ERR_NOTFOUND)
2784201d057SRob Herring 			return -FDT_ERR_BADOVERLAY;
2794201d057SRob Herring 		if (tree_child < 0)
2804201d057SRob Herring 			return tree_child;
2814201d057SRob Herring 
2824201d057SRob Herring 		ret = overlay_update_local_node_references(fdto,
2834201d057SRob Herring 							   tree_child,
2844201d057SRob Herring 							   fixup_child,
2854201d057SRob Herring 							   delta);
2864201d057SRob Herring 		if (ret)
2874201d057SRob Herring 			return ret;
2884201d057SRob Herring 	}
2894201d057SRob Herring 
2904201d057SRob Herring 	return 0;
2914201d057SRob Herring }
2924201d057SRob Herring 
2934201d057SRob Herring /**
2944201d057SRob Herring  * overlay_update_local_references - Adjust the overlay references
2954201d057SRob Herring  * @fdto: Device tree overlay blob
2964201d057SRob Herring  * @delta: Offset to shift the phandles of
2974201d057SRob Herring  *
2984201d057SRob Herring  * overlay_update_local_references() update all the phandles pointing
2994201d057SRob Herring  * to a node within the device tree overlay by adding a constant
3004201d057SRob Herring  * delta to not conflict with the base overlay.
3014201d057SRob Herring  *
3024201d057SRob Herring  * This is mainly used as part of a device tree application process,
3034201d057SRob Herring  * where you want the device tree overlays phandles to not conflict
3044201d057SRob Herring  * with the ones from the base device tree before merging them.
3054201d057SRob Herring  *
3064201d057SRob Herring  * returns:
3074201d057SRob Herring  *      0 on success
3084201d057SRob Herring  *      Negative error code on failure
3094201d057SRob Herring  */
overlay_update_local_references(void * fdto,uint32_t delta)3104201d057SRob Herring static int overlay_update_local_references(void *fdto, uint32_t delta)
3114201d057SRob Herring {
3124201d057SRob Herring 	int fixups;
3134201d057SRob Herring 
3144201d057SRob Herring 	fixups = fdt_path_offset(fdto, "/__local_fixups__");
3154201d057SRob Herring 	if (fixups < 0) {
3164201d057SRob Herring 		/* There's no local phandles to adjust, bail out */
3174201d057SRob Herring 		if (fixups == -FDT_ERR_NOTFOUND)
3184201d057SRob Herring 			return 0;
3194201d057SRob Herring 
3204201d057SRob Herring 		return fixups;
3214201d057SRob Herring 	}
3224201d057SRob Herring 
3234201d057SRob Herring 	/*
3244201d057SRob Herring 	 * Update our local references from the root of the tree
3254201d057SRob Herring 	 */
3264201d057SRob Herring 	return overlay_update_local_node_references(fdto, 0, fixups,
3274201d057SRob Herring 						    delta);
3284201d057SRob Herring }
3294201d057SRob Herring 
3304201d057SRob Herring /**
3314201d057SRob Herring  * overlay_fixup_one_phandle - Set an overlay phandle to the base one
3324201d057SRob Herring  * @fdt: Base Device Tree blob
3334201d057SRob Herring  * @fdto: Device tree overlay blob
3344201d057SRob Herring  * @symbols_off: Node offset of the symbols node in the base device tree
3354201d057SRob Herring  * @path: Path to a node holding a phandle in the overlay
3364201d057SRob Herring  * @path_len: number of path characters to consider
3374201d057SRob Herring  * @name: Name of the property holding the phandle reference in the overlay
3384201d057SRob Herring  * @name_len: number of name characters to consider
3394201d057SRob Herring  * @poffset: Offset within the overlay property where the phandle is stored
3404201d057SRob Herring  * @label: Label of the node referenced by the phandle
3414201d057SRob Herring  *
3424201d057SRob Herring  * overlay_fixup_one_phandle() resolves an overlay phandle pointing to
3434201d057SRob Herring  * a node in the base device tree.
3444201d057SRob Herring  *
3454201d057SRob Herring  * This is part of the device tree overlay application process, when
3464201d057SRob Herring  * you want all the phandles in the overlay to point to the actual
3474201d057SRob Herring  * base dt nodes.
3484201d057SRob Herring  *
3494201d057SRob Herring  * returns:
3504201d057SRob Herring  *      0 on success
3514201d057SRob Herring  *      Negative error code on failure
3524201d057SRob Herring  */
overlay_fixup_one_phandle(void * fdt,void * fdto,int symbols_off,const char * path,uint32_t path_len,const char * name,uint32_t name_len,int poffset,const char * label)3534201d057SRob Herring static int overlay_fixup_one_phandle(void *fdt, void *fdto,
3544201d057SRob Herring 				     int symbols_off,
3554201d057SRob Herring 				     const char *path, uint32_t path_len,
3564201d057SRob Herring 				     const char *name, uint32_t name_len,
3574201d057SRob Herring 				     int poffset, const char *label)
3584201d057SRob Herring {
3594201d057SRob Herring 	const char *symbol_path;
3604201d057SRob Herring 	uint32_t phandle;
3614201d057SRob Herring 	fdt32_t phandle_prop;
3624201d057SRob Herring 	int symbol_off, fixup_off;
3634201d057SRob Herring 	int prop_len;
3644201d057SRob Herring 
3654201d057SRob Herring 	if (symbols_off < 0)
3664201d057SRob Herring 		return symbols_off;
3674201d057SRob Herring 
3684201d057SRob Herring 	symbol_path = fdt_getprop(fdt, symbols_off, label,
3694201d057SRob Herring 				  &prop_len);
3704201d057SRob Herring 	if (!symbol_path)
3714201d057SRob Herring 		return prop_len;
3724201d057SRob Herring 
3734201d057SRob Herring 	symbol_off = fdt_path_offset(fdt, symbol_path);
3744201d057SRob Herring 	if (symbol_off < 0)
3754201d057SRob Herring 		return symbol_off;
3764201d057SRob Herring 
3774201d057SRob Herring 	phandle = fdt_get_phandle(fdt, symbol_off);
3784201d057SRob Herring 	if (!phandle)
3794201d057SRob Herring 		return -FDT_ERR_NOTFOUND;
3804201d057SRob Herring 
3814201d057SRob Herring 	fixup_off = fdt_path_offset_namelen(fdto, path, path_len);
3824201d057SRob Herring 	if (fixup_off == -FDT_ERR_NOTFOUND)
3834201d057SRob Herring 		return -FDT_ERR_BADOVERLAY;
3844201d057SRob Herring 	if (fixup_off < 0)
3854201d057SRob Herring 		return fixup_off;
3864201d057SRob Herring 
3874201d057SRob Herring 	phandle_prop = cpu_to_fdt32(phandle);
3884201d057SRob Herring 	return fdt_setprop_inplace_namelen_partial(fdto, fixup_off,
3894201d057SRob Herring 						   name, name_len, poffset,
3904201d057SRob Herring 						   &phandle_prop,
3914201d057SRob Herring 						   sizeof(phandle_prop));
3924201d057SRob Herring };
3934201d057SRob Herring 
3944201d057SRob Herring /**
3954201d057SRob Herring  * overlay_fixup_phandle - Set an overlay phandle to the base one
3964201d057SRob Herring  * @fdt: Base Device Tree blob
3974201d057SRob Herring  * @fdto: Device tree overlay blob
3984201d057SRob Herring  * @symbols_off: Node offset of the symbols node in the base device tree
3994201d057SRob Herring  * @property: Property offset in the overlay holding the list of fixups
4004201d057SRob Herring  *
4014201d057SRob Herring  * overlay_fixup_phandle() resolves all the overlay phandles pointed
4024201d057SRob Herring  * to in a __fixups__ property, and updates them to match the phandles
4034201d057SRob Herring  * in use in the base device tree.
4044201d057SRob Herring  *
4054201d057SRob Herring  * This is part of the device tree overlay application process, when
4064201d057SRob Herring  * you want all the phandles in the overlay to point to the actual
4074201d057SRob Herring  * base dt nodes.
4084201d057SRob Herring  *
4094201d057SRob Herring  * returns:
4104201d057SRob Herring  *      0 on success
4114201d057SRob Herring  *      Negative error code on failure
4124201d057SRob Herring  */
overlay_fixup_phandle(void * fdt,void * fdto,int symbols_off,int property)4134201d057SRob Herring static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
4144201d057SRob Herring 				 int property)
4154201d057SRob Herring {
4164201d057SRob Herring 	const char *value;
4174201d057SRob Herring 	const char *label;
4184201d057SRob Herring 	int len;
4194201d057SRob Herring 
4204201d057SRob Herring 	value = fdt_getprop_by_offset(fdto, property,
4214201d057SRob Herring 				      &label, &len);
4224201d057SRob Herring 	if (!value) {
4234201d057SRob Herring 		if (len == -FDT_ERR_NOTFOUND)
4244201d057SRob Herring 			return -FDT_ERR_INTERNAL;
4254201d057SRob Herring 
4264201d057SRob Herring 		return len;
4274201d057SRob Herring 	}
4284201d057SRob Herring 
4294201d057SRob Herring 	do {
4304201d057SRob Herring 		const char *path, *name, *fixup_end;
4314201d057SRob Herring 		const char *fixup_str = value;
4324201d057SRob Herring 		uint32_t path_len, name_len;
4334201d057SRob Herring 		uint32_t fixup_len;
4344201d057SRob Herring 		char *sep, *endptr;
4354201d057SRob Herring 		int poffset, ret;
4364201d057SRob Herring 
4374201d057SRob Herring 		fixup_end = memchr(value, '\0', len);
4384201d057SRob Herring 		if (!fixup_end)
4394201d057SRob Herring 			return -FDT_ERR_BADOVERLAY;
4404201d057SRob Herring 		fixup_len = fixup_end - fixup_str;
4414201d057SRob Herring 
4424201d057SRob Herring 		len -= fixup_len + 1;
4434201d057SRob Herring 		value += fixup_len + 1;
4444201d057SRob Herring 
4454201d057SRob Herring 		path = fixup_str;
4464201d057SRob Herring 		sep = memchr(fixup_str, ':', fixup_len);
4474201d057SRob Herring 		if (!sep || *sep != ':')
4484201d057SRob Herring 			return -FDT_ERR_BADOVERLAY;
4494201d057SRob Herring 
4504201d057SRob Herring 		path_len = sep - path;
4514201d057SRob Herring 		if (path_len == (fixup_len - 1))
4524201d057SRob Herring 			return -FDT_ERR_BADOVERLAY;
4534201d057SRob Herring 
4544201d057SRob Herring 		fixup_len -= path_len + 1;
4554201d057SRob Herring 		name = sep + 1;
4564201d057SRob Herring 		sep = memchr(name, ':', fixup_len);
4574201d057SRob Herring 		if (!sep || *sep != ':')
4584201d057SRob Herring 			return -FDT_ERR_BADOVERLAY;
4594201d057SRob Herring 
4604201d057SRob Herring 		name_len = sep - name;
4614201d057SRob Herring 		if (!name_len)
4624201d057SRob Herring 			return -FDT_ERR_BADOVERLAY;
4634201d057SRob Herring 
4644201d057SRob Herring 		poffset = strtoul(sep + 1, &endptr, 10);
4654201d057SRob Herring 		if ((*endptr != '\0') || (endptr <= (sep + 1)))
4664201d057SRob Herring 			return -FDT_ERR_BADOVERLAY;
4674201d057SRob Herring 
4684201d057SRob Herring 		ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off,
4694201d057SRob Herring 						path, path_len, name, name_len,
4704201d057SRob Herring 						poffset, label);
4714201d057SRob Herring 		if (ret)
4724201d057SRob Herring 			return ret;
4734201d057SRob Herring 	} while (len > 0);
4744201d057SRob Herring 
4754201d057SRob Herring 	return 0;
4764201d057SRob Herring }
4774201d057SRob Herring 
4784201d057SRob Herring /**
4794201d057SRob Herring  * overlay_fixup_phandles - Resolve the overlay phandles to the base
4804201d057SRob Herring  *                          device tree
4814201d057SRob Herring  * @fdt: Base Device Tree blob
4824201d057SRob Herring  * @fdto: Device tree overlay blob
4834201d057SRob Herring  *
4844201d057SRob Herring  * overlay_fixup_phandles() resolves all the overlay phandles pointing
4854201d057SRob Herring  * to nodes in the base device tree.
4864201d057SRob Herring  *
4874201d057SRob Herring  * This is one of the steps of the device tree overlay application
4884201d057SRob Herring  * process, when you want all the phandles in the overlay to point to
4894201d057SRob Herring  * the actual base dt nodes.
4904201d057SRob Herring  *
4914201d057SRob Herring  * returns:
4924201d057SRob Herring  *      0 on success
4934201d057SRob Herring  *      Negative error code on failure
4944201d057SRob Herring  */
overlay_fixup_phandles(void * fdt,void * fdto)4954201d057SRob Herring static int overlay_fixup_phandles(void *fdt, void *fdto)
4964201d057SRob Herring {
4974201d057SRob Herring 	int fixups_off, symbols_off;
4984201d057SRob Herring 	int property;
4994201d057SRob Herring 
5004201d057SRob Herring 	/* We can have overlays without any fixups */
5014201d057SRob Herring 	fixups_off = fdt_path_offset(fdto, "/__fixups__");
5024201d057SRob Herring 	if (fixups_off == -FDT_ERR_NOTFOUND)
5034201d057SRob Herring 		return 0; /* nothing to do */
5044201d057SRob Herring 	if (fixups_off < 0)
5054201d057SRob Herring 		return fixups_off;
5064201d057SRob Herring 
5074201d057SRob Herring 	/* And base DTs without symbols */
5084201d057SRob Herring 	symbols_off = fdt_path_offset(fdt, "/__symbols__");
5094201d057SRob Herring 	if ((symbols_off < 0 && (symbols_off != -FDT_ERR_NOTFOUND)))
5104201d057SRob Herring 		return symbols_off;
5114201d057SRob Herring 
5124201d057SRob Herring 	fdt_for_each_property_offset(property, fdto, fixups_off) {
5134201d057SRob Herring 		int ret;
5144201d057SRob Herring 
5154201d057SRob Herring 		ret = overlay_fixup_phandle(fdt, fdto, symbols_off, property);
5164201d057SRob Herring 		if (ret)
5174201d057SRob Herring 			return ret;
5184201d057SRob Herring 	}
5194201d057SRob Herring 
5204201d057SRob Herring 	return 0;
5214201d057SRob Herring }
5224201d057SRob Herring 
5234201d057SRob Herring /**
5244201d057SRob Herring  * overlay_apply_node - Merges a node into the base device tree
5254201d057SRob Herring  * @fdt: Base Device Tree blob
5264201d057SRob Herring  * @target: Node offset in the base device tree to apply the fragment to
5274201d057SRob Herring  * @fdto: Device tree overlay blob
5284201d057SRob Herring  * @node: Node offset in the overlay holding the changes to merge
5294201d057SRob Herring  *
5304201d057SRob Herring  * overlay_apply_node() merges a node into a target base device tree
5314201d057SRob Herring  * node pointed.
5324201d057SRob Herring  *
5334201d057SRob Herring  * This is part of the final step in the device tree overlay
5344201d057SRob Herring  * application process, when all the phandles have been adjusted and
5354201d057SRob Herring  * resolved and you just have to merge overlay into the base device
5364201d057SRob Herring  * tree.
5374201d057SRob Herring  *
5384201d057SRob Herring  * returns:
5394201d057SRob Herring  *      0 on success
5404201d057SRob Herring  *      Negative error code on failure
5414201d057SRob Herring  */
overlay_apply_node(void * fdt,int target,void * fdto,int node)5424201d057SRob Herring static int overlay_apply_node(void *fdt, int target,
5434201d057SRob Herring 			      void *fdto, int node)
5444201d057SRob Herring {
5454201d057SRob Herring 	int property;
5464201d057SRob Herring 	int subnode;
5474201d057SRob Herring 
5484201d057SRob Herring 	fdt_for_each_property_offset(property, fdto, node) {
5494201d057SRob Herring 		const char *name;
5504201d057SRob Herring 		const void *prop;
5514201d057SRob Herring 		int prop_len;
5524201d057SRob Herring 		int ret;
5534201d057SRob Herring 
5544201d057SRob Herring 		prop = fdt_getprop_by_offset(fdto, property, &name,
5554201d057SRob Herring 					     &prop_len);
5564201d057SRob Herring 		if (prop_len == -FDT_ERR_NOTFOUND)
5574201d057SRob Herring 			return -FDT_ERR_INTERNAL;
5584201d057SRob Herring 		if (prop_len < 0)
5594201d057SRob Herring 			return prop_len;
5604201d057SRob Herring 
5614201d057SRob Herring 		ret = fdt_setprop(fdt, target, name, prop, prop_len);
5624201d057SRob Herring 		if (ret)
5634201d057SRob Herring 			return ret;
5644201d057SRob Herring 	}
5654201d057SRob Herring 
5664201d057SRob Herring 	fdt_for_each_subnode(subnode, fdto, node) {
5674201d057SRob Herring 		const char *name = fdt_get_name(fdto, subnode, NULL);
5684201d057SRob Herring 		int nnode;
5694201d057SRob Herring 		int ret;
5704201d057SRob Herring 
5714201d057SRob Herring 		nnode = fdt_add_subnode(fdt, target, name);
5724201d057SRob Herring 		if (nnode == -FDT_ERR_EXISTS) {
5734201d057SRob Herring 			nnode = fdt_subnode_offset(fdt, target, name);
5744201d057SRob Herring 			if (nnode == -FDT_ERR_NOTFOUND)
5754201d057SRob Herring 				return -FDT_ERR_INTERNAL;
5764201d057SRob Herring 		}
5774201d057SRob Herring 
5784201d057SRob Herring 		if (nnode < 0)
5794201d057SRob Herring 			return nnode;
5804201d057SRob Herring 
5814201d057SRob Herring 		ret = overlay_apply_node(fdt, nnode, fdto, subnode);
5824201d057SRob Herring 		if (ret)
5834201d057SRob Herring 			return ret;
5844201d057SRob Herring 	}
5854201d057SRob Herring 
5864201d057SRob Herring 	return 0;
5874201d057SRob Herring }
5884201d057SRob Herring 
5894201d057SRob Herring /**
5904201d057SRob Herring  * overlay_merge - Merge an overlay into its base device tree
5914201d057SRob Herring  * @fdt: Base Device Tree blob
5924201d057SRob Herring  * @fdto: Device tree overlay blob
5934201d057SRob Herring  *
5944201d057SRob Herring  * overlay_merge() merges an overlay into its base device tree.
5954201d057SRob Herring  *
5964201d057SRob Herring  * This is the next to last step in the device tree overlay application
5974201d057SRob Herring  * process, when all the phandles have been adjusted and resolved and
5984201d057SRob Herring  * you just have to merge overlay into the base device tree.
5994201d057SRob Herring  *
6004201d057SRob Herring  * returns:
6014201d057SRob Herring  *      0 on success
6024201d057SRob Herring  *      Negative error code on failure
6034201d057SRob Herring  */
overlay_merge(void * fdt,void * fdto)6044201d057SRob Herring static int overlay_merge(void *fdt, void *fdto)
6054201d057SRob Herring {
6064201d057SRob Herring 	int fragment;
6074201d057SRob Herring 
6084201d057SRob Herring 	fdt_for_each_subnode(fragment, fdto, 0) {
6094201d057SRob Herring 		int overlay;
6104201d057SRob Herring 		int target;
6114201d057SRob Herring 		int ret;
6124201d057SRob Herring 
6134201d057SRob Herring 		/*
6144201d057SRob Herring 		 * Each fragments will have an __overlay__ node. If
6154201d057SRob Herring 		 * they don't, it's not supposed to be merged
6164201d057SRob Herring 		 */
6174201d057SRob Herring 		overlay = fdt_subnode_offset(fdto, fragment, "__overlay__");
6184201d057SRob Herring 		if (overlay == -FDT_ERR_NOTFOUND)
6194201d057SRob Herring 			continue;
6204201d057SRob Herring 
6214201d057SRob Herring 		if (overlay < 0)
6224201d057SRob Herring 			return overlay;
6234201d057SRob Herring 
624*ea3723a5SRob Herring 		target = fdt_overlay_target_offset(fdt, fdto, fragment, NULL);
6254201d057SRob Herring 		if (target < 0)
6264201d057SRob Herring 			return target;
6274201d057SRob Herring 
6284201d057SRob Herring 		ret = overlay_apply_node(fdt, target, fdto, overlay);
6294201d057SRob Herring 		if (ret)
6304201d057SRob Herring 			return ret;
6314201d057SRob Herring 	}
6324201d057SRob Herring 
6334201d057SRob Herring 	return 0;
6344201d057SRob Herring }
6354201d057SRob Herring 
get_path_len(const void * fdt,int nodeoffset)6364201d057SRob Herring static int get_path_len(const void *fdt, int nodeoffset)
6374201d057SRob Herring {
6384201d057SRob Herring 	int len = 0, namelen;
6394201d057SRob Herring 	const char *name;
6404201d057SRob Herring 
641f858927fSRob Herring 	FDT_RO_PROBE(fdt);
6424201d057SRob Herring 
6434201d057SRob Herring 	for (;;) {
6444201d057SRob Herring 		name = fdt_get_name(fdt, nodeoffset, &namelen);
6454201d057SRob Herring 		if (!name)
6464201d057SRob Herring 			return namelen;
6474201d057SRob Herring 
6484201d057SRob Herring 		/* root? we're done */
6494201d057SRob Herring 		if (namelen == 0)
6504201d057SRob Herring 			break;
6514201d057SRob Herring 
6524201d057SRob Herring 		nodeoffset = fdt_parent_offset(fdt, nodeoffset);
6534201d057SRob Herring 		if (nodeoffset < 0)
6544201d057SRob Herring 			return nodeoffset;
6554201d057SRob Herring 		len += namelen + 1;
6564201d057SRob Herring 	}
6574201d057SRob Herring 
6584201d057SRob Herring 	/* in case of root pretend it's "/" */
6594201d057SRob Herring 	if (len == 0)
6604201d057SRob Herring 		len++;
6614201d057SRob Herring 	return len;
6624201d057SRob Herring }
6634201d057SRob Herring 
6644201d057SRob Herring /**
6654201d057SRob Herring  * overlay_symbol_update - Update the symbols of base tree after a merge
6664201d057SRob Herring  * @fdt: Base Device Tree blob
6674201d057SRob Herring  * @fdto: Device tree overlay blob
6684201d057SRob Herring  *
6694201d057SRob Herring  * overlay_symbol_update() updates the symbols of the base tree with the
6704201d057SRob Herring  * symbols of the applied overlay
6714201d057SRob Herring  *
6724201d057SRob Herring  * This is the last step in the device tree overlay application
6734201d057SRob Herring  * process, allowing the reference of overlay symbols by subsequent
6744201d057SRob Herring  * overlay operations.
6754201d057SRob Herring  *
6764201d057SRob Herring  * returns:
6774201d057SRob Herring  *      0 on success
6784201d057SRob Herring  *      Negative error code on failure
6794201d057SRob Herring  */
overlay_symbol_update(void * fdt,void * fdto)6804201d057SRob Herring static int overlay_symbol_update(void *fdt, void *fdto)
6814201d057SRob Herring {
6824201d057SRob Herring 	int root_sym, ov_sym, prop, path_len, fragment, target;
6834201d057SRob Herring 	int len, frag_name_len, ret, rel_path_len;
6844201d057SRob Herring 	const char *s, *e;
6854201d057SRob Herring 	const char *path;
6864201d057SRob Herring 	const char *name;
6874201d057SRob Herring 	const char *frag_name;
6884201d057SRob Herring 	const char *rel_path;
6894201d057SRob Herring 	const char *target_path;
6904201d057SRob Herring 	char *buf;
6914201d057SRob Herring 	void *p;
6924201d057SRob Herring 
6934201d057SRob Herring 	ov_sym = fdt_subnode_offset(fdto, 0, "__symbols__");
6944201d057SRob Herring 
6954201d057SRob Herring 	/* if no overlay symbols exist no problem */
6964201d057SRob Herring 	if (ov_sym < 0)
6974201d057SRob Herring 		return 0;
6984201d057SRob Herring 
6994201d057SRob Herring 	root_sym = fdt_subnode_offset(fdt, 0, "__symbols__");
7004201d057SRob Herring 
7014201d057SRob Herring 	/* it no root symbols exist we should create them */
7024201d057SRob Herring 	if (root_sym == -FDT_ERR_NOTFOUND)
7034201d057SRob Herring 		root_sym = fdt_add_subnode(fdt, 0, "__symbols__");
7044201d057SRob Herring 
7054201d057SRob Herring 	/* any error is fatal now */
7064201d057SRob Herring 	if (root_sym < 0)
7074201d057SRob Herring 		return root_sym;
7084201d057SRob Herring 
7094201d057SRob Herring 	/* iterate over each overlay symbol */
7104201d057SRob Herring 	fdt_for_each_property_offset(prop, fdto, ov_sym) {
7114201d057SRob Herring 		path = fdt_getprop_by_offset(fdto, prop, &name, &path_len);
7124201d057SRob Herring 		if (!path)
7134201d057SRob Herring 			return path_len;
7144201d057SRob Herring 
7154201d057SRob Herring 		/* verify it's a string property (terminated by a single \0) */
7164201d057SRob Herring 		if (path_len < 1 || memchr(path, '\0', path_len) != &path[path_len - 1])
7174201d057SRob Herring 			return -FDT_ERR_BADVALUE;
7184201d057SRob Herring 
7194201d057SRob Herring 		/* keep end marker to avoid strlen() */
7204201d057SRob Herring 		e = path + path_len;
7214201d057SRob Herring 
7224201d057SRob Herring 		if (*path != '/')
7234201d057SRob Herring 			return -FDT_ERR_BADVALUE;
7244201d057SRob Herring 
7254201d057SRob Herring 		/* get fragment name first */
7264201d057SRob Herring 		s = strchr(path + 1, '/');
7270cec114eSRob Herring 		if (!s) {
7280cec114eSRob Herring 			/* Symbol refers to something that won't end
7290cec114eSRob Herring 			 * up in the target tree */
7300cec114eSRob Herring 			continue;
7310cec114eSRob Herring 		}
7324201d057SRob Herring 
7334201d057SRob Herring 		frag_name = path + 1;
7344201d057SRob Herring 		frag_name_len = s - path - 1;
7354201d057SRob Herring 
7364201d057SRob Herring 		/* verify format; safe since "s" lies in \0 terminated prop */
7374201d057SRob Herring 		len = sizeof("/__overlay__/") - 1;
7380cec114eSRob Herring 		if ((e - s) > len && (memcmp(s, "/__overlay__/", len) == 0)) {
7390cec114eSRob Herring 			/* /<fragment-name>/__overlay__/<relative-subnode-path> */
7404201d057SRob Herring 			rel_path = s + len;
7410cec114eSRob Herring 			rel_path_len = e - rel_path - 1;
7420cec114eSRob Herring 		} else if ((e - s) == len
7430cec114eSRob Herring 			   && (memcmp(s, "/__overlay__", len - 1) == 0)) {
7440cec114eSRob Herring 			/* /<fragment-name>/__overlay__ */
7450cec114eSRob Herring 			rel_path = "";
7460cec114eSRob Herring 			rel_path_len = 0;
7470cec114eSRob Herring 		} else {
7480cec114eSRob Herring 			/* Symbol refers to something that won't end
7490cec114eSRob Herring 			 * up in the target tree */
7500cec114eSRob Herring 			continue;
7510cec114eSRob Herring 		}
7524201d057SRob Herring 
7534201d057SRob Herring 		/* find the fragment index in which the symbol lies */
7544201d057SRob Herring 		ret = fdt_subnode_offset_namelen(fdto, 0, frag_name,
7554201d057SRob Herring 					       frag_name_len);
7564201d057SRob Herring 		/* not found? */
7574201d057SRob Herring 		if (ret < 0)
7584201d057SRob Herring 			return -FDT_ERR_BADOVERLAY;
7594201d057SRob Herring 		fragment = ret;
7604201d057SRob Herring 
7614201d057SRob Herring 		/* an __overlay__ subnode must exist */
7624201d057SRob Herring 		ret = fdt_subnode_offset(fdto, fragment, "__overlay__");
7634201d057SRob Herring 		if (ret < 0)
7644201d057SRob Herring 			return -FDT_ERR_BADOVERLAY;
7654201d057SRob Herring 
7664201d057SRob Herring 		/* get the target of the fragment */
767*ea3723a5SRob Herring 		ret = fdt_overlay_target_offset(fdt, fdto, fragment, &target_path);
7684201d057SRob Herring 		if (ret < 0)
7694201d057SRob Herring 			return ret;
7704201d057SRob Herring 		target = ret;
7714201d057SRob Herring 
7724201d057SRob Herring 		/* if we have a target path use */
7734201d057SRob Herring 		if (!target_path) {
7744201d057SRob Herring 			ret = get_path_len(fdt, target);
7754201d057SRob Herring 			if (ret < 0)
7764201d057SRob Herring 				return ret;
7774201d057SRob Herring 			len = ret;
7784201d057SRob Herring 		} else {
7794201d057SRob Herring 			len = strlen(target_path);
7804201d057SRob Herring 		}
7814201d057SRob Herring 
7824201d057SRob Herring 		ret = fdt_setprop_placeholder(fdt, root_sym, name,
7834201d057SRob Herring 				len + (len > 1) + rel_path_len + 1, &p);
7844201d057SRob Herring 		if (ret < 0)
7854201d057SRob Herring 			return ret;
7864201d057SRob Herring 
7874201d057SRob Herring 		if (!target_path) {
7884201d057SRob Herring 			/* again in case setprop_placeholder changed it */
789*ea3723a5SRob Herring 			ret = fdt_overlay_target_offset(fdt, fdto, fragment, &target_path);
7904201d057SRob Herring 			if (ret < 0)
7914201d057SRob Herring 				return ret;
7924201d057SRob Herring 			target = ret;
7934201d057SRob Herring 		}
7944201d057SRob Herring 
7954201d057SRob Herring 		buf = p;
7964201d057SRob Herring 		if (len > 1) { /* target is not root */
7974201d057SRob Herring 			if (!target_path) {
7984201d057SRob Herring 				ret = fdt_get_path(fdt, target, buf, len + 1);
7994201d057SRob Herring 				if (ret < 0)
8004201d057SRob Herring 					return ret;
8014201d057SRob Herring 			} else
8024201d057SRob Herring 				memcpy(buf, target_path, len + 1);
8034201d057SRob Herring 
8044201d057SRob Herring 		} else
8054201d057SRob Herring 			len--;
8064201d057SRob Herring 
8074201d057SRob Herring 		buf[len] = '/';
8084201d057SRob Herring 		memcpy(buf + len + 1, rel_path, rel_path_len);
8094201d057SRob Herring 		buf[len + 1 + rel_path_len] = '\0';
8104201d057SRob Herring 	}
8114201d057SRob Herring 
8124201d057SRob Herring 	return 0;
8134201d057SRob Herring }
8144201d057SRob Herring 
fdt_overlay_apply(void * fdt,void * fdto)8154201d057SRob Herring int fdt_overlay_apply(void *fdt, void *fdto)
8164201d057SRob Herring {
8179bb9c6a1SRob Herring 	uint32_t delta;
8184201d057SRob Herring 	int ret;
8194201d057SRob Herring 
820f858927fSRob Herring 	FDT_RO_PROBE(fdt);
821f858927fSRob Herring 	FDT_RO_PROBE(fdto);
8224201d057SRob Herring 
8239bb9c6a1SRob Herring 	ret = fdt_find_max_phandle(fdt, &delta);
8249bb9c6a1SRob Herring 	if (ret)
8259bb9c6a1SRob Herring 		goto err;
8269bb9c6a1SRob Herring 
8274201d057SRob Herring 	ret = overlay_adjust_local_phandles(fdto, delta);
8284201d057SRob Herring 	if (ret)
8294201d057SRob Herring 		goto err;
8304201d057SRob Herring 
8314201d057SRob Herring 	ret = overlay_update_local_references(fdto, delta);
8324201d057SRob Herring 	if (ret)
8334201d057SRob Herring 		goto err;
8344201d057SRob Herring 
8354201d057SRob Herring 	ret = overlay_fixup_phandles(fdt, fdto);
8364201d057SRob Herring 	if (ret)
8374201d057SRob Herring 		goto err;
8384201d057SRob Herring 
8394201d057SRob Herring 	ret = overlay_merge(fdt, fdto);
8404201d057SRob Herring 	if (ret)
8414201d057SRob Herring 		goto err;
8424201d057SRob Herring 
8434201d057SRob Herring 	ret = overlay_symbol_update(fdt, fdto);
8444201d057SRob Herring 	if (ret)
8454201d057SRob Herring 		goto err;
8464201d057SRob Herring 
8474201d057SRob Herring 	/*
8484201d057SRob Herring 	 * The overlay has been damaged, erase its magic.
8494201d057SRob Herring 	 */
8504201d057SRob Herring 	fdt_set_magic(fdto, ~0);
8514201d057SRob Herring 
8524201d057SRob Herring 	return 0;
8534201d057SRob Herring 
8544201d057SRob Herring err:
8554201d057SRob Herring 	/*
8564201d057SRob Herring 	 * The overlay might have been damaged, erase its magic.
8574201d057SRob Herring 	 */
8584201d057SRob Herring 	fdt_set_magic(fdto, ~0);
8594201d057SRob Herring 
8604201d057SRob Herring 	/*
8614201d057SRob Herring 	 * The base device tree might have been damaged, erase its
8624201d057SRob Herring 	 * magic.
8634201d057SRob Herring 	 */
8644201d057SRob Herring 	fdt_set_magic(fdt, ~0);
8654201d057SRob Herring 
8664201d057SRob Herring 	return ret;
8674201d057SRob Herring }
868