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 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 */ 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 */ 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 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 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 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 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 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 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 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 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 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 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 */ 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 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 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 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 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