int ft_del_prop(struct ft_cxt *cxt, const void *phandle, const char *propname) { struct ft_atom atom; void *node; char *p, *next; int size; node = ft_node_ph2node(cxt, phandle); if (node == NULL) return -1; p = node; while ((next = ft_next(cxt, p, &atom)) != NULL) { switch (atom.tag) { case OF_DT_BEGIN_NODE: case OF_DT_END_NODE: return -1; case OF_DT_PROP: if (strcmp(atom.name, propname)) break; /* found the property, remove it */ size = 12 + -_ALIGN(atom.size, 4); cxt->p = p; if (!ft_make_space(cxt, &cxt->p, FT_STRUCT, -size)) return -1; return 0; } p = next; } return -1; }
int ft_begin_node(struct ft_cxt *cxt, const char *name) { unsigned long nlen = strlen(name) + 1; unsigned long len = 8 + _ALIGN(nlen, 4); if (!ft_make_space(cxt, &cxt->p, FT_STRUCT, len)) return -1; ft_put_word(cxt, OF_DT_BEGIN_NODE); ft_put_bin(cxt, name, strlen(name) + 1); return 0; }
/* lookup string and insert if not found */ static int map_string(struct ft_cxt *cxt, const char *name) { int off; char *p; off = lookup_string(cxt, name); if (off != NO_STRING) return off; p = cxt->rgn[FT_STRINGS].start; if (!ft_make_space(cxt, &p, FT_STRINGS, strlen(name) + 1)) return NO_STRING; strcpy(p, name); return p - cxt->str_anchor; }
/* add a reserver physical area to the rsvmap */ int ft_add_rsvmap(struct ft_cxt *cxt, u64 physaddr, u64 size) { char *p; struct ft_reserve *pres; p = cxt->rgn[FT_RSVMAP].start + cxt->rgn[FT_RSVMAP].size - sizeof(struct ft_reserve); if (!ft_make_space(cxt, &p, FT_RSVMAP, sizeof(struct ft_reserve))) return -1; pres = (struct ft_reserve *)p; pres->start = cpu_to_be64(physaddr); pres->len = cpu_to_be64(size); return 0; }
int ft_prop(struct ft_cxt *cxt, const char *name, const void *data, unsigned int sz) { int off, len; off = map_string(cxt, name); if (off == NO_STRING) return -1; len = 12 + _ALIGN(sz, 4); if (!ft_make_space(cxt, &cxt->p, FT_STRUCT, len)) return -1; ft_put_word(cxt, OF_DT_PROP); ft_put_word(cxt, sz); ft_put_word(cxt, off); ft_put_bin(cxt, data, sz); return 0; }
int ft_set_prop(struct ft_cxt *cxt, const void *phandle, const char *propname, const void *buf, const unsigned int buflen) { struct ft_atom atom; void *node; char *p, *next; int nextra, depth; node = ft_node_ph2node(cxt, phandle); if (node == NULL) return -1; depth = 0; p = node; while ((next = ft_next(cxt, p, &atom)) != NULL) { switch (atom.tag) { case OF_DT_BEGIN_NODE: ++depth; break; case OF_DT_END_NODE: if (--depth > 0) break; /* haven't found the property, insert here */ cxt->p = p; return ft_prop(cxt, propname, buf, buflen); case OF_DT_PROP: if ((depth != 1) || strcmp(atom.name, propname)) break; /* found an existing property, overwrite it */ nextra = _ALIGN(buflen, 4) - _ALIGN(atom.size, 4); cxt->p = atom.data; if (nextra && !ft_make_space(cxt, &cxt->p, FT_STRUCT, nextra)) return -1; *(u32 *) (cxt->p - 8) = cpu_to_be32(buflen); ft_put_bin(cxt, buf, buflen); return 0; } p = next; } return -1; }
void ft_nop(struct ft_cxt *cxt) { if (ft_make_space(cxt, &cxt->p, FT_STRUCT, 4)) ft_put_word(cxt, OF_DT_NOP); }