\r
#include "libfdt_internal.h"\r
\r
-static int _fdt_nodename_eq(const void *fdt, int offset,\r
- const char *s, int len)\r
+static int\r
+_fdt_nodename_eq (\r
+ const void *fdt,\r
+ int offset,\r
+ const char *s,\r
+ int len\r
+ )\r
{\r
- const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1);\r
+ const char *p = fdt_offset_ptr (fdt, offset + FDT_TAGSIZE, len+1);\r
\r
- if (!p)\r
- /* short match */\r
- return 0;\r
+ if (!p) {\r
+ /* short match */\r
+ return 0;\r
+ }\r
\r
- if (memcmp(p, s, len) != 0)\r
- return 0;\r
+ if (memcmp (p, s, len) != 0) {\r
+ return 0;\r
+ }\r
\r
- if (p[len] == '\0')\r
- return 1;\r
- else if (!memchr(s, '@', len) && (p[len] == '@'))\r
- return 1;\r
- else\r
- return 0;\r
+ if (p[len] == '\0') {\r
+ return 1;\r
+ } else if (!memchr (s, '@', len) && (p[len] == '@')) {\r
+ return 1;\r
+ } else {\r
+ return 0;\r
+ }\r
}\r
\r
-const char *fdt_string(const void *fdt, int stroffset)\r
+const char *\r
+fdt_string (\r
+ const void *fdt,\r
+ int stroffset\r
+ )\r
{\r
- return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;\r
+ return (const char *)fdt + fdt_off_dt_strings (fdt) + stroffset;\r
}\r
\r
-static int _fdt_string_eq(const void *fdt, int stroffset,\r
- const char *s, int len)\r
+static int\r
+_fdt_string_eq (\r
+ const void *fdt,\r
+ int stroffset,\r
+ const char *s,\r
+ int len\r
+ )\r
{\r
- const char *p = fdt_string(fdt, stroffset);\r
+ const char *p = fdt_string (fdt, stroffset);\r
\r
- return (strlen(p) == len) && (memcmp(p, s, len) == 0);\r
+ return (strlen (p) == len) && (memcmp (p, s, len) == 0);\r
}\r
\r
-uint32_t fdt_get_max_phandle(const void *fdt)\r
+uint32_t\r
+fdt_get_max_phandle (\r
+ const void *fdt\r
+ )\r
{\r
- uint32_t max_phandle = 0;\r
- int offset;\r
+ uint32_t max_phandle = 0;\r
+ int offset;\r
\r
- for (offset = fdt_next_node(fdt, -1, NULL);;\r
- offset = fdt_next_node(fdt, offset, NULL)) {\r
- uint32_t phandle;\r
+ for (offset = fdt_next_node (fdt, -1, NULL); ;\r
+ offset = fdt_next_node (fdt, offset, NULL))\r
+ {\r
+ uint32_t phandle;\r
\r
- if (offset == -FDT_ERR_NOTFOUND)\r
- return max_phandle;\r
+ if (offset == -FDT_ERR_NOTFOUND) {\r
+ return max_phandle;\r
+ }\r
\r
- if (offset < 0)\r
- return (uint32_t)-1;\r
+ if (offset < 0) {\r
+ return (uint32_t)-1;\r
+ }\r
\r
- phandle = fdt_get_phandle(fdt, offset);\r
- if (phandle == (uint32_t)-1)\r
- continue;\r
+ phandle = fdt_get_phandle (fdt, offset);\r
+ if (phandle == (uint32_t)-1) {\r
+ continue;\r
+ }\r
\r
- if (phandle > max_phandle)\r
- max_phandle = phandle;\r
- }\r
+ if (phandle > max_phandle) {\r
+ max_phandle = phandle;\r
+ }\r
+ }\r
\r
- return 0;\r
+ return 0;\r
}\r
\r
-int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)\r
+int\r
+fdt_get_mem_rsv (\r
+ const void *fdt,\r
+ int n,\r
+ uint64_t *address,\r
+ uint64_t *size\r
+ )\r
{\r
- FDT_CHECK_HEADER(fdt);\r
- *address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address);\r
- *size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size);\r
- return 0;\r
+ FDT_CHECK_HEADER (fdt);\r
+ *address = fdt64_to_cpu (_fdt_mem_rsv (fdt, n)->address);\r
+ *size = fdt64_to_cpu (_fdt_mem_rsv (fdt, n)->size);\r
+ return 0;\r
}\r
\r
-int fdt_num_mem_rsv(const void *fdt)\r
+int\r
+fdt_num_mem_rsv (\r
+ const void *fdt\r
+ )\r
{\r
- int i = 0;\r
+ int i = 0;\r
\r
- while (fdt64_to_cpu(_fdt_mem_rsv(fdt, i)->size) != 0)\r
- i++;\r
- return i;\r
-}\r
-\r
-static int _nextprop(const void *fdt, int offset)\r
-{\r
- uint32_t tag;\r
- int nextoffset;\r
-\r
- do {\r
- tag = fdt_next_tag(fdt, offset, &nextoffset);\r
-\r
- switch (tag) {\r
- case FDT_END:\r
- if (nextoffset >= 0)\r
- return -FDT_ERR_BADSTRUCTURE;\r
- else\r
- return nextoffset;\r
+ while (fdt64_to_cpu (_fdt_mem_rsv (fdt, i)->size) != 0) {\r
+ i++;\r
+ }\r
\r
- case FDT_PROP:\r
- return offset;\r
- }\r
- offset = nextoffset;\r
- } while (tag == FDT_NOP);\r
-\r
- return -FDT_ERR_NOTFOUND;\r
+ return i;\r
}\r
\r
-int fdt_subnode_offset_namelen(const void *fdt, int offset,\r
- const char *name, int namelen)\r
+static int\r
+_nextprop (\r
+ const void *fdt,\r
+ int offset\r
+ )\r
{\r
- int depth;\r
-\r
- FDT_CHECK_HEADER(fdt);\r
-\r
- for (depth = 0;\r
- (offset >= 0) && (depth >= 0);\r
- offset = fdt_next_node(fdt, offset, &depth))\r
- if ((depth == 1)\r
- && _fdt_nodename_eq(fdt, offset, name, namelen))\r
- return offset;\r
-\r
- if (depth < 0)\r
- return -FDT_ERR_NOTFOUND;\r
- return offset; /* error */\r
-}\r
-\r
-int fdt_subnode_offset(const void *fdt, int parentoffset,\r
- const char *name)\r
-{\r
- return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name));\r
-}\r
-\r
-int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen)\r
-{\r
- const char *end = path + namelen;\r
- const char *p = path;\r
- int offset = 0;\r
-\r
- FDT_CHECK_HEADER(fdt);\r
-\r
- /* see if we have an alias */\r
- if (*path != '/') {\r
- const char *q = memchr(path, '/', end - p);\r
+ uint32_t tag;\r
+ int nextoffset;\r
\r
- if (!q)\r
- q = end;\r
+ do {\r
+ tag = fdt_next_tag (fdt, offset, &nextoffset);\r
\r
- p = fdt_get_alias_namelen(fdt, p, q - p);\r
- if (!p)\r
- return -FDT_ERR_BADPATH;\r
- offset = fdt_path_offset(fdt, p);\r
+ switch (tag) {\r
+ case FDT_END:\r
+ if (nextoffset >= 0) {\r
+ return -FDT_ERR_BADSTRUCTURE;\r
+ } else {\r
+ return nextoffset;\r
+ }\r
\r
- p = q;\r
- }\r
+ case FDT_PROP:\r
+ return offset;\r
+ }\r
\r
- while (p < end) {\r
- const char *q;\r
+ offset = nextoffset;\r
+ } while (tag == FDT_NOP);\r
\r
- while (*p == '/') {\r
- p++;\r
- if (p == end)\r
- return offset;\r
- }\r
- q = memchr(p, '/', end - p);\r
- if (! q)\r
- q = end;\r
-\r
- offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p);\r
- if (offset < 0)\r
- return offset;\r
-\r
- p = q;\r
- }\r
-\r
- return offset;\r
+ return -FDT_ERR_NOTFOUND;\r
}\r
\r
-int fdt_path_offset(const void *fdt, const char *path)\r
+int\r
+fdt_subnode_offset_namelen (\r
+ const void *fdt,\r
+ int offset,\r
+ const char *name,\r
+ int namelen\r
+ )\r
{\r
- return fdt_path_offset_namelen(fdt, path, strlen(path));\r
-}\r
+ int depth;\r
\r
-const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)\r
-{\r
- const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset);\r
- int err;\r
+ FDT_CHECK_HEADER (fdt);\r
\r
- if (((err = fdt_check_header(fdt)) != 0)\r
- || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0))\r
- goto fail;\r
+ for (depth = 0;\r
+ (offset >= 0) && (depth >= 0);\r
+ offset = fdt_next_node (fdt, offset, &depth))\r
+ {\r
+ if ( (depth == 1)\r
+ && _fdt_nodename_eq (fdt, offset, name, namelen))\r
+ {\r
+ return offset;\r
+ }\r
+ }\r
\r
- if (len)\r
- *len = strlen(nh->name);\r
+ if (depth < 0) {\r
+ return -FDT_ERR_NOTFOUND;\r
+ }\r
\r
- return nh->name;\r
-\r
- fail:\r
- if (len)\r
- *len = err;\r
- return NULL;\r
+ return offset; /* error */\r
}\r
\r
-int fdt_first_property_offset(const void *fdt, int nodeoffset)\r
+int\r
+fdt_subnode_offset (\r
+ const void *fdt,\r
+ int parentoffset,\r
+ const char *name\r
+ )\r
{\r
- int offset;\r
-\r
- if ((offset = _fdt_check_node_offset(fdt, nodeoffset)) < 0)\r
- return offset;\r
-\r
- return _nextprop(fdt, offset);\r
+ return fdt_subnode_offset_namelen (fdt, parentoffset, name, strlen (name));\r
}\r
\r
-int fdt_next_property_offset(const void *fdt, int offset)\r
+int\r
+fdt_path_offset_namelen (\r
+ const void *fdt,\r
+ const char *path,\r
+ int namelen\r
+ )\r
{\r
- if ((offset = _fdt_check_prop_offset(fdt, offset)) < 0)\r
- return offset;\r
+ const char *end = path + namelen;\r
+ const char *p = path;\r
+ int offset = 0;\r
\r
- return _nextprop(fdt, offset);\r
-}\r
+ FDT_CHECK_HEADER (fdt);\r
\r
-const struct fdt_property *fdt_get_property_by_offset(const void *fdt,\r
- int offset,\r
- int *lenp)\r
-{\r
- int err;\r
- const struct fdt_property *prop;\r
-\r
- if ((err = _fdt_check_prop_offset(fdt, offset)) < 0) {\r
- if (lenp)\r
- *lenp = err;\r
- return NULL;\r
- }\r
+ /* see if we have an alias */\r
+ if (*path != '/') {\r
+ const char *q = memchr (path, '/', end - p);\r
\r
- prop = _fdt_offset_ptr(fdt, offset);\r
+ if (!q) {\r
+ q = end;\r
+ }\r
\r
- if (lenp)\r
- *lenp = fdt32_to_cpu(prop->len);\r
+ p = fdt_get_alias_namelen (fdt, p, q - p);\r
+ if (!p) {\r
+ return -FDT_ERR_BADPATH;\r
+ }\r
\r
- return prop;\r
-}\r
+ offset = fdt_path_offset (fdt, p);\r
\r
-const struct fdt_property *fdt_get_property_namelen(const void *fdt,\r
- int offset,\r
- const char *name,\r
- int namelen, int *lenp)\r
-{\r
- for (offset = fdt_first_property_offset(fdt, offset);\r
- (offset >= 0);\r
- (offset = fdt_next_property_offset(fdt, offset))) {\r
- const struct fdt_property *prop;\r
+ p = q;\r
+ }\r
\r
- if (!(prop = fdt_get_property_by_offset(fdt, offset, lenp))) {\r
- offset = -FDT_ERR_INTERNAL;\r
- break;\r
- }\r
- if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff),\r
- name, namelen))\r
- return prop;\r
- }\r
+ while (p < end) {\r
+ const char *q;\r
\r
- if (lenp)\r
- *lenp = offset;\r
- return NULL;\r
-}\r
+ while (*p == '/') {\r
+ p++;\r
+ if (p == end) {\r
+ return offset;\r
+ }\r
+ }\r
\r
-const struct fdt_property *fdt_get_property(const void *fdt,\r
- int nodeoffset,\r
- const char *name, int *lenp)\r
-{\r
- return fdt_get_property_namelen(fdt, nodeoffset, name,\r
- strlen(name), lenp);\r
-}\r
+ q = memchr (p, '/', end - p);\r
+ if (!q) {\r
+ q = end;\r
+ }\r
\r
-const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,\r
- const char *name, int namelen, int *lenp)\r
-{\r
- const struct fdt_property *prop;\r
+ offset = fdt_subnode_offset_namelen (fdt, offset, p, q-p);\r
+ if (offset < 0) {\r
+ return offset;\r
+ }\r
\r
- prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp);\r
- if (!prop)\r
- return NULL;\r
+ p = q;\r
+ }\r
\r
- return prop->data;\r
+ return offset;\r
}\r
\r
-const void *fdt_getprop_by_offset(const void *fdt, int offset,\r
- const char **namep, int *lenp)\r
+int\r
+fdt_path_offset (\r
+ const void *fdt,\r
+ const char *path\r
+ )\r
{\r
- const struct fdt_property *prop;\r
-\r
- prop = fdt_get_property_by_offset(fdt, offset, lenp);\r
- if (!prop)\r
- return NULL;\r
- if (namep)\r
- *namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));\r
- return prop->data;\r
+ return fdt_path_offset_namelen (fdt, path, strlen (path));\r
}\r
\r
-const void *fdt_getprop(const void *fdt, int nodeoffset,\r
- const char *name, int *lenp)\r
+const char *\r
+fdt_get_name (\r
+ const void *fdt,\r
+ int nodeoffset,\r
+ int *len\r
+ )\r
{\r
- return fdt_getprop_namelen(fdt, nodeoffset, name, strlen(name), lenp);\r
-}\r
+ const struct fdt_node_header *nh = _fdt_offset_ptr (fdt, nodeoffset);\r
+ int err;\r
\r
-uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)\r
-{\r
- const fdt32_t *php;\r
- int len;\r
+ if ( ((err = fdt_check_header (fdt)) != 0)\r
+ || ((err = _fdt_check_node_offset (fdt, nodeoffset)) < 0))\r
+ {\r
+ goto fail;\r
+ }\r
\r
- /* FIXME: This is a bit sub-optimal, since we potentially scan\r
- * over all the properties twice. */\r
- php = fdt_getprop(fdt, nodeoffset, "phandle", &len);\r
- if (!php || (len != sizeof(*php))) {\r
- php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len);\r
- if (!php || (len != sizeof(*php)))\r
- return 0;\r
- }\r
+ if (len) {\r
+ *len = strlen (nh->name);\r
+ }\r
\r
- return fdt32_to_cpu(*php);\r
-}\r
+ return nh->name;\r
\r
-const char *fdt_get_alias_namelen(const void *fdt,\r
- const char *name, int namelen)\r
-{\r
- int aliasoffset;\r
+fail:\r
+ if (len) {\r
+ *len = err;\r
+ }\r
\r
- aliasoffset = fdt_path_offset(fdt, "/aliases");\r
- if (aliasoffset < 0)\r
- return NULL;\r
-\r
- return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL);\r
-}\r
-\r
-const char *fdt_get_alias(const void *fdt, const char *name)\r
-{\r
- return fdt_get_alias_namelen(fdt, name, strlen(name));\r
+ return NULL;\r
}\r
\r
-int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)\r
+int\r
+fdt_first_property_offset (\r
+ const void *fdt,\r
+ int nodeoffset\r
+ )\r
{\r
- int pdepth = 0, p = 0;\r
- int offset, depth, namelen;\r
- const char *name;\r
+ int offset;\r
\r
- FDT_CHECK_HEADER(fdt);\r
+ if ((offset = _fdt_check_node_offset (fdt, nodeoffset)) < 0) {\r
+ return offset;\r
+ }\r
\r
- if (buflen < 2)\r
- return -FDT_ERR_NOSPACE;\r
-\r
- for (offset = 0, depth = 0;\r
- (offset >= 0) && (offset <= nodeoffset);\r
- offset = fdt_next_node(fdt, offset, &depth)) {\r
- while (pdepth > depth) {\r
- do {\r
- p--;\r
- } while (buf[p-1] != '/');\r
- pdepth--;\r
- }\r
-\r
- if (pdepth >= depth) {\r
- name = fdt_get_name(fdt, offset, &namelen);\r
- if (!name)\r
- return namelen;\r
- if ((p + namelen + 1) <= buflen) {\r
- memcpy(buf + p, name, namelen);\r
- p += namelen;\r
- buf[p++] = '/';\r
- pdepth++;\r
- }\r
- }\r
-\r
- if (offset == nodeoffset) {\r
- if (pdepth < (depth + 1))\r
- return -FDT_ERR_NOSPACE;\r
-\r
- if (p > 1) /* special case so that root path is "/", not "" */\r
- p--;\r
- buf[p] = '\0';\r
- return 0;\r
- }\r
- }\r
-\r
- if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))\r
- return -FDT_ERR_BADOFFSET;\r
- else if (offset == -FDT_ERR_BADOFFSET)\r
- return -FDT_ERR_BADSTRUCTURE;\r
-\r
- return offset; /* error from fdt_next_node() */\r
+ return _nextprop (fdt, offset);\r
}\r
\r
-int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,\r
- int supernodedepth, int *nodedepth)\r
+int\r
+fdt_next_property_offset (\r
+ const void *fdt,\r
+ int offset\r
+ )\r
{\r
- int offset, depth;\r
- int supernodeoffset = -FDT_ERR_INTERNAL;\r
-\r
- FDT_CHECK_HEADER(fdt);\r
-\r
- if (supernodedepth < 0)\r
- return -FDT_ERR_NOTFOUND;\r
+ if ((offset = _fdt_check_prop_offset (fdt, offset)) < 0) {\r
+ return offset;\r
+ }\r
\r
- for (offset = 0, depth = 0;\r
- (offset >= 0) && (offset <= nodeoffset);\r
- offset = fdt_next_node(fdt, offset, &depth)) {\r
- if (depth == supernodedepth)\r
- supernodeoffset = offset;\r
-\r
- if (offset == nodeoffset) {\r
- if (nodedepth)\r
- *nodedepth = depth;\r
-\r
- if (supernodedepth > depth)\r
- return -FDT_ERR_NOTFOUND;\r
- else\r
- return supernodeoffset;\r
- }\r
- }\r
-\r
- if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))\r
- return -FDT_ERR_BADOFFSET;\r
- else if (offset == -FDT_ERR_BADOFFSET)\r
- return -FDT_ERR_BADSTRUCTURE;\r
-\r
- return offset; /* error from fdt_next_node() */\r
-}\r
-\r
-int fdt_node_depth(const void *fdt, int nodeoffset)\r
-{\r
- int nodedepth;\r
- int err;\r
-\r
- err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth);\r
- if (err)\r
- return (err < 0) ? err : -FDT_ERR_INTERNAL;\r
- return nodedepth;\r
+ return _nextprop (fdt, offset);\r
}\r
\r
-int fdt_parent_offset(const void *fdt, int nodeoffset)\r
+const struct fdt_property *\r
+fdt_get_property_by_offset (\r
+ const void *fdt,\r
+ int offset,\r
+ int *lenp\r
+ )\r
{\r
- int nodedepth = fdt_node_depth(fdt, nodeoffset);\r
+ int err;\r
+ const struct fdt_property *prop;\r
\r
- if (nodedepth < 0)\r
- return nodedepth;\r
- return fdt_supernode_atdepth_offset(fdt, nodeoffset,\r
- nodedepth - 1, NULL);\r
-}\r
+ if ((err = _fdt_check_prop_offset (fdt, offset)) < 0) {\r
+ if (lenp) {\r
+ *lenp = err;\r
+ }\r
\r
-int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,\r
- const char *propname,\r
- const void *propval, int proplen)\r
-{\r
- int offset;\r
- const void *val;\r
- int len;\r
+ return NULL;\r
+ }\r
\r
- FDT_CHECK_HEADER(fdt);\r
+ prop = _fdt_offset_ptr (fdt, offset);\r
\r
- /* FIXME: The algorithm here is pretty horrible: we scan each\r
- * property of a node in fdt_getprop(), then if that didn't\r
- * find what we want, we scan over them again making our way\r
- * to the next node. Still it's the easiest to implement\r
- * approach; performance can come later. */\r
- for (offset = fdt_next_node(fdt, startoffset, NULL);\r
- offset >= 0;\r
- offset = fdt_next_node(fdt, offset, NULL)) {\r
- val = fdt_getprop(fdt, offset, propname, &len);\r
- if (val && (len == proplen)\r
- && (memcmp(val, propval, len) == 0))\r
- return offset;\r
- }\r
+ if (lenp) {\r
+ *lenp = fdt32_to_cpu (prop->len);\r
+ }\r
\r
- return offset; /* error from fdt_next_node() */\r
+ return prop;\r
}\r
\r
-int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)\r
+const struct fdt_property *\r
+fdt_get_property_namelen (\r
+ const void *fdt,\r
+ int offset,\r
+ const char *name,\r
+ int namelen,\r
+ int *lenp\r
+ )\r
{\r
- int offset;\r
+ for (offset = fdt_first_property_offset (fdt, offset);\r
+ (offset >= 0);\r
+ (offset = fdt_next_property_offset (fdt, offset)))\r
+ {\r
+ const struct fdt_property *prop;\r
\r
- if ((phandle == 0) || (phandle == -1))\r
- return -FDT_ERR_BADPHANDLE;\r
+ if (!(prop = fdt_get_property_by_offset (fdt, offset, lenp))) {\r
+ offset = -FDT_ERR_INTERNAL;\r
+ break;\r
+ }\r
\r
- FDT_CHECK_HEADER(fdt);\r
+ if (_fdt_string_eq (\r
+ fdt,\r
+ fdt32_to_cpu (prop->nameoff),\r
+ name,\r
+ namelen\r
+ ))\r
+ {\r
+ return prop;\r
+ }\r
+ }\r
\r
- /* FIXME: The algorithm here is pretty horrible: we\r
- * potentially scan each property of a node in\r
- * fdt_get_phandle(), then if that didn't find what\r
- * we want, we scan over them again making our way to the next\r
- * node. Still it's the easiest to implement approach;\r
- * performance can come later. */\r
- for (offset = fdt_next_node(fdt, -1, NULL);\r
- offset >= 0;\r
- offset = fdt_next_node(fdt, offset, NULL)) {\r
- if (fdt_get_phandle(fdt, offset) == phandle)\r
- return offset;\r
- }\r
+ if (lenp) {\r
+ *lenp = offset;\r
+ }\r
\r
- return offset; /* error from fdt_next_node() */\r
+ return NULL;\r
}\r
\r
-int fdt_stringlist_contains(const char *strlist, int listlen, const char *str)\r
+const struct fdt_property *\r
+fdt_get_property (\r
+ const void *fdt,\r
+ int nodeoffset,\r
+ const char *name,\r
+ int *lenp\r
+ )\r
{\r
- int len = strlen(str);\r
- const char *p;\r
-\r
- while (listlen >= len) {\r
- if (memcmp(str, strlist, len+1) == 0)\r
- return 1;\r
- p = memchr(strlist, '\0', listlen);\r
- if (!p)\r
- return 0; /* malformed strlist.. */\r
- listlen -= (p-strlist) + 1;\r
- strlist = p + 1;\r
- }\r
- return 0;\r
+ return fdt_get_property_namelen (\r
+ fdt,\r
+ nodeoffset,\r
+ name,\r
+ strlen (name),\r
+ lenp\r
+ );\r
}\r
\r
-int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property)\r
+const void *\r
+fdt_getprop_namelen (\r
+ const void *fdt,\r
+ int nodeoffset,\r
+ const char *name,\r
+ int namelen,\r
+ int *lenp\r
+ )\r
{\r
- const char *list, *end;\r
- int length, count = 0;\r
-\r
- list = fdt_getprop(fdt, nodeoffset, property, &length);\r
- if (!list)\r
- return length;\r
+ const struct fdt_property *prop;\r
\r
- end = list + length;\r
+ prop = fdt_get_property_namelen (fdt, nodeoffset, name, namelen, lenp);\r
+ if (!prop) {\r
+ return NULL;\r
+ }\r
\r
- while (list < end) {\r
- length = strnlen(list, end - list) + 1;\r
-\r
- /* Abort if the last string isn't properly NUL-terminated. */\r
- if (list + length > end)\r
- return -FDT_ERR_BADVALUE;\r
+ return prop->data;\r
+}\r
+\r
+const void *\r
+fdt_getprop_by_offset (\r
+ const void *fdt,\r
+ int offset,\r
+ const char **namep,\r
+ int *lenp\r
+ )\r
+{\r
+ const struct fdt_property *prop;\r
+\r
+ prop = fdt_get_property_by_offset (fdt, offset, lenp);\r
+ if (!prop) {\r
+ return NULL;\r
+ }\r
+\r
+ if (namep) {\r
+ *namep = fdt_string (fdt, fdt32_to_cpu (prop->nameoff));\r
+ }\r
+\r
+ return prop->data;\r
+}\r
+\r
+const void *\r
+fdt_getprop (\r
+ const void *fdt,\r
+ int nodeoffset,\r
+ const char *name,\r
+ int *lenp\r
+ )\r
+{\r
+ return fdt_getprop_namelen (fdt, nodeoffset, name, strlen (name), lenp);\r
+}\r
+\r
+uint32_t\r
+fdt_get_phandle (\r
+ const void *fdt,\r
+ int nodeoffset\r
+ )\r
+{\r
+ const fdt32_t *php;\r
+ int len;\r
+\r
+ /* FIXME: This is a bit sub-optimal, since we potentially scan\r
+ * over all the properties twice. */\r
+ php = fdt_getprop (fdt, nodeoffset, "phandle", &len);\r
+ if (!php || (len != sizeof (*php))) {\r
+ php = fdt_getprop (fdt, nodeoffset, "linux,phandle", &len);\r
+ if (!php || (len != sizeof (*php))) {\r
+ return 0;\r
+ }\r
+ }\r
+\r
+ return fdt32_to_cpu (*php);\r
+}\r
+\r
+const char *\r
+fdt_get_alias_namelen (\r
+ const void *fdt,\r
+ const char *name,\r
+ int namelen\r
+ )\r
+{\r
+ int aliasoffset;\r
+\r
+ aliasoffset = fdt_path_offset (fdt, "/aliases");\r
+ if (aliasoffset < 0) {\r
+ return NULL;\r
+ }\r
+\r
+ return fdt_getprop_namelen (fdt, aliasoffset, name, namelen, NULL);\r
+}\r
+\r
+const char *\r
+fdt_get_alias (\r
+ const void *fdt,\r
+ const char *name\r
+ )\r
+{\r
+ return fdt_get_alias_namelen (fdt, name, strlen (name));\r
+}\r
+\r
+int\r
+fdt_get_path (\r
+ const void *fdt,\r
+ int nodeoffset,\r
+ char *buf,\r
+ int buflen\r
+ )\r
+{\r
+ int pdepth = 0, p = 0;\r
+ int offset, depth, namelen;\r
+ const char *name;\r
+\r
+ FDT_CHECK_HEADER (fdt);\r
+\r
+ if (buflen < 2) {\r
+ return -FDT_ERR_NOSPACE;\r
+ }\r
+\r
+ for (offset = 0, depth = 0;\r
+ (offset >= 0) && (offset <= nodeoffset);\r
+ offset = fdt_next_node (fdt, offset, &depth))\r
+ {\r
+ while (pdepth > depth) {\r
+ do {\r
+ p--;\r
+ } while (buf[p-1] != '/');\r
+\r
+ pdepth--;\r
+ }\r
+\r
+ if (pdepth >= depth) {\r
+ name = fdt_get_name (fdt, offset, &namelen);\r
+ if (!name) {\r
+ return namelen;\r
+ }\r
+\r
+ if ((p + namelen + 1) <= buflen) {\r
+ memcpy (buf + p, name, namelen);\r
+ p += namelen;\r
+ buf[p++] = '/';\r
+ pdepth++;\r
+ }\r
+ }\r
+\r
+ if (offset == nodeoffset) {\r
+ if (pdepth < (depth + 1)) {\r
+ return -FDT_ERR_NOSPACE;\r
+ }\r
+\r
+ if (p > 1) {\r
+ /* special case so that root path is "/", not "" */\r
+ p--;\r
+ }\r
+\r
+ buf[p] = '\0';\r
+ return 0;\r
+ }\r
+ }\r
+\r
+ if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) {\r
+ return -FDT_ERR_BADOFFSET;\r
+ } else if (offset == -FDT_ERR_BADOFFSET) {\r
+ return -FDT_ERR_BADSTRUCTURE;\r
+ }\r
+\r
+ return offset; /* error from fdt_next_node() */\r
+}\r
+\r
+int\r
+fdt_supernode_atdepth_offset (\r
+ const void *fdt,\r
+ int nodeoffset,\r
+ int supernodedepth,\r
+ int *nodedepth\r
+ )\r
+{\r
+ int offset, depth;\r
+ int supernodeoffset = -FDT_ERR_INTERNAL;\r
+\r
+ FDT_CHECK_HEADER (fdt);\r
+\r
+ if (supernodedepth < 0) {\r
+ return -FDT_ERR_NOTFOUND;\r
+ }\r
+\r
+ for (offset = 0, depth = 0;\r
+ (offset >= 0) && (offset <= nodeoffset);\r
+ offset = fdt_next_node (fdt, offset, &depth))\r
+ {\r
+ if (depth == supernodedepth) {\r
+ supernodeoffset = offset;\r
+ }\r
+\r
+ if (offset == nodeoffset) {\r
+ if (nodedepth) {\r
+ *nodedepth = depth;\r
+ }\r
+\r
+ if (supernodedepth > depth) {\r
+ return -FDT_ERR_NOTFOUND;\r
+ } else {\r
+ return supernodeoffset;\r
+ }\r
+ }\r
+ }\r
+\r
+ if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) {\r
+ return -FDT_ERR_BADOFFSET;\r
+ } else if (offset == -FDT_ERR_BADOFFSET) {\r
+ return -FDT_ERR_BADSTRUCTURE;\r
+ }\r
+\r
+ return offset; /* error from fdt_next_node() */\r
+}\r
+\r
+int\r
+fdt_node_depth (\r
+ const void *fdt,\r
+ int nodeoffset\r
+ )\r
+{\r
+ int nodedepth;\r
+ int err;\r
+\r
+ err = fdt_supernode_atdepth_offset (fdt, nodeoffset, 0, &nodedepth);\r
+ if (err) {\r
+ return (err < 0) ? err : -FDT_ERR_INTERNAL;\r
+ }\r
+\r
+ return nodedepth;\r
+}\r
+\r
+int\r
+fdt_parent_offset (\r
+ const void *fdt,\r
+ int nodeoffset\r
+ )\r
+{\r
+ int nodedepth = fdt_node_depth (fdt, nodeoffset);\r
+\r
+ if (nodedepth < 0) {\r
+ return nodedepth;\r
+ }\r
+\r
+ return fdt_supernode_atdepth_offset (\r
+ fdt,\r
+ nodeoffset,\r
+ nodedepth - 1,\r
+ NULL\r
+ );\r
+}\r
+\r
+int\r
+fdt_node_offset_by_prop_value (\r
+ const void *fdt,\r
+ int startoffset,\r
+ const char *propname,\r
+ const void *propval,\r
+ int proplen\r
+ )\r
+{\r
+ int offset;\r
+ const void *val;\r
+ int len;\r
+\r
+ FDT_CHECK_HEADER (fdt);\r
+\r
+ /* FIXME: The algorithm here is pretty horrible: we scan each\r
+ * property of a node in fdt_getprop(), then if that didn't\r
+ * find what we want, we scan over them again making our way\r
+ * to the next node. Still it's the easiest to implement\r
+ * approach; performance can come later. */\r
+ for (offset = fdt_next_node (fdt, startoffset, NULL);\r
+ offset >= 0;\r
+ offset = fdt_next_node (fdt, offset, NULL))\r
+ {\r
+ val = fdt_getprop (fdt, offset, propname, &len);\r
+ if ( val && (len == proplen)\r
+ && (memcmp (val, propval, len) == 0))\r
+ {\r
+ return offset;\r
+ }\r
+ }\r
+\r
+ return offset; /* error from fdt_next_node() */\r
+}\r
+\r
+int\r
+fdt_node_offset_by_phandle (\r
+ const void *fdt,\r
+ uint32_t phandle\r
+ )\r
+{\r
+ int offset;\r
+\r
+ if ((phandle == 0) || (phandle == -1)) {\r
+ return -FDT_ERR_BADPHANDLE;\r
+ }\r
+\r
+ FDT_CHECK_HEADER (fdt);\r
+\r
+ /* FIXME: The algorithm here is pretty horrible: we\r
+ * potentially scan each property of a node in\r
+ * fdt_get_phandle(), then if that didn't find what\r
+ * we want, we scan over them again making our way to the next\r
+ * node. Still it's the easiest to implement approach;\r
+ * performance can come later. */\r
+ for (offset = fdt_next_node (fdt, -1, NULL);\r
+ offset >= 0;\r
+ offset = fdt_next_node (fdt, offset, NULL))\r
+ {\r
+ if (fdt_get_phandle (fdt, offset) == phandle) {\r
+ return offset;\r
+ }\r
+ }\r
+\r
+ return offset; /* error from fdt_next_node() */\r
+}\r
+\r
+int\r
+fdt_stringlist_contains (\r
+ const char *strlist,\r
+ int listlen,\r
+ const char *str\r
+ )\r
+{\r
+ int len = strlen (str);\r
+ const char *p;\r
+\r
+ while (listlen >= len) {\r
+ if (memcmp (str, strlist, len+1) == 0) {\r
+ return 1;\r
+ }\r
+\r
+ p = memchr (strlist, '\0', listlen);\r
+ if (!p) {\r
+ return 0; /* malformed strlist.. */\r
+ }\r
+\r
+ listlen -= (p-strlist) + 1;\r
+ strlist = p + 1;\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+int\r
+fdt_stringlist_count (\r
+ const void *fdt,\r
+ int nodeoffset,\r
+ const char *property\r
+ )\r
+{\r
+ const char *list, *end;\r
+ int length, count = 0;\r
+\r
+ list = fdt_getprop (fdt, nodeoffset, property, &length);\r
+ if (!list) {\r
+ return length;\r
+ }\r
+\r
+ end = list + length;\r
+\r
+ while (list < end) {\r
+ length = strnlen (list, end - list) + 1;\r
+\r
+ /* Abort if the last string isn't properly NUL-terminated. */\r
+ if (list + length > end) {\r
+ return -FDT_ERR_BADVALUE;\r
+ }\r
\r
- list += length;\r
- count++;\r
- }\r
+ list += length;\r
+ count++;\r
+ }\r
\r
- return count;\r
+ return count;\r
}\r
\r
-int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,\r
- const char *string)\r
+int\r
+fdt_stringlist_search (\r
+ const void *fdt,\r
+ int nodeoffset,\r
+ const char *property,\r
+ const char *string\r
+ )\r
{\r
- int length, len, idx = 0;\r
- const char *list, *end;\r
+ int length, len, idx = 0;\r
+ const char *list, *end;\r
\r
- list = fdt_getprop(fdt, nodeoffset, property, &length);\r
- if (!list)\r
- return length;\r
+ list = fdt_getprop (fdt, nodeoffset, property, &length);\r
+ if (!list) {\r
+ return length;\r
+ }\r
\r
- len = strlen(string) + 1;\r
- end = list + length;\r
+ len = strlen (string) + 1;\r
+ end = list + length;\r
\r
- while (list < end) {\r
- length = strnlen(list, end - list) + 1;\r
+ while (list < end) {\r
+ length = strnlen (list, end - list) + 1;\r
\r
- /* Abort if the last string isn't properly NUL-terminated. */\r
- if (list + length > end)\r
- return -FDT_ERR_BADVALUE;\r
+ /* Abort if the last string isn't properly NUL-terminated. */\r
+ if (list + length > end) {\r
+ return -FDT_ERR_BADVALUE;\r
+ }\r
\r
- if (length == len && memcmp(list, string, length) == 0)\r
- return idx;\r
+ if ((length == len) && (memcmp (list, string, length) == 0)) {\r
+ return idx;\r
+ }\r
\r
- list += length;\r
- idx++;\r
- }\r
+ list += length;\r
+ idx++;\r
+ }\r
\r
- return -FDT_ERR_NOTFOUND;\r
+ return -FDT_ERR_NOTFOUND;\r
}\r
\r
-const char *fdt_stringlist_get(const void *fdt, int nodeoffset,\r
- const char *property, int idx,\r
- int *lenp)\r
+const char *\r
+fdt_stringlist_get (\r
+ const void *fdt,\r
+ int nodeoffset,\r
+ const char *property,\r
+ int idx,\r
+ int *lenp\r
+ )\r
{\r
- const char *list, *end;\r
- int length;\r
+ const char *list, *end;\r
+ int length;\r
\r
- list = fdt_getprop(fdt, nodeoffset, property, &length);\r
- if (!list) {\r
- if (lenp)\r
- *lenp = length;\r
+ list = fdt_getprop (fdt, nodeoffset, property, &length);\r
+ if (!list) {\r
+ if (lenp) {\r
+ *lenp = length;\r
+ }\r
\r
- return NULL;\r
- }\r
+ return NULL;\r
+ }\r
\r
- end = list + length;\r
+ end = list + length;\r
\r
- while (list < end) {\r
- length = strnlen(list, end - list) + 1;\r
+ while (list < end) {\r
+ length = strnlen (list, end - list) + 1;\r
\r
- /* Abort if the last string isn't properly NUL-terminated. */\r
- if (list + length > end) {\r
- if (lenp)\r
- *lenp = -FDT_ERR_BADVALUE;\r
+ /* Abort if the last string isn't properly NUL-terminated. */\r
+ if (list + length > end) {\r
+ if (lenp) {\r
+ *lenp = -FDT_ERR_BADVALUE;\r
+ }\r
\r
- return NULL;\r
- }\r
+ return NULL;\r
+ }\r
\r
- if (idx == 0) {\r
- if (lenp)\r
- *lenp = length - 1;\r
+ if (idx == 0) {\r
+ if (lenp) {\r
+ *lenp = length - 1;\r
+ }\r
\r
- return list;\r
- }\r
+ return list;\r
+ }\r
\r
- list += length;\r
- idx--;\r
- }\r
+ list += length;\r
+ idx--;\r
+ }\r
\r
- if (lenp)\r
- *lenp = -FDT_ERR_NOTFOUND;\r
+ if (lenp) {\r
+ *lenp = -FDT_ERR_NOTFOUND;\r
+ }\r
\r
- return NULL;\r
+ return NULL;\r
}\r
\r
-int fdt_node_check_compatible(const void *fdt, int nodeoffset,\r
- const char *compatible)\r
+int\r
+fdt_node_check_compatible (\r
+ const void *fdt,\r
+ int nodeoffset,\r
+ const char *compatible\r
+ )\r
{\r
- const void *prop;\r
- int len;\r
+ const void *prop;\r
+ int len;\r
+\r
+ prop = fdt_getprop (fdt, nodeoffset, "compatible", &len);\r
+ if (!prop) {\r
+ return len;\r
+ }\r
\r
- prop = fdt_getprop(fdt, nodeoffset, "compatible", &len);\r
- if (!prop)\r
- return len;\r
-\r
- return !fdt_stringlist_contains(prop, len, compatible);\r
+ return !fdt_stringlist_contains (prop, len, compatible);\r
}\r
\r
-int fdt_node_offset_by_compatible(const void *fdt, int startoffset,\r
- const char *compatible)\r
+int\r
+fdt_node_offset_by_compatible (\r
+ const void *fdt,\r
+ int startoffset,\r
+ const char *compatible\r
+ )\r
{\r
- int offset, err;\r
-\r
- FDT_CHECK_HEADER(fdt);\r
+ int offset, err;\r
\r
- /* FIXME: The algorithm here is pretty horrible: we scan each\r
- * property of a node in fdt_node_check_compatible(), then if\r
- * that didn't find what we want, we scan over them again\r
- * making our way to the next node. Still it's the easiest to\r
- * implement approach; performance can come later. */\r
- for (offset = fdt_next_node(fdt, startoffset, NULL);\r
- offset >= 0;\r
- offset = fdt_next_node(fdt, offset, NULL)) {\r
- err = fdt_node_check_compatible(fdt, offset, compatible);\r
- if ((err < 0) && (err != -FDT_ERR_NOTFOUND))\r
- return err;\r
- else if (err == 0)\r
- return offset;\r
- }\r
+ FDT_CHECK_HEADER (fdt);\r
\r
- return offset; /* error from fdt_next_node() */\r
+ /* FIXME: The algorithm here is pretty horrible: we scan each\r
+ * property of a node in fdt_node_check_compatible(), then if\r
+ * that didn't find what we want, we scan over them again\r
+ * making our way to the next node. Still it's the easiest to\r
+ * implement approach; performance can come later. */\r
+ for (offset = fdt_next_node (fdt, startoffset, NULL);\r
+ offset >= 0;\r
+ offset = fdt_next_node (fdt, offset, NULL))\r
+ {\r
+ err = fdt_node_check_compatible (fdt, offset, compatible);\r
+ if ((err < 0) && (err != -FDT_ERR_NOTFOUND)) {\r
+ return err;\r
+ } else if (err == 0) {\r
+ return offset;\r
+ }\r
+ }\r
+\r
+ return offset; /* error from fdt_next_node() */\r
}\r