X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=arch%2Fpowerpc%2Fboot%2Fflatdevtree.c;h=cf30675c61166cb666d5e14f89cdd5b55315f190;hb=37e58df30063e229ee5157f9d1c1fa1d749917c2;hp=b732644788db799f83c6c90921ac14cd5f4e8069;hpb=a43266355b3d8cf6717a27159f9a417bdff73782;p=pandora-kernel.git diff --git a/arch/powerpc/boot/flatdevtree.c b/arch/powerpc/boot/flatdevtree.c index b732644788db..cf30675c6116 100644 --- a/arch/powerpc/boot/flatdevtree.c +++ b/arch/powerpc/boot/flatdevtree.c @@ -134,20 +134,6 @@ static char *ft_next(struct ft_cxt *cxt, char *p, struct ft_atom *ret) #define HDR_SIZE _ALIGN(sizeof(struct boot_param_header), 8) #define EXPAND_INCR 1024 /* alloc this much extra when expanding */ -/* See if the regions are in the standard order and non-overlapping */ -static int ft_ordered(struct ft_cxt *cxt) -{ - char *p = (char *)cxt->bph + HDR_SIZE; - enum ft_rgn_id r; - - for (r = FT_RSVMAP; r <= FT_STRINGS; ++r) { - if (p > cxt->rgn[r].start) - return 0; - p = cxt->rgn[r].start + cxt->rgn[r].size; - } - return p <= (char *)cxt->bph + cxt->max_size; -} - /* Copy the tree to a newly-allocated region and put things in order */ static int ft_reorder(struct ft_cxt *cxt, int nextra) { @@ -368,16 +354,21 @@ static void ft_put_bin(struct ft_cxt *cxt, const void *data, unsigned int sz) cxt->p += sza; } -int ft_begin_node(struct ft_cxt *cxt, const char *name) +char *ft_begin_node(struct ft_cxt *cxt, const char *name) { unsigned long nlen = strlen(name) + 1; unsigned long len = 8 + _ALIGN(nlen, 4); + char *ret; if (!ft_make_space(cxt, &cxt->p, FT_STRUCT, len)) - return -1; + return NULL; + + ret = cxt->p; + ft_put_word(cxt, OF_DT_BEGIN_NODE); ft_put_bin(cxt, name, strlen(name) + 1); - return 0; + + return ret; } void ft_end_node(struct ft_cxt *cxt) @@ -573,10 +564,6 @@ int ft_open(struct ft_cxt *cxt, void *blob, unsigned int max_size, cxt->rgn[FT_STRUCT].size = struct_size(cxt); cxt->rgn[FT_STRINGS].start = blob + be32_to_cpu(bph->off_dt_strings); cxt->rgn[FT_STRINGS].size = be32_to_cpu(bph->dt_strings_size); - /* Leave as '0' to force first ft_make_space call to do a ft_reorder - * and move dt to an area allocated by realloc. - cxt->isordered = ft_ordered(cxt); - */ cxt->p = cxt->rgn[FT_STRUCT].start; cxt->str_anchor = cxt->rgn[FT_STRINGS].start; @@ -643,25 +630,17 @@ void ft_end_tree(struct ft_cxt *cxt) bph->dt_strings_size = cpu_to_be32(ssize); } -void *ft_find_device(struct ft_cxt *cxt, const char *srch_path) -{ - char *node; - - /* require absolute path */ - if (srch_path[0] != '/') - return NULL; - node = ft_find_descendent(cxt, ft_root_node(cxt), srch_path); - return ft_get_phandle(cxt, node); -} - -void *ft_find_device_rel(struct ft_cxt *cxt, const void *top, - const char *srch_path) +void *ft_find_device(struct ft_cxt *cxt, const void *top, const char *srch_path) { char *node; - node = ft_node_ph2node(cxt, top); - if (node == NULL) - return NULL; + if (top) { + node = ft_node_ph2node(cxt, top); + if (node == NULL) + return NULL; + } else { + node = ft_root_node(cxt); + } node = ft_find_descendent(cxt, node, srch_path); return ft_get_phandle(cxt, node); @@ -963,7 +942,7 @@ int ft_del_prop(struct ft_cxt *cxt, const void *phandle, const char *propname) void *ft_create_node(struct ft_cxt *cxt, const void *parent, const char *name) { struct ft_atom atom; - char *p, *next; + char *p, *next, *ret; int depth = 0; if (parent) { @@ -988,11 +967,70 @@ void *ft_create_node(struct ft_cxt *cxt, const void *parent, const char *name) break; /* end of node, insert here */ cxt->p = p; - ft_begin_node(cxt, name); + ret = ft_begin_node(cxt, name); ft_end_node(cxt); - return p; + return ft_get_phandle(cxt, ret); } p = next; } return NULL; } + +/* Returns the start of the path within the provided buffer, or NULL on + * error. + */ +char *ft_get_path(struct ft_cxt *cxt, const void *phandle, + char *buf, int len) +{ + const char *path_comp[FT_MAX_DEPTH]; + struct ft_atom atom; + char *p, *next, *pos; + int depth = 0, i; + void *node; + + node = ft_node_ph2node(cxt, phandle); + if (node == NULL) + return NULL; + + p = ft_root_node(cxt); + + while ((next = ft_next(cxt, p, &atom)) != NULL) { + switch (atom.tag) { + case OF_DT_BEGIN_NODE: + path_comp[depth++] = atom.name; + if (p == node) + goto found; + + break; + + case OF_DT_END_NODE: + if (--depth == 0) + return NULL; + } + + p = next; + } + +found: + pos = buf; + for (i = 1; i < depth; i++) { + int this_len; + + if (len <= 1) + return NULL; + + *pos++ = '/'; + len--; + + strncpy(pos, path_comp[i], len); + + if (pos[len - 1] != 0) + return NULL; + + this_len = strlen(pos); + len -= this_len; + pos += this_len; + } + + return buf; +}