[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[UNIKRAFT PATCH RFCv2 15/27] lib/fdt: Fix fdt_address_cell and fdt_size_cell



The address-cell and size_cell should be probed from parent.

Signed-off-by: Jia He <justin.he@xxxxxxx>
---
 lib/fdt/fdt_addresses.c | 57 ++++++++++++++++++++++-------------------
 plat/drivers/ofw/fdt.c  |  7 +++--
 2 files changed, 34 insertions(+), 30 deletions(-)

diff --git a/lib/fdt/fdt_addresses.c b/lib/fdt/fdt_addresses.c
index a1860e6..736858a 100644
--- a/lib/fdt/fdt_addresses.c
+++ b/lib/fdt/fdt_addresses.c
@@ -55,42 +55,47 @@
 
 #include "libfdt_internal.h"
 
+#define OFW_ROOT_NODE_ADDR_CELLS_DEFAULT 2
+#define OFW_ROOT_NODE_SIZE_CELLS_DEFAULT 1
+
 int fdt_address_cells(const void *fdt, int nodeoffset)
 {
-       const fdt32_t *ac;
-       int val;
-       int len;
-
-       ac = fdt_getprop(fdt, nodeoffset, "#address-cells", &len);
-       if (!ac)
-               return 2;
+       int cells;
+       int parent;
+       int off = nodeoffset;
+       const fdt32_t *prop;
 
-       if (len != sizeof(*ac))
-               return -FDT_ERR_BADNCELLS;
+       do {
+               parent = fdt_parent_offset(fdt, off);
+               if (parent >= 0)
+                       off = parent;
 
-       val = fdt32_to_cpu(*ac);
-       if ((val <= 0) || (val > FDT_MAX_NCELLS))
-               return -FDT_ERR_BADNCELLS;
+               prop = fdt_getprop(fdt, off, "#address-cells", &cells);
+               if (prop != NULL)
+                       return fdt32_to_cpu(prop[0]);
+       } while (parent >= 0);
 
-       return val;
+       /* No #address-cells property for the root node */
+       return OFW_ROOT_NODE_ADDR_CELLS_DEFAULT;
 }
 
 int fdt_size_cells(const void *fdt, int nodeoffset)
 {
-       const fdt32_t *sc;
-       int val;
-       int len;
-
-       sc = fdt_getprop(fdt, nodeoffset, "#size-cells", &len);
-       if (!sc)
-               return 1;
+       int cells;
+       int parent;
+       int off = nodeoffset;
+       const fdt32_t *prop;
 
-       if (len != sizeof(*sc))
-               return -FDT_ERR_BADNCELLS;
+       do {
+               parent = fdt_parent_offset(fdt, off);
+               if (parent >= 0)
+                       off = parent;
 
-       val = fdt32_to_cpu(*sc);
-       if ((val < 0) || (val > FDT_MAX_NCELLS))
-               return -FDT_ERR_BADNCELLS;
+               prop = fdt_getprop(fdt, off, "#size-cells", &cells);
+               if (prop != NULL)
+                       return fdt32_to_cpu(prop[0]);
+       } while (parent >= 0);
 
-       return val;
+       /* No #size-cells property for the root node */
+       return OFW_ROOT_NODE_SIZE_CELLS_DEFAULT;
 }
diff --git a/plat/drivers/ofw/fdt.c b/plat/drivers/ofw/fdt.c
index 780b8dd..876637d 100644
--- a/plat/drivers/ofw/fdt.c
+++ b/plat/drivers/ofw/fdt.c
@@ -234,7 +234,7 @@ bail:
 int fdt_get_address(const void *fdt, int nodeoffset, uint32_t index,
                        uint64_t *addr, uint64_t *size)
 {
-       int parent;
+       int off = nodeoffset;
        int len, prop_addr, prop_size;
        int naddr, nsize, term_size;
        const void *regs;
@@ -242,12 +242,11 @@ int fdt_get_address(const void *fdt, int nodeoffset, 
uint32_t index,
        UK_ASSERT(addr && size);
 
        /* Get address,size cell from parent */
-       parent = fdt_parent_offset(fdt, nodeoffset);
-       naddr = fdt_address_cells(fdt, parent);
+       naddr = fdt_address_cells(fdt, off);
        if (naddr < 0 || naddr >= FDT_MAX_NCELLS)
                return naddr;
 
-       nsize = fdt_size_cells(fdt, parent);
+       nsize = fdt_size_cells(fdt, off);
        if (nsize < 0 || nsize >= FDT_MAX_NCELLS)
                return nsize;
 
-- 
2.17.1




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.