diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/fdtdec.c | 71 | ||||
-rw-r--r-- | lib/initcall.c | 8 | ||||
-rw-r--r-- | lib/libfdt/fdt_ro.c | 76 |
3 files changed, 152 insertions, 3 deletions
diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 65db739c50..9714620ab3 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -709,4 +709,75 @@ int fdtdec_read_fmap_entry(const void *blob, int node, const char *name, return 0; } + +static u64 fdtdec_get_number(const fdt32_t *ptr, unsigned int cells) +{ + u64 number = 0; + + while (cells--) + number = (number << 32) | fdt32_to_cpu(*ptr++); + + return number; +} + +int fdt_get_resource(const void *fdt, int node, const char *property, + unsigned int index, struct fdt_resource *res) +{ + const fdt32_t *ptr, *end; + int na, ns, len, parent; + unsigned int i = 0; + + parent = fdt_parent_offset(fdt, node); + if (parent < 0) + return parent; + + na = fdt_address_cells(fdt, parent); + ns = fdt_size_cells(fdt, parent); + + ptr = fdt_getprop(fdt, node, property, &len); + if (!ptr) + return len; + + end = ptr + len / sizeof(*ptr); + + while (ptr + na + ns <= end) { + if (i == index) { + res->start = res->end = fdtdec_get_number(ptr, na); + res->end += fdtdec_get_number(&ptr[na], ns) - 1; + return 0; + } + + ptr += na + ns; + i++; + } + + return -FDT_ERR_NOTFOUND; +} + +int fdt_get_named_resource(const void *fdt, int node, const char *property, + const char *prop_names, const char *name, + struct fdt_resource *res) +{ + int index; + + index = fdt_find_string(fdt, node, prop_names, name); + if (index < 0) + return index; + + return fdt_get_resource(fdt, node, property, index, res); +} + +int fdtdec_pci_get_bdf(const void *fdt, int node, int *bdf) +{ + const fdt32_t *prop; + int len; + + prop = fdt_getprop(fdt, node, "reg", &len); + if (!prop) + return len; + + *bdf = fdt32_to_cpu(*prop) & 0xffffff; + + return 0; +} #endif diff --git a/lib/initcall.c b/lib/initcall.c index 7597bad555..39f4b3f8ad 100644 --- a/lib/initcall.c +++ b/lib/initcall.c @@ -15,14 +15,16 @@ int initcall_run_list(const init_fnc_t init_sequence[]) for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) { unsigned long reloc_ofs = 0; + int ret; if (gd->flags & GD_FLG_RELOC) reloc_ofs = gd->reloc_off; debug("initcall: %p\n", (char *)*init_fnc_ptr - reloc_ofs); - if ((*init_fnc_ptr)()) { - printf("initcall sequence %p failed at call %p\n", + ret = (*init_fnc_ptr)(); + if (ret) { + printf("initcall sequence %p failed at call %p (err=%d)\n", init_sequence, - (char *)*init_fnc_ptr - reloc_ofs); + (char *)*init_fnc_ptr - reloc_ofs, ret); return -1; } } diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c index 36af043525..03733e574f 100644 --- a/lib/libfdt/fdt_ro.c +++ b/lib/libfdt/fdt_ro.c @@ -491,6 +491,82 @@ 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 length, i, count = 0; + const char *list; + + list = fdt_getprop(fdt, node, property, &length); + if (!list) + return -length; + + for (i = 0; i < length; i++) { + int len = strlen(list); + + list += len + 1; + i += len; + count++; + } + + return count; +} + +int fdt_find_string(const void *fdt, int node, const char *property, + const char *string) +{ + const char *list, *end; + int len, index = 0; + + list = fdt_getprop(fdt, node, property, &len); + if (!list) + return len; + + end = list + len; + len = strlen(string); + + while (list < end) { + int l = strlen(list); + + if (l == len && memcmp(list, string, len) == 0) + return index; + + list += l + 1; + index++; + } + + return -FDT_ERR_NOTFOUND; +} + +int fdt_get_string_index(const void *fdt, int node, const char *property, + int index, const char **output) +{ + const char *list; + int length, i; + + list = fdt_getprop(fdt, node, property, &length); + + for (i = 0; i < length; i++) { + int len = strlen(list); + + if (index == 0) { + *output = list; + return 0; + } + + list += len + 1; + i += len; + index--; + } + + return 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); +} + int fdt_node_check_compatible(const void *fdt, int nodeoffset, const char *compatible) { |