int fdt_resize(void *fdt, void *buf, int bufsize) { size_t headsize, tailsize; char *oldtail, *newtail; FDT_SW_CHECK_HEADER(fdt); headsize = fdt_off_dt_struct(fdt); tailsize = fdt_size_dt_strings(fdt); if ((headsize + tailsize) > bufsize) return -FDT_ERR_NOSPACE; oldtail = (char *)fdt + fdt_totalsize(fdt) - tailsize; newtail = (char *)buf + bufsize - tailsize; /* Two cases to avoid clobbering data if the old and new * buffers partially overlap */ if (buf <= fdt) { memmove(buf, fdt, headsize); memmove(newtail, oldtail, tailsize); } else { memmove(newtail, oldtail, tailsize); memmove(buf, fdt, headsize); } fdt_set_off_dt_strings(buf, bufsize); fdt_set_totalsize(buf, bufsize); return 0; }
int fdt_end_node(void *fdt) { uint32_t *en; FDT_SW_CHECK_HEADER(fdt); en = _fdt_grab_space(fdt, FDT_TAGSIZE); if (! en) return -FDT_ERR_NOSPACE; *en = cpu_to_fdt32(FDT_END_NODE); return 0; }
int fdt_begin_node(void *fdt, const char *name) { struct fdt_node_header *nh; int namelen = strlen(name) + 1; FDT_SW_CHECK_HEADER(fdt); nh = _fdt_grab_space(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen)); if (! nh) return -FDT_ERR_NOSPACE; nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); memcpy(nh->name, name, namelen); return 0; }
int fdt_finish(void *fdt) { char *p = (char *)fdt; uint32_t *end; int oldstroffset, newstroffset; uint32_t tag; int offset, nextoffset; FDT_SW_CHECK_HEADER(fdt); /* Add terminator */ end = _fdt_grab_space(fdt, sizeof(*end)); if (! end) return -FDT_ERR_NOSPACE; *end = cpu_to_fdt32(FDT_END); /* Relocate the string table */ oldstroffset = fdt_totalsize(fdt) - fdt_size_dt_strings(fdt); newstroffset = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); memmove(p + newstroffset, p + oldstroffset, fdt_size_dt_strings(fdt)); fdt_set_off_dt_strings(fdt, newstroffset); /* Walk the structure, correcting string offsets */ offset = 0; while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) { if (tag == FDT_PROP) { struct fdt_property *prop = fdt_offset_ptr_w(fdt, offset, sizeof(*prop)); int nameoff; if (! prop) return -FDT_ERR_BADSTRUCTURE; nameoff = fdt32_to_cpu(prop->nameoff); nameoff += fdt_size_dt_strings(fdt); prop->nameoff = cpu_to_fdt32(nameoff); } offset = nextoffset; } /* Finally, adjust the header */ fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt)); fdt_set_magic(fdt, FDT_MAGIC); return 0; }
int fdt_finish(void *fdt) { char *p = (char *)fdt; uint32_t *end; int oldstroffset, newstroffset; uint32_t tag; int offset, nextoffset; FDT_SW_CHECK_HEADER(fdt); end = _fdt_grab_space(fdt, sizeof(*end)); if (! end) return -FDT_ERR_NOSPACE; *end = cpu_to_fdt32(FDT_END); oldstroffset = fdt_totalsize(fdt) - fdt_size_dt_strings(fdt); newstroffset = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); memmove(p + newstroffset, p + oldstroffset, fdt_size_dt_strings(fdt)); fdt_set_off_dt_strings(fdt, newstroffset); offset = 0; while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) { if (tag == FDT_PROP) { struct fdt_property *prop = _fdt_offset_ptr_w(fdt, offset); int nameoff; nameoff = fdt32_to_cpu(prop->nameoff); nameoff += fdt_size_dt_strings(fdt); prop->nameoff = cpu_to_fdt32(nameoff); } offset = nextoffset; } if (nextoffset < 0) return nextoffset; fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt)); fdt_set_magic(fdt, FDT_MAGIC); return 0; }
int fdt_property(void *fdt, const char *name, const void *val, int len) { struct fdt_property *prop; int nameoff; FDT_SW_CHECK_HEADER(fdt); nameoff = _fdt_find_add_string(fdt, name); if (nameoff == 0) return -FDT_ERR_NOSPACE; prop = _fdt_grab_space(fdt, sizeof(*prop) + FDT_TAGALIGN(len)); if (! prop) return -FDT_ERR_NOSPACE; prop->tag = cpu_to_fdt32(FDT_PROP); prop->nameoff = cpu_to_fdt32(nameoff); prop->len = cpu_to_fdt32(len); memcpy(prop->data, val, len); return 0; }
int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size) { struct fdt_reserve_entry *re; unsigned int offset; FDT_SW_CHECK_HEADER(fdt); if (fdt_size_dt_struct(fdt)) return -FDT_ERR_BADSTATE; offset = fdt_off_dt_struct(fdt); if ((offset + sizeof(*re)) > fdt_totalsize(fdt)) return -FDT_ERR_NOSPACE; re = (struct fdt_reserve_entry *)((char *)fdt + offset); re->address = cpu_to_fdt64(addr); re->size = cpu_to_fdt64(size); fdt_set_off_dt_struct(fdt, offset + sizeof(*re)); return 0; }