]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - libfdt/fdt_ro.c
ppc/85xx: Fix enabling of L2 cache
[karo-tx-uboot.git] / libfdt / fdt_ro.c
index 8382afd38835c674702889caf0833815c55de38e..1e1e32209ce71d3087941bde94381f30932c7b23 100644 (file)
@@ -59,8 +59,8 @@
 
 #include "libfdt_internal.h"
 
-static int nodename_eq(const void *fdt, int offset,
-                      const char *s, int len)
+static int _fdt_nodename_eq(const void *fdt, int offset,
+                           const char *s, int len)
 {
        const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1);
 
@@ -81,12 +81,20 @@ static int nodename_eq(const void *fdt, int offset,
 
 const char *fdt_string(const void *fdt, int stroffset)
 {
-       return (char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
+       return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
+}
+
+static int _fdt_string_eq(const void *fdt, int stroffset,
+                         const char *s, int len)
+{
+       const char *p = fdt_string(fdt, stroffset);
+
+       return (strlen(p) == len) && (memcmp(p, s, len) == 0);
 }
 
 int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
 {
-       CHECK_HEADER(fdt);
+       FDT_CHECK_HEADER(fdt);
        *address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address);
        *size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size);
        return 0;
@@ -106,18 +114,17 @@ int fdt_subnode_offset_namelen(const void *fdt, int offset,
 {
        int depth;
 
-       CHECK_HEADER(fdt);
+       FDT_CHECK_HEADER(fdt);
 
        for (depth = 0;
-            offset >= 0;
-            offset = fdt_next_node(fdt, offset, &depth)) {
-               if (depth < 0)
-                       return -FDT_ERR_NOTFOUND;
-               else if ((depth == 1)
-                        && nodename_eq(fdt, offset, name, namelen))
+            (offset >= 0) && (depth >= 0);
+            offset = fdt_next_node(fdt, offset, &depth))
+               if ((depth == 1)
+                   && _fdt_nodename_eq(fdt, offset, name, namelen))
                        return offset;
-       }
 
+       if (depth < 0)
+               return -FDT_ERR_NOTFOUND;
        return offset; /* error */
 }
 
@@ -133,10 +140,22 @@ int fdt_path_offset(const void *fdt, const char *path)
        const char *p = path;
        int offset = 0;
 
-       CHECK_HEADER(fdt);
+       FDT_CHECK_HEADER(fdt);
+
+       /* see if we have an alias */
+       if (*path != '/') {
+               const char *q = strchr(path, '/');
 
-       if (*path != '/')
-               return -FDT_ERR_BADPATH;
+               if (!q)
+                       q = end;
+
+               p = fdt_get_alias_namelen(fdt, p, q - p);
+               if (!p)
+                       return -FDT_ERR_BADPATH;
+               offset = fdt_path_offset(fdt, p);
+
+               p = q;
+       }
 
        while (*p) {
                const char *q;
@@ -179,13 +198,13 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
        return NULL;
 }
 
-const struct fdt_property *fdt_get_property(const void *fdt,
-                                           int nodeoffset,
-                                           const char *name, int *lenp)
+const struct fdt_property *fdt_get_property_namelen(const void *fdt,
+                                                   int nodeoffset,
+                                                   const char *name,
+                                                   int namelen, int *lenp)
 {
        uint32_t tag;
        const struct fdt_property *prop;
-       int namestroff;
        int offset, nextoffset;
        int err;
 
@@ -200,38 +219,24 @@ const struct fdt_property *fdt_get_property(const void *fdt,
                tag = fdt_next_tag(fdt, offset, &nextoffset);
                switch (tag) {
                case FDT_END:
-                       err = -FDT_ERR_TRUNCATED;
+                       if (nextoffset < 0)
+                               err = nextoffset;
+                       else
+                               /* FDT_END tag with unclosed nodes */
+                               err = -FDT_ERR_BADSTRUCTURE;
                        goto fail;
 
-               case FDT_BEGIN_NODE:
-               case FDT_END_NODE:
-               case FDT_NOP:
-                       break;
-
                case FDT_PROP:
-                       err = -FDT_ERR_BADSTRUCTURE;
-                       prop = fdt_offset_ptr(fdt, offset, sizeof(*prop));
-                       if (! prop)
-                               goto fail;
-                       namestroff = fdt32_to_cpu(prop->nameoff);
-                       if (streq(fdt_string(fdt, namestroff), name)) {
+                       prop = _fdt_offset_ptr(fdt, offset);
+                       if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff),
+                                          name, namelen)) {
                                /* Found it! */
-                               int len = fdt32_to_cpu(prop->len);
-                               prop = fdt_offset_ptr(fdt, offset,
-                                                     sizeof(*prop)+len);
-                               if (! prop)
-                                       goto fail;
-
                                if (lenp)
-                                       *lenp = len;
+                                       *lenp = fdt32_to_cpu(prop->len);
 
                                return prop;
                        }
                        break;
-
-               default:
-                       err = -FDT_ERR_BADSTRUCTURE;
-                       goto fail;
                }
        } while ((tag != FDT_BEGIN_NODE) && (tag != FDT_END_NODE));
 
