* [PATCH v2 0/3] libfdt: make lib/libfdt/ contain only wrappers
@ 2020-04-16 9:30 Masahiro Yamada
2020-04-16 9:30 ` [PATCH v2 1/3] libfdt: migrate fdt_ro.c to a wrapper of scripts/dtc/libfdt/fdt_ro.c Masahiro Yamada
` (5 more replies)
0 siblings, 6 replies; 7+ messages in thread
From: Masahiro Yamada @ 2020-04-16 9:30 UTC (permalink / raw)
To: u-boot
Linux DT community follows the strict rule that they never locally
modify libfdt. In Linux, lib/fdt_*.c are wrapper files to
scripts/dtc/libfdt/fdt_*.c and scripts/dtc/ is synced with upstream
DTC by running scripts/dtc/update-dtc-source.sh
The local code in Linux is separated in drivers/of/.
On the other hand, U-Boot originally had own copies in lib/libfdt/,
and people locally modified them. The code diverged, and made it difficult
to re-sync with upstream.
In 2018, I worked on migrating them to wrapper files, just like Linux does.
50a327ded68b7e675389ad284ea3f8c62e683bda
87be1e9fb4dcc130e90d497cc5ce49c715efc6c2
26e961c8cfdff00c5c9389d301d9a2eb10eb844c
This series completes this work.
1/3 migrates fdt_ro.c to a wrapper.
Two years ago, it diverged from the upstream, and gave up resync.
Now, I do not see essential diff.
2/3 and 3/3 separate fdt_region out of the upstream code.
I am resending them after two years since the previous rejection.
It was unfortuate that they were rejected based on the assumption
that is unlikely to happen. They should be re-evaluated.
Masahiro Yamada (3):
libfdt: migrate fdt_ro.c to a wrapper of scripts/dtc/libfdt/fdt_ro.c
fdt_region: move fdt_region.c to common/ from lib/libfdt/
libfdt: split fdt_region declarations out to <fdt_region.h>
common/Makefile | 1 +
{lib/libfdt => common}/fdt_region.c | 1 +
common/image-fit-sig.c | 1 +
include/fdt_region.h | 304 +++++++++
include/linux/libfdt.h | 299 ---------
lib/libfdt/Makefile | 9 +-
lib/libfdt/fdt_ro.c | 925 +---------------------------
tools/Makefile | 13 +-
tools/fdtgrep.c | 1 +
tools/image-host.c | 1 +
tools/libfdt/fdt_ro.c | 2 +
11 files changed, 317 insertions(+), 1240 deletions(-)
rename {lib/libfdt => common}/fdt_region.c (99%)
create mode 100644 include/fdt_region.h
create mode 100644 tools/libfdt/fdt_ro.c
--
2.25.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 1/3] libfdt: migrate fdt_ro.c to a wrapper of scripts/dtc/libfdt/fdt_ro.c
2020-04-16 9:30 [PATCH v2 0/3] libfdt: make lib/libfdt/ contain only wrappers Masahiro Yamada
@ 2020-04-16 9:30 ` Masahiro Yamada
2020-04-16 9:30 ` [PATCH v2 2/3] fdt_region: move fdt_region.c to common/ from lib/libfdt/ Masahiro Yamada
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Masahiro Yamada @ 2020-04-16 9:30 UTC (permalink / raw)
To: u-boot
There is no essential difference between scripts/dtc/libfdt/fdt_ro.c
and lib/libfdt/fdt_ro.c
Migrate to a simple wrapper like the other files.
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
---
Changes in v2:
- refactor tools/Makefile
lib/libfdt/Makefile | 6 +-
lib/libfdt/fdt_ro.c | 925 +-----------------------------------------
tools/Makefile | 5 +-
tools/libfdt/fdt_ro.c | 2 +
4 files changed, 6 insertions(+), 932 deletions(-)
create mode 100644 tools/libfdt/fdt_ro.c
diff --git a/lib/libfdt/Makefile b/lib/libfdt/Makefile
index 5d3ae4e2f1..878659f99e 100644
--- a/lib/libfdt/Makefile
+++ b/lib/libfdt/Makefile
@@ -3,9 +3,9 @@
# (C) Copyright 2000-2007
# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
-# Use upstream code.
obj-y += \
fdt.o \
+ fdt_ro.o \
fdt_wip.o \
fdt_strerror.o \
fdt_sw.o \
@@ -15,10 +15,6 @@ obj-y += \
obj-$(CONFIG_OF_LIBFDT_OVERLAY) += fdt_overlay.o
-# Locally modified for U-Boot.
-# TODO: split out the local modifiction.
-obj-y += fdt_ro.o
-
# U-Boot own file
obj-y += fdt_region.o
diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c
index be03aea9eb..7ede074537 100644
--- a/lib/libfdt/fdt_ro.c
+++ b/lib/libfdt/fdt_ro.c
@@ -1,925 +1,2 @@
-// SPDX-License-Identifier: GPL-2.0+ OR BSD-2-Clause
-/*
- * libfdt - Flat Device Tree manipulation
- * Copyright (C) 2006 David Gibson, IBM Corporation.
- */
#include <linux/libfdt_env.h>
-
-#ifndef USE_HOSTCC
-#include <fdt.h>
-#include <linux/libfdt.h>
-#else
-#include "fdt_host.h"
-#endif
-
-#include "libfdt_internal.h"
-
-static int fdt_nodename_eq_(const void *fdt, int offset,
- const char *s, int len)
-{
- int olen;
- const char *p = fdt_get_name(fdt, offset, &olen);
-
- if (!p || (fdt_chk_extra() && olen < len))
- /* 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_get_string(const void *fdt, int stroffset, int *lenp)
-{
- int32_t totalsize;
- uint32_t absoffset;
- size_t len;
- int err;
- const char *s, *n;
-
- if (!fdt_chk_extra()) {
- s = (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
-
- if (lenp)
- *lenp = strlen(s);
- return s;
- }
- totalsize = fdt_ro_probe_(fdt);
- err = totalsize;
- if (totalsize < 0)
- goto fail;
-
- err = -FDT_ERR_BADOFFSET;
- absoffset = stroffset + fdt_off_dt_strings(fdt);
- if (absoffset >= totalsize)
- goto fail;
- len = totalsize - absoffset;
-
- if (fdt_magic(fdt) == FDT_MAGIC) {
- if (stroffset < 0)
- goto fail;
- if (!fdt_chk_version() || fdt_version(fdt) >= 17) {
- if (stroffset >= fdt_size_dt_strings(fdt))
- goto fail;
- if ((fdt_size_dt_strings(fdt) - stroffset) < len)
- len = fdt_size_dt_strings(fdt) - stroffset;
- }
- } else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
- if ((stroffset >= 0)
- || (stroffset < -fdt_size_dt_strings(fdt)))
- goto fail;
- if ((-stroffset) < len)
- len = -stroffset;
- } else {
- err = -FDT_ERR_INTERNAL;
- goto fail;
- }
-
- s = (const char *)fdt + absoffset;
- n = memchr(s, '\0', len);
- if (!n) {
- /* missing terminating NULL */
- err = -FDT_ERR_TRUNCATED;
- goto fail;
- }
-
- if (lenp)
- *lenp = n - s;
- return s;
-
-fail:
- if (lenp)
- *lenp = err;
- return NULL;
-}
-
-const char *fdt_string(const void *fdt, int stroffset)
-{
- return fdt_get_string(fdt, stroffset, NULL);
-}
-
-static int fdt_string_eq_(const void *fdt, int stroffset,
- const char *s, int len)
-{
- int slen;
- const char *p = fdt_get_string(fdt, stroffset, &slen);
-
- return p && (slen == len) && (memcmp(p, s, len) == 0);
-}
-
-int fdt_find_max_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 (phandle)
- *phandle = max;
-
- return 0;
-}
-
-int fdt_generate_phandle(const void *fdt, uint32_t *phandle)
-{
- uint32_t max;
- int err;
-
- err = fdt_find_max_phandle(fdt, &max);
- if (err < 0)
- return err;
-
- if (max == FDT_MAX_PHANDLE)
- return -FDT_ERR_NOPHANDLES;
-
- if (phandle)
- *phandle = max + 1;
-
- return 0;
-}
-
-static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n)
-{
- int offset = n * sizeof(struct fdt_reserve_entry);
- int absoffset = fdt_off_mem_rsvmap(fdt) + offset;
-
- if (fdt_chk_extra()) {
- if (absoffset < fdt_off_mem_rsvmap(fdt))
- return NULL;
- if (absoffset > fdt_totalsize(fdt) -
- sizeof(struct fdt_reserve_entry))
- return NULL;
- }
- return fdt_mem_rsv_(fdt, n);
-}
-
-int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
-{
- const struct fdt_reserve_entry *re;
-
- FDT_RO_PROBE(fdt);
- re = fdt_mem_rsv(fdt, n);
- if (fdt_chk_extra() && !re)
- return -FDT_ERR_BADOFFSET;
-
- *address = fdt64_to_cpu(re->address);
- *size = fdt64_to_cpu(re->size);
- return 0;
-}
-
-int fdt_num_mem_rsv(const void *fdt)
-{
- int i;
- const struct fdt_reserve_entry *re;
-
- for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) {
- if (fdt64_to_cpu(re->size) == 0)
- return i;
- }
- return -FDT_ERR_TRUNCATED;
-}
-
-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_RO_PROBE(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_RO_PROBE(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);
- const char *nameptr;
- int err;
-
- if (fdt_chk_extra() &&
- (((err = fdt_ro_probe_(fdt)) < 0)
- || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0)))
- goto fail;
-
- nameptr = nh->name;
-
- if (fdt_chk_version() && fdt_version(fdt) < 0x10) {
- /*
- * For old FDT versions, match the naming conventions of V16:
- * give only the leaf name (after all /). The actual tree
- * contents are loosely checked.
- */
- const char *leaf;
- leaf = strrchr(nameptr, '/');
- if (leaf == NULL) {
- err = -FDT_ERR_BADSTRUCTURE;
- goto fail;
- }
- nameptr = leaf+1;
- }
-
- if (len)
- *len = strlen(nameptr);
-
- return nameptr;
-
- 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);
-}
-
-static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt,
- int offset,
- int *lenp)
-{
- int err;
- const struct fdt_property *prop;
-
- if (fdt_chk_basic() && (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_by_offset(const void *fdt,
- int offset,
- int *lenp)
-{
- /* Prior to version 16, properties may need realignment
- * and this API does not work. fdt_getprop_*() will, however. */
-
- if (fdt_chk_version() && fdt_version(fdt) < 0x10) {
- if (lenp)
- *lenp = -FDT_ERR_BADVERSION;
- return NULL;
- }
-
- return fdt_get_property_by_offset_(fdt, offset, lenp);
-}
-
-static const struct fdt_property *fdt_get_property_namelen_(const void *fdt,
- int offset,
- const char *name,
- int namelen,
- int *lenp,
- int *poffset)
-{
- for (offset = fdt_first_property_offset(fdt, offset);
- (offset >= 0);
- (offset = fdt_next_property_offset(fdt, offset))) {
- const struct fdt_property *prop;
-
- prop = fdt_get_property_by_offset_(fdt, offset, lenp);
- if (fdt_chk_extra() && !prop) {
- offset = -FDT_ERR_INTERNAL;
- break;
- }
- if (fdt_string_eq_(fdt, fdt32_to_cpu(prop->nameoff),
- name, namelen)) {
- if (poffset)
- *poffset = offset;
- return prop;
- }
- }
-
- if (lenp)
- *lenp = offset;
- return NULL;
-}
-
-
-const struct fdt_property *fdt_get_property_namelen(const void *fdt,
- int offset,
- const char *name,
- int namelen, int *lenp)
-{
- /* Prior to version 16, properties may need realignment
- * and this API does not work. fdt_getprop_*() will, however. */
- if (fdt_chk_version() && fdt_version(fdt) < 0x10) {
- if (lenp)
- *lenp = -FDT_ERR_BADVERSION;
- return NULL;
- }
-
- return fdt_get_property_namelen_(fdt, offset, name, namelen, lenp,
- 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)
-{
- int poffset;
- const struct fdt_property *prop;
-
- prop = fdt_get_property_namelen_(fdt, nodeoffset, name, namelen, lenp,
- &poffset);
- if (!prop)
- return NULL;
-
- /* Handle realignment */
- if (fdt_chk_version() && fdt_version(fdt) < 0x10 &&
- (poffset + sizeof(*prop)) % 8 && fdt32_to_cpu(prop->len) >= 8)
- return prop->data + 4;
- 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) {
- const char *name;
- int namelen;
-
- if (fdt_chk_extra()) {
- name = fdt_get_string(fdt, fdt32_to_cpu(prop->nameoff),
- &namelen);
- if (!name) {
- if (lenp)
- *lenp = namelen;
- return NULL;
- }
- *namep = name;
- } else {
- *namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
- }
- }
-
- /* Handle realignment */
- if (fdt_chk_version() && fdt_version(fdt) < 0x10 &&
- (offset + sizeof(*prop)) % 8 && fdt32_to_cpu(prop->len) >= 8)
- return prop->data + 4;
- 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_RO_PROBE(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_RO_PROBE(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 (fdt_chk_extra()) {
- 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 (!fdt_chk_extra() || 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_RO_PROBE(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_RO_PROBE(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_RO_PROBE(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() */
-}
-
-#if !defined(CHECK_LEVEL) || CHECK_LEVEL > 0
-int fdt_check_full(const void *fdt, size_t bufsize)
-{
- int err;
- int num_memrsv;
- int offset, nextoffset = 0;
- uint32_t tag;
- unsigned depth = 0;
- const void *prop;
- const char *propname;
-
- if (bufsize < FDT_V1_SIZE)
- return -FDT_ERR_TRUNCATED;
- err = fdt_check_header(fdt);
- if (err != 0)
- return err;
- if (bufsize < fdt_totalsize(fdt))
- return -FDT_ERR_TRUNCATED;
-
- num_memrsv = fdt_num_mem_rsv(fdt);
- if (num_memrsv < 0)
- return num_memrsv;
-
- while (1) {
- offset = nextoffset;
- tag = fdt_next_tag(fdt, offset, &nextoffset);
-
- if (nextoffset < 0)
- return nextoffset;
-
- switch (tag) {
- case FDT_NOP:
- break;
-
- case FDT_END:
- if (depth != 0)
- return -FDT_ERR_BADSTRUCTURE;
- return 0;
-
- case FDT_BEGIN_NODE:
- depth++;
- if (depth > INT_MAX)
- return -FDT_ERR_BADSTRUCTURE;
- break;
-
- case FDT_END_NODE:
- if (depth == 0)
- return -FDT_ERR_BADSTRUCTURE;
- depth--;
- break;
-
- case FDT_PROP:
- prop = fdt_getprop_by_offset(fdt, offset, &propname,
- &err);
- if (!prop)
- return err;
- break;
-
- default:
- return -FDT_ERR_INTERNAL;
- }
- }
-}
-#endif
+#include "../../scripts/dtc/libfdt/fdt_ro.c"
diff --git a/tools/Makefile b/tools/Makefile
index 3b9ae90369..bfdbb1339c 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -63,11 +63,10 @@ FIT_CIPHER_OBJS-$(CONFIG_FIT_CIPHER) := common/image-cipher.o
# The following files are synced with upstream DTC.
# Use synced versions from scripts/dtc/libfdt/.
-LIBFDT_SRCS_SYNCED := fdt.c fdt_wip.c fdt_sw.c fdt_rw.c \
+LIBFDT_SRCS_SYNCED := fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c \
fdt_strerror.c fdt_empty_tree.c fdt_addresses.c fdt_overlay.c
-# The following files are locally modified for U-Boot (unfotunately).
# Use U-Boot own versions from lib/libfdt/.
-LIBFDT_SRCS_UNSYNCED := fdt_ro.c fdt_region.c
+LIBFDT_SRCS_UNSYNCED := fdt_region.c
LIBFDT_OBJS := $(addprefix libfdt/, $(patsubst %.c, %.o, $(LIBFDT_SRCS_SYNCED))) \
$(addprefix lib/libfdt/, $(patsubst %.c, %.o, $(LIBFDT_SRCS_UNSYNCED)))
diff --git a/tools/libfdt/fdt_ro.c b/tools/libfdt/fdt_ro.c
new file mode 100644
index 0000000000..8a9735a48c
--- /dev/null
+++ b/tools/libfdt/fdt_ro.c
@@ -0,0 +1,2 @@
+#include "fdt_host.h"
+#include "../scripts/dtc/libfdt/fdt_ro.c"
--
2.25.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 2/3] fdt_region: move fdt_region.c to common/ from lib/libfdt/
2020-04-16 9:30 [PATCH v2 0/3] libfdt: make lib/libfdt/ contain only wrappers Masahiro Yamada
2020-04-16 9:30 ` [PATCH v2 1/3] libfdt: migrate fdt_ro.c to a wrapper of scripts/dtc/libfdt/fdt_ro.c Masahiro Yamada
@ 2020-04-16 9:30 ` Masahiro Yamada
2020-04-16 9:30 ` [PATCH v2 3/3] libfdt: split fdt_region declarations out to <fdt_region.h> Masahiro Yamada
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Masahiro Yamada @ 2020-04-16 9:30 UTC (permalink / raw)
To: u-boot
My goal is to sync lib/libfdt/ with scripts/dtc/libfdt/, that is,
make lib/libfdt/ contain only wrapper files.
fdt_region.c was written only for U-Boot to implement the verified
boot. So, this belongs to the same group as common/fdt_support.c,
which is a collection of U-Boot own fdt helpers.
Move lib/libfdt/fdt_region.c to common/fdt_region.c . This is
necessary only when CONFIG_(SPL_TPL_)_FIT_SIGNATURE is enabled.
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
---
I am resending this after two years since v1.
My previous attempt sank by this comment:
http://patchwork.ozlabs.org/project/uboot/patch/1521623017-29312-5-git-send-email-yamada.masahiro at socionext.com/#1881196
Two years have passed, but I still do not see this file
in upstream DTC.
Changes in v2:
- rebase
common/Makefile | 1 +
{lib/libfdt => common}/fdt_region.c | 0
lib/libfdt/Makefile | 3 ---
tools/Makefile | 12 ++++--------
4 files changed, 5 insertions(+), 11 deletions(-)
rename {lib/libfdt => common}/fdt_region.c (100%)
diff --git a/common/Makefile b/common/Makefile
index 702f2396cf..a3f3faf479 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -110,6 +110,7 @@ obj-y += image.o
obj-$(CONFIG_ANDROID_AB) += android_ab.o
obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o image-android-dt.o
obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += image-fdt.o
+obj-$(CONFIG_$(SPL_TPL_)FIT_SIGNATURE) += fdt_region.o
obj-$(CONFIG_$(SPL_TPL_)FIT) += image-fit.o
obj-$(CONFIG_$(SPL_)MULTI_DTB_FIT) += boot_fit.o common_fit.o
obj-$(CONFIG_IMAGE_SIGN_INFO) += image-sig.o
diff --git a/lib/libfdt/fdt_region.c b/common/fdt_region.c
similarity index 100%
rename from lib/libfdt/fdt_region.c
rename to common/fdt_region.c
diff --git a/lib/libfdt/Makefile b/lib/libfdt/Makefile
index 878659f99e..1fe50ecbe5 100644
--- a/lib/libfdt/Makefile
+++ b/lib/libfdt/Makefile
@@ -15,8 +15,5 @@ obj-y += \
obj-$(CONFIG_OF_LIBFDT_OVERLAY) += fdt_overlay.o
-# U-Boot own file
-obj-y += fdt_region.o
-
ccflags-y := -I$(srctree)/scripts/dtc/libfdt \
-DFDT_ASSUME_MASK=$(CONFIG_$(SPL_TPL_)OF_LIBFDT_ASSUME_MASK)
diff --git a/tools/Makefile b/tools/Makefile
index bfdbb1339c..ee9077ca82 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -63,13 +63,8 @@ FIT_CIPHER_OBJS-$(CONFIG_FIT_CIPHER) := common/image-cipher.o
# The following files are synced with upstream DTC.
# Use synced versions from scripts/dtc/libfdt/.
-LIBFDT_SRCS_SYNCED := fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c \
- fdt_strerror.c fdt_empty_tree.c fdt_addresses.c fdt_overlay.c
-# Use U-Boot own versions from lib/libfdt/.
-LIBFDT_SRCS_UNSYNCED := fdt_region.c
-
-LIBFDT_OBJS := $(addprefix libfdt/, $(patsubst %.c, %.o, $(LIBFDT_SRCS_SYNCED))) \
- $(addprefix lib/libfdt/, $(patsubst %.c, %.o, $(LIBFDT_SRCS_UNSYNCED)))
+LIBFDT_OBJS := $(addprefix libfdt/, fdt.o fdt_ro.o fdt_wip.o fdt_sw.o fdt_rw.o \
+ fdt_strerror.o fdt_empty_tree.o fdt_addresses.o fdt_overlay.o)
RSA_OBJS-$(CONFIG_FIT_SIGNATURE) := $(addprefix lib/rsa/, \
rsa-sign.o rsa-verify.o rsa-checksum.o \
@@ -86,6 +81,7 @@ dumpimage-mkimage-objs := aisimage.o \
$(FIT_OBJS-y) \
$(FIT_SIG_OBJS-y) \
$(FIT_CIPHER_OBJS-y) \
+ common/fdt_region.o \
common/bootm.o \
lib/crc32.o \
default_image.o \
@@ -210,7 +206,7 @@ hostprogs-$(CONFIG_STATIC_RELA) += relocate-rela
hostprogs-$(CONFIG_RISCV) += prelink-riscv
hostprogs-y += fdtgrep
-fdtgrep-objs += $(LIBFDT_OBJS) fdtgrep.o
+fdtgrep-objs += $(LIBFDT_OBJS) common/fdt_region.o fdtgrep.o
ifneq ($(TOOLS_ONLY),y)
hostprogs-y += spl_size_limit
--
2.25.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 3/3] libfdt: split fdt_region declarations out to <fdt_region.h>
2020-04-16 9:30 [PATCH v2 0/3] libfdt: make lib/libfdt/ contain only wrappers Masahiro Yamada
2020-04-16 9:30 ` [PATCH v2 1/3] libfdt: migrate fdt_ro.c to a wrapper of scripts/dtc/libfdt/fdt_ro.c Masahiro Yamada
2020-04-16 9:30 ` [PATCH v2 2/3] fdt_region: move fdt_region.c to common/ from lib/libfdt/ Masahiro Yamada
@ 2020-04-16 9:30 ` Masahiro Yamada
2020-04-27 3:07 ` sjg at google.com
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Masahiro Yamada @ 2020-04-16 9:30 UTC (permalink / raw)
To: u-boot
fdt_region APIs are not part of libfdt. They are U-Boot extension
for the verified boot. Split the declarations related to fdt_region
out of <fdt_region.h>. This allows <linux/libfdt.h> to become a
simple wrapper file, like Linux does.
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
---
I am resending this after two years since v1.
My previous attempt sank by this comment:
http://patchwork.ozlabs.org/project/uboot/patch/1521623017-29312-6-git-send-email-yamada.masahiro at socionext.com/#1881345
Two years have passed, but I still do not see such code
in upstream DTC.
Changes in v2:
- Rebase
common/fdt_region.c | 1 +
common/image-fit-sig.c | 1 +
include/fdt_region.h | 304 +++++++++++++++++++++++++++++++++++++++++
include/linux/libfdt.h | 299 ----------------------------------------
tools/fdtgrep.c | 1 +
tools/image-host.c | 1 +
6 files changed, 308 insertions(+), 299 deletions(-)
create mode 100644 include/fdt_region.h
diff --git a/common/fdt_region.c b/common/fdt_region.c
index 7e9fa9272e..bf0a9be730 100644
--- a/common/fdt_region.c
+++ b/common/fdt_region.c
@@ -6,6 +6,7 @@
*/
#include <linux/libfdt_env.h>
+#include <fdt_region.h>
#ifndef USE_HOSTCC
#include <fdt.h>
diff --git a/common/image-fit-sig.c b/common/image-fit-sig.c
index f6caeb0c59..64a181266e 100644
--- a/common/image-fit-sig.c
+++ b/common/image-fit-sig.c
@@ -11,6 +11,7 @@
#include <malloc.h>
DECLARE_GLOBAL_DATA_PTR;
#endif /* !USE_HOSTCC*/
+#include <fdt_region.h>
#include <image.h>
#include <u-boot/rsa.h>
#include <u-boot/rsa-checksum.h>
diff --git a/include/fdt_region.h b/include/fdt_region.h
new file mode 100644
index 0000000000..ff7a1ccb9a
--- /dev/null
+++ b/include/fdt_region.h
@@ -0,0 +1,304 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _FDT_REGION_H
+#define _FDT_REGION_H
+
+#ifndef SWIG /* Not available in Python */
+struct fdt_region {
+ int offset;
+ int size;
+};
+
+/*
+ * Flags for fdt_find_regions()
+ *
+ * Add a region for the string table (always the last region)
+ */
+#define FDT_REG_ADD_STRING_TAB (1 << 0)
+
+/*
+ * Add all supernodes of a matching node/property, useful for creating a
+ * valid subset tree
+ */
+#define FDT_REG_SUPERNODES (1 << 1)
+
+/* Add the FDT_BEGIN_NODE tags of subnodes, including their names */
+#define FDT_REG_DIRECT_SUBNODES (1 << 2)
+
+/* Add all subnodes of a matching node */
+#define FDT_REG_ALL_SUBNODES (1 << 3)
+
+/* Add a region for the mem_rsvmap table (always the first region) */
+#define FDT_REG_ADD_MEM_RSVMAP (1 << 4)
+
+/* Indicates what an fdt part is (node, property, value) */
+#define FDT_IS_NODE (1 << 0)
+#define FDT_IS_PROP (1 << 1)
+#define FDT_IS_VALUE (1 << 2) /* not supported */
+#define FDT_IS_COMPAT (1 << 3) /* used internally */
+#define FDT_NODE_HAS_PROP (1 << 4) /* node contains prop */
+
+#define FDT_ANY_GLOBAL (FDT_IS_NODE | FDT_IS_PROP | FDT_IS_VALUE | \
+ FDT_IS_COMPAT)
+#define FDT_IS_ANY 0x1f /* all the above */
+
+/* We set a reasonable limit on the number of nested nodes */
+#define FDT_MAX_DEPTH 32
+
+/* Decribes what we want to include from the current tag */
+enum want_t {
+ WANT_NOTHING,
+ WANT_NODES_ONLY, /* No properties */
+ WANT_NODES_AND_PROPS, /* Everything for one level */
+ WANT_ALL_NODES_AND_PROPS /* Everything for all levels */
+};
+
+/* Keeps track of the state at parent nodes */
+struct fdt_subnode_stack {
+ int offset; /* Offset of node */
+ enum want_t want; /* The 'want' value here */
+ int included; /* 1 if we included this node, 0 if not */
+};
+
+struct fdt_region_ptrs {
+ int depth; /* Current tree depth */
+ int done; /* What we have completed scanning */
+ enum want_t want; /* What we are currently including */
+ char *end; /* Pointer to end of full node path */
+ int nextoffset; /* Next node offset to check */
+};
+
+/* The state of our finding algortihm */
+struct fdt_region_state {
+ struct fdt_subnode_stack stack[FDT_MAX_DEPTH]; /* node stack */
+ struct fdt_region *region; /* Contains list of regions found */
+ int count; /* Numnber of regions found */
+ const void *fdt; /* FDT blob */
+ int max_regions; /* Maximum regions to find */
+ int can_merge; /* 1 if we can merge with previous region */
+ int start; /* Start position of current region */
+ struct fdt_region_ptrs ptrs; /* Pointers for what we are up to */
+};
+
+/**
+ * fdt_find_regions() - find regions in device tree
+ *
+ * Given a list of nodes to include and properties to exclude, find
+ * the regions of the device tree which describe those included parts.
+ *
+ * The intent is to get a list of regions which will be invariant provided
+ * those parts are invariant. For example, if you request a list of regions
+ * for all nodes but exclude the property "data", then you will get the
+ * same region contents regardless of any change to "data" properties.
+ *
+ * This function can be used to produce a byte-stream to send to a hashing
+ * function to verify that critical parts of the FDT have not changed.
+ *
+ * Nodes which are given in 'inc' are included in the region list, as
+ * are the names of the immediate subnodes nodes (but not the properties
+ * or subnodes of those subnodes).
+ *
+ * For eaxample "/" means to include the root node, all root properties
+ * and the FDT_BEGIN_NODE and FDT_END_NODE of all subnodes of /. The latter
+ * ensures that we capture the names of the subnodes. In a hashing situation
+ * it prevents the root node from changing@all Any change to non-excluded
+ * properties, names of subnodes or number of subnodes would be detected.
+ *
+ * When used with FITs this provides the ability to hash and sign parts of
+ * the FIT based on different configurations in the FIT. Then it is
+ * impossible to change anything about that configuration (include images
+ * attached to the configuration), but it may be possible to add new
+ * configurations, new images or new signatures within the existing
+ * framework.
+ *
+ * Adding new properties to a device tree may result in the string table
+ * being extended (if the new property names are different from those
+ * already added). This function can optionally include a region for
+ * the string table so that this can be part of the hash too.
+ *
+ * The device tree header is not included in the list.
+ *
+ * @fdt: Device tree to check
+ * @inc: List of node paths to included
+ * @inc_count: Number of node paths in list
+ * @exc_prop: List of properties names to exclude
+ * @exc_prop_count: Number of properties in exclude list
+ * @region: Returns list of regions
+ * @max_region: Maximum length of region list
+ * @path: Pointer to a temporary string for the function to use for
+ * building path names
+ * @path_len: Length of path, must be large enough to hold the longest
+ * path in the tree
+ * @add_string_tab: 1 to add a region for the string table
+ * @return number of regions in list. If this is >max_regions then the
+ * region array was exhausted. You should increase max_regions and try
+ * the call again.
+ */
+int fdt_find_regions(const void *fdt, char * const inc[], int inc_count,
+ char * const exc_prop[], int exc_prop_count,
+ struct fdt_region region[], int max_regions,
+ char *path, int path_len, int add_string_tab);
+
+/**
+ * fdt_first_region() - find regions in device tree
+ *
+ * Given a nodes and properties to include and properties to exclude, find
+ * the regions of the device tree which describe those included parts.
+ *
+ * The use for this function is twofold. Firstly it provides a convenient
+ * way of performing a structure-aware grep of the tree. For example it is
+ * possible to grep for a node and get all the properties associated with
+ * that node. Trees can be subsetted easily, by specifying the nodes that
+ * are required, and then writing out the regions returned by this function.
+ * This is useful for small resource-constrained systems, such as boot
+ * loaders, which want to use an FDT but do not need to know about all of
+ * it.
+ *
+ * Secondly it makes it easy to hash parts of the tree and detect changes.
+ * The intent is to get a list of regions which will be invariant provided
+ * those parts are invariant. For example, if you request a list of regions
+ * for all nodes but exclude the property "data", then you will get the
+ * same region contents regardless of any change to "data" properties.
+ *
+ * This function can be used to produce a byte-stream to send to a hashing
+ * function to verify that critical parts of the FDT have not changed.
+ * Note that semantically null changes in order could still cause false
+ * hash misses. Such reordering might happen if the tree is regenerated
+ * from source, and nodes are reordered (the bytes-stream will be emitted
+ * in a different order and many hash functions will detect this). However
+ * if an existing tree is modified using libfdt functions, such as
+ * fdt_add_subnode() and fdt_setprop(), then this problem is avoided.
+ *
+ * The nodes/properties to include/exclude are defined by a function
+ * provided by the caller. This function is called for each node and
+ * property, and must return:
+ *
+ * 0 - to exclude this part
+ * 1 - to include this part
+ * -1 - for FDT_IS_PROP only: no information is available, so include
+ * if its containing node is included
+ *
+ * The last case is only used to deal with properties. Often a property is
+ * included if its containing node is included - this is the case where
+ * -1 is returned.. However if the property is specifically required to be
+ * included/excluded, then 0 or 1 can be returned. Note that including a
+ * property when the FDT_REG_SUPERNODES flag is given will force its
+ * containing node to be included since it is not valid to have a property
+ * that is not in a node.
+ *
+ * Using the information provided, the inclusion of a node can be controlled
+ * either by a node name or its compatible string, or any other property
+ * that the function can determine.
+ *
+ * As an example, including node "/" means to include the root node and all
+ * root properties. A flag provides a way of also including supernodes (of
+ * which there is none for the root node), and another flag includes
+ * immediate subnodes, so in this case we would get the FDT_BEGIN_NODE and
+ * FDT_END_NODE of all subnodes of /.
+ *
+ * The subnode feature helps in a hashing situation since it prevents the
+ * root node from changing at all. Any change to non-excluded properties,
+ * names of subnodes or number of subnodes would be detected.
+ *
+ * When used with FITs this provides the ability to hash and sign parts of
+ * the FIT based on different configurations in the FIT. Then it is
+ * impossible to change anything about that configuration (include images
+ * attached to the configuration), but it may be possible to add new
+ * configurations, new images or new signatures within the existing
+ * framework.
+ *
+ * Adding new properties to a device tree may result in the string table
+ * being extended (if the new property names are different from those
+ * already added). This function can optionally include a region for
+ * the string table so that this can be part of the hash too. This is always
+ * the last region.
+ *
+ * The FDT also has a mem_rsvmap table which can also be included, and is
+ * always the first region if so.
+ *
+ * The device tree header is not included in the region list. Since the
+ * contents of the FDT are changing (shrinking, often), the caller will need
+ * to regenerate the header anyway.
+ *
+ * @fdt: Device tree to check
+ * @h_include: Function to call to determine whether to include a part or
+ * not:
+ *
+ * @priv: Private pointer as passed to fdt_find_regions()
+ * @fdt: Pointer to FDT blob
+ * @offset: Offset of this node / property
+ * @type: Type of this part, FDT_IS_...
+ * @data: Pointer to data (node name, property name, compatible
+ * string, value (not yet supported)
+ * @size: Size of data, or 0 if none
+ * @return 0 to exclude, 1 to include, -1 if no information is
+ * available
+ * @priv: Private pointer passed to h_include
+ * @region: Returns list of regions, sorted by offset
+ * @max_regions: Maximum length of region list
+ * @path: Pointer to a temporary string for the function to use for
+ * building path names
+ * @path_len: Length of path, must be large enough to hold the longest
+ * path in the tree
+ * @flags: Various flags that control the region algortihm, see
+ * FDT_REG_...
+ * @return number of regions in list. If this is >max_regions then the
+ * region array was exhausted. You should increase max_regions and try
+ * the call again. Only the first max_regions elements are available in the
+ * array.
+ *
+ * On error a -ve value is return, which can be:
+ *
+ * -FDT_ERR_BADSTRUCTURE (too deep or more END tags than BEGIN tags
+ * -FDT_ERR_BADLAYOUT
+ * -FDT_ERR_NOSPACE (path area is too small)
+ */
+int fdt_first_region(const void *fdt,
+ int (*h_include)(void *priv, const void *fdt, int offset,
+ int type, const char *data, int size),
+ void *priv, struct fdt_region *region,
+ char *path, int path_len, int flags,
+ struct fdt_region_state *info);
+
+/** fdt_next_region() - find next region
+ *
+ * See fdt_first_region() for full description. This function finds the
+ * next region according to the provided parameters, which must be the same
+ * as passed to fdt_first_region().
+ *
+ * This function can additionally return -FDT_ERR_NOTFOUND when there are no
+ * more regions
+ */
+int fdt_next_region(const void *fdt,
+ int (*h_include)(void *priv, const void *fdt, int offset,
+ int type, const char *data, int size),
+ void *priv, struct fdt_region *region,
+ char *path, int path_len, int flags,
+ struct fdt_region_state *info);
+
+/**
+ * fdt_add_alias_regions() - find aliases that point to existing regions
+ *
+ * Once a device tree grep is complete some of the nodes will be present
+ * and some will have been dropped. This function checks all the alias nodes
+ * to figure out which points point to nodes which are still present. These
+ * aliases need to be kept, along with the nodes they reference.
+ *
+ * Given a list of regions function finds the aliases that still apply and
+ * adds more regions to the list for these. This function is called after
+ * fdt_next_region() has finished returning regions and requires the same
+ * state.
+ *
+ * @fdt: Device tree file to reference
+ * @region: List of regions that will be kept
+ * @count: Number of regions
+ * @max_regions: Number of entries that can fit in @region
+ * @info: Region state as returned from fdt_next_region()
+ * @return new number of regions in @region (i.e. count + the number added)
+ * or -FDT_ERR_NOSPACE if there was not enough space.
+ */
+int fdt_add_alias_regions(const void *fdt, struct fdt_region *region, int count,
+ int max_regions, struct fdt_region_state *info);
+#endif /* SWIG */
+
+#endif /* _FDT_REGION_H */
diff --git a/include/linux/libfdt.h b/include/linux/libfdt.h
index eeb2344971..39dbc88aa5 100644
--- a/include/linux/libfdt.h
+++ b/include/linux/libfdt.h
@@ -8,305 +8,6 @@
#include "../../scripts/dtc/libfdt/libfdt.h"
/* U-Boot local hacks */
-
-#ifndef SWIG /* Not available in Python */
-struct fdt_region {
- int offset;
- int size;
-};
-
-/*
- * Flags for fdt_find_regions()
- *
- * Add a region for the string table (always the last region)
- */
-#define FDT_REG_ADD_STRING_TAB (1 << 0)
-
-/*
- * Add all supernodes of a matching node/property, useful for creating a
- * valid subset tree
- */
-#define FDT_REG_SUPERNODES (1 << 1)
-
-/* Add the FDT_BEGIN_NODE tags of subnodes, including their names */
-#define FDT_REG_DIRECT_SUBNODES (1 << 2)
-
-/* Add all subnodes of a matching node */
-#define FDT_REG_ALL_SUBNODES (1 << 3)
-
-/* Add a region for the mem_rsvmap table (always the first region) */
-#define FDT_REG_ADD_MEM_RSVMAP (1 << 4)
-
-/* Indicates what an fdt part is (node, property, value) */
-#define FDT_IS_NODE (1 << 0)
-#define FDT_IS_PROP (1 << 1)
-#define FDT_IS_VALUE (1 << 2) /* not supported */
-#define FDT_IS_COMPAT (1 << 3) /* used internally */
-#define FDT_NODE_HAS_PROP (1 << 4) /* node contains prop */
-
-#define FDT_ANY_GLOBAL (FDT_IS_NODE | FDT_IS_PROP | FDT_IS_VALUE | \
- FDT_IS_COMPAT)
-#define FDT_IS_ANY 0x1f /* all the above */
-
-/* We set a reasonable limit on the number of nested nodes */
-#define FDT_MAX_DEPTH 32
-
-/* Decribes what we want to include from the current tag */
-enum want_t {
- WANT_NOTHING,
- WANT_NODES_ONLY, /* No properties */
- WANT_NODES_AND_PROPS, /* Everything for one level */
- WANT_ALL_NODES_AND_PROPS /* Everything for all levels */
-};
-
-/* Keeps track of the state at parent nodes */
-struct fdt_subnode_stack {
- int offset; /* Offset of node */
- enum want_t want; /* The 'want' value here */
- int included; /* 1 if we included this node, 0 if not */
-};
-
-struct fdt_region_ptrs {
- int depth; /* Current tree depth */
- int done; /* What we have completed scanning */
- enum want_t want; /* What we are currently including */
- char *end; /* Pointer to end of full node path */
- int nextoffset; /* Next node offset to check */
-};
-
-/* The state of our finding algortihm */
-struct fdt_region_state {
- struct fdt_subnode_stack stack[FDT_MAX_DEPTH]; /* node stack */
- struct fdt_region *region; /* Contains list of regions found */
- int count; /* Numnber of regions found */
- const void *fdt; /* FDT blob */
- int max_regions; /* Maximum regions to find */
- int can_merge; /* 1 if we can merge with previous region */
- int start; /* Start position of current region */
- struct fdt_region_ptrs ptrs; /* Pointers for what we are up to */
-};
-
-/**
- * fdt_find_regions() - find regions in device tree
- *
- * Given a list of nodes to include and properties to exclude, find
- * the regions of the device tree which describe those included parts.
- *
- * The intent is to get a list of regions which will be invariant provided
- * those parts are invariant. For example, if you request a list of regions
- * for all nodes but exclude the property "data", then you will get the
- * same region contents regardless of any change to "data" properties.
- *
- * This function can be used to produce a byte-stream to send to a hashing
- * function to verify that critical parts of the FDT have not changed.
- *
- * Nodes which are given in 'inc' are included in the region list, as
- * are the names of the immediate subnodes nodes (but not the properties
- * or subnodes of those subnodes).
- *
- * For eaxample "/" means to include the root node, all root properties
- * and the FDT_BEGIN_NODE and FDT_END_NODE of all subnodes of /. The latter
- * ensures that we capture the names of the subnodes. In a hashing situation
- * it prevents the root node from changing@all Any change to non-excluded
- * properties, names of subnodes or number of subnodes would be detected.
- *
- * When used with FITs this provides the ability to hash and sign parts of
- * the FIT based on different configurations in the FIT. Then it is
- * impossible to change anything about that configuration (include images
- * attached to the configuration), but it may be possible to add new
- * configurations, new images or new signatures within the existing
- * framework.
- *
- * Adding new properties to a device tree may result in the string table
- * being extended (if the new property names are different from those
- * already added). This function can optionally include a region for
- * the string table so that this can be part of the hash too.
- *
- * The device tree header is not included in the list.
- *
- * @fdt: Device tree to check
- * @inc: List of node paths to included
- * @inc_count: Number of node paths in list
- * @exc_prop: List of properties names to exclude
- * @exc_prop_count: Number of properties in exclude list
- * @region: Returns list of regions
- * @max_region: Maximum length of region list
- * @path: Pointer to a temporary string for the function to use for
- * building path names
- * @path_len: Length of path, must be large enough to hold the longest
- * path in the tree
- * @add_string_tab: 1 to add a region for the string table
- * @return number of regions in list. If this is >max_regions then the
- * region array was exhausted. You should increase max_regions and try
- * the call again.
- */
-int fdt_find_regions(const void *fdt, char * const inc[], int inc_count,
- char * const exc_prop[], int exc_prop_count,
- struct fdt_region region[], int max_regions,
- char *path, int path_len, int add_string_tab);
-
-/**
- * fdt_first_region() - find regions in device tree
- *
- * Given a nodes and properties to include and properties to exclude, find
- * the regions of the device tree which describe those included parts.
- *
- * The use for this function is twofold. Firstly it provides a convenient
- * way of performing a structure-aware grep of the tree. For example it is
- * possible to grep for a node and get all the properties associated with
- * that node. Trees can be subsetted easily, by specifying the nodes that
- * are required, and then writing out the regions returned by this function.
- * This is useful for small resource-constrained systems, such as boot
- * loaders, which want to use an FDT but do not need to know about all of
- * it.
- *
- * Secondly it makes it easy to hash parts of the tree and detect changes.
- * The intent is to get a list of regions which will be invariant provided
- * those parts are invariant. For example, if you request a list of regions
- * for all nodes but exclude the property "data", then you will get the
- * same region contents regardless of any change to "data" properties.
- *
- * This function can be used to produce a byte-stream to send to a hashing
- * function to verify that critical parts of the FDT have not changed.
- * Note that semantically null changes in order could still cause false
- * hash misses. Such reordering might happen if the tree is regenerated
- * from source, and nodes are reordered (the bytes-stream will be emitted
- * in a different order and many hash functions will detect this). However
- * if an existing tree is modified using libfdt functions, such as
- * fdt_add_subnode() and fdt_setprop(), then this problem is avoided.
- *
- * The nodes/properties to include/exclude are defined by a function
- * provided by the caller. This function is called for each node and
- * property, and must return:
- *
- * 0 - to exclude this part
- * 1 - to include this part
- * -1 - for FDT_IS_PROP only: no information is available, so include
- * if its containing node is included
- *
- * The last case is only used to deal with properties. Often a property is
- * included if its containing node is included - this is the case where
- * -1 is returned.. However if the property is specifically required to be
- * included/excluded, then 0 or 1 can be returned. Note that including a
- * property when the FDT_REG_SUPERNODES flag is given will force its
- * containing node to be included since it is not valid to have a property
- * that is not in a node.
- *
- * Using the information provided, the inclusion of a node can be controlled
- * either by a node name or its compatible string, or any other property
- * that the function can determine.
- *
- * As an example, including node "/" means to include the root node and all
- * root properties. A flag provides a way of also including supernodes (of
- * which there is none for the root node), and another flag includes
- * immediate subnodes, so in this case we would get the FDT_BEGIN_NODE and
- * FDT_END_NODE of all subnodes of /.
- *
- * The subnode feature helps in a hashing situation since it prevents the
- * root node from changing at all. Any change to non-excluded properties,
- * names of subnodes or number of subnodes would be detected.
- *
- * When used with FITs this provides the ability to hash and sign parts of
- * the FIT based on different configurations in the FIT. Then it is
- * impossible to change anything about that configuration (include images
- * attached to the configuration), but it may be possible to add new
- * configurations, new images or new signatures within the existing
- * framework.
- *
- * Adding new properties to a device tree may result in the string table
- * being extended (if the new property names are different from those
- * already added). This function can optionally include a region for
- * the string table so that this can be part of the hash too. This is always
- * the last region.
- *
- * The FDT also has a mem_rsvmap table which can also be included, and is
- * always the first region if so.
- *
- * The device tree header is not included in the region list. Since the
- * contents of the FDT are changing (shrinking, often), the caller will need
- * to regenerate the header anyway.
- *
- * @fdt: Device tree to check
- * @h_include: Function to call to determine whether to include a part or
- * not:
- *
- * @priv: Private pointer as passed to fdt_find_regions()
- * @fdt: Pointer to FDT blob
- * @offset: Offset of this node / property
- * @type: Type of this part, FDT_IS_...
- * @data: Pointer to data (node name, property name, compatible
- * string, value (not yet supported)
- * @size: Size of data, or 0 if none
- * @return 0 to exclude, 1 to include, -1 if no information is
- * available
- * @priv: Private pointer passed to h_include
- * @region: Returns list of regions, sorted by offset
- * @max_regions: Maximum length of region list
- * @path: Pointer to a temporary string for the function to use for
- * building path names
- * @path_len: Length of path, must be large enough to hold the longest
- * path in the tree
- * @flags: Various flags that control the region algortihm, see
- * FDT_REG_...
- * @return number of regions in list. If this is >max_regions then the
- * region array was exhausted. You should increase max_regions and try
- * the call again. Only the first max_regions elements are available in the
- * array.
- *
- * On error a -ve value is return, which can be:
- *
- * -FDT_ERR_BADSTRUCTURE (too deep or more END tags than BEGIN tags
- * -FDT_ERR_BADLAYOUT
- * -FDT_ERR_NOSPACE (path area is too small)
- */
-int fdt_first_region(const void *fdt,
- int (*h_include)(void *priv, const void *fdt, int offset,
- int type, const char *data, int size),
- void *priv, struct fdt_region *region,
- char *path, int path_len, int flags,
- struct fdt_region_state *info);
-
-/** fdt_next_region() - find next region
- *
- * See fdt_first_region() for full description. This function finds the
- * next region according to the provided parameters, which must be the same
- * as passed to fdt_first_region().
- *
- * This function can additionally return -FDT_ERR_NOTFOUND when there are no
- * more regions
- */
-int fdt_next_region(const void *fdt,
- int (*h_include)(void *priv, const void *fdt, int offset,
- int type, const char *data, int size),
- void *priv, struct fdt_region *region,
- char *path, int path_len, int flags,
- struct fdt_region_state *info);
-
-/**
- * fdt_add_alias_regions() - find aliases that point to existing regions
- *
- * Once a device tree grep is complete some of the nodes will be present
- * and some will have been dropped. This function checks all the alias nodes
- * to figure out which points point to nodes which are still present. These
- * aliases need to be kept, along with the nodes they reference.
- *
- * Given a list of regions function finds the aliases that still apply and
- * adds more regions to the list for these. This function is called after
- * fdt_next_region() has finished returning regions and requires the same
- * state.
- *
- * @fdt: Device tree file to reference
- * @region: List of regions that will be kept
- * @count: Number of regions
- * @max_regions: Number of entries that can fit in @region
- * @info: Region state as returned from fdt_next_region()
- * @return new number of regions in @region (i.e. count + the number added)
- * or -FDT_ERR_NOSPACE if there was not enough space.
- */
-int fdt_add_alias_regions(const void *fdt, struct fdt_region *region, int count,
- int max_regions, struct fdt_region_state *info);
-#endif /* SWIG */
-
extern struct fdt_header *working_fdt; /* Pointer to the working fdt */
#endif /* _INCLUDE_LIBFDT_H_ */
diff --git a/tools/fdtgrep.c b/tools/fdtgrep.c
index 2a8058f57f..7e168a1e6b 100644
--- a/tools/fdtgrep.c
+++ b/tools/fdtgrep.c
@@ -17,6 +17,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <fdt_region.h>
#include "fdt_host.h"
#include "libfdt_internal.h"
diff --git a/tools/image-host.c b/tools/image-host.c
index 76a361b9d6..1b4bc0eb58 100644
--- a/tools/image-host.c
+++ b/tools/image-host.c
@@ -10,6 +10,7 @@
#include "mkimage.h"
#include <bootm.h>
+#include <fdt_region.h>
#include <image.h>
#include <version.h>
--
2.25.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 3/3] libfdt: split fdt_region declarations out to <fdt_region.h>
2020-04-16 9:30 [PATCH v2 0/3] libfdt: make lib/libfdt/ contain only wrappers Masahiro Yamada
` (2 preceding siblings ...)
2020-04-16 9:30 ` [PATCH v2 3/3] libfdt: split fdt_region declarations out to <fdt_region.h> Masahiro Yamada
@ 2020-04-27 3:07 ` sjg at google.com
2020-04-27 3:07 ` [PATCH v2 2/3] fdt_region: move fdt_region.c to common/ from lib/libfdt/ sjg at google.com
2020-04-27 3:07 ` [PATCH v2 1/3] libfdt: migrate fdt_ro.c to a wrapper of scripts/dtc/libfdt/fdt_ro.c sjg at google.com
5 siblings, 0 replies; 7+ messages in thread
From: sjg at google.com @ 2020-04-27 3:07 UTC (permalink / raw)
To: u-boot
fdt_region APIs are not part of libfdt. They are U-Boot extension
for the verified boot. Split the declarations related to fdt_region
out of <fdt_region.h>. This allows <linux/libfdt.h> to become a
simple wrapper file, like Linux does.
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
---
I am resending this after two years since v1.
My previous attempt sank by this comment:
http://patchwork.ozlabs.org/project/uboot/patch/1521623017-29312-6-git-send-email-yamada.masahiro at socionext.com/#1881345
Two years have passed, but I still do not see such code
in upstream DTC.
Changes in v2:
- Rebase
common/fdt_region.c | 1 +
common/image-fit-sig.c | 1 +
include/fdt_region.h | 304 +++++++++++++++++++++++++++++++++++++++++
include/linux/libfdt.h | 299 ----------------------------------------
tools/fdtgrep.c | 1 +
tools/image-host.c | 1 +
6 files changed, 308 insertions(+), 299 deletions(-)
create mode 100644 include/fdt_region.h
Applied to u-boot-dm, thanks!
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 2/3] fdt_region: move fdt_region.c to common/ from lib/libfdt/
2020-04-16 9:30 [PATCH v2 0/3] libfdt: make lib/libfdt/ contain only wrappers Masahiro Yamada
` (3 preceding siblings ...)
2020-04-27 3:07 ` sjg at google.com
@ 2020-04-27 3:07 ` sjg at google.com
2020-04-27 3:07 ` [PATCH v2 1/3] libfdt: migrate fdt_ro.c to a wrapper of scripts/dtc/libfdt/fdt_ro.c sjg at google.com
5 siblings, 0 replies; 7+ messages in thread
From: sjg at google.com @ 2020-04-27 3:07 UTC (permalink / raw)
To: u-boot
My goal is to sync lib/libfdt/ with scripts/dtc/libfdt/, that is,
make lib/libfdt/ contain only wrapper files.
fdt_region.c was written only for U-Boot to implement the verified
boot. So, this belongs to the same group as common/fdt_support.c,
which is a collection of U-Boot own fdt helpers.
Move lib/libfdt/fdt_region.c to common/fdt_region.c . This is
necessary only when CONFIG_(SPL_TPL_)_FIT_SIGNATURE is enabled.
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
---
I am resending this after two years since v1.
My previous attempt sank by this comment:
http://patchwork.ozlabs.org/project/uboot/patch/1521623017-29312-5-git-send-email-yamada.masahiro at socionext.com/#1881196
Two years have passed, but I still do not see this file
in upstream DTC.
Changes in v2:
- rebase
common/Makefile | 1 +
{lib/libfdt => common}/fdt_region.c | 0
lib/libfdt/Makefile | 3 ---
tools/Makefile | 12 ++++--------
4 files changed, 5 insertions(+), 11 deletions(-)
rename {lib/libfdt => common}/fdt_region.c (100%)
Applied to u-boot-dm, thanks!
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 1/3] libfdt: migrate fdt_ro.c to a wrapper of scripts/dtc/libfdt/fdt_ro.c
2020-04-16 9:30 [PATCH v2 0/3] libfdt: make lib/libfdt/ contain only wrappers Masahiro Yamada
` (4 preceding siblings ...)
2020-04-27 3:07 ` [PATCH v2 2/3] fdt_region: move fdt_region.c to common/ from lib/libfdt/ sjg at google.com
@ 2020-04-27 3:07 ` sjg at google.com
5 siblings, 0 replies; 7+ messages in thread
From: sjg at google.com @ 2020-04-27 3:07 UTC (permalink / raw)
To: u-boot
There is no essential difference between scripts/dtc/libfdt/fdt_ro.c
and lib/libfdt/fdt_ro.c
Migrate to a simple wrapper like the other files.
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
---
Changes in v2:
- refactor tools/Makefile
lib/libfdt/Makefile | 6 +-
lib/libfdt/fdt_ro.c | 925 +-----------------------------------------
tools/Makefile | 5 +-
tools/libfdt/fdt_ro.c | 2 +
4 files changed, 6 insertions(+), 932 deletions(-)
create mode 100644 tools/libfdt/fdt_ro.c
Applied to u-boot-dm, thanks!
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2020-04-27 3:07 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-04-16 9:30 [PATCH v2 0/3] libfdt: make lib/libfdt/ contain only wrappers Masahiro Yamada
2020-04-16 9:30 ` [PATCH v2 1/3] libfdt: migrate fdt_ro.c to a wrapper of scripts/dtc/libfdt/fdt_ro.c Masahiro Yamada
2020-04-16 9:30 ` [PATCH v2 2/3] fdt_region: move fdt_region.c to common/ from lib/libfdt/ Masahiro Yamada
2020-04-16 9:30 ` [PATCH v2 3/3] libfdt: split fdt_region declarations out to <fdt_region.h> Masahiro Yamada
2020-04-27 3:07 ` sjg at google.com
2020-04-27 3:07 ` [PATCH v2 2/3] fdt_region: move fdt_region.c to common/ from lib/libfdt/ sjg at google.com
2020-04-27 3:07 ` [PATCH v2 1/3] libfdt: migrate fdt_ro.c to a wrapper of scripts/dtc/libfdt/fdt_ro.c sjg at google.com
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.