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 | } | ||