@@ -242,18 +247,32 @@ const struct fdt_property *fdt_get_property(const void *fdt,
        return NULL;
 }
 
-const void *fdt_getprop(const void *fdt, int nodeoffset,
-                 const char *name, int *lenp)
+const struct fdt_property *fdt_get_property(const void *fdt,
+                                           int nodeoffset,
+                                           const char *name, int *lenp)
+{
+       return fdt_get_property_namelen(fdt, nodeoffset, name,
+                                       strlen(name), lenp);
+}
+
+const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
+                               const char *name, int namelen, int *lenp)
 {
        const struct fdt_property *prop;
 
-       prop = fdt_get_property(fdt, nodeoffset, name, lenp);
+       prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp);
        if (! prop)
                return NULL;
 
        return prop->data;
 }
 
+const void *fdt_getprop(const void *fdt, int nodeoffset,
+                       const char *name, int *lenp)
+{
+       return fdt_getprop_namelen(fdt, nodeoffset, name, strlen(name), lenp);
+}
+
 uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
 {
        const uint32_t *php;
@@ -266,13 +285,30 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
        return fdt32_to_cpu(*php);
 }
 
+const char *fdt_get_alias_namelen(const void *fdt,
+                                 const char *name, int namelen)
+{
+       int aliasoffset;
+
+       aliasoffset = fdt_path_offset(fdt, "/aliases");
+       if (aliasoffset < 0)
+               return NULL;
+
+       return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL);
+}
+
+const char *fdt_get_alias(const void *fdt, const char *name)
+{
+       return fdt_get_alias_namelen(fdt, name, strlen(name));
+}
+
 int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
 {
        int pdepth = 0, p = 0;
        int offset, depth, namelen;
        const char *name;
 
-       CHECK_HEADER(fdt);
+       FDT_CHECK_HEADER(fdt);
 
        if (buflen < 2)
                return -FDT_ERR_NOSPACE;
@@ -280,9 +316,6 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
        for (offset = 0, depth = 0;
             (offset >= 0) && (offset <= nodeoffset);
             offset = fdt_next_node(fdt, offset, &depth)) {
-               if (pdepth < depth)
-                       continue; /* overflowed buffer */
-
                while (pdepth > depth) {
                        do {
                                p--;
@@ -290,14 +323,16 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
                        pdepth--;
                }
 
-               name = fdt_get_name(fdt, offset, &namelen);
-               if (!name)
-                       return namelen;
-               if ((p + namelen + 1) <= buflen) {
-                       memcpy(buf + p, name, namelen);
-                       p += namelen;
-                       buf[p++] = '/';
-                       pdepth++;
+               if (pdepth >= depth) {
+                       name = fdt_get_name(fdt, offset, &namelen);
+                       if (!name)
+                               return namelen;
+                       if ((p + namelen + 1) <= buflen) {
+                               memcpy(buf + p, name, namelen);
+                               p += namelen;
+                               buf[p++] = '/';
+                               pdepth++;
+                       }
                }
 
                if (offset == nodeoffset) {
@@ -307,7 +342,7 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
                        if (p > 1) /* special case so that root path is "/", not "" */
                                p--;
                        buf[p] = '\0';
-                       return p;
+                       return 0;
                }
        }
 
@@ -325,7 +360,7 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
        int offset, depth;
        int supernodeoffset = -FDT_ERR_INTERNAL;
 
-       CHECK_HEADER(fdt);
+       FDT_CHECK_HEADER(fdt);
 
        if (supernodedepth < 0)
                return -FDT_ERR_NOTFOUND;
@@ -384,7 +419,7 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
        const void *val;
        int len;
 
-       CHECK_HEADER(fdt);
+       FDT_CHECK_HEADER(fdt);
 
        /* FIXME: The algorithm here is pretty horrible: we scan each
         * property of a node in fdt_getprop(), then if that didn't
@@ -412,7 +447,8 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
                                             &phandle, sizeof(phandle));
 }
 
-int _stringlist_contains(const char *strlist, int listlen, const char *str)
+static int _fdt_stringlist_contains(const char *strlist, int listlen,
+                                   const char *str)
 {
        int len = strlen(str);
        const char *p;
@@ -438,7 +474,7 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset,
        prop = fdt_getprop(fdt, nodeoffset, "compatible", &len);
        if (!prop)
                return len;
-       if (_stringlist_contains(prop, len, compatible))
+       if (_fdt_stringlist_contains(prop, len, compatible))
                return 0;
        else
                return 1;
@@ -449,7 +485,7 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
 {
        int offset, err;
 
-       CHECK_HEADER(fdt);
+       FDT_CHECK_HEADER(fdt);
 
        /* FIXME: The algorithm here is pretty horrible: we scan each
         * property of a node in fdt_node_check_compatible(), then if