diff options
Diffstat (limited to 'contrib/dtc/libfdt/fdt_ro.c')
-rw-r--r-- | contrib/dtc/libfdt/fdt_ro.c | 703 |
1 files changed, 0 insertions, 703 deletions
diff --git a/contrib/dtc/libfdt/fdt_ro.c b/contrib/dtc/libfdt/fdt_ro.c deleted file mode 100644 index 3d00d2eee0e3..000000000000 --- a/contrib/dtc/libfdt/fdt_ro.c +++ /dev/null @@ -1,703 +0,0 @@ -/* - * libfdt - Flat Device Tree manipulation - * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "libfdt_env.h" - -#include <fdt.h> -#include <libfdt.h> - -#include "libfdt_internal.h" - -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); - - if (! p) - /* short match */ - return 0; - - if (memcmp(p, s, len) != 0) - return 0; - - if (p[len] == '\0') - return 1; - else if (!memchr(s, '@', len) && (p[len] == '@')) - return 1; - else - return 0; -} - -const char *fdt_string(const void *fdt, int 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); -} - -uint32_t fdt_get_max_phandle(const void *fdt) -{ - uint32_t max_phandle = 0; - int offset; - - for (offset = fdt_next_node(fdt, -1, NULL);; - offset = fdt_next_node(fdt, offset, NULL)) { - uint32_t phandle; - - if (offset == -FDT_ERR_NOTFOUND) - return max_phandle; - - if (offset < 0) - return (uint32_t)-1; - - phandle = fdt_get_phandle(fdt, offset); - if (phandle == (uint32_t)-1) - continue; - - if (phandle > max_phandle) - max_phandle = phandle; - } - - return 0; -} - -int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) -{ - 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; -} - -int fdt_num_mem_rsv(const void *fdt) -{ - int i = 0; - - while (fdt64_to_cpu(_fdt_mem_rsv(fdt, i)->size) != 0) - i++; - return i; -} - -static int _nextprop(const void *fdt, int offset) -{ - uint32_t tag; - int nextoffset; - - do { - tag = fdt_next_tag(fdt, offset, &nextoffset); - - switch (tag) { - case FDT_END: - if (nextoffset >= 0) - return -FDT_ERR_BADSTRUCTURE; - else - return nextoffset; - - case FDT_PROP: - return offset; - } - offset = nextoffset; - } while (tag == FDT_NOP); - - return -FDT_ERR_NOTFOUND; -} - -int fdt_subnode_offset_namelen(const void *fdt, int offset, - const char *name, int namelen) -{ - int depth; - - FDT_CHECK_HEADER(fdt); - - for (depth = 0; - (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 */ -} - -int fdt_subnode_offset(const void *fdt, int parentoffset, - const char *name) -{ - return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name)); -} - -int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen) -{ - const char *end = path + namelen; - const char *p = path; - int offset = 0; - - FDT_CHECK_HEADER(fdt); - - /* see if we have an alias */ - if (*path != '/') { - const char *q = memchr(path, '/', end - p); - - 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 < end) { - const char *q; - - while (*p == '/') { - p++; - if (p == end) - return offset; - } - q = memchr(p, '/', end - p); - if (! q) - q = end; - - offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p); - if (offset < 0) - return offset; - - p = q; - } - - return offset; -} - -int fdt_path_offset(const void *fdt, const char *path) -{ - return fdt_path_offset_namelen(fdt, path, strlen(path)); -} - -const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) -{ - const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset); - int err; - - if (((err = fdt_check_header(fdt)) != 0) - || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0)) - goto fail; - - if (len) - *len = strlen(nh->name); - - return nh->name; - - fail: - if (len) - *len = err; - return NULL; -} - -int fdt_first_property_offset(const void *fdt, int nodeoffset) -{ - int offset; - - if ((offset = _fdt_check_node_offset(fdt, nodeoffset)) < 0) - return offset; - - return _nextprop(fdt, offset); -} - -int fdt_next_property_offset(const void *fdt, int offset) -{ - if ((offset = _fdt_check_prop_offset(fdt, offset)) < 0) - return offset; - - return _nextprop(fdt, offset); -} - -const struct fdt_property *fdt_get_property_by_offset(const void *fdt, - int offset, - int *lenp) -{ - int err; - const struct fdt_property *prop; - - if ((err = _fdt_check_prop_offset(fdt, offset)) < 0) { - if (lenp) - *lenp = err; - return NULL; - } - - prop = _fdt_offset_ptr(fdt, offset); - - if (lenp) - *lenp = fdt32_to_cpu(prop->len); - - return prop; -} - -const struct fdt_property *fdt_get_property_namelen(const void *fdt, - int offset, - const char *name, - int namelen, int *lenp) -{ - for (offset = fdt_first_property_offset(fdt, offset); - (offset >= 0); - (offset = fdt_next_property_offset(fdt, offset))) { - const struct fdt_property *prop; - - if (!(prop = fdt_get_property_by_offset(fdt, offset, lenp))) { - offset = -FDT_ERR_INTERNAL; - break; - } - if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff), - name, namelen)) - return prop; - } - - if (lenp) - *lenp = offset; - return NULL; -} - -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_namelen(fdt, nodeoffset, name, namelen, lenp); - if (! prop) - return NULL; - - return prop->data; -} - -const void *fdt_getprop_by_offset(const void *fdt, int offset, - const char **namep, int *lenp) -{ - const struct fdt_property *prop; - - prop = fdt_get_property_by_offset(fdt, offset, lenp); - if (!prop) - return NULL; - if (namep) - *namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff)); - 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 fdt32_t *php; - int len; - - /* FIXME: This is a bit sub-optimal, since we potentially scan - * over all the properties twice. */ - php = fdt_getprop(fdt, nodeoffset, "phandle", &len); - if (!php || (len != sizeof(*php))) { - php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len); - if (!php || (len != sizeof(*php))) - return 0; - } - - 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; - - FDT_CHECK_HEADER(fdt); - - if (buflen < 2) - return -FDT_ERR_NOSPACE; - - for (offset = 0, depth = 0; - (offset >= 0) && (offset <= nodeoffset); - offset = fdt_next_node(fdt, offset, &depth)) { - while (pdepth > depth) { - do { - p--; - } while (buf[p-1] != '/'); - 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) { - if (pdepth < (depth + 1)) - return -FDT_ERR_NOSPACE; - - if (p > 1) /* special case so that root path is "/", not "" */ - p--; - buf[p] = '\0'; - return 0; - } - } - - if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) - return -FDT_ERR_BADOFFSET; - else if (offset == -FDT_ERR_BADOFFSET) - return -FDT_ERR_BADSTRUCTURE; - - return offset; /* error from fdt_next_node() */ -} - -int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, - int supernodedepth, int *nodedepth) -{ - int offset, depth; - int supernodeoffset = -FDT_ERR_INTERNAL; - - FDT_CHECK_HEADER(fdt); - - if (supernodedepth < 0) - return -FDT_ERR_NOTFOUND; - - for (offset = 0, depth = 0; - (offset >= 0) && (offset <= nodeoffset); - offset = fdt_next_node(fdt, offset, &depth)) { - if (depth == supernodedepth) - supernodeoffset = offset; - - if (offset == nodeoffset) { - if (nodedepth) - *nodedepth = depth; - - if (supernodedepth > depth) - return -FDT_ERR_NOTFOUND; - else - return supernodeoffset; - } - } - - if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) - return -FDT_ERR_BADOFFSET; - else if (offset == -FDT_ERR_BADOFFSET) - return -FDT_ERR_BADSTRUCTURE; - - return offset; /* error from fdt_next_node() */ -} - -int fdt_node_depth(const void *fdt, int nodeoffset) -{ - int nodedepth; - int err; - - err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth); - if (err) - return (err < 0) ? err : -FDT_ERR_INTERNAL; - return nodedepth; -} - -int fdt_parent_offset(const void *fdt, int nodeoffset) -{ - int nodedepth = fdt_node_depth(fdt, nodeoffset); - - if (nodedepth < 0) - return nodedepth; - return fdt_supernode_atdepth_offset(fdt, nodeoffset, - nodedepth - 1, NULL); -} - -int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, - const char *propname, - const void *propval, int proplen) -{ - int offset; - const void *val; - int len; - - 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 - * find what we want, we scan over them again making our way - * to the next node. Still it's the easiest to implement - * approach; performance can come later. */ - for (offset = fdt_next_node(fdt, startoffset, NULL); - offset >= 0; - offset = fdt_next_node(fdt, offset, NULL)) { - val = fdt_getprop(fdt, offset, propname, &len); - if (val && (len == proplen) - && (memcmp(val, propval, len) == 0)) - return offset; - } - - return offset; /* error from fdt_next_node() */ -} - -int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) -{ - int offset; - - if ((phandle == 0) || (phandle == -1)) - return -FDT_ERR_BADPHANDLE; - - FDT_CHECK_HEADER(fdt); - - /* FIXME: The algorithm here is pretty horrible: we - * potentially scan each property of a node in - * fdt_get_phandle(), then if that didn't find what - * we want, we scan over them again making our way to the next - * node. Still it's the easiest to implement approach; - * performance can come later. */ - for (offset = fdt_next_node(fdt, -1, NULL); - offset >= 0; - offset = fdt_next_node(fdt, offset, NULL)) { - if (fdt_get_phandle(fdt, offset) == phandle) - return offset; - } - - return offset; /* error from fdt_next_node() */ -} - -int fdt_stringlist_contains(const char *strlist, int listlen, const char *str) -{ - int len = strlen(str); - const char *p; - - while (listlen >= len) { - if (memcmp(str, strlist, len+1) == 0) - return 1; - p = memchr(strlist, '\0', listlen); - if (!p) - return 0; /* malformed strlist.. */ - listlen -= (p-strlist) + 1; - strlist = p + 1; - } - return 0; -} - -int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property) -{ - const char *list, *end; - int length, count = 0; - - list = fdt_getprop(fdt, nodeoffset, property, &length); - if (!list) - return length; - - end = list + length; - - while (list < end) { - length = strnlen(list, end - list) + 1; - - /* Abort if the last string isn't properly NUL-terminated. */ - if (list + length > end) - return -FDT_ERR_BADVALUE; - - list += length; - count++; - } - - return count; -} - -int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property, - const char *string) -{ - int length, len, idx = 0; - const char *list, *end; - - list = fdt_getprop(fdt, nodeoffset, property, &length); - if (!list) - return length; - - len = strlen(string) + 1; - end = list + length; - - while (list < end) { - length = strnlen(list, end - list) + 1; - - /* Abort if the last string isn't properly NUL-terminated. */ - if (list + length > end) - return -FDT_ERR_BADVALUE; - - if (length == len && memcmp(list, string, length) == 0) - return idx; - - list += length; - idx++; - } - - return -FDT_ERR_NOTFOUND; -} - -const char *fdt_stringlist_get(const void *fdt, int nodeoffset, - const char *property, int idx, - int *lenp) -{ - const char *list, *end; - int length; - - list = fdt_getprop(fdt, nodeoffset, property, &length); - if (!list) { - if (lenp) - *lenp = length; - - return NULL; - } - - end = list + length; - - while (list < end) { - length = strnlen(list, end - list) + 1; - - /* Abort if the last string isn't properly NUL-terminated. */ - if (list + length > end) { - if (lenp) - *lenp = -FDT_ERR_BADVALUE; - - return NULL; - } - - if (idx == 0) { - if (lenp) - *lenp = length - 1; - - return list; - } - - list += length; - idx--; - } - - if (lenp) - *lenp = -FDT_ERR_NOTFOUND; - - return NULL; -} - -int fdt_node_check_compatible(const void *fdt, int nodeoffset, - const char *compatible) -{ - const void *prop; - int len; - - prop = fdt_getprop(fdt, nodeoffset, "compatible", &len); - if (!prop) - return len; - - return !fdt_stringlist_contains(prop, len, compatible); -} - -int fdt_node_offset_by_compatible(const void *fdt, int startoffset, - const char *compatible) -{ - int offset, err; - - 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 - * that didn't find what we want, we scan over them again - * making our way to the next node. Still it's the easiest to - * implement approach; performance can come later. */ - for (offset = fdt_next_node(fdt, startoffset, NULL); - offset >= 0; - offset = fdt_next_node(fdt, offset, NULL)) { - err = fdt_node_check_compatible(fdt, offset, compatible); - if ((err < 0) && (err != -FDT_ERR_NOTFOUND)) - return err; - else if (err == 0) - return offset; - } - - return offset; /* error from fdt_next_node() */ -} |