xref: /optee_os/core/lib/libfdt/fdt_sw.c (revision 17f326eba66aab9ea16549754a95252dd5551a13)
1*17f326ebSJerome Forissier // SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
2b908c675SJens Wiklander /*
3b908c675SJens Wiklander  * libfdt - Flat Device Tree manipulation
4b908c675SJens Wiklander  * Copyright (C) 2006 David Gibson, IBM Corporation.
5b908c675SJens Wiklander  */
6b908c675SJens Wiklander #include "libfdt_env.h"
7b908c675SJens Wiklander 
8b908c675SJens Wiklander #include <fdt.h>
9b908c675SJens Wiklander #include <libfdt.h>
10b908c675SJens Wiklander 
11b908c675SJens Wiklander #include "libfdt_internal.h"
12b908c675SJens Wiklander 
fdt_sw_probe_(void * fdt)13*17f326ebSJerome Forissier static int fdt_sw_probe_(void *fdt)
14b908c675SJens Wiklander {
15*17f326ebSJerome Forissier 	if (fdt_magic(fdt) == FDT_MAGIC)
16*17f326ebSJerome Forissier 		return -FDT_ERR_BADSTATE;
17*17f326ebSJerome Forissier 	else if (fdt_magic(fdt) != FDT_SW_MAGIC)
18b908c675SJens Wiklander 		return -FDT_ERR_BADMAGIC;
19b908c675SJens Wiklander 	return 0;
20b908c675SJens Wiklander }
21b908c675SJens Wiklander 
22*17f326ebSJerome Forissier #define FDT_SW_PROBE(fdt) \
23b908c675SJens Wiklander 	{ \
24b908c675SJens Wiklander 		int err; \
25*17f326ebSJerome Forissier 		if ((err = fdt_sw_probe_(fdt)) != 0) \
26b908c675SJens Wiklander 			return err; \
27b908c675SJens Wiklander 	}
28b908c675SJens Wiklander 
29*17f326ebSJerome Forissier /* 'memrsv' state:	Initial state after fdt_create()
30*17f326ebSJerome Forissier  *
31*17f326ebSJerome Forissier  * Allowed functions:
32*17f326ebSJerome Forissier  *	fdt_add_reservmap_entry()
33*17f326ebSJerome Forissier  *	fdt_finish_reservemap()		[moves to 'struct' state]
34*17f326ebSJerome Forissier  */
fdt_sw_probe_memrsv_(void * fdt)35*17f326ebSJerome Forissier static int fdt_sw_probe_memrsv_(void *fdt)
36*17f326ebSJerome Forissier {
37*17f326ebSJerome Forissier 	int err = fdt_sw_probe_(fdt);
38*17f326ebSJerome Forissier 	if (err)
39*17f326ebSJerome Forissier 		return err;
40*17f326ebSJerome Forissier 
41*17f326ebSJerome Forissier 	if (fdt_off_dt_strings(fdt) != 0)
42*17f326ebSJerome Forissier 		return -FDT_ERR_BADSTATE;
43*17f326ebSJerome Forissier 	return 0;
44*17f326ebSJerome Forissier }
45*17f326ebSJerome Forissier 
46*17f326ebSJerome Forissier #define FDT_SW_PROBE_MEMRSV(fdt) \
47*17f326ebSJerome Forissier 	{ \
48*17f326ebSJerome Forissier 		int err; \
49*17f326ebSJerome Forissier 		if ((err = fdt_sw_probe_memrsv_(fdt)) != 0) \
50*17f326ebSJerome Forissier 			return err; \
51*17f326ebSJerome Forissier 	}
52*17f326ebSJerome Forissier 
53*17f326ebSJerome Forissier /* 'struct' state:	Enter this state after fdt_finish_reservemap()
54*17f326ebSJerome Forissier  *
55*17f326ebSJerome Forissier  * Allowed functions:
56*17f326ebSJerome Forissier  *	fdt_begin_node()
57*17f326ebSJerome Forissier  *	fdt_end_node()
58*17f326ebSJerome Forissier  *	fdt_property*()
59*17f326ebSJerome Forissier  *	fdt_finish()			[moves to 'complete' state]
60*17f326ebSJerome Forissier  */
fdt_sw_probe_struct_(void * fdt)61*17f326ebSJerome Forissier static int fdt_sw_probe_struct_(void *fdt)
62*17f326ebSJerome Forissier {
63*17f326ebSJerome Forissier 	int err = fdt_sw_probe_(fdt);
64*17f326ebSJerome Forissier 	if (err)
65*17f326ebSJerome Forissier 		return err;
66*17f326ebSJerome Forissier 
67*17f326ebSJerome Forissier 	if (fdt_off_dt_strings(fdt) != fdt_totalsize(fdt))
68*17f326ebSJerome Forissier 		return -FDT_ERR_BADSTATE;
69*17f326ebSJerome Forissier 	return 0;
70*17f326ebSJerome Forissier }
71*17f326ebSJerome Forissier 
72*17f326ebSJerome Forissier #define FDT_SW_PROBE_STRUCT(fdt) \
73*17f326ebSJerome Forissier 	{ \
74*17f326ebSJerome Forissier 		int err; \
75*17f326ebSJerome Forissier 		if ((err = fdt_sw_probe_struct_(fdt)) != 0) \
76*17f326ebSJerome Forissier 			return err; \
77*17f326ebSJerome Forissier 	}
78*17f326ebSJerome Forissier 
sw_flags(void * fdt)79*17f326ebSJerome Forissier static inline uint32_t sw_flags(void *fdt)
80*17f326ebSJerome Forissier {
81*17f326ebSJerome Forissier 	/* assert: (fdt_magic(fdt) == FDT_SW_MAGIC) */
82*17f326ebSJerome Forissier 	return fdt_last_comp_version(fdt);
83*17f326ebSJerome Forissier }
84*17f326ebSJerome Forissier 
85*17f326ebSJerome Forissier /* 'complete' state:	Enter this state after fdt_finish()
86*17f326ebSJerome Forissier  *
87*17f326ebSJerome Forissier  * Allowed functions: none
88*17f326ebSJerome Forissier  */
89*17f326ebSJerome Forissier 
fdt_grab_space_(void * fdt,size_t len)9001d6a9daSBryan O'Donoghue static void *fdt_grab_space_(void *fdt, size_t len)
91b908c675SJens Wiklander {
92b908c675SJens Wiklander 	int offset = fdt_size_dt_struct(fdt);
93b908c675SJens Wiklander 	int spaceleft;
94b908c675SJens Wiklander 
95b908c675SJens Wiklander 	spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt)
96b908c675SJens Wiklander 		- fdt_size_dt_strings(fdt);
97b908c675SJens Wiklander 
98b908c675SJens Wiklander 	if ((offset + len < offset) || (offset + len > spaceleft))
99b908c675SJens Wiklander 		return NULL;
100b908c675SJens Wiklander 
101b908c675SJens Wiklander 	fdt_set_size_dt_struct(fdt, offset + len);
10201d6a9daSBryan O'Donoghue 	return fdt_offset_ptr_w_(fdt, offset);
103b908c675SJens Wiklander }
104b908c675SJens Wiklander 
fdt_create_with_flags(void * buf,int bufsize,uint32_t flags)105*17f326ebSJerome Forissier int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags)
106b908c675SJens Wiklander {
107*17f326ebSJerome Forissier 	const size_t hdrsize = FDT_ALIGN(sizeof(struct fdt_header),
108*17f326ebSJerome Forissier 					 sizeof(struct fdt_reserve_entry));
109b908c675SJens Wiklander 	void *fdt = buf;
110b908c675SJens Wiklander 
111*17f326ebSJerome Forissier 	if (bufsize < hdrsize)
112b908c675SJens Wiklander 		return -FDT_ERR_NOSPACE;
113b908c675SJens Wiklander 
114*17f326ebSJerome Forissier 	if (flags & ~FDT_CREATE_FLAGS_ALL)
115*17f326ebSJerome Forissier 		return -FDT_ERR_BADFLAGS;
116*17f326ebSJerome Forissier 
117b908c675SJens Wiklander 	memset(buf, 0, bufsize);
118b908c675SJens Wiklander 
119*17f326ebSJerome Forissier 	/*
120*17f326ebSJerome Forissier 	 * magic and last_comp_version keep intermediate state during the fdt
121*17f326ebSJerome Forissier 	 * creation process, which is replaced with the proper FDT format by
122*17f326ebSJerome Forissier 	 * fdt_finish().
123*17f326ebSJerome Forissier 	 *
124*17f326ebSJerome Forissier 	 * flags should be accessed with sw_flags().
125*17f326ebSJerome Forissier 	 */
126b908c675SJens Wiklander 	fdt_set_magic(fdt, FDT_SW_MAGIC);
127b908c675SJens Wiklander 	fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION);
128*17f326ebSJerome Forissier 	fdt_set_last_comp_version(fdt, flags);
129*17f326ebSJerome Forissier 
130b908c675SJens Wiklander 	fdt_set_totalsize(fdt,  bufsize);
131b908c675SJens Wiklander 
132*17f326ebSJerome Forissier 	fdt_set_off_mem_rsvmap(fdt, hdrsize);
133b908c675SJens Wiklander 	fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt));
134*17f326ebSJerome Forissier 	fdt_set_off_dt_strings(fdt, 0);
135b908c675SJens Wiklander 
136b908c675SJens Wiklander 	return 0;
137b908c675SJens Wiklander }
138b908c675SJens Wiklander 
fdt_create(void * buf,int bufsize)139*17f326ebSJerome Forissier int fdt_create(void *buf, int bufsize)
140*17f326ebSJerome Forissier {
141*17f326ebSJerome Forissier 	return fdt_create_with_flags(buf, bufsize, 0);
142*17f326ebSJerome Forissier }
143*17f326ebSJerome Forissier 
fdt_resize(void * fdt,void * buf,int bufsize)144b908c675SJens Wiklander int fdt_resize(void *fdt, void *buf, int bufsize)
145b908c675SJens Wiklander {
146b908c675SJens Wiklander 	size_t headsize, tailsize;
147b908c675SJens Wiklander 	char *oldtail, *newtail;
148b908c675SJens Wiklander 
149*17f326ebSJerome Forissier 	FDT_SW_PROBE(fdt);
150b908c675SJens Wiklander 
151*17f326ebSJerome Forissier 	headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
152b908c675SJens Wiklander 	tailsize = fdt_size_dt_strings(fdt);
153b908c675SJens Wiklander 
154*17f326ebSJerome Forissier 	if ((headsize + tailsize) > fdt_totalsize(fdt))
155*17f326ebSJerome Forissier 		return -FDT_ERR_INTERNAL;
156*17f326ebSJerome Forissier 
157b908c675SJens Wiklander 	if ((headsize + tailsize) > bufsize)
158b908c675SJens Wiklander 		return -FDT_ERR_NOSPACE;
159b908c675SJens Wiklander 
160b908c675SJens Wiklander 	oldtail = (char *)fdt + fdt_totalsize(fdt) - tailsize;
161b908c675SJens Wiklander 	newtail = (char *)buf + bufsize - tailsize;
162b908c675SJens Wiklander 
163b908c675SJens Wiklander 	/* Two cases to avoid clobbering data if the old and new
164b908c675SJens Wiklander 	 * buffers partially overlap */
165b908c675SJens Wiklander 	if (buf <= fdt) {
166b908c675SJens Wiklander 		memmove(buf, fdt, headsize);
167b908c675SJens Wiklander 		memmove(newtail, oldtail, tailsize);
168b908c675SJens Wiklander 	} else {
169b908c675SJens Wiklander 		memmove(newtail, oldtail, tailsize);
170b908c675SJens Wiklander 		memmove(buf, fdt, headsize);
171b908c675SJens Wiklander 	}
172b908c675SJens Wiklander 
173b908c675SJens Wiklander 	fdt_set_totalsize(buf, bufsize);
174*17f326ebSJerome Forissier 	if (fdt_off_dt_strings(buf))
175*17f326ebSJerome Forissier 		fdt_set_off_dt_strings(buf, bufsize);
176b908c675SJens Wiklander 
177b908c675SJens Wiklander 	return 0;
178b908c675SJens Wiklander }
179b908c675SJens Wiklander 
fdt_add_reservemap_entry(void * fdt,uint64_t addr,uint64_t size)180b908c675SJens Wiklander int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)
181b908c675SJens Wiklander {
182b908c675SJens Wiklander 	struct fdt_reserve_entry *re;
183b908c675SJens Wiklander 	int offset;
184b908c675SJens Wiklander 
185*17f326ebSJerome Forissier 	FDT_SW_PROBE_MEMRSV(fdt);
186b908c675SJens Wiklander 
187b908c675SJens Wiklander 	offset = fdt_off_dt_struct(fdt);
188b908c675SJens Wiklander 	if ((offset + sizeof(*re)) > fdt_totalsize(fdt))
189b908c675SJens Wiklander 		return -FDT_ERR_NOSPACE;
190b908c675SJens Wiklander 
191b908c675SJens Wiklander 	re = (struct fdt_reserve_entry *)((char *)fdt + offset);
192b908c675SJens Wiklander 	re->address = cpu_to_fdt64(addr);
193b908c675SJens Wiklander 	re->size = cpu_to_fdt64(size);
194b908c675SJens Wiklander 
195b908c675SJens Wiklander 	fdt_set_off_dt_struct(fdt, offset + sizeof(*re));
196b908c675SJens Wiklander 
197b908c675SJens Wiklander 	return 0;
198b908c675SJens Wiklander }
199b908c675SJens Wiklander 
fdt_finish_reservemap(void * fdt)200b908c675SJens Wiklander int fdt_finish_reservemap(void *fdt)
201b908c675SJens Wiklander {
202*17f326ebSJerome Forissier 	int err = fdt_add_reservemap_entry(fdt, 0, 0);
203*17f326ebSJerome Forissier 
204*17f326ebSJerome Forissier 	if (err)
205*17f326ebSJerome Forissier 		return err;
206*17f326ebSJerome Forissier 
207*17f326ebSJerome Forissier 	fdt_set_off_dt_strings(fdt, fdt_totalsize(fdt));
208*17f326ebSJerome Forissier 	return 0;
209b908c675SJens Wiklander }
210b908c675SJens Wiklander 
fdt_begin_node(void * fdt,const char * name)211b908c675SJens Wiklander int fdt_begin_node(void *fdt, const char *name)
212b908c675SJens Wiklander {
213b908c675SJens Wiklander 	struct fdt_node_header *nh;
214*17f326ebSJerome Forissier 	int namelen;
215b908c675SJens Wiklander 
216*17f326ebSJerome Forissier 	FDT_SW_PROBE_STRUCT(fdt);
217b908c675SJens Wiklander 
218*17f326ebSJerome Forissier 	namelen = strlen(name) + 1;
21901d6a9daSBryan O'Donoghue 	nh = fdt_grab_space_(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen));
220b908c675SJens Wiklander 	if (! nh)
221b908c675SJens Wiklander 		return -FDT_ERR_NOSPACE;
222b908c675SJens Wiklander 
223b908c675SJens Wiklander 	nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE);
224b908c675SJens Wiklander 	memcpy(nh->name, name, namelen);
225b908c675SJens Wiklander 	return 0;
226b908c675SJens Wiklander }
227b908c675SJens Wiklander 
fdt_end_node(void * fdt)228b908c675SJens Wiklander int fdt_end_node(void *fdt)
229b908c675SJens Wiklander {
230b908c675SJens Wiklander 	fdt32_t *en;
231b908c675SJens Wiklander 
232*17f326ebSJerome Forissier 	FDT_SW_PROBE_STRUCT(fdt);
233b908c675SJens Wiklander 
23401d6a9daSBryan O'Donoghue 	en = fdt_grab_space_(fdt, FDT_TAGSIZE);
235b908c675SJens Wiklander 	if (! en)
236b908c675SJens Wiklander 		return -FDT_ERR_NOSPACE;
237b908c675SJens Wiklander 
238b908c675SJens Wiklander 	*en = cpu_to_fdt32(FDT_END_NODE);
239b908c675SJens Wiklander 	return 0;
240b908c675SJens Wiklander }
241b908c675SJens Wiklander 
fdt_add_string_(void * fdt,const char * s)242*17f326ebSJerome Forissier static int fdt_add_string_(void *fdt, const char *s)
243b908c675SJens Wiklander {
244b908c675SJens Wiklander 	char *strtab = (char *)fdt + fdt_totalsize(fdt);
245b908c675SJens Wiklander 	int strtabsize = fdt_size_dt_strings(fdt);
246b908c675SJens Wiklander 	int len = strlen(s) + 1;
247b908c675SJens Wiklander 	int struct_top, offset;
248b908c675SJens Wiklander 
249b908c675SJens Wiklander 	offset = -strtabsize - len;
250b908c675SJens Wiklander 	struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
251b908c675SJens Wiklander 	if (fdt_totalsize(fdt) + offset < struct_top)
252b908c675SJens Wiklander 		return 0; /* no more room :( */
253b908c675SJens Wiklander 
254b908c675SJens Wiklander 	memcpy(strtab + offset, s, len);
255b908c675SJens Wiklander 	fdt_set_size_dt_strings(fdt, strtabsize + len);
256b908c675SJens Wiklander 	return offset;
257b908c675SJens Wiklander }
258b908c675SJens Wiklander 
259*17f326ebSJerome Forissier /* Must only be used to roll back in case of error */
fdt_del_last_string_(void * fdt,const char * s)260*17f326ebSJerome Forissier static void fdt_del_last_string_(void *fdt, const char *s)
261*17f326ebSJerome Forissier {
262*17f326ebSJerome Forissier 	int strtabsize = fdt_size_dt_strings(fdt);
263*17f326ebSJerome Forissier 	int len = strlen(s) + 1;
264*17f326ebSJerome Forissier 
265*17f326ebSJerome Forissier 	fdt_set_size_dt_strings(fdt, strtabsize - len);
266*17f326ebSJerome Forissier }
267*17f326ebSJerome Forissier 
fdt_find_add_string_(void * fdt,const char * s,int * allocated)268*17f326ebSJerome Forissier static int fdt_find_add_string_(void *fdt, const char *s, int *allocated)
269*17f326ebSJerome Forissier {
270*17f326ebSJerome Forissier 	char *strtab = (char *)fdt + fdt_totalsize(fdt);
271*17f326ebSJerome Forissier 	int strtabsize = fdt_size_dt_strings(fdt);
272*17f326ebSJerome Forissier 	const char *p;
273*17f326ebSJerome Forissier 
274*17f326ebSJerome Forissier 	*allocated = 0;
275*17f326ebSJerome Forissier 
276*17f326ebSJerome Forissier 	p = fdt_find_string_(strtab - strtabsize, strtabsize, s);
277*17f326ebSJerome Forissier 	if (p)
278*17f326ebSJerome Forissier 		return p - strtab;
279*17f326ebSJerome Forissier 
280*17f326ebSJerome Forissier 	*allocated = 1;
281*17f326ebSJerome Forissier 
282*17f326ebSJerome Forissier 	return fdt_add_string_(fdt, s);
283*17f326ebSJerome Forissier }
284*17f326ebSJerome Forissier 
fdt_property_placeholder(void * fdt,const char * name,int len,void ** valp)28501d6a9daSBryan O'Donoghue int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp)
286b908c675SJens Wiklander {
287b908c675SJens Wiklander 	struct fdt_property *prop;
288b908c675SJens Wiklander 	int nameoff;
289*17f326ebSJerome Forissier 	int allocated;
290b908c675SJens Wiklander 
291*17f326ebSJerome Forissier 	FDT_SW_PROBE_STRUCT(fdt);
292b908c675SJens Wiklander 
293*17f326ebSJerome Forissier 	/* String de-duplication can be slow, _NO_NAME_DEDUP skips it */
294*17f326ebSJerome Forissier 	if (sw_flags(fdt) & FDT_CREATE_FLAG_NO_NAME_DEDUP) {
295*17f326ebSJerome Forissier 		allocated = 1;
296*17f326ebSJerome Forissier 		nameoff = fdt_add_string_(fdt, name);
297*17f326ebSJerome Forissier 	} else {
298*17f326ebSJerome Forissier 		nameoff = fdt_find_add_string_(fdt, name, &allocated);
299*17f326ebSJerome Forissier 	}
300b908c675SJens Wiklander 	if (nameoff == 0)
301b908c675SJens Wiklander 		return -FDT_ERR_NOSPACE;
302b908c675SJens Wiklander 
30301d6a9daSBryan O'Donoghue 	prop = fdt_grab_space_(fdt, sizeof(*prop) + FDT_TAGALIGN(len));
304*17f326ebSJerome Forissier 	if (! prop) {
305*17f326ebSJerome Forissier 		if (allocated)
306*17f326ebSJerome Forissier 			fdt_del_last_string_(fdt, name);
307b908c675SJens Wiklander 		return -FDT_ERR_NOSPACE;
308*17f326ebSJerome Forissier 	}
309b908c675SJens Wiklander 
310b908c675SJens Wiklander 	prop->tag = cpu_to_fdt32(FDT_PROP);
311b908c675SJens Wiklander 	prop->nameoff = cpu_to_fdt32(nameoff);
312b908c675SJens Wiklander 	prop->len = cpu_to_fdt32(len);
31301d6a9daSBryan O'Donoghue 	*valp = prop->data;
31401d6a9daSBryan O'Donoghue 	return 0;
31501d6a9daSBryan O'Donoghue }
31601d6a9daSBryan O'Donoghue 
fdt_property(void * fdt,const char * name,const void * val,int len)31701d6a9daSBryan O'Donoghue int fdt_property(void *fdt, const char *name, const void *val, int len)
31801d6a9daSBryan O'Donoghue {
31901d6a9daSBryan O'Donoghue 	void *ptr;
32001d6a9daSBryan O'Donoghue 	int ret;
32101d6a9daSBryan O'Donoghue 
32201d6a9daSBryan O'Donoghue 	ret = fdt_property_placeholder(fdt, name, len, &ptr);
32301d6a9daSBryan O'Donoghue 	if (ret)
32401d6a9daSBryan O'Donoghue 		return ret;
32501d6a9daSBryan O'Donoghue 	memcpy(ptr, val, len);
326b908c675SJens Wiklander 	return 0;
327b908c675SJens Wiklander }
328b908c675SJens Wiklander 
fdt_finish(void * fdt)329b908c675SJens Wiklander int fdt_finish(void *fdt)
330b908c675SJens Wiklander {
331b908c675SJens Wiklander 	char *p = (char *)fdt;
332b908c675SJens Wiklander 	fdt32_t *end;
333b908c675SJens Wiklander 	int oldstroffset, newstroffset;
334b908c675SJens Wiklander 	uint32_t tag;
335b908c675SJens Wiklander 	int offset, nextoffset;
336b908c675SJens Wiklander 
337*17f326ebSJerome Forissier 	FDT_SW_PROBE_STRUCT(fdt);
338b908c675SJens Wiklander 
339b908c675SJens Wiklander 	/* Add terminator */
34001d6a9daSBryan O'Donoghue 	end = fdt_grab_space_(fdt, sizeof(*end));
341b908c675SJens Wiklander 	if (! end)
342b908c675SJens Wiklander 		return -FDT_ERR_NOSPACE;
343b908c675SJens Wiklander 	*end = cpu_to_fdt32(FDT_END);
344b908c675SJens Wiklander 
345b908c675SJens Wiklander 	/* Relocate the string table */
346b908c675SJens Wiklander 	oldstroffset = fdt_totalsize(fdt) - fdt_size_dt_strings(fdt);
347b908c675SJens Wiklander 	newstroffset = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
348b908c675SJens Wiklander 	memmove(p + newstroffset, p + oldstroffset, fdt_size_dt_strings(fdt));
349b908c675SJens Wiklander 	fdt_set_off_dt_strings(fdt, newstroffset);
350b908c675SJens Wiklander 
351b908c675SJens Wiklander 	/* Walk the structure, correcting string offsets */
352b908c675SJens Wiklander 	offset = 0;
353b908c675SJens Wiklander 	while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) {
354b908c675SJens Wiklander 		if (tag == FDT_PROP) {
355b908c675SJens Wiklander 			struct fdt_property *prop =
35601d6a9daSBryan O'Donoghue 				fdt_offset_ptr_w_(fdt, offset);
357b908c675SJens Wiklander 			int nameoff;
358b908c675SJens Wiklander 
359b908c675SJens Wiklander 			nameoff = fdt32_to_cpu(prop->nameoff);
360b908c675SJens Wiklander 			nameoff += fdt_size_dt_strings(fdt);
361b908c675SJens Wiklander 			prop->nameoff = cpu_to_fdt32(nameoff);
362b908c675SJens Wiklander 		}
363b908c675SJens Wiklander 		offset = nextoffset;
364b908c675SJens Wiklander 	}
365b908c675SJens Wiklander 	if (nextoffset < 0)
366b908c675SJens Wiklander 		return nextoffset;
367b908c675SJens Wiklander 
368b908c675SJens Wiklander 	/* Finally, adjust the header */
369b908c675SJens Wiklander 	fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
370*17f326ebSJerome Forissier 
371*17f326ebSJerome Forissier 	/* And fix up fields that were keeping intermediate state. */
372*17f326ebSJerome Forissier 	fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
373b908c675SJens Wiklander 	fdt_set_magic(fdt, FDT_MAGIC);
374*17f326ebSJerome Forissier 
375b908c675SJens Wiklander 	return 0;
376b908c675SJens Wiklander }
377