diff options
author | David Gibson <david@gibson.dropbear.id.au> | 2018-03-18 00:12:12 +1100 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-07-19 07:01:12 +0200 |
commit | 0d851d49c5299975168b3187d90530008c47d958 (patch) | |
tree | 033846fe64c2973f3690b06182d4ba1d74c258d0 /cpukit/dtc/libfdt | |
parent | libfdt: Add fdt_header_size() (diff) | |
download | rtems-0d851d49c5299975168b3187d90530008c47d958.tar.bz2 |
libfdt: Add fdt_check_full() function
This new function implements a complete and thorough check of an fdt blob's
structure. Given a buffer containing an fdt, it should return 0 only if
the fdt within is structurally sound in all regards. It doesn't check
anything about the blob's contents (i.e. the actual values of the nodes and
properties), of course.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Tested-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Reviewed-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Reviewed-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'cpukit/dtc/libfdt')
-rw-r--r-- | cpukit/dtc/libfdt/fdt_ro.c | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/cpukit/dtc/libfdt/fdt_ro.c b/cpukit/dtc/libfdt/fdt_ro.c index c74b9629af..4ba7c93313 100644 --- a/cpukit/dtc/libfdt/fdt_ro.c +++ b/cpukit/dtc/libfdt/fdt_ro.c @@ -857,3 +857,66 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset, return offset; /* error from fdt_next_node() */ } + +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; + } + } +} |