/*
* 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.
+ * SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause
*/
#include "libfdt_env.h"
{
const char *p = fdt_string(fdt, stroffset);
- return (strlen(p) == len) && (memcmp(p, s, len) == 0);
+ return (strnlen(p, len + 1) == len) && (memcmp(p, s, len) == 0);
}
int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
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)
{
return NULL;
}
-const struct fdt_property *fdt_get_property_namelen(const void *fdt,
- int nodeoffset,
- const char *name,
- int namelen, int *lenp)
+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)
{
- uint32_t tag;
- const struct fdt_property *prop;
- int offset, nextoffset;
int err;
+ const struct fdt_property *prop;
- if (((err = fdt_check_header(fdt)) != 0)
- || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0))
- goto fail;
+ if ((err = _fdt_check_prop_offset(fdt, offset)) < 0) {
+ if (lenp)
+ *lenp = err;
+ return NULL;
+ }
- nextoffset = err;
- do {
- offset = nextoffset;
+ prop = _fdt_offset_ptr(fdt, offset);
- tag = fdt_next_tag(fdt, offset, &nextoffset);
- switch (tag) {
- case FDT_END:
- if (nextoffset < 0)
- err = nextoffset;
- else
- /* FDT_END tag with unclosed nodes */
- err = -FDT_ERR_BADSTRUCTURE;
- goto fail;
+ if (lenp)
+ *lenp = fdt32_to_cpu(prop->len);
- case FDT_PROP:
- prop = _fdt_offset_ptr(fdt, offset);
- if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff),
- name, namelen)) {
- /* Found it! */
- if (lenp)
- *lenp = fdt32_to_cpu(prop->len);
-
- return prop;
- }
+ 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;
}
- } while ((tag != FDT_BEGIN_NODE) && (tag != FDT_END_NODE));
+ if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff),
+ name, namelen))
+ return prop;
+ }
- err = -FDT_ERR_NOTFOUND;
- fail:
if (lenp)
- *lenp = err;
+ *lenp = offset;
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)
{
uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
{
- const uint32_t *php;
+ const fdt32_t *php;
int len;
/* FIXME: This is a bit sub-optimal, since we potentially scan
return offset; /* error from fdt_next_node() */
}
-static int _fdt_stringlist_contains(const char *strlist, int listlen,
- const char *str)
+int fdt_stringlist_contains(const char *strlist, int listlen, const char *str)
{
int len = strlen(str);
const char *p;
return 0;
}
+int fdt_count_strings(const void *fdt, int node, const char *property)
+{
+ int length, i, count = 0;
+ const char *list;
+
+ list = fdt_getprop(fdt, node, property, &length);
+ if (!list)
+ return -length;
+
+ for (i = 0; i < length; i++) {
+ int len = strlen(list);
+
+ list += len + 1;
+ i += len;
+ count++;
+ }
+
+ return count;
+}
+
+int fdt_find_string(const void *fdt, int node, const char *property,
+ const char *string)
+{
+ const char *list, *end;
+ int len, index = 0;
+
+ list = fdt_getprop(fdt, node, property, &len);
+ if (!list)
+ return len;
+
+ end = list + len;
+ len = strlen(string);
+
+ while (list < end) {
+ int l = strlen(list);
+
+ if (l == len && memcmp(list, string, len) == 0)
+ return index;
+
+ list += l + 1;
+ index++;
+ }
+
+ return -FDT_ERR_NOTFOUND;
+}
+
+int fdt_get_string_index(const void *fdt, int node, const char *property,
+ int index, const char **output)
+{
+ const char *list;
+ int length, i;
+
+ list = fdt_getprop(fdt, node, property, &length);
+
+ for (i = 0; i < length; i++) {
+ int len = strlen(list);
+
+ if (index == 0) {
+ *output = list;
+ return 0;
+ }
+
+ list += len + 1;
+ i += len;
+ index--;
+ }
+
+ return FDT_ERR_NOTFOUND;
+}
+
+int fdt_get_string(const void *fdt, int node, const char *property,
+ const char **output)
+{
+ return fdt_get_string_index(fdt, node, property, 0, output);
+}
+
int fdt_node_check_compatible(const void *fdt, int nodeoffset,
const char *compatible)
{
prop = fdt_getprop(fdt, nodeoffset, "compatible", &len);
if (!prop)
return len;
- if (_fdt_stringlist_contains(prop, len, compatible))
+ if (fdt_stringlist_contains(prop, len, compatible))
return 0;
else
return 1;