aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorTom Rini2015-09-16 09:53:37 -0400
committerTom Rini2015-09-16 09:53:37 -0400
commitfa43ce842c3026c2abf19d4234d02cd4c62eeec0 (patch)
tree39ec6c77155553eb1865ac67504dd8502cebaff8 /lib
parent2fc1c80edefddd72b91be5fcfae0a6cb8e3f597c (diff)
parent02464e386bb5f0a022c121f95ae75cf583759d95 (diff)
Merge git://git.denx.de/u-boot-fdt
Diffstat (limited to 'lib')
-rw-r--r--lib/fdtdec.c114
1 files changed, 93 insertions, 21 deletions
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 5770094fbfa..9f0b65de383 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -86,32 +86,104 @@ const char *fdtdec_get_compatible(enum fdt_compat_id id)
return compat_names[id];
}
-fdt_addr_t fdtdec_get_addr_size(const void *blob, int node,
- const char *prop_name, fdt_size_t *sizep)
+fdt_addr_t fdtdec_get_addr_size_fixed(const void *blob, int node,
+ const char *prop_name, int index, int na, int ns,
+ fdt_size_t *sizep)
{
- const fdt_addr_t *cell;
+ const fdt32_t *prop, *prop_end;
+ const fdt32_t *prop_addr, *prop_size, *prop_after_size;
int len;
+ fdt_addr_t addr;
debug("%s: %s: ", __func__, prop_name);
- cell = fdt_getprop(blob, node, prop_name, &len);
- if (cell && ((!sizep && len == sizeof(fdt_addr_t)) ||
- len == sizeof(fdt_addr_t) * 2)) {
- fdt_addr_t addr = fdt_addr_to_cpu(*cell);
- if (sizep) {
- const fdt_size_t *size;
-
- size = (fdt_size_t *)((char *)cell +
- sizeof(fdt_addr_t));
- *sizep = fdt_size_to_cpu(*size);
- debug("addr=%08lx, size=%llx\n",
- (ulong)addr, (u64)*sizep);
- } else {
- debug("%08lx\n", (ulong)addr);
- }
- return addr;
+
+ if (na > (sizeof(fdt_addr_t) / sizeof(fdt32_t))) {
+ debug("(na too large for fdt_addr_t type)\n");
+ return FDT_ADDR_T_NONE;
}
- debug("(not found)\n");
- return FDT_ADDR_T_NONE;
+
+ if (ns > (sizeof(fdt_size_t) / sizeof(fdt32_t))) {
+ debug("(ns too large for fdt_size_t type)\n");
+ return FDT_ADDR_T_NONE;
+ }
+
+ prop = fdt_getprop(blob, node, prop_name, &len);
+ if (!prop) {
+ debug("(not found)\n");
+ return FDT_ADDR_T_NONE;
+ }
+ prop_end = prop + (len / sizeof(*prop));
+
+ prop_addr = prop + (index * (na + ns));
+ prop_size = prop_addr + na;
+ prop_after_size = prop_size + ns;
+ if (prop_after_size > prop_end) {
+ debug("(not enough data: expected >= %d cells, got %d cells)\n",
+ (u32)(prop_after_size - prop), ((u32)(prop_end - prop)));
+ return FDT_ADDR_T_NONE;
+ }
+
+ addr = fdtdec_get_number(prop_addr, na);
+
+ if (sizep) {
+ *sizep = fdtdec_get_number(prop_size, ns);
+ debug("addr=%08llx, size=%llx\n", (u64)addr, (u64)*sizep);
+ } else {
+ debug("addr=%08llx\n", (u64)addr);
+ }
+
+ return addr;
+}
+
+fdt_addr_t fdtdec_get_addr_size_auto_parent(const void *blob, int parent,
+ int node, const char *prop_name, int index, fdt_size_t *sizep)
+{
+ int na, ns;
+
+ debug("%s: ", __func__);
+
+ na = fdt_address_cells(blob, parent);
+ if (na < 1) {
+ debug("(bad #address-cells)\n");
+ return FDT_ADDR_T_NONE;
+ }
+
+ ns = fdt_size_cells(blob, parent);
+ if (ns < 1) {
+ debug("(bad #size-cells)\n");
+ return FDT_ADDR_T_NONE;
+ }
+
+ debug("na=%d, ns=%d, ", na, ns);
+
+ return fdtdec_get_addr_size_fixed(blob, node, prop_name, index, na,
+ ns, sizep);
+}
+
+fdt_addr_t fdtdec_get_addr_size_auto_noparent(const void *blob, int node,
+ const char *prop_name, int index, fdt_size_t *sizep)
+{
+ int parent;
+
+ debug("%s: ", __func__);
+
+ parent = fdt_parent_offset(blob, node);
+ if (parent < 0) {
+ debug("(no parent found)\n");
+ return FDT_ADDR_T_NONE;
+ }
+
+ return fdtdec_get_addr_size_auto_parent(blob, parent, node, prop_name,
+ index, sizep);
+}
+
+fdt_addr_t fdtdec_get_addr_size(const void *blob, int node,
+ const char *prop_name, fdt_size_t *sizep)
+{
+ return fdtdec_get_addr_size_fixed(blob, node, prop_name, 0,
+ sizeof(fdt_addr_t) / sizeof(fdt32_t),
+ sizeof(fdt_size_t) / sizeof(fdt32_t),
+ sizep);
}
fdt_addr_t fdtdec_get_addr(const void *blob, int node,