summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2015-07-23 10:51:30 -0600
committerTom Warren <twarren@nvidia.com>2015-07-28 10:30:17 -0700
commit5b34436035fc862b5e8d0d2c3eab74ba36f1a7f4 (patch)
tree0b7c81645f7fbad38614f5a0723715d56a229d9c
parent8b19dff579759719b83a3dcbeefecd774077dc08 (diff)
downloadu-boot-imx-5b34436035fc862b5e8d0d2c3eab74ba36f1a7f4.zip
u-boot-imx-5b34436035fc862b5e8d0d2c3eab74ba36f1a7f4.tar.gz
u-boot-imx-5b34436035fc862b5e8d0d2c3eab74ba36f1a7f4.tar.bz2
fdt: Fix fdtdec_get_addr_size() for 64-bit
Signed-off-by: Thierry Reding <treding@nvidia.com> Signed-off-by: Tom Warren <twarren@nvidia.com> Signed-off-by: Stephen Warren <swarren@nvidia.com>
-rw-r--r--lib/fdtdec.c56
1 files changed, 36 insertions, 20 deletions
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 232ca74..00c7e6d 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -88,29 +88,45 @@ const char *fdtdec_get_compatible(enum fdt_compat_id id)
fdt_addr_t fdtdec_get_addr_size(const void *blob, int node,
const char *prop_name, fdt_size_t *sizep)
{
- const fdt_addr_t *cell;
- int len;
+ const fdt32_t *ptr, *end;
+ int parent, na, ns, 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;
+
+ parent = fdt_parent_offset(blob, node);
+ if (parent < 0) {
+ debug("(no parent found)\n");
+ return FDT_ADDR_T_NONE;
}
- debug("(not found)\n");
- return FDT_ADDR_T_NONE;
+
+ na = fdt_address_cells(blob, parent);
+ ns = fdt_size_cells(blob, parent);
+
+ ptr = fdt_getprop(blob, node, prop_name, &len);
+ if (!ptr) {
+ debug("(not found)\n");
+ return FDT_ADDR_T_NONE;
+ }
+
+ end = ptr + len / sizeof(*ptr);
+
+ if (ptr + na + ns > end) {
+ debug("(not enough data: expected %d bytes, got %d bytes)\n",
+ (na + ns) * 4, len);
+ return FDT_ADDR_T_NONE;
+ }
+
+ addr = fdtdec_get_number(ptr, na);
+
+ if (sizep) {
+ *sizep = fdtdec_get_number(ptr + na, ns);
+ debug("addr=%pa, size=%pa\n", &addr, sizep);
+ } else {
+ debug("%pa\n", &addr);
+ }
+
+ return addr;
}
fdt_addr_t fdtdec_get_addr(const void *blob, int node,