diff options
Diffstat (limited to 'lib/libfdt/fdt_ro.c')
-rw-r--r-- | lib/libfdt/fdt_ro.c | 154 |
1 files changed, 142 insertions, 12 deletions
diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c index 50007f61c..04590984b 100644 --- a/lib/libfdt/fdt_ro.c +++ b/lib/libfdt/fdt_ro.c @@ -88,6 +88,32 @@ static int _fdt_string_eq(const void *fdt, int stroffset, return (strlen(p) == len) && (memcmp(p, s, len) == 0); } +uint32_t fdt_get_max_phandle(const void *fdt) +{ + uint32_t max_phandle = 0; + int offset; + + for (offset = fdt_next_node(fdt, -1, NULL);; + offset = fdt_next_node(fdt, offset, NULL)) { + uint32_t phandle; + + if (offset == -FDT_ERR_NOTFOUND) + return max_phandle; + + if (offset < 0) + return (uint32_t)-1; + + phandle = fdt_get_phandle(fdt, offset); + if (phandle == (uint32_t)-1) + continue; + + if (phandle > max_phandle) + max_phandle = phandle; + } + + return 0; +} + int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) { FDT_CHECK_HEADER(fdt); @@ -154,9 +180,9 @@ int fdt_subnode_offset(const void *fdt, int parentoffset, return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name)); } -int fdt_path_offset(const void *fdt, const char *path) +int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen) { - const char *end = path + strlen(path); + const char *end = path + namelen; const char *p = path; int offset = 0; @@ -164,7 +190,7 @@ int fdt_path_offset(const void *fdt, const char *path) /* see if we have an alias */ if (*path != '/') { - const char *q = strchr(path, '/'); + const char *q = memchr(path, '/', end - p); if (!q) q = end; @@ -177,14 +203,15 @@ int fdt_path_offset(const void *fdt, const char *path) p = q; } - while (*p) { + while (p < end) { const char *q; - while (*p == '/') + while (*p == '/') { p++; - if (! *p) - return offset; - q = strchr(p, '/'); + if (p == end) + return offset; + } + q = memchr(p, '/', end - p); if (! q) q = end; @@ -198,6 +225,11 @@ int fdt_path_offset(const void *fdt, const char *path) return offset; } +int fdt_path_offset(const void *fdt, const char *path) +{ + return fdt_path_offset_namelen(fdt, path, strlen(path)); +} + const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) { const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset); @@ -532,6 +564,106 @@ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str) return 0; } +int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property) +{ + const char *list, *end; + int length, count = 0; + + list = fdt_getprop(fdt, nodeoffset, property, &length); + if (!list) + return -length; + + end = list + length; + + while (list < end) { + length = strnlen(list, end - list) + 1; + + /* Abort if the last string isn't properly NUL-terminated. */ + if (list + length > end) + return -FDT_ERR_BADVALUE; + + list += length; + count++; + } + + return count; +} + +int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property, + const char *string) +{ + int length, len, idx = 0; + const char *list, *end; + + list = fdt_getprop(fdt, nodeoffset, property, &length); + if (!list) + return -length; + + len = strlen(string) + 1; + end = list + length; + + while (list < end) { + length = strnlen(list, end - list) + 1; + + /* Abort if the last string isn't properly NUL-terminated. */ + if (list + length > end) + return -FDT_ERR_BADVALUE; + + if (length == len && memcmp(list, string, length) == 0) + return idx; + + list += length; + idx++; + } + + return -FDT_ERR_NOTFOUND; +} + +const char *fdt_stringlist_get(const void *fdt, int nodeoffset, + const char *property, int idx, + int *lenp) +{ + const char *list, *end; + int length; + + list = fdt_getprop(fdt, nodeoffset, property, &length); + if (!list) { + if (lenp) + *lenp = length; + + return NULL; + } + + end = list + length; + + while (list < end) { + length = strnlen(list, end - list) + 1; + + /* Abort if the last string isn't properly NUL-terminated. */ + if (list + length > end) { + if (lenp) + *lenp = -FDT_ERR_BADVALUE; + + return NULL; + } + + if (idx == 0) { + if (lenp) + *lenp = length - 1; + + return list; + } + + list += length; + idx--; + } + + if (lenp) + *lenp = -FDT_ERR_NOTFOUND; + + return NULL; +} + int fdt_node_check_compatible(const void *fdt, int nodeoffset, const char *compatible) { @@ -541,10 +673,8 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset, prop = fdt_getprop(fdt, nodeoffset, "compatible", &len); if (!prop) return len; - if (fdt_stringlist_contains(prop, len, compatible)) - return 0; - else - return 1; + + return !fdt_stringlist_contains(prop, len, compatible); } int fdt_node_offset_by_compatible(const void *fdt, int startoffset, |