diff options
-rw-r--r-- | arch/powerpc/boot/flatdevtree.c | 59 | ||||
-rw-r--r-- | arch/powerpc/boot/flatdevtree.h | 1 | ||||
-rw-r--r-- | arch/powerpc/boot/flatdevtree_misc.c | 6 | ||||
-rw-r--r-- | arch/powerpc/boot/ops.h | 9 |
4 files changed, 75 insertions, 0 deletions
diff --git a/arch/powerpc/boot/flatdevtree.c b/arch/powerpc/boot/flatdevtree.c index 0af7291fc67c..cf30675c6116 100644 --- a/arch/powerpc/boot/flatdevtree.c +++ b/arch/powerpc/boot/flatdevtree.c @@ -975,3 +975,62 @@ void *ft_create_node(struct ft_cxt *cxt, const void *parent, const char *name) } 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; +} diff --git a/arch/powerpc/boot/flatdevtree.h b/arch/powerpc/boot/flatdevtree.h index 2c1c826c4eca..b0957a2d967f 100644 --- a/arch/powerpc/boot/flatdevtree.h +++ b/arch/powerpc/boot/flatdevtree.h @@ -108,5 +108,6 @@ void *ft_find_node_by_prop_value(struct ft_cxt *cxt, const void *prev, const char *propname, const char *propval, int proplen); void *ft_create_node(struct ft_cxt *cxt, const void *parent, const char *name); +char *ft_get_path(struct ft_cxt *cxt, const void *phandle, char *buf, int len); #endif /* FLATDEVTREE_H */ diff --git a/arch/powerpc/boot/flatdevtree_misc.c b/arch/powerpc/boot/flatdevtree_misc.c index 8d1debe8d941..b3670096fa71 100644 --- a/arch/powerpc/boot/flatdevtree_misc.c +++ b/arch/powerpc/boot/flatdevtree_misc.c @@ -58,6 +58,11 @@ static unsigned long fdtm_finalize(void) return (unsigned long)cxt.bph; } +static char *fdtm_get_path(const void *phandle, char *buf, int len) +{ + return ft_get_path(&cxt, phandle, buf, len); +} + int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device) { dt_ops.finddevice = fdtm_finddevice; @@ -67,6 +72,7 @@ int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device) dt_ops.create_node = fdtm_create_node; dt_ops.find_node_by_prop_value = fdtm_find_node_by_prop_value; dt_ops.finalize = fdtm_finalize; + dt_ops.get_path = fdtm_get_path; return ft_open(&cxt, dt_blob, max_size, max_find_device, platform_ops.realloc); diff --git a/arch/powerpc/boot/ops.h b/arch/powerpc/boot/ops.h index 45c2268d5c56..703255bf0089 100644 --- a/arch/powerpc/boot/ops.h +++ b/arch/powerpc/boot/ops.h @@ -47,6 +47,7 @@ struct dt_ops { const char *propname, const char *propval, int proplen); unsigned long (*finalize)(void); + char *(*get_path)(const void *phandle, char *buf, int len); }; extern struct dt_ops dt_ops; @@ -170,6 +171,14 @@ static inline void *find_node_by_linuxphandle(const u32 linuxphandle) (char *)&linuxphandle, sizeof(u32)); } +static inline char *get_path(const void *phandle, char *buf, int len) +{ + if (dt_ops.get_path) + return dt_ops.get_path(phandle, buf, len); + + return NULL; +} + static inline void *malloc(unsigned long size) { return (platform_ops.malloc) ? platform_ops.malloc(size) : NULL; |