diff options
author | Thierry Reding <treding@nvidia.com> | 2015-07-23 10:51:30 -0600 |
---|---|---|
committer | Tom Warren <twarren@nvidia.com> | 2015-07-28 10:30:17 -0700 |
commit | 5b34436035fc862b5e8d0d2c3eab74ba36f1a7f4 (patch) | |
tree | 0b7c81645f7fbad38614f5a0723715d56a229d9c | |
parent | 8b19dff579759719b83a3dcbeefecd774077dc08 (diff) | |
download | u-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.c | 56 |
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, |