diff options
Diffstat (limited to 'arch/powerpc/boot/flatdevtree.c')
-rw-r--r-- | arch/powerpc/boot/flatdevtree.c | 100 |
1 files changed, 78 insertions, 22 deletions
diff --git a/arch/powerpc/boot/flatdevtree.c b/arch/powerpc/boot/flatdevtree.c index 13761bf160c4..cf30675c6116 100644 --- a/arch/powerpc/boot/flatdevtree.c +++ b/arch/powerpc/boot/flatdevtree.c | |||
@@ -354,16 +354,21 @@ static void ft_put_bin(struct ft_cxt *cxt, const void *data, unsigned int sz) | |||
354 | cxt->p += sza; | 354 | cxt->p += sza; |
355 | } | 355 | } |
356 | 356 | ||
357 | int ft_begin_node(struct ft_cxt *cxt, const char *name) | 357 | char *ft_begin_node(struct ft_cxt *cxt, const char *name) |
358 | { | 358 | { |
359 | unsigned long nlen = strlen(name) + 1; | 359 | unsigned long nlen = strlen(name) + 1; |
360 | unsigned long len = 8 + _ALIGN(nlen, 4); | 360 | unsigned long len = 8 + _ALIGN(nlen, 4); |
361 | char *ret; | ||
361 | 362 | ||
362 | if (!ft_make_space(cxt, &cxt->p, FT_STRUCT, len)) | 363 | if (!ft_make_space(cxt, &cxt->p, FT_STRUCT, len)) |
363 | return -1; | 364 | return NULL; |
365 | |||
366 | ret = cxt->p; | ||
367 | |||
364 | ft_put_word(cxt, OF_DT_BEGIN_NODE); | 368 | ft_put_word(cxt, OF_DT_BEGIN_NODE); |
365 | ft_put_bin(cxt, name, strlen(name) + 1); | 369 | ft_put_bin(cxt, name, strlen(name) + 1); |
366 | return 0; | 370 | |
371 | return ret; | ||
367 | } | 372 | } |
368 | 373 | ||
369 | void ft_end_node(struct ft_cxt *cxt) | 374 | void ft_end_node(struct ft_cxt *cxt) |
@@ -625,25 +630,17 @@ void ft_end_tree(struct ft_cxt *cxt) | |||
625 | bph->dt_strings_size = cpu_to_be32(ssize); | 630 | bph->dt_strings_size = cpu_to_be32(ssize); |
626 | } | 631 | } |
627 | 632 | ||
628 | void *ft_find_device(struct ft_cxt *cxt, const char *srch_path) | 633 | void *ft_find_device(struct ft_cxt *cxt, const void *top, const char *srch_path) |
629 | { | ||
630 | char *node; | ||
631 | |||
632 | /* require absolute path */ | ||
633 | if (srch_path[0] != '/') | ||
634 | return NULL; | ||
635 | node = ft_find_descendent(cxt, ft_root_node(cxt), srch_path); | ||
636 | return ft_get_phandle(cxt, node); | ||
637 | } | ||
638 | |||
639 | void *ft_find_device_rel(struct ft_cxt *cxt, const void *top, | ||
640 | const char *srch_path) | ||
641 | { | 634 | { |
642 | char *node; | 635 | char *node; |
643 | 636 | ||
644 | node = ft_node_ph2node(cxt, top); | 637 | if (top) { |
645 | if (node == NULL) | 638 | node = ft_node_ph2node(cxt, top); |
646 | return NULL; | 639 | if (node == NULL) |
640 | return NULL; | ||
641 | } else { | ||
642 | node = ft_root_node(cxt); | ||
643 | } | ||
647 | 644 | ||
648 | node = ft_find_descendent(cxt, node, srch_path); | 645 | node = ft_find_descendent(cxt, node, srch_path); |
649 | return ft_get_phandle(cxt, node); | 646 | return ft_get_phandle(cxt, node); |
@@ -945,7 +942,7 @@ int ft_del_prop(struct ft_cxt *cxt, const void *phandle, const char *propname) | |||
945 | void *ft_create_node(struct ft_cxt *cxt, const void *parent, const char *name) | 942 | void *ft_create_node(struct ft_cxt *cxt, const void *parent, const char *name) |
946 | { | 943 | { |
947 | struct ft_atom atom; | 944 | struct ft_atom atom; |
948 | char *p, *next; | 945 | char *p, *next, *ret; |
949 | int depth = 0; | 946 | int depth = 0; |
950 | 947 | ||
951 | if (parent) { | 948 | if (parent) { |
@@ -970,11 +967,70 @@ void *ft_create_node(struct ft_cxt *cxt, const void *parent, const char *name) | |||
970 | break; | 967 | break; |
971 | /* end of node, insert here */ | 968 | /* end of node, insert here */ |
972 | cxt->p = p; | 969 | cxt->p = p; |
973 | ft_begin_node(cxt, name); | 970 | ret = ft_begin_node(cxt, name); |
974 | ft_end_node(cxt); | 971 | ft_end_node(cxt); |
975 | return p; | 972 | return ft_get_phandle(cxt, ret); |
976 | } | 973 | } |
977 | p = next; | 974 | p = next; |
978 | } | 975 | } |
979 | return NULL; | 976 | return NULL; |
980 | } | 977 | } |
978 | |||
979 | /* Returns the start of the path within the provided buffer, or NULL on | ||
980 | * error. | ||
981 | */ | ||
982 | char *ft_get_path(struct ft_cxt *cxt, const void *phandle, | ||
983 | char *buf, int len) | ||
984 | { | ||
985 | const char *path_comp[FT_MAX_DEPTH]; | ||
986 | struct ft_atom atom; | ||
987 | char *p, *next, *pos; | ||
988 | int depth = 0, i; | ||
989 | void *node; | ||
990 | |||
991 | node = ft_node_ph2node(cxt, phandle); | ||
992 | if (node == NULL) | ||
993 | return NULL; | ||
994 | |||
995 | p = ft_root_node(cxt); | ||
996 | |||
997 | while ((next = ft_next(cxt, p, &atom)) != NULL) { | ||
998 | switch (atom.tag) { | ||
999 | case OF_DT_BEGIN_NODE: | ||
1000 | path_comp[depth++] = atom.name; | ||
1001 | if (p == node) | ||
1002 | goto found; | ||
1003 | |||
1004 | break; | ||
1005 | |||
1006 | case OF_DT_END_NODE: | ||
1007 | if (--depth == 0) | ||
1008 | return NULL; | ||
1009 | } | ||
1010 | |||
1011 | p = next; | ||
1012 | } | ||
1013 | |||
1014 | found: | ||
1015 | pos = buf; | ||
1016 | for (i = 1; i < depth; i++) { | ||
1017 | int this_len; | ||
1018 | |||
1019 | if (len <= 1) | ||
1020 | return NULL; | ||
1021 | |||
1022 | *pos++ = '/'; | ||
1023 | len--; | ||
1024 | |||
1025 | strncpy(pos, path_comp[i], len); | ||
1026 | |||
1027 | if (pos[len - 1] != 0) | ||
1028 | return NULL; | ||
1029 | |||
1030 | this_len = strlen(pos); | ||
1031 | len -= this_len; | ||
1032 | pos += this_len; | ||
1033 | } | ||
1034 | |||
1035 | return buf; | ||
1036 | } | ||