xref: /linux/scripts/dtc/libfdt/fdt_sw.c (revision d0034a7a4ac7fae708146ac0059b9c47a1543f0d)
112869ecdSRob Herring // SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
29fffb55fSDavid Gibson /*
39fffb55fSDavid Gibson  * libfdt - Flat Device Tree manipulation
49fffb55fSDavid Gibson  * Copyright (C) 2006 David Gibson, IBM Corporation.
59fffb55fSDavid Gibson  */
69fffb55fSDavid Gibson #include "libfdt_env.h"
79fffb55fSDavid Gibson 
89fffb55fSDavid Gibson #include <fdt.h>
99fffb55fSDavid Gibson #include <libfdt.h>
109fffb55fSDavid Gibson 
119fffb55fSDavid Gibson #include "libfdt_internal.h"
129fffb55fSDavid Gibson 
fdt_sw_probe_(void * fdt)13f858927fSRob Herring static int fdt_sw_probe_(void *fdt)
149fffb55fSDavid Gibson {
15d047cd8aSRob Herring 	if (!can_assume(VALID_INPUT)) {
16f858927fSRob Herring 		if (fdt_magic(fdt) == FDT_MAGIC)
17f858927fSRob Herring 			return -FDT_ERR_BADSTATE;
18f858927fSRob Herring 		else if (fdt_magic(fdt) != FDT_SW_MAGIC)
199fffb55fSDavid Gibson 			return -FDT_ERR_BADMAGIC;
20d047cd8aSRob Herring 	}
21d047cd8aSRob Herring 
229fffb55fSDavid Gibson 	return 0;
239fffb55fSDavid Gibson }
249fffb55fSDavid Gibson 
25f858927fSRob Herring #define FDT_SW_PROBE(fdt) \
269fffb55fSDavid Gibson 	{ \
279fffb55fSDavid Gibson 		int err; \
28f858927fSRob Herring 		if ((err = fdt_sw_probe_(fdt)) != 0) \
299fffb55fSDavid Gibson 			return err; \
309fffb55fSDavid Gibson 	}
319fffb55fSDavid Gibson 
32f858927fSRob Herring /* 'memrsv' state:	Initial state after fdt_create()
33f858927fSRob Herring  *
34f858927fSRob Herring  * Allowed functions:
353eb619b2SRob Herring  *	fdt_add_reservemap_entry()
36f858927fSRob Herring  *	fdt_finish_reservemap()		[moves to 'struct' state]
37f858927fSRob Herring  */
fdt_sw_probe_memrsv_(void * fdt)38f858927fSRob Herring static int fdt_sw_probe_memrsv_(void *fdt)
39f858927fSRob Herring {
40f858927fSRob Herring 	int err = fdt_sw_probe_(fdt);
41f858927fSRob Herring 	if (err)
42f858927fSRob Herring 		return err;
43f858927fSRob Herring 
44d047cd8aSRob Herring 	if (!can_assume(VALID_INPUT) && fdt_off_dt_strings(fdt) != 0)
45f858927fSRob Herring 		return -FDT_ERR_BADSTATE;
46f858927fSRob Herring 	return 0;
47f858927fSRob Herring }
48f858927fSRob Herring 
49f858927fSRob Herring #define FDT_SW_PROBE_MEMRSV(fdt) \
50f858927fSRob Herring 	{ \
51f858927fSRob Herring 		int err; \
52f858927fSRob Herring 		if ((err = fdt_sw_probe_memrsv_(fdt)) != 0) \
53f858927fSRob Herring 			return err; \
54f858927fSRob Herring 	}
55f858927fSRob Herring 
56f858927fSRob Herring /* 'struct' state:	Enter this state after fdt_finish_reservemap()
57f858927fSRob Herring  *
58f858927fSRob Herring  * Allowed functions:
59f858927fSRob Herring  *	fdt_begin_node()
60f858927fSRob Herring  *	fdt_end_node()
61f858927fSRob Herring  *	fdt_property*()
62f858927fSRob Herring  *	fdt_finish()			[moves to 'complete' state]
63f858927fSRob Herring  */
fdt_sw_probe_struct_(void * fdt)64f858927fSRob Herring static int fdt_sw_probe_struct_(void *fdt)
65f858927fSRob Herring {
66f858927fSRob Herring 	int err = fdt_sw_probe_(fdt);
67f858927fSRob Herring 	if (err)
68f858927fSRob Herring 		return err;
69f858927fSRob Herring 
70d047cd8aSRob Herring 	if (!can_assume(VALID_INPUT) &&
71d047cd8aSRob Herring 	    fdt_off_dt_strings(fdt) != fdt_totalsize(fdt))
72f858927fSRob Herring 		return -FDT_ERR_BADSTATE;
73f858927fSRob Herring 	return 0;
74f858927fSRob Herring }
75f858927fSRob Herring 
76f858927fSRob Herring #define FDT_SW_PROBE_STRUCT(fdt) \
77f858927fSRob Herring 	{ \
78f858927fSRob Herring 		int err; \
79f858927fSRob Herring 		if ((err = fdt_sw_probe_struct_(fdt)) != 0) \
80f858927fSRob Herring 			return err; \
81f858927fSRob Herring 	}
82f858927fSRob Herring 
sw_flags(void * fdt)839bb9c6a1SRob Herring static inline uint32_t sw_flags(void *fdt)
849bb9c6a1SRob Herring {
859bb9c6a1SRob Herring 	/* assert: (fdt_magic(fdt) == FDT_SW_MAGIC) */
869bb9c6a1SRob Herring 	return fdt_last_comp_version(fdt);
879bb9c6a1SRob Herring }
889bb9c6a1SRob Herring 
89f858927fSRob Herring /* 'complete' state:	Enter this state after fdt_finish()
90f858927fSRob Herring  *
91f858927fSRob Herring  * Allowed functions: none
92f858927fSRob Herring  */
93f858927fSRob Herring 
fdt_grab_space_(void * fdt,size_t len)949130ba88SRob Herring static void *fdt_grab_space_(void *fdt, size_t len)
959fffb55fSDavid Gibson {
966e9c9686SRob Herring 	unsigned int offset = fdt_size_dt_struct(fdt);
976e9c9686SRob Herring 	unsigned int spaceleft;
989fffb55fSDavid Gibson 
999fffb55fSDavid Gibson 	spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt)
1009fffb55fSDavid Gibson 		- fdt_size_dt_strings(fdt);
1019fffb55fSDavid Gibson 
1029fffb55fSDavid Gibson 	if ((offset + len < offset) || (offset + len > spaceleft))
1039fffb55fSDavid Gibson 		return NULL;
1049fffb55fSDavid Gibson 
1059fffb55fSDavid Gibson 	fdt_set_size_dt_struct(fdt, offset + len);
1069130ba88SRob Herring 	return fdt_offset_ptr_w_(fdt, offset);
1079fffb55fSDavid Gibson }
1089fffb55fSDavid Gibson 
fdt_create_with_flags(void * buf,int bufsize,uint32_t flags)1099bb9c6a1SRob Herring int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags)
1109fffb55fSDavid Gibson {
1116e9c9686SRob Herring 	const int hdrsize = FDT_ALIGN(sizeof(struct fdt_header),
112f858927fSRob Herring 				      sizeof(struct fdt_reserve_entry));
1139fffb55fSDavid Gibson 	void *fdt = buf;
1149fffb55fSDavid Gibson 
115f858927fSRob Herring 	if (bufsize < hdrsize)
1169fffb55fSDavid Gibson 		return -FDT_ERR_NOSPACE;
1179fffb55fSDavid Gibson 
1189bb9c6a1SRob Herring 	if (flags & ~FDT_CREATE_FLAGS_ALL)
1199bb9c6a1SRob Herring 		return -FDT_ERR_BADFLAGS;
1209bb9c6a1SRob Herring 
1219fffb55fSDavid Gibson 	memset(buf, 0, bufsize);
1229fffb55fSDavid Gibson 
1239bb9c6a1SRob Herring 	/*
1249bb9c6a1SRob Herring 	 * magic and last_comp_version keep intermediate state during the fdt
1259bb9c6a1SRob Herring 	 * creation process, which is replaced with the proper FDT format by
1269bb9c6a1SRob Herring 	 * fdt_finish().
1279bb9c6a1SRob Herring 	 *
1289bb9c6a1SRob Herring 	 * flags should be accessed with sw_flags().
1299bb9c6a1SRob Herring 	 */
1309fffb55fSDavid Gibson 	fdt_set_magic(fdt, FDT_SW_MAGIC);
1319fffb55fSDavid Gibson 	fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION);
1329bb9c6a1SRob Herring 	fdt_set_last_comp_version(fdt, flags);
1339bb9c6a1SRob Herring 
1349fffb55fSDavid Gibson 	fdt_set_totalsize(fdt,  bufsize);
1359fffb55fSDavid Gibson 
136f858927fSRob Herring 	fdt_set_off_mem_rsvmap(fdt, hdrsize);
1379fffb55fSDavid Gibson 	fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt));
138f858927fSRob Herring 	fdt_set_off_dt_strings(fdt, 0);
1399fffb55fSDavid Gibson 
1409fffb55fSDavid Gibson 	return 0;
1419fffb55fSDavid Gibson }
1429fffb55fSDavid Gibson 
fdt_create(void * buf,int bufsize)1439bb9c6a1SRob Herring int fdt_create(void *buf, int bufsize)
1449bb9c6a1SRob Herring {
1459bb9c6a1SRob Herring 	return fdt_create_with_flags(buf, bufsize, 0);
1469bb9c6a1SRob Herring }
1479bb9c6a1SRob Herring 
fdt_resize(void * fdt,void * buf,int bufsize)14847605971SRob Herring int fdt_resize(void *fdt, void *buf, int bufsize)
14947605971SRob Herring {
15047605971SRob Herring 	size_t headsize, tailsize;
15147605971SRob Herring 	char *oldtail, *newtail;
15247605971SRob Herring 
153f858927fSRob Herring 	FDT_SW_PROBE(fdt);
15447605971SRob Herring 
1556e9c9686SRob Herring 	if (bufsize < 0)
1566e9c9686SRob Herring 		return -FDT_ERR_NOSPACE;
1576e9c9686SRob Herring 
158f858927fSRob Herring 	headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
15947605971SRob Herring 	tailsize = fdt_size_dt_strings(fdt);
16047605971SRob Herring 
161d047cd8aSRob Herring 	if (!can_assume(VALID_DTB) &&
162d047cd8aSRob Herring 	    headsize + tailsize > fdt_totalsize(fdt))
163f858927fSRob Herring 		return -FDT_ERR_INTERNAL;
164f858927fSRob Herring 
1656e9c9686SRob Herring 	if ((headsize + tailsize) > (unsigned)bufsize)
16647605971SRob Herring 		return -FDT_ERR_NOSPACE;
16747605971SRob Herring 
16847605971SRob Herring 	oldtail = (char *)fdt + fdt_totalsize(fdt) - tailsize;
16947605971SRob Herring 	newtail = (char *)buf + bufsize - tailsize;
17047605971SRob Herring 
17147605971SRob Herring 	/* Two cases to avoid clobbering data if the old and new
17247605971SRob Herring 	 * buffers partially overlap */
17347605971SRob Herring 	if (buf <= fdt) {
17447605971SRob Herring 		memmove(buf, fdt, headsize);
17547605971SRob Herring 		memmove(newtail, oldtail, tailsize);
17647605971SRob Herring 	} else {
17747605971SRob Herring 		memmove(newtail, oldtail, tailsize);
17847605971SRob Herring 		memmove(buf, fdt, headsize);
17947605971SRob Herring 	}
18047605971SRob Herring 
18147605971SRob Herring 	fdt_set_totalsize(buf, bufsize);
182f858927fSRob Herring 	if (fdt_off_dt_strings(buf))
183f858927fSRob Herring 		fdt_set_off_dt_strings(buf, bufsize);
18447605971SRob Herring 
18547605971SRob Herring 	return 0;
18647605971SRob Herring }
18747605971SRob Herring 
fdt_add_reservemap_entry(void * fdt,uint64_t addr,uint64_t size)1889fffb55fSDavid Gibson int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)
1899fffb55fSDavid Gibson {
1909fffb55fSDavid Gibson 	struct fdt_reserve_entry *re;
1919fffb55fSDavid Gibson 	int offset;
1929fffb55fSDavid Gibson 
193f858927fSRob Herring 	FDT_SW_PROBE_MEMRSV(fdt);
1949fffb55fSDavid Gibson 
1959fffb55fSDavid Gibson 	offset = fdt_off_dt_struct(fdt);
1969fffb55fSDavid Gibson 	if ((offset + sizeof(*re)) > fdt_totalsize(fdt))
1979fffb55fSDavid Gibson 		return -FDT_ERR_NOSPACE;
1989fffb55fSDavid Gibson 
1999fffb55fSDavid Gibson 	re = (struct fdt_reserve_entry *)((char *)fdt + offset);
2009fffb55fSDavid Gibson 	re->address = cpu_to_fdt64(addr);
2019fffb55fSDavid Gibson 	re->size = cpu_to_fdt64(size);
2029fffb55fSDavid Gibson 
2039fffb55fSDavid Gibson 	fdt_set_off_dt_struct(fdt, offset + sizeof(*re));
2049fffb55fSDavid Gibson 
2059fffb55fSDavid Gibson 	return 0;
2069fffb55fSDavid Gibson }
2079fffb55fSDavid Gibson 
fdt_finish_reservemap(void * fdt)2089fffb55fSDavid Gibson int fdt_finish_reservemap(void *fdt)
2099fffb55fSDavid Gibson {
210f858927fSRob Herring 	int err = fdt_add_reservemap_entry(fdt, 0, 0);
211f858927fSRob Herring 
212f858927fSRob Herring 	if (err)
213f858927fSRob Herring 		return err;
214f858927fSRob Herring 
215f858927fSRob Herring 	fdt_set_off_dt_strings(fdt, fdt_totalsize(fdt));
216f858927fSRob Herring 	return 0;
2179fffb55fSDavid Gibson }
2189fffb55fSDavid Gibson 
fdt_begin_node(void * fdt,const char * name)2199fffb55fSDavid Gibson int fdt_begin_node(void *fdt, const char *name)
2209fffb55fSDavid Gibson {
2219fffb55fSDavid Gibson 	struct fdt_node_header *nh;
222f858927fSRob Herring 	int namelen;
2239fffb55fSDavid Gibson 
224f858927fSRob Herring 	FDT_SW_PROBE_STRUCT(fdt);
2259fffb55fSDavid Gibson 
226f858927fSRob Herring 	namelen = strlen(name) + 1;
2279130ba88SRob Herring 	nh = fdt_grab_space_(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen));
2289fffb55fSDavid Gibson 	if (! nh)
2299fffb55fSDavid Gibson 		return -FDT_ERR_NOSPACE;
2309fffb55fSDavid Gibson 
2319fffb55fSDavid Gibson 	nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE);
2329fffb55fSDavid Gibson 	memcpy(nh->name, name, namelen);
2339fffb55fSDavid Gibson 	return 0;
2349fffb55fSDavid Gibson }
2359fffb55fSDavid Gibson 
fdt_end_node(void * fdt)2369fffb55fSDavid Gibson int fdt_end_node(void *fdt)
2379fffb55fSDavid Gibson {
23847605971SRob Herring 	fdt32_t *en;
2399fffb55fSDavid Gibson 
240f858927fSRob Herring 	FDT_SW_PROBE_STRUCT(fdt);
2419fffb55fSDavid Gibson 
2429130ba88SRob Herring 	en = fdt_grab_space_(fdt, FDT_TAGSIZE);
2439fffb55fSDavid Gibson 	if (! en)
2449fffb55fSDavid Gibson 		return -FDT_ERR_NOSPACE;
2459fffb55fSDavid Gibson 
2469fffb55fSDavid Gibson 	*en = cpu_to_fdt32(FDT_END_NODE);
2479fffb55fSDavid Gibson 	return 0;
2489fffb55fSDavid Gibson }
2499fffb55fSDavid Gibson 
fdt_add_string_(void * fdt,const char * s)2509bb9c6a1SRob Herring static int fdt_add_string_(void *fdt, const char *s)
2519fffb55fSDavid Gibson {
2529fffb55fSDavid Gibson 	char *strtab = (char *)fdt + fdt_totalsize(fdt);
2536e9c9686SRob Herring 	unsigned int strtabsize = fdt_size_dt_strings(fdt);
2546e9c9686SRob Herring 	unsigned int len = strlen(s) + 1;
2556e9c9686SRob Herring 	unsigned int struct_top, offset;
2569fffb55fSDavid Gibson 
2576e9c9686SRob Herring 	offset = strtabsize + len;
2589fffb55fSDavid Gibson 	struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
2596e9c9686SRob Herring 	if (fdt_totalsize(fdt) - offset < struct_top)
2609fffb55fSDavid Gibson 		return 0; /* no more room :( */
2619fffb55fSDavid Gibson 
2626e9c9686SRob Herring 	memcpy(strtab - offset, s, len);
2639fffb55fSDavid Gibson 	fdt_set_size_dt_strings(fdt, strtabsize + len);
2646e9c9686SRob Herring 	return -offset;
2659fffb55fSDavid Gibson }
2669fffb55fSDavid Gibson 
2679bb9c6a1SRob Herring /* Must only be used to roll back in case of error */
fdt_del_last_string_(void * fdt,const char * s)2689bb9c6a1SRob Herring static void fdt_del_last_string_(void *fdt, const char *s)
2699bb9c6a1SRob Herring {
2709bb9c6a1SRob Herring 	int strtabsize = fdt_size_dt_strings(fdt);
2719bb9c6a1SRob Herring 	int len = strlen(s) + 1;
2729bb9c6a1SRob Herring 
2739bb9c6a1SRob Herring 	fdt_set_size_dt_strings(fdt, strtabsize - len);
2749bb9c6a1SRob Herring }
2759bb9c6a1SRob Herring 
fdt_find_add_string_(void * fdt,const char * s,int * allocated)2769bb9c6a1SRob Herring static int fdt_find_add_string_(void *fdt, const char *s, int *allocated)
2779bb9c6a1SRob Herring {
2789bb9c6a1SRob Herring 	char *strtab = (char *)fdt + fdt_totalsize(fdt);
2799bb9c6a1SRob Herring 	int strtabsize = fdt_size_dt_strings(fdt);
2809bb9c6a1SRob Herring 	const char *p;
2819bb9c6a1SRob Herring 
2829bb9c6a1SRob Herring 	*allocated = 0;
2839bb9c6a1SRob Herring 
2849bb9c6a1SRob Herring 	p = fdt_find_string_(strtab - strtabsize, strtabsize, s);
2859bb9c6a1SRob Herring 	if (p)
2869bb9c6a1SRob Herring 		return p - strtab;
2879bb9c6a1SRob Herring 
2889bb9c6a1SRob Herring 	*allocated = 1;
2899bb9c6a1SRob Herring 
2909bb9c6a1SRob Herring 	return fdt_add_string_(fdt, s);
2919bb9c6a1SRob Herring }
2929bb9c6a1SRob Herring 
fdt_property_placeholder(void * fdt,const char * name,int len,void ** valp)2934201d057SRob Herring int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp)
2949fffb55fSDavid Gibson {
2959fffb55fSDavid Gibson 	struct fdt_property *prop;
2969fffb55fSDavid Gibson 	int nameoff;
2979bb9c6a1SRob Herring 	int allocated;
2989fffb55fSDavid Gibson 
299f858927fSRob Herring 	FDT_SW_PROBE_STRUCT(fdt);
3009fffb55fSDavid Gibson 
3019bb9c6a1SRob Herring 	/* String de-duplication can be slow, _NO_NAME_DEDUP skips it */
3029bb9c6a1SRob Herring 	if (sw_flags(fdt) & FDT_CREATE_FLAG_NO_NAME_DEDUP) {
3039bb9c6a1SRob Herring 		allocated = 1;
3049bb9c6a1SRob Herring 		nameoff = fdt_add_string_(fdt, name);
3059bb9c6a1SRob Herring 	} else {
3069bb9c6a1SRob Herring 		nameoff = fdt_find_add_string_(fdt, name, &allocated);
3079bb9c6a1SRob Herring 	}
3089fffb55fSDavid Gibson 	if (nameoff == 0)
3099fffb55fSDavid Gibson 		return -FDT_ERR_NOSPACE;
3109fffb55fSDavid Gibson 
3119130ba88SRob Herring 	prop = fdt_grab_space_(fdt, sizeof(*prop) + FDT_TAGALIGN(len));
3129bb9c6a1SRob Herring 	if (! prop) {
3139bb9c6a1SRob Herring 		if (allocated)
3149bb9c6a1SRob Herring 			fdt_del_last_string_(fdt, name);
3159fffb55fSDavid Gibson 		return -FDT_ERR_NOSPACE;
3169bb9c6a1SRob Herring 	}
3179fffb55fSDavid Gibson 
3189fffb55fSDavid Gibson 	prop->tag = cpu_to_fdt32(FDT_PROP);
3199fffb55fSDavid Gibson 	prop->nameoff = cpu_to_fdt32(nameoff);
3209fffb55fSDavid Gibson 	prop->len = cpu_to_fdt32(len);
3214201d057SRob Herring 	*valp = prop->data;
3224201d057SRob Herring 	return 0;
3234201d057SRob Herring }
3244201d057SRob Herring 
fdt_property(void * fdt,const char * name,const void * val,int len)3254201d057SRob Herring int fdt_property(void *fdt, const char *name, const void *val, int len)
3264201d057SRob Herring {
3274201d057SRob Herring 	void *ptr;
3284201d057SRob Herring 	int ret;
3294201d057SRob Herring 
3304201d057SRob Herring 	ret = fdt_property_placeholder(fdt, name, len, &ptr);
3314201d057SRob Herring 	if (ret)
3324201d057SRob Herring 		return ret;
3334201d057SRob Herring 	memcpy(ptr, val, len);
3349fffb55fSDavid Gibson 	return 0;
3359fffb55fSDavid Gibson }
3369fffb55fSDavid Gibson 
fdt_finish(void * fdt)3379fffb55fSDavid Gibson int fdt_finish(void *fdt)
3389fffb55fSDavid Gibson {
3399fffb55fSDavid Gibson 	char *p = (char *)fdt;
34047605971SRob Herring 	fdt32_t *end;
3419fffb55fSDavid Gibson 	int oldstroffset, newstroffset;
3429fffb55fSDavid Gibson 	uint32_t tag;
3439fffb55fSDavid Gibson 	int offset, nextoffset;
3449fffb55fSDavid Gibson 
345f858927fSRob Herring 	FDT_SW_PROBE_STRUCT(fdt);
3469fffb55fSDavid Gibson 
3479fffb55fSDavid Gibson 	/* Add terminator */
3489130ba88SRob Herring 	end = fdt_grab_space_(fdt, sizeof(*end));
3499fffb55fSDavid Gibson 	if (! end)
3509fffb55fSDavid Gibson 		return -FDT_ERR_NOSPACE;
3519fffb55fSDavid Gibson 	*end = cpu_to_fdt32(FDT_END);
3529fffb55fSDavid Gibson 
3539fffb55fSDavid Gibson 	/* Relocate the string table */
3549fffb55fSDavid Gibson 	oldstroffset = fdt_totalsize(fdt) - fdt_size_dt_strings(fdt);
3559fffb55fSDavid Gibson 	newstroffset = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
3569fffb55fSDavid Gibson 	memmove(p + newstroffset, p + oldstroffset, fdt_size_dt_strings(fdt));
3579fffb55fSDavid Gibson 	fdt_set_off_dt_strings(fdt, newstroffset);
3589fffb55fSDavid Gibson 
3599fffb55fSDavid Gibson 	/* Walk the structure, correcting string offsets */
3609fffb55fSDavid Gibson 	offset = 0;
3619fffb55fSDavid Gibson 	while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) {
3629fffb55fSDavid Gibson 		if (tag == FDT_PROP) {
3639fffb55fSDavid Gibson 			struct fdt_property *prop =
3649130ba88SRob Herring 				fdt_offset_ptr_w_(fdt, offset);
3659fffb55fSDavid Gibson 			int nameoff;
3669fffb55fSDavid Gibson 
3679fffb55fSDavid Gibson 			nameoff = fdt32_to_cpu(prop->nameoff);
3689fffb55fSDavid Gibson 			nameoff += fdt_size_dt_strings(fdt);
3699fffb55fSDavid Gibson 			prop->nameoff = cpu_to_fdt32(nameoff);
3709fffb55fSDavid Gibson 		}
3719fffb55fSDavid Gibson 		offset = nextoffset;
3729fffb55fSDavid Gibson 	}
373cd296721SStephen Warren 	if (nextoffset < 0)
374cd296721SStephen Warren 		return nextoffset;
3759fffb55fSDavid Gibson 
3769fffb55fSDavid Gibson 	/* Finally, adjust the header */
3779fffb55fSDavid Gibson 	fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
3789bb9c6a1SRob Herring 
3799bb9c6a1SRob Herring 	/* And fix up fields that were keeping intermediate state. */
380*79edff12SRob Herring 	fdt_set_last_comp_version(fdt, FDT_LAST_COMPATIBLE_VERSION);
3819fffb55fSDavid Gibson 	fdt_set_magic(fdt, FDT_MAGIC);
3829bb9c6a1SRob Herring 
3839fffb55fSDavid Gibson 	return 0;
3849fffb55fSDavid Gibson }
385