+// SPDX-License-Identifier: GPL-2.0+ OR BSD-2-Clause
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
- * SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause
*/
-#include <libfdt_env.h>
+#include <linux/libfdt_env.h>
#ifndef USE_HOSTCC
#include <fdt.h>
-#include <libfdt.h>
+#include <linux/libfdt.h>
#else
#include "fdt_host.h"
#endif
return max_phandle;
if (offset < 0)
- return 0;
+ return (uint32_t)-1;
phandle = fdt_get_phandle(fdt, offset);
if (phandle == (uint32_t)-1)
- return 0;
+ continue;
if (phandle > max_phandle)
max_phandle = phandle;
return 0;
}
+int fdt_generate_phandle(const void *fdt, uint32_t *phandle)
+{
+ uint32_t max = 0;
+ int offset = -1;
+
+ while (true) {
+ uint32_t value;
+
+ offset = fdt_next_node(fdt, offset, NULL);
+ if (offset < 0) {
+ if (offset == -FDT_ERR_NOTFOUND)
+ break;
+
+ return offset;
+ }
+
+ value = fdt_get_phandle(fdt, offset);
+
+ if (value > max)
+ max = value;
+ }
+
+ if (max == FDT_MAX_PHANDLE)
+ return -FDT_ERR_NOPHANDLES;
+
+ if (phandle)
+ *phandle = max + 1;
+
+ 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);
+ *address = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->address);
+ *size = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->size);
return 0;
}
{
int i = 0;
- while (fdt64_to_cpu(_fdt_mem_rsv(fdt, i)->size) != 0)
+ while (fdt64_to_cpu(fdt_mem_rsv_(fdt, i)->size) != 0)
i++;
return i;
}
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);
+ 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))
+ || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0))
goto fail;
if (len)
{
int offset;
- if ((offset = _fdt_check_node_offset(fdt, nodeoffset)) < 0)
+ 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)
+ if ((offset = fdt_check_prop_offset_(fdt, offset)) < 0)
return offset;
return _nextprop(fdt, offset);
int err;
const struct fdt_property *prop;
- if ((err = _fdt_check_prop_offset(fdt, offset)) < 0) {
+ if ((err = fdt_check_prop_offset_(fdt, offset)) < 0) {
if (lenp)
*lenp = err;
return NULL;
}
- prop = _fdt_offset_ptr(fdt, offset);
+ prop = fdt_offset_ptr_(fdt, offset);
if (lenp)
*lenp = fdt32_to_cpu(prop->len);
return 0;
}
-int fdt_count_strings(const void *fdt, int node, const char *property)
+int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property)
{
- int length, i, count = 0;
- const char *list;
+ const char *list, *end;
+ int length, count = 0;
- list = fdt_getprop(fdt, node, property, &length);
+ list = fdt_getprop(fdt, nodeoffset, property, &length);
if (!list)
return length;
- for (i = 0; i < length; i++) {
- int len = strlen(list);
+ 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 += len + 1;
- i += len;
+ list += length;
count++;
}
return count;
}
-int fdt_find_string(const void *fdt, int node, const char *property,
- const char *string)
+int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,
+ const char *string)
{
+ int length, len, idx = 0;
const char *list, *end;
- int len, index = 0;
- list = fdt_getprop(fdt, node, property, &len);
+ list = fdt_getprop(fdt, nodeoffset, property, &length);
if (!list)
- return len;
+ return length;
- end = list + len;
- len = strlen(string);
+ len = strlen(string) + 1;
+ end = list + length;
while (list < end) {
- int l = strlen(list);
+ 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 (l == len && memcmp(list, string, len) == 0)
- return index;
+ if (length == len && memcmp(list, string, length) == 0)
+ return idx;
- list += l + 1;
- index++;
+ list += length;
+ idx++;
}
return -FDT_ERR_NOTFOUND;
}
-int fdt_get_string_index(const void *fdt, int node, const char *property,
- int index, const char **output)
+const char *fdt_stringlist_get(const void *fdt, int nodeoffset,
+ const char *property, int idx,
+ int *lenp)
{
- const char *list;
- int length, i;
+ const char *list, *end;
+ int length;
+
+ list = fdt_getprop(fdt, nodeoffset, property, &length);
+ if (!list) {
+ if (lenp)
+ *lenp = length;
- list = fdt_getprop(fdt, node, property, &length);
+ return NULL;
+ }
- for (i = 0; i < length; i++) {
- int len = strlen(list);
+ end = list + length;
- if (index == 0) {
- *output = list;
- return 0;
+ 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;
}
- list += len + 1;
- i += len;
- index--;
+ if (idx == 0) {
+ if (lenp)
+ *lenp = length - 1;
+
+ return list;
+ }
+
+ list += length;
+ idx--;
}
- return -FDT_ERR_NOTFOUND;
-}
+ if (lenp)
+ *lenp = -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);
+ return NULL;
}
int fdt_node_check_compatible(const void *fdt, int nodeoffset,
prop = fdt_getprop(fdt, nodeoffset, "compatible", &len);
if (!prop)
return len;
- if (fdt_stringlist_contains(prop, len, compatible))
- return 0;
- else
- return 1;
+
+ return !fdt_stringlist_contains(prop, len, compatible);
}
int fdt_node_offset_by_compatible(const void *fdt, int startoffset,