]> 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 63fa1290be2bd5433f63e8bddb0007c1f3b77777..1e1e32209ce71d3087941bde94381f30932c7b23 100644 (file)
  */
 #include "libfdt_env.h"
 
+#ifndef USE_HOSTCC
 #include <fdt.h>
 #include <libfdt.h>
+#else
+#include "fdt_host.h"
+#endif
 
 #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);
 
@@ -77,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;
@@ -102,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 */
 }
 
@@ -129,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 (!q)
+                       q = end;
+
+               p = fdt_get_alias_namelen(fdt, p, q - p);
+               if (!p)
+                       return -FDT_ERR_BADPATH;
+               offset = fdt_path_offset(fdt, p);
 
-       if (*path != '/')
-               return -FDT_ERR_BADPATH;
+               p = q;
+       }
 
        while (*p) {
                const char *q;
@@ -157,16 +180,12 @@ int fdt_path_offset(const void *fdt, const char *path)
 
 const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
 {
-       const struct fdt_node_header *nh;
+       const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset);
        int err;
 
-       if ((err = fdt_check_header(fdt)) != 0)
-               goto fail;
-
-       err = -FDT_ERR_BADOFFSET;
-       nh = fdt_offset_ptr(fdt, nodeoffset, sizeof(*nh));
-       if (!nh || (fdt32_to_cpu(nh->tag) != FDT_BEGIN_NODE))
-               goto fail;
+       if (((err = fdt_check_header(fdt)) != 0)
+           || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0))
+                       goto fail;
 
        if (len)
                *len = strlen(nh->name);
@@ -179,65 +198,45 @@ 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;
 
-       if ((err = fdt_check_header(fdt)) != 0)
-               goto fail;
-
-       err = -FDT_ERR_BADOFFSET;
-       if (nodeoffset % FDT_TAGSIZE)
-               goto fail;
-
-       tag = fdt_next_tag(fdt, nodeoffset, &nextoffset);
-       if (tag != FDT_BEGIN_NODE)
-               goto fail;
+       if (((err = fdt_check_header(fdt)) != 0)
+           || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0))
+                       goto fail;
 
+       nextoffset = err;
        do {
                offset = nextoffset;
 
                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));
 
@@ -248,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;
@@ -272,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;
@@ -286,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--;
@@ -296,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) {
@@ -313,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;
                }
        }
 
@@ -331,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;
@@ -390,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
@@ -418,10 +447,11 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
                                             &phandle, sizeof(phandle));
 }
 
-int _stringlist_contains(const void *strlist, int listlen, const char *str)
+static int _fdt_stringlist_contains(const char *strlist, int listlen,
+                                   const char *str)
 {
        int len = strlen(str);
-       const void *p;
+       const char *p;
 
        while (listlen >= len) {
                if (memcmp(str, strlist, len+1) == 0)
@@ -444,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;
@@ -455,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