fdt: Fix fdtdec_get_addr_size() for 64-bit
authorThierry Reding <treding@nvidia.com>
Thu, 23 Jul 2015 16:51:30 +0000 (10:51 -0600)
committerTom Warren <twarren@nvidia.com>
Tue, 28 Jul 2015 17:30:17 +0000 (10:30 -0700)
Signed-off-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Tom Warren <twarren@nvidia.com>
Signed-off-by: Stephen Warren <swarren@nvidia.com>
lib/fdtdec.c

index 232ca7471215aa08e47fd52b7b9d472b57f25cb7..00c7e6dba1140a8501a6b9395487f8935e85696a 100644 (file)
@@ -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,