X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=lib%2Flibfdt%2Ffdt_ro.c;h=693de9aa5ad8032375b22749a25bc236dc15d950;hb=e731af4893f7741c66254161ad9b6f5280369895;hp=12214c2dc2b58473707a3052a64a6d43b4ca157f;hpb=09849f4a7779a247be8af5cfae44f7aad30e1222;p=oweals%2Fu-boot.git diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c index 12214c2dc2..693de9aa5a 100644 --- a/lib/libfdt/fdt_ro.c +++ b/lib/libfdt/fdt_ro.c @@ -1,13 +1,13 @@ +// SPDX-License-Identifier: GPL-2.0+ OR BSD-2-Clause /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. - * SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause */ -#include +#include #ifndef USE_HOSTCC #include -#include +#include #else #include "fdt_host.h" #endif @@ -47,11 +47,68 @@ static int _fdt_string_eq(const void *fdt, int stroffset, return (strnlen(p, len + 1) == 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_generate_phandle(const void *fdt, uint32_t *phandle) +{ + uint32_t max = 0; + int offset = -1; + + while (true) { + uint32_t value; + + offset = fdt_next_node(fdt, offset, NULL); + if (offset < 0) { + if (offset == -FDT_ERR_NOTFOUND) + break; + + return offset; + } + + value = fdt_get_phandle(fdt, offset); + + if (value > max) + max = value; + } + + if (max == FDT_MAX_PHANDLE) + return -FDT_ERR_NOPHANDLES; + + if (phandle) + *phandle = max + 1; + + return 0; +} + int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) { FDT_CHECK_HEADER(fdt); - *address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address); - *size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size); + *address = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->address); + *size = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->size); return 0; } @@ -59,7 +116,7 @@ int fdt_num_mem_rsv(const void *fdt) { int i = 0; - while (fdt64_to_cpu(_fdt_mem_rsv(fdt, i)->size) != 0) + while (fdt64_to_cpu(fdt_mem_rsv_(fdt, i)->size) != 0) i++; return i; } @@ -114,15 +171,15 @@ int fdt_subnode_offset(const void *fdt, int parentoffset, } /* - * Find the next of path seperator, note we need to search for both '/' and ':' + * Find the next of path separator, note we need to search for both '/' and ':' * and then take the first one so that we do the right thing for e.g. * "foo/bar:option" and "bar:option/otheroption", both of which happen, so * first searching for either ':' or '/' does not work. */ -static const char *fdt_path_next_seperator(const char *path) +static const char *fdt_path_next_separator(const char *path, int len) { - const char *sep1 = strchr(path, '/'); - const char *sep2 = strchr(path, ':'); + const void *sep1 = memchr(path, '/', len); + const void *sep2 = memchr(path, ':', len); if (sep1 && sep2) return (sep1 < sep2) ? sep1 : sep2; @@ -132,9 +189,9 @@ static const char *fdt_path_next_seperator(const char *path) return sep2; } -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; @@ -142,7 +199,7 @@ int fdt_path_offset(const void *fdt, const char *path) /* see if we have an alias */ if (*path != '/') { - const char *q = fdt_path_next_seperator(path); + const char *q = fdt_path_next_separator(path, namelen); if (!q) q = end; @@ -155,14 +212,16 @@ int fdt_path_offset(const void *fdt, const char *path) p = q; } - while (*p) { + while (*p && (p < end)) { const char *q; while (*p == '/') p++; + if (*p == '\0' || *p == ':') return offset; - q = fdt_path_next_seperator(p); + + q = fdt_path_next_separator(p, end - p); if (!q) q = end; @@ -176,13 +235,18 @@ 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); + const struct fdt_node_header *nh = fdt_offset_ptr_(fdt, nodeoffset); int err; if (((err = fdt_check_header(fdt)) != 0) - || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0)) + || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0)) goto fail; if (len) @@ -200,7 +264,7 @@ int fdt_first_property_offset(const void *fdt, int nodeoffset) { int offset; - if ((offset = _fdt_check_node_offset(fdt, nodeoffset)) < 0) + if ((offset = fdt_check_node_offset_(fdt, nodeoffset)) < 0) return offset; return _nextprop(fdt, offset); @@ -208,7 +272,7 @@ int fdt_first_property_offset(const void *fdt, int nodeoffset) int fdt_next_property_offset(const void *fdt, int offset) { - if ((offset = _fdt_check_prop_offset(fdt, offset)) < 0) + if ((offset = fdt_check_prop_offset_(fdt, offset)) < 0) return offset; return _nextprop(fdt, offset); @@ -221,13 +285,13 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt, int err; const struct fdt_property *prop; - if ((err = _fdt_check_prop_offset(fdt, offset)) < 0) { + if ((err = fdt_check_prop_offset_(fdt, offset)) < 0) { if (lenp) *lenp = err; return NULL; } - prop = _fdt_offset_ptr(fdt, offset); + prop = fdt_offset_ptr_(fdt, offset); if (lenp) *lenp = fdt32_to_cpu(prop->len); @@ -510,80 +574,104 @@ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str) return 0; } -int fdt_count_strings(const void *fdt, int node, const char *property) +int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property) { - int length, i, count = 0; - const char *list; + const char *list, *end; + int length, count = 0; - list = fdt_getprop(fdt, node, property, &length); + list = fdt_getprop(fdt, nodeoffset, property, &length); if (!list) return length; - for (i = 0; i < length; i++) { - int len = strlen(list); + 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 += len + 1; - i += len; + list += length; count++; } return count; } -int fdt_find_string(const void *fdt, int node, const char *property, - const char *string) +int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property, + const char *string) { + int length, len, idx = 0; const char *list, *end; - int len, index = 0; - list = fdt_getprop(fdt, node, property, &len); + list = fdt_getprop(fdt, nodeoffset, property, &length); if (!list) - return len; + return length; - end = list + len; - len = strlen(string); + len = strlen(string) + 1; + end = list + length; while (list < end) { - int l = strlen(list); + length = strnlen(list, end - list) + 1; - if (l == len && memcmp(list, string, len) == 0) - return index; + /* Abort if the last string isn't properly NUL-terminated. */ + if (list + length > end) + return -FDT_ERR_BADVALUE; - list += l + 1; - index++; + if (length == len && memcmp(list, string, length) == 0) + return idx; + + list += length; + idx++; } return -FDT_ERR_NOTFOUND; } -int fdt_get_string_index(const void *fdt, int node, const char *property, - int index, const char **output) +const char *fdt_stringlist_get(const void *fdt, int nodeoffset, + const char *property, int idx, + int *lenp) { - const char *list; - int length, i; + const char *list, *end; + int length; - list = fdt_getprop(fdt, node, property, &length); + list = fdt_getprop(fdt, nodeoffset, property, &length); + if (!list) { + if (lenp) + *lenp = length; - for (i = 0; i < length; i++) { - int len = strlen(list); + return NULL; + } - if (index == 0) { - *output = list; - return 0; + 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; } - list += len + 1; - i += len; - index--; + if (idx == 0) { + if (lenp) + *lenp = length - 1; + + return list; + } + + list += length; + idx--; } - return -FDT_ERR_NOTFOUND; -} + if (lenp) + *lenp = -FDT_ERR_NOTFOUND; -int fdt_get_string(const void *fdt, int node, const char *property, - const char **output) -{ - return fdt_get_string_index(fdt, node, property, 0, output); + return NULL; } int fdt_node_check_compatible(const void *fdt, int nodeoffset, @@ -595,10 +683,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,