From bbdbc7cb3abefda5bd998edbcf0508fe6256327d Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 29 Aug 2008 14:19:13 +1000 Subject: [PATCH 1/5] libfdt: Fix bugs in fdt_get_path() The current implementation of fdt_get_path() has a couple of bugs, fixed by this patch. First, contrary to its documentation, on success it returns the length of the node's path, rather than 0. The testcase is correspondingly wrong, and the patch fixes this as well. Second, in some circumstances, it will return -FDT_ERR_BADOFFSET instead of -FDT_ERR_NOSPACE when given insufficient buffer space. Specifically this happens when there is insufficient space even to hold the path's second last component. This behaviour is corrected, and the testcase updated to check it. Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index b09a6e9eb7..f559eeda06 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -320,9 +320,6 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) for (offset = 0, depth = 0; (offset >= 0) && (offset <= nodeoffset); offset = fdt_next_node(fdt, offset, &depth)) { - if (pdepth < depth) - continue; /* overflowed buffer */ - while (pdepth > depth) { do { p--; @@ -330,14 +327,16 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) pdepth--; } - name = fdt_get_name(fdt, offset, &namelen); - if (!name) - return namelen; - if ((p + namelen + 1) <= buflen) { - memcpy(buf + p, name, namelen); - p += namelen; - buf[p++] = '/'; - pdepth++; + if (pdepth >= depth) { + name = fdt_get_name(fdt, offset, &namelen); + if (!name) + return namelen; + if ((p + namelen + 1) <= buflen) { + memcpy(buf + p, name, namelen); + p += namelen; + buf[p++] = '/'; + pdepth++; + } } if (offset == nodeoffset) { @@ -347,7 +346,7 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) if (p > 1) /* special case so that root path is "/", not "" */ p--; buf[p] = '\0'; - return p; + return 0; } } From 741a6d010d09b5bafca8e4cdfb6b2f8a2c07994d Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Thu, 25 Sep 2008 11:02:17 -0500 Subject: [PATCH 2/5] Fix an overflow case in fdt_offset_ptr() detected by GCC 4.3. Using Gcc 4.3 detected this problem: ../dtc/libfdt/fdt.c: In function 'fdt_next_tag': ../dtc/libfdt/fdt.c:82: error: assuming signed overflow does not occur when assuming that (X + c) < X is always false To fix the problem, treat the offset as an unsigned int. The problem report and proposed fix were provided by Steve Papacharalambous . Signed-off-by: Jon Loeliger --- include/libfdt.h | 2 +- libfdt/fdt.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/libfdt.h b/include/libfdt.h index 94c35e330c..5492a53520 100644 --- a/include/libfdt.h +++ b/include/libfdt.h @@ -122,7 +122,7 @@ /* Low-level functions (you probably don't need these) */ /**********************************************************************/ -const void *fdt_offset_ptr(const void *fdt, int offset, int checklen); +const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen); static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen) { return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen); diff --git a/libfdt/fdt.c b/libfdt/fdt.c index 732103b07b..a59a518b0e 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -78,7 +78,7 @@ int fdt_check_header(const void *fdt) return 0; } -const void *fdt_offset_ptr(const void *fdt, int offset, int len) +const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len) { const char *p; From 3e38577208e4256956bc33bb8bcd0a6b6fab55c3 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Fri, 26 Sep 2008 17:03:26 +0200 Subject: [PATCH 3/5] fdt: Overwrite /chosen node in bootm if it already exists in the dtb Set force parameter in fdt_chosen() call in do_bootm_linux() call. Without this, the chosen node is not overwritten if it already exists. Signed-off-by: Stefan Roese --- lib_ppc/bootm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_ppc/bootm.c b/lib_ppc/bootm.c index 38266e1da2..5af25dd222 100644 --- a/lib_ppc/bootm.c +++ b/lib_ppc/bootm.c @@ -145,7 +145,7 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) * if the user wants it (the logic is in the subroutines). */ if (of_size) { - if (fdt_chosen(of_flat_tree, 0) < 0) { + if (fdt_chosen(of_flat_tree, 1) < 0) { puts ("ERROR: "); puts ("/chosen node create failed"); puts (" - must RESET the board to recover.\n"); From 9a6cf73a88ddab2e1ac39088f2806177982cc62c Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 20 Aug 2008 16:55:14 +1000 Subject: [PATCH 4/5] libfdt: Add function to explicitly expand aliases Kumar has already added alias expansion to fdt_path_offset(). However, in some circumstances it may be convenient for the user of libfdt to explicitly get the string expansion of an alias. This patch adds a function to do this, fdt_get_alias(), and uses it to implement fdt_path_offset(). Signed-off-by: David Gibson --- include/libfdt.h | 26 ++++++++++++++++++++++++++ libfdt/fdt_ro.c | 26 +++++++++++++++++++------- 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/include/libfdt.h b/include/libfdt.h index 5492a53520..7cad68c3ce 100644 --- a/include/libfdt.h +++ b/include/libfdt.h @@ -458,6 +458,32 @@ static inline void *fdt_getprop_w(void *fdt, int nodeoffset, */ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset); +/** + * fdt_get_namelen - get alias based on substring + * @fdt: pointer to the device tree blob + * @name: name of the alias th look up + * @namelen: number of characters of name to consider + * + * Identical to fdt_get_alias(), but only examine the first namelen + * characters of name for matching the alias name. + */ +const char *fdt_get_alias_namelen(const void *fdt, + const char *name, int namelen); + +/** + * fdt_get_alias - retreive the path referenced by a given alias + * @fdt: pointer to the device tree blob + * @name: name of the alias th look up + * + * fdt_get_alias() retrieves the value of a given alias. That is, the + * value of the property named 'name' in the node /aliases. + * + * returns: + * a pointer to the expansion of the alias named 'name', of it exists + * NULL, if the given alias or the /aliases node does not exist + */ +const char *fdt_get_alias(const void *fdt, const char *name); + /** * fdt_get_path - determine the full path of a node * @fdt: pointer to the device tree blob diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index f559eeda06..b705f91ecb 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -145,17 +145,12 @@ int fdt_path_offset(const void *fdt, const char *path) /* see if we have an alias */ if (*path != '/') { - const char *q; - int aliasoffset = fdt_path_offset(fdt, "/aliases"); + const char *q = strchr(path, '/'); - if (aliasoffset < 0) - return -FDT_ERR_BADPATH; - - q = strchr(path, '/'); if (!q) q = end; - p = fdt_getprop_namelen(fdt, aliasoffset, path, q - p, NULL); + p = fdt_get_alias_namelen(fdt, p, q - p); if (!p) return -FDT_ERR_BADPATH; offset = fdt_path_offset(fdt, p); @@ -306,6 +301,23 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) return fdt32_to_cpu(*php); } +const char *fdt_get_alias_namelen(const void *fdt, + const char *name, int namelen) +{ + int aliasoffset; + + aliasoffset = fdt_path_offset(fdt, "/aliases"); + if (aliasoffset < 0) + return NULL; + + return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL); +} + +const char *fdt_get_alias(const void *fdt, const char *name) +{ + return fdt_get_alias_namelen(fdt, name, strlen(name)); +} + int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) { int pdepth = 0, p = 0; From cd3cb0d9269d155276b00207e3816a9347fd1c92 Mon Sep 17 00:00:00 2001 From: Gerald Van Baren Date: Sat, 4 Oct 2008 07:56:06 -0400 Subject: [PATCH 5/5] libfdt: Fix error in documentation for fdt_get_alias_namelen() Oops, screwed up the function name in the documenting comment for this function. Trivial correction in this patch. Signed-off-by: David Gibson Acked-by: Gerald Van Baren --- include/libfdt.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/libfdt.h b/include/libfdt.h index 7cad68c3ce..ce374fded1 100644 --- a/include/libfdt.h +++ b/include/libfdt.h @@ -459,7 +459,7 @@ static inline void *fdt_getprop_w(void *fdt, int nodeoffset, uint32_t fdt_get_phandle(const void *fdt, int nodeoffset); /** - * fdt_get_namelen - get alias based on substring + * fdt_get_alias_namelen - get alias based on substring * @fdt: pointer to the device tree blob * @name: name of the alias th look up * @namelen: number of characters of name to consider