1553125dfSNikos Nikoleris // SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
2a322d4c5SAndrew Jones /*
3a322d4c5SAndrew Jones * libfdt - Flat Device Tree manipulation
4a322d4c5SAndrew Jones * Copyright (C) 2006 David Gibson, IBM Corporation.
5a322d4c5SAndrew Jones */
6a322d4c5SAndrew Jones #include "libfdt_env.h"
7a322d4c5SAndrew Jones
8a322d4c5SAndrew Jones #include <fdt.h>
9a322d4c5SAndrew Jones #include <libfdt.h>
10a322d4c5SAndrew Jones
11a322d4c5SAndrew Jones #include "libfdt_internal.h"
12a322d4c5SAndrew Jones
fdt_sw_probe_(void * fdt)13553125dfSNikos Nikoleris static int fdt_sw_probe_(void *fdt)
14a322d4c5SAndrew Jones {
15553125dfSNikos Nikoleris if (!can_assume(VALID_INPUT)) {
16553125dfSNikos Nikoleris if (fdt_magic(fdt) == FDT_MAGIC)
17553125dfSNikos Nikoleris return -FDT_ERR_BADSTATE;
18553125dfSNikos Nikoleris else if (fdt_magic(fdt) != FDT_SW_MAGIC)
19a322d4c5SAndrew Jones return -FDT_ERR_BADMAGIC;
20553125dfSNikos Nikoleris }
21553125dfSNikos Nikoleris
22a322d4c5SAndrew Jones return 0;
23a322d4c5SAndrew Jones }
24a322d4c5SAndrew Jones
25553125dfSNikos Nikoleris #define FDT_SW_PROBE(fdt) \
26a322d4c5SAndrew Jones { \
27a322d4c5SAndrew Jones int err; \
28553125dfSNikos Nikoleris if ((err = fdt_sw_probe_(fdt)) != 0) \
29a322d4c5SAndrew Jones return err; \
30a322d4c5SAndrew Jones }
31a322d4c5SAndrew Jones
32553125dfSNikos Nikoleris /* 'memrsv' state: Initial state after fdt_create()
33553125dfSNikos Nikoleris *
34553125dfSNikos Nikoleris * Allowed functions:
35*80a6d74fSAndrew Jones * fdt_add_reservemap_entry()
36553125dfSNikos Nikoleris * fdt_finish_reservemap() [moves to 'struct' state]
37553125dfSNikos Nikoleris */
fdt_sw_probe_memrsv_(void * fdt)38553125dfSNikos Nikoleris static int fdt_sw_probe_memrsv_(void *fdt)
39553125dfSNikos Nikoleris {
40553125dfSNikos Nikoleris int err = fdt_sw_probe_(fdt);
41553125dfSNikos Nikoleris if (err)
42553125dfSNikos Nikoleris return err;
43553125dfSNikos Nikoleris
44553125dfSNikos Nikoleris if (!can_assume(VALID_INPUT) && fdt_off_dt_strings(fdt) != 0)
45553125dfSNikos Nikoleris return -FDT_ERR_BADSTATE;
46553125dfSNikos Nikoleris return 0;
47553125dfSNikos Nikoleris }
48553125dfSNikos Nikoleris
49553125dfSNikos Nikoleris #define FDT_SW_PROBE_MEMRSV(fdt) \
50553125dfSNikos Nikoleris { \
51553125dfSNikos Nikoleris int err; \
52553125dfSNikos Nikoleris if ((err = fdt_sw_probe_memrsv_(fdt)) != 0) \
53553125dfSNikos Nikoleris return err; \
54553125dfSNikos Nikoleris }
55553125dfSNikos Nikoleris
56553125dfSNikos Nikoleris /* 'struct' state: Enter this state after fdt_finish_reservemap()
57553125dfSNikos Nikoleris *
58553125dfSNikos Nikoleris * Allowed functions:
59553125dfSNikos Nikoleris * fdt_begin_node()
60553125dfSNikos Nikoleris * fdt_end_node()
61553125dfSNikos Nikoleris * fdt_property*()
62553125dfSNikos Nikoleris * fdt_finish() [moves to 'complete' state]
63553125dfSNikos Nikoleris */
fdt_sw_probe_struct_(void * fdt)64553125dfSNikos Nikoleris static int fdt_sw_probe_struct_(void *fdt)
65553125dfSNikos Nikoleris {
66553125dfSNikos Nikoleris int err = fdt_sw_probe_(fdt);
67553125dfSNikos Nikoleris if (err)
68553125dfSNikos Nikoleris return err;
69553125dfSNikos Nikoleris
70553125dfSNikos Nikoleris if (!can_assume(VALID_INPUT) &&
71553125dfSNikos Nikoleris fdt_off_dt_strings(fdt) != fdt_totalsize(fdt))
72553125dfSNikos Nikoleris return -FDT_ERR_BADSTATE;
73553125dfSNikos Nikoleris return 0;
74553125dfSNikos Nikoleris }
75553125dfSNikos Nikoleris
76553125dfSNikos Nikoleris #define FDT_SW_PROBE_STRUCT(fdt) \
77553125dfSNikos Nikoleris { \
78553125dfSNikos Nikoleris int err; \
79553125dfSNikos Nikoleris if ((err = fdt_sw_probe_struct_(fdt)) != 0) \
80553125dfSNikos Nikoleris return err; \
81553125dfSNikos Nikoleris }
82553125dfSNikos Nikoleris
sw_flags(void * fdt)83553125dfSNikos Nikoleris static inline uint32_t sw_flags(void *fdt)
84553125dfSNikos Nikoleris {
85553125dfSNikos Nikoleris /* assert: (fdt_magic(fdt) == FDT_SW_MAGIC) */
86553125dfSNikos Nikoleris return fdt_last_comp_version(fdt);
87553125dfSNikos Nikoleris }
88553125dfSNikos Nikoleris
89553125dfSNikos Nikoleris /* 'complete' state: Enter this state after fdt_finish()
90553125dfSNikos Nikoleris *
91553125dfSNikos Nikoleris * Allowed functions: none
92553125dfSNikos Nikoleris */
93553125dfSNikos Nikoleris
fdt_grab_space_(void * fdt,size_t len)94553125dfSNikos Nikoleris static void *fdt_grab_space_(void *fdt, size_t len)
95a322d4c5SAndrew Jones {
96*80a6d74fSAndrew Jones unsigned int offset = fdt_size_dt_struct(fdt);
97*80a6d74fSAndrew Jones unsigned int spaceleft;
98a322d4c5SAndrew Jones
99a322d4c5SAndrew Jones spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt)
100a322d4c5SAndrew Jones - fdt_size_dt_strings(fdt);
101a322d4c5SAndrew Jones
102a322d4c5SAndrew Jones if ((offset + len < offset) || (offset + len > spaceleft))
103a322d4c5SAndrew Jones return NULL;
104a322d4c5SAndrew Jones
105a322d4c5SAndrew Jones fdt_set_size_dt_struct(fdt, offset + len);
106553125dfSNikos Nikoleris return fdt_offset_ptr_w_(fdt, offset);
107553125dfSNikos Nikoleris }
108553125dfSNikos Nikoleris
fdt_create_with_flags(void * buf,int bufsize,uint32_t flags)109553125dfSNikos Nikoleris int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags)
110553125dfSNikos Nikoleris {
111*80a6d74fSAndrew Jones const int hdrsize = FDT_ALIGN(sizeof(struct fdt_header),
112553125dfSNikos Nikoleris sizeof(struct fdt_reserve_entry));
113553125dfSNikos Nikoleris void *fdt = buf;
114553125dfSNikos Nikoleris
115553125dfSNikos Nikoleris if (bufsize < hdrsize)
116553125dfSNikos Nikoleris return -FDT_ERR_NOSPACE;
117553125dfSNikos Nikoleris
118553125dfSNikos Nikoleris if (flags & ~FDT_CREATE_FLAGS_ALL)
119553125dfSNikos Nikoleris return -FDT_ERR_BADFLAGS;
120553125dfSNikos Nikoleris
121553125dfSNikos Nikoleris memset(buf, 0, bufsize);
122553125dfSNikos Nikoleris
123553125dfSNikos Nikoleris /*
124553125dfSNikos Nikoleris * magic and last_comp_version keep intermediate state during the fdt
125553125dfSNikos Nikoleris * creation process, which is replaced with the proper FDT format by
126553125dfSNikos Nikoleris * fdt_finish().
127553125dfSNikos Nikoleris *
128553125dfSNikos Nikoleris * flags should be accessed with sw_flags().
129553125dfSNikos Nikoleris */
130553125dfSNikos Nikoleris fdt_set_magic(fdt, FDT_SW_MAGIC);
131553125dfSNikos Nikoleris fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION);
132553125dfSNikos Nikoleris fdt_set_last_comp_version(fdt, flags);
133553125dfSNikos Nikoleris
134553125dfSNikos Nikoleris fdt_set_totalsize(fdt, bufsize);
135553125dfSNikos Nikoleris
136553125dfSNikos Nikoleris fdt_set_off_mem_rsvmap(fdt, hdrsize);
137553125dfSNikos Nikoleris fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt));
138553125dfSNikos Nikoleris fdt_set_off_dt_strings(fdt, 0);
139553125dfSNikos Nikoleris
140553125dfSNikos Nikoleris return 0;
141a322d4c5SAndrew Jones }
142a322d4c5SAndrew Jones
fdt_create(void * buf,int bufsize)143a322d4c5SAndrew Jones int fdt_create(void *buf, int bufsize)
144a322d4c5SAndrew Jones {
145553125dfSNikos Nikoleris return fdt_create_with_flags(buf, bufsize, 0);
146553125dfSNikos Nikoleris }
147a322d4c5SAndrew Jones
fdt_resize(void * fdt,void * buf,int bufsize)148553125dfSNikos Nikoleris int fdt_resize(void *fdt, void *buf, int bufsize)
149553125dfSNikos Nikoleris {
150553125dfSNikos Nikoleris size_t headsize, tailsize;
151553125dfSNikos Nikoleris char *oldtail, *newtail;
152553125dfSNikos Nikoleris
153553125dfSNikos Nikoleris FDT_SW_PROBE(fdt);
154553125dfSNikos Nikoleris
155*80a6d74fSAndrew Jones if (bufsize < 0)
156*80a6d74fSAndrew Jones return -FDT_ERR_NOSPACE;
157*80a6d74fSAndrew Jones
158553125dfSNikos Nikoleris headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
159553125dfSNikos Nikoleris tailsize = fdt_size_dt_strings(fdt);
160553125dfSNikos Nikoleris
161553125dfSNikos Nikoleris if (!can_assume(VALID_DTB) &&
162553125dfSNikos Nikoleris headsize + tailsize > fdt_totalsize(fdt))
163553125dfSNikos Nikoleris return -FDT_ERR_INTERNAL;
164553125dfSNikos Nikoleris
165*80a6d74fSAndrew Jones if ((headsize + tailsize) > (unsigned)bufsize)
166a322d4c5SAndrew Jones return -FDT_ERR_NOSPACE;
167a322d4c5SAndrew Jones
168553125dfSNikos Nikoleris oldtail = (char *)fdt + fdt_totalsize(fdt) - tailsize;
169553125dfSNikos Nikoleris newtail = (char *)buf + bufsize - tailsize;
170a322d4c5SAndrew Jones
171553125dfSNikos Nikoleris /* Two cases to avoid clobbering data if the old and new
172553125dfSNikos Nikoleris * buffers partially overlap */
173553125dfSNikos Nikoleris if (buf <= fdt) {
174553125dfSNikos Nikoleris memmove(buf, fdt, headsize);
175553125dfSNikos Nikoleris memmove(newtail, oldtail, tailsize);
176553125dfSNikos Nikoleris } else {
177553125dfSNikos Nikoleris memmove(newtail, oldtail, tailsize);
178553125dfSNikos Nikoleris memmove(buf, fdt, headsize);
179553125dfSNikos Nikoleris }
180a322d4c5SAndrew Jones
181553125dfSNikos Nikoleris fdt_set_totalsize(buf, bufsize);
182553125dfSNikos Nikoleris if (fdt_off_dt_strings(buf))
183553125dfSNikos Nikoleris fdt_set_off_dt_strings(buf, bufsize);
184a322d4c5SAndrew Jones
185a322d4c5SAndrew Jones return 0;
186a322d4c5SAndrew Jones }
187a322d4c5SAndrew Jones
fdt_add_reservemap_entry(void * fdt,uint64_t addr,uint64_t size)188a322d4c5SAndrew Jones int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)
189a322d4c5SAndrew Jones {
190a322d4c5SAndrew Jones struct fdt_reserve_entry *re;
191a322d4c5SAndrew Jones int offset;
192a322d4c5SAndrew Jones
193553125dfSNikos Nikoleris FDT_SW_PROBE_MEMRSV(fdt);
194a322d4c5SAndrew Jones
195a322d4c5SAndrew Jones offset = fdt_off_dt_struct(fdt);
196a322d4c5SAndrew Jones if ((offset + sizeof(*re)) > fdt_totalsize(fdt))
197a322d4c5SAndrew Jones return -FDT_ERR_NOSPACE;
198a322d4c5SAndrew Jones
199a322d4c5SAndrew Jones re = (struct fdt_reserve_entry *)((char *)fdt + offset);
200a322d4c5SAndrew Jones re->address = cpu_to_fdt64(addr);
201a322d4c5SAndrew Jones re->size = cpu_to_fdt64(size);
202a322d4c5SAndrew Jones
203a322d4c5SAndrew Jones fdt_set_off_dt_struct(fdt, offset + sizeof(*re));
204a322d4c5SAndrew Jones
205a322d4c5SAndrew Jones return 0;
206a322d4c5SAndrew Jones }
207a322d4c5SAndrew Jones
fdt_finish_reservemap(void * fdt)208a322d4c5SAndrew Jones int fdt_finish_reservemap(void *fdt)
209a322d4c5SAndrew Jones {
210553125dfSNikos Nikoleris int err = fdt_add_reservemap_entry(fdt, 0, 0);
211553125dfSNikos Nikoleris
212553125dfSNikos Nikoleris if (err)
213553125dfSNikos Nikoleris return err;
214553125dfSNikos Nikoleris
215553125dfSNikos Nikoleris fdt_set_off_dt_strings(fdt, fdt_totalsize(fdt));
216553125dfSNikos Nikoleris return 0;
217a322d4c5SAndrew Jones }
218a322d4c5SAndrew Jones
fdt_begin_node(void * fdt,const char * name)219a322d4c5SAndrew Jones int fdt_begin_node(void *fdt, const char *name)
220a322d4c5SAndrew Jones {
221a322d4c5SAndrew Jones struct fdt_node_header *nh;
222553125dfSNikos Nikoleris int namelen;
223a322d4c5SAndrew Jones
224553125dfSNikos Nikoleris FDT_SW_PROBE_STRUCT(fdt);
225a322d4c5SAndrew Jones
226553125dfSNikos Nikoleris namelen = strlen(name) + 1;
227553125dfSNikos Nikoleris nh = fdt_grab_space_(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen));
228a322d4c5SAndrew Jones if (! nh)
229a322d4c5SAndrew Jones return -FDT_ERR_NOSPACE;
230a322d4c5SAndrew Jones
231a322d4c5SAndrew Jones nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE);
232a322d4c5SAndrew Jones memcpy(nh->name, name, namelen);
233a322d4c5SAndrew Jones return 0;
234a322d4c5SAndrew Jones }
235a322d4c5SAndrew Jones
fdt_end_node(void * fdt)236a322d4c5SAndrew Jones int fdt_end_node(void *fdt)
237a322d4c5SAndrew Jones {
238a322d4c5SAndrew Jones fdt32_t *en;
239a322d4c5SAndrew Jones
240553125dfSNikos Nikoleris FDT_SW_PROBE_STRUCT(fdt);
241a322d4c5SAndrew Jones
242553125dfSNikos Nikoleris en = fdt_grab_space_(fdt, FDT_TAGSIZE);
243a322d4c5SAndrew Jones if (! en)
244a322d4c5SAndrew Jones return -FDT_ERR_NOSPACE;
245a322d4c5SAndrew Jones
246a322d4c5SAndrew Jones *en = cpu_to_fdt32(FDT_END_NODE);
247a322d4c5SAndrew Jones return 0;
248a322d4c5SAndrew Jones }
249a322d4c5SAndrew Jones
fdt_add_string_(void * fdt,const char * s)250553125dfSNikos Nikoleris static int fdt_add_string_(void *fdt, const char *s)
251a322d4c5SAndrew Jones {
252a322d4c5SAndrew Jones char *strtab = (char *)fdt + fdt_totalsize(fdt);
253*80a6d74fSAndrew Jones unsigned int strtabsize = fdt_size_dt_strings(fdt);
254*80a6d74fSAndrew Jones unsigned int len = strlen(s) + 1;
255*80a6d74fSAndrew Jones unsigned int struct_top, offset;
256a322d4c5SAndrew Jones
257*80a6d74fSAndrew Jones offset = strtabsize + len;
258a322d4c5SAndrew Jones struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
259*80a6d74fSAndrew Jones if (fdt_totalsize(fdt) - offset < struct_top)
260a322d4c5SAndrew Jones return 0; /* no more room :( */
261a322d4c5SAndrew Jones
262*80a6d74fSAndrew Jones memcpy(strtab - offset, s, len);
263a322d4c5SAndrew Jones fdt_set_size_dt_strings(fdt, strtabsize + len);
264*80a6d74fSAndrew Jones return -offset;
265a322d4c5SAndrew Jones }
266a322d4c5SAndrew Jones
267553125dfSNikos Nikoleris /* Must only be used to roll back in case of error */
fdt_del_last_string_(void * fdt,const char * s)268553125dfSNikos Nikoleris static void fdt_del_last_string_(void *fdt, const char *s)
269553125dfSNikos Nikoleris {
270553125dfSNikos Nikoleris int strtabsize = fdt_size_dt_strings(fdt);
271553125dfSNikos Nikoleris int len = strlen(s) + 1;
272553125dfSNikos Nikoleris
273553125dfSNikos Nikoleris fdt_set_size_dt_strings(fdt, strtabsize - len);
274553125dfSNikos Nikoleris }
275553125dfSNikos Nikoleris
fdt_find_add_string_(void * fdt,const char * s,int * allocated)276553125dfSNikos Nikoleris static int fdt_find_add_string_(void *fdt, const char *s, int *allocated)
277553125dfSNikos Nikoleris {
278553125dfSNikos Nikoleris char *strtab = (char *)fdt + fdt_totalsize(fdt);
279553125dfSNikos Nikoleris int strtabsize = fdt_size_dt_strings(fdt);
280553125dfSNikos Nikoleris const char *p;
281553125dfSNikos Nikoleris
282553125dfSNikos Nikoleris *allocated = 0;
283553125dfSNikos Nikoleris
284553125dfSNikos Nikoleris p = fdt_find_string_(strtab - strtabsize, strtabsize, s);
285553125dfSNikos Nikoleris if (p)
286553125dfSNikos Nikoleris return p - strtab;
287553125dfSNikos Nikoleris
288553125dfSNikos Nikoleris *allocated = 1;
289553125dfSNikos Nikoleris
290553125dfSNikos Nikoleris return fdt_add_string_(fdt, s);
291553125dfSNikos Nikoleris }
292553125dfSNikos Nikoleris
fdt_property_placeholder(void * fdt,const char * name,int len,void ** valp)293553125dfSNikos Nikoleris int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp)
294a322d4c5SAndrew Jones {
295a322d4c5SAndrew Jones struct fdt_property *prop;
296a322d4c5SAndrew Jones int nameoff;
297553125dfSNikos Nikoleris int allocated;
298a322d4c5SAndrew Jones
299553125dfSNikos Nikoleris FDT_SW_PROBE_STRUCT(fdt);
300a322d4c5SAndrew Jones
301553125dfSNikos Nikoleris /* String de-duplication can be slow, _NO_NAME_DEDUP skips it */
302553125dfSNikos Nikoleris if (sw_flags(fdt) & FDT_CREATE_FLAG_NO_NAME_DEDUP) {
303553125dfSNikos Nikoleris allocated = 1;
304553125dfSNikos Nikoleris nameoff = fdt_add_string_(fdt, name);
305553125dfSNikos Nikoleris } else {
306553125dfSNikos Nikoleris nameoff = fdt_find_add_string_(fdt, name, &allocated);
307553125dfSNikos Nikoleris }
308a322d4c5SAndrew Jones if (nameoff == 0)
309a322d4c5SAndrew Jones return -FDT_ERR_NOSPACE;
310a322d4c5SAndrew Jones
311553125dfSNikos Nikoleris prop = fdt_grab_space_(fdt, sizeof(*prop) + FDT_TAGALIGN(len));
312553125dfSNikos Nikoleris if (! prop) {
313553125dfSNikos Nikoleris if (allocated)
314553125dfSNikos Nikoleris fdt_del_last_string_(fdt, name);
315a322d4c5SAndrew Jones return -FDT_ERR_NOSPACE;
316553125dfSNikos Nikoleris }
317a322d4c5SAndrew Jones
318a322d4c5SAndrew Jones prop->tag = cpu_to_fdt32(FDT_PROP);
319a322d4c5SAndrew Jones prop->nameoff = cpu_to_fdt32(nameoff);
320a322d4c5SAndrew Jones prop->len = cpu_to_fdt32(len);
321553125dfSNikos Nikoleris *valp = prop->data;
322553125dfSNikos Nikoleris return 0;
323553125dfSNikos Nikoleris }
324553125dfSNikos Nikoleris
fdt_property(void * fdt,const char * name,const void * val,int len)325553125dfSNikos Nikoleris int fdt_property(void *fdt, const char *name, const void *val, int len)
326553125dfSNikos Nikoleris {
327553125dfSNikos Nikoleris void *ptr;
328553125dfSNikos Nikoleris int ret;
329553125dfSNikos Nikoleris
330553125dfSNikos Nikoleris ret = fdt_property_placeholder(fdt, name, len, &ptr);
331553125dfSNikos Nikoleris if (ret)
332553125dfSNikos Nikoleris return ret;
333553125dfSNikos Nikoleris memcpy(ptr, val, len);
334a322d4c5SAndrew Jones return 0;
335a322d4c5SAndrew Jones }
336a322d4c5SAndrew Jones
fdt_finish(void * fdt)337a322d4c5SAndrew Jones int fdt_finish(void *fdt)
338a322d4c5SAndrew Jones {
339a322d4c5SAndrew Jones char *p = (char *)fdt;
340a322d4c5SAndrew Jones fdt32_t *end;
341a322d4c5SAndrew Jones int oldstroffset, newstroffset;
342a322d4c5SAndrew Jones uint32_t tag;
343a322d4c5SAndrew Jones int offset, nextoffset;
344a322d4c5SAndrew Jones
345553125dfSNikos Nikoleris FDT_SW_PROBE_STRUCT(fdt);
346a322d4c5SAndrew Jones
347a322d4c5SAndrew Jones /* Add terminator */
348553125dfSNikos Nikoleris end = fdt_grab_space_(fdt, sizeof(*end));
349a322d4c5SAndrew Jones if (! end)
350a322d4c5SAndrew Jones return -FDT_ERR_NOSPACE;
351a322d4c5SAndrew Jones *end = cpu_to_fdt32(FDT_END);
352a322d4c5SAndrew Jones
353a322d4c5SAndrew Jones /* Relocate the string table */
354a322d4c5SAndrew Jones oldstroffset = fdt_totalsize(fdt) - fdt_size_dt_strings(fdt);
355a322d4c5SAndrew Jones newstroffset = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
356a322d4c5SAndrew Jones memmove(p + newstroffset, p + oldstroffset, fdt_size_dt_strings(fdt));
357a322d4c5SAndrew Jones fdt_set_off_dt_strings(fdt, newstroffset);
358a322d4c5SAndrew Jones
359a322d4c5SAndrew Jones /* Walk the structure, correcting string offsets */
360a322d4c5SAndrew Jones offset = 0;
361a322d4c5SAndrew Jones while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) {
362a322d4c5SAndrew Jones if (tag == FDT_PROP) {
363a322d4c5SAndrew Jones struct fdt_property *prop =
364553125dfSNikos Nikoleris fdt_offset_ptr_w_(fdt, offset);
365a322d4c5SAndrew Jones int nameoff;
366a322d4c5SAndrew Jones
367a322d4c5SAndrew Jones nameoff = fdt32_to_cpu(prop->nameoff);
368a322d4c5SAndrew Jones nameoff += fdt_size_dt_strings(fdt);
369a322d4c5SAndrew Jones prop->nameoff = cpu_to_fdt32(nameoff);
370a322d4c5SAndrew Jones }
371a322d4c5SAndrew Jones offset = nextoffset;
372a322d4c5SAndrew Jones }
373a322d4c5SAndrew Jones if (nextoffset < 0)
374a322d4c5SAndrew Jones return nextoffset;
375a322d4c5SAndrew Jones
376a322d4c5SAndrew Jones /* Finally, adjust the header */
377a322d4c5SAndrew Jones fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
378553125dfSNikos Nikoleris
379553125dfSNikos Nikoleris /* And fix up fields that were keeping intermediate state. */
380*80a6d74fSAndrew Jones fdt_set_last_comp_version(fdt, FDT_LAST_COMPATIBLE_VERSION);
381a322d4c5SAndrew Jones fdt_set_magic(fdt, FDT_MAGIC);
382553125dfSNikos Nikoleris
383a322d4c5SAndrew Jones return 0;
384a322d4c5SAndrew Jones }
385