Commit graph

22 commits

Author SHA1 Message Date
David Gibson
812b1956a0 libfdt: Tweak data handling to satisfy Coverity
In libfdt we often sanity test fdt_totalsize(fdt) fairly early, then
trust it (but *only* that header field) for the remainder of our work.
However, Coverity gets confused by this - it sees the byteswap in
fdt32_ld() and assumes that means it is coming from an untrusted source
everytime, resulting in many tainted data warnings.

Most of these end up with logic in fdt_get_string() as the unsafe
destination for this tainted data, so let's tweak the logic there to make
it clearer to Coverity that this is ok.

We add a sanity test on fdt_totalsize() to fdt_probe_ro_().  Because the
interface allows bare ints to be used for offsets, we already have the
assumption that totalsize must be 31-bits or less (2GiB would be a
ludicrously large fdt).  This makes this more explicit.

We also make fdt_probe_ro() return the size for convenience, and change the
logic in fdt_get_string() to keep it in a local so that Coverity can see
that it has already been bounds-checked.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-07-05 15:31:12 +10:00
Rob Herring
7fb0f4db2e libfdt: Replace GPL/BSD boilerplate/reference with SPDX tags
Replace instances of dual GPLv2 or BSD license boilerplate with SPDX tags.

Signed-off-by: Rob Herring <robh@kernel.org>
Message-Id: <20190620211944.9378-3-robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-06-21 21:06:10 +10:00
David Gibson
0112fda03b libfdt: Add fdt_header_size()
We have a couple of places within libfdt and its tests where we need to
find the size of the header, based on the version.  Add a helper function
for it.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Simon Glass <sjg@chromium.org>
Tested-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Reviewed-by: Alexey Kardashevskiy <aik@ozlabs.ru>
2018-06-07 11:49:14 +10:00
David Gibson
eb890c0f77 libfdt: Make fdt_check_header() more thorough
Currently fdt_check_header() performs only some rudimentary checks, which
is not really what the name suggests.  This strengthens fdt_check_header()
to check as much about the blob as is possible from the header alone:  as
well as checking the magic number and version, it checks that the total
size is sane, and that all the sub-blocks within the blob lie within the
total size.

 * This broadens the meaning of FDT_ERR_TRUNCATED to cover all sorts of
   improperly terminated blocks as well as just a structure block without
   FDT_END.

 * This makes fdt_check_header() only succeed on "complete" blobs, not
   in-progress sequential write blobs.  The only reason this didn't fail
   before was that this function used to be called by many RO functions
   which are supposed to also work on incomplete SW blobs.

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>
2018-06-07 11:47:59 +10:00
David Gibson
04b5b4062c libfdt: Clean up header checking functions
Many of the libfdt entry points call some sort of sanity check function
before doing anything else.  These need to do slightly different things for
the various classes of functions.

The read-only version is shared with the exported fdt_check_header(), which
limits us a bit in how we can improve it.  For that reason split the two
functions apart (though the exported one just calls the ro one for now).

We also rename the functions for more consistency - they're all named
fdt_XX_probe_() where the XX indicates which class of functions they're
for.  "probe" is a better "term" than the previous check, since they really
only do minimal validation.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Tested-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Reviewed-by: Alexey Kardashevskiy <aik@ozlabs.ru>
2018-06-07 11:45:44 +10:00
Nathan Whitehorn
f1879e1a50 Add limited read-only support for older (V2 and V3) device tree to libfdt.
This can be useful in particular in the kernel when booting on systems
with FDT-emitting firmware that is out of date. Releases of kexec-tools
on ppc64 prior to the end of 2014 are notable examples of such.

Signed-off-by: Nathan Whitehorn <nwhitehorn@freebsd.org>
[dwg: Some whitespace cleanups]
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2018-01-27 18:43:21 +11:00
David Gibson
c8b38f65fd libfdt: Remove leading underscores from identifiers
In a lot of places libfdt uses a leading _ character to mark an identifier
as "internal" (not part of the published libfdt API).  This is a bad idea,
because identifiers with a leading _ are generally reserved by the C
library or system.  It's particularly dangerous for libfdt, because it's
designed to be able to be integrated into lots of different environments.

In some cases the leading _ has no purpose, so we simply drop it.  In most
cases we move it to the end, as our new convention for marking internal
identifiers.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2017-10-26 09:25:14 +02:00
David Gibson
d0b3ab0a0f libfdt: Fix undefined behaviour in fdt_offset_ptr()
Using pointer arithmetic to generate a pointer outside a known object is,
technically, undefined behaviour in C.  Unfortunately, we were using that
in fdt_offset_ptr() to detect overflows.

To fix this we need to do our bounds / overflow checking on the offsets
before constructing pointers from them.

Reported-by: David Binderman <dcb314@hotmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2015-12-17 17:19:11 +11:00
Simon Glass
4e76ec796c libfdt: Add fdt_next_subnode() to permit easy subnode iteration
Iterating through subnodes with libfdt is a little painful to write as we
need something like this:

for (depth = 0, count = 0,
	offset = fdt_next_node(fdt, parent_offset, &depth);
     (offset >= 0) && (depth > 0);
     offset = fdt_next_node(fdt, offset, &depth)) {
	if (depth == 1) {
		/* code body */
	}
}

Using fdt_next_subnode() we can instead write this, which is shorter and
easier to get right:

for (offset = fdt_first_subnode(fdt, parent_offset);
     offset >= 0;
     offset = fdt_next_subnode(fdt, offset)) {
	/* code body */
}

Also, it doesn't require two levels of indentation for the loop body.

Signed-off-by: Simon Glass <sjg@chromium.org>
Acked-by: David Gibson <david@gibson.dropbear.id.au>
2013-04-28 07:30:49 -05:00
Kim Phillips
142419e43c dtc/libfdt: sparse fixes
libfdt/fdt.c:104:28: warning: incorrect type in argument 1 (different base types)
libfdt/fdt.c:104:28:    expected restricted fdt32_t [usertype] x
libfdt/fdt.c:104:28:    got unsigned int const [unsigned] [usertype] <noident>
libfdt/fdt.c:124:40: warning: incorrect type in argument 1 (different base types)
libfdt/fdt.c:124:40:    expected restricted fdt32_t [usertype] x
libfdt/fdt.c:124:40:    got unsigned int const [unsigned] [usertype] <noident>
libfdt/fdt_ro.c:337:29: warning: incorrect type in argument 1 (different base types)
libfdt/fdt_ro.c:337:29:    expected restricted fdt32_t [usertype] x
libfdt/fdt_ro.c:337:29:    got unsigned int const [unsigned] [usertype] <noident>
libfdt/fdt_rw.c:370:17: warning: incorrect type in assignment (different base types)
libfdt/fdt_rw.c:370:17:    expected unsigned int [unsigned] [usertype] <noident>
libfdt/fdt_rw.c:370:17:    got restricted fdt32_t
libfdt/fdt_sw.c:164:13: warning: incorrect type in assignment (different base types)
libfdt/fdt_sw.c:164:13:    expected unsigned int [unsigned] [usertype] <noident>
libfdt/fdt_sw.c:164:13:    got restricted fdt32_t
libfdt/fdt_sw.c:227:14: warning: incorrect type in assignment (different base types)
libfdt/fdt_sw.c:227:14:    expected unsigned int [unsigned] [usertype] <noident>
libfdt/fdt_sw.c:227:14:    got restricted fdt32_t
libfdt/fdt_wip.c:80:20: warning: incorrect type in assignment (different base types)
libfdt/fdt_wip.c:80:20:    expected unsigned int [unsigned] [usertype] <noident>
libfdt/fdt_wip.c:80:20:    got restricted fdt32_t
libfdt/libfdt.h:1001:13: warning: incorrect type in assignment (different base types)
libfdt/libfdt.h:1001:13:    expected unsigned long [unsigned] [usertype] val
libfdt/libfdt.h:1001:13:    got restricted fdt64_t
libfdt/libfdt.h:1157:13: warning: incorrect type in assignment (different base types)
libfdt/libfdt.h:1157:13:    expected unsigned int [unsigned] [usertype] val
libfdt/libfdt.h:1157:13:    got restricted fdt32_t
libfdt/libfdt.h:1192:13: warning: incorrect type in assignment (different base types)
libfdt/libfdt.h:1192:13:    expected unsigned long [unsigned] [usertype] val
libfdt/libfdt.h:1192:13:    got restricted fdt64_t
libfdt/libfdt.h:1299:13: warning: incorrect type in assignment (different base types)
libfdt/libfdt.h:1299:13:    expected unsigned int [unsigned] [usertype] val
libfdt/libfdt.h:1299:13:    got restricted fdt32_t
libfdt/libfdt.h:1334:13: warning: incorrect type in assignment (different base types)
libfdt/libfdt.h:1334:13:    expected unsigned long [unsigned] [usertype] val
libfdt/libfdt.h:1334:13:    got restricted fdt64_t
libfdt/libfdt.h:885:13: warning: incorrect type in assignment (different base types)
libfdt/libfdt.h:885:13:    expected unsigned int [unsigned] [usertype] val
libfdt/libfdt.h:885:13:    got restricted fdt32_t
libfdt/libfdt.h:920:13: warning: incorrect type in assignment (different base types)
libfdt/libfdt.h:920:13:    expected unsigned long [unsigned] [usertype] val
libfdt/libfdt.h:920:13:    got restricted fdt64_t
libfdt/libfdt.h:996:13: warning: incorrect type in assignment (different base types)
libfdt/libfdt.h:996:13:    expected unsigned int [unsigned] [usertype] val
libfdt/libfdt.h:996:13:    got restricted fdt32_t

Signed-off-by: Kim Phillips <kim.phillips@freescale.com>
2013-01-06 15:58:23 -06:00
David Gibson
73dca9ae0b libfdt: Implement property iteration functions
For ages, we've been talking about adding functions to libfdt to allow
iteration through properties.  So, finally, here are some.

I got bogged down on this for a long time because I didn't want to
expose offsets directly to properties to the callers.  But without
that, attempting to make reasonable iteration functions just became
horrible.  So eventually, I settled on an interface which does now
expose property offsets.  fdt_first_property_offset() and
fdt_next_property_offset() are used to step through the offsets of the
properties starting from a particularly node offset.  The details of
the property at each offset can then be retrieved with either
fdt_get_property_by_offset() or fdt_getprop_by_offset() which have
interfaces similar to fdt_get_property() and fdt_getprop()
respectively.

No explicit testcases are included, but we do use the new functions to
reimplement the existing fdt_get_property() function.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2010-03-10 08:13:00 -06:00
David Gibson
1a020e4030 libfdt: Rework/cleanup fdt_next_tag()
Currently, callers of fdt_next_tag() must usually follow the call with
some sort of call to fdt_offset_ptr() to verify that the blob isn't
truncated in the middle of the tag data they're going to process.
This is a bit silly, since fdt_next_tag() generally has to call
fdt_offset_ptr() on at least some of the data following the tag for
its own operation.

This patch alters fdt_next_tag() to always use fdt_offset_ptr() to
verify the data between its starting offset and the offset it returns
in nextoffset.  This simplifies fdt_get_property() which no longer has
to verify itself that the property data is all present.

At the same time, I neaten and clarify the error handling for
fdt_next_tag().  Previously, fdt_next_tag() could return -1 instead of
a tag value in some circumstances - which almost none of the callers
checked for.  Also, fdt_next_tag() could return FDT_END either because
it encountered an FDT_END tag, or because it reached the end of the
structure block - no way was provided to tell between these cases.

With this patch, fdt_next_tag() always returns FDT_END with a negative
value in nextoffset for an error.  This means the several places which
loop looking for FDT_END will still work correctly - they only need to
check for errors at the end.  The errors which fdt_next_tag() can
report are:
	- -FDT_ERR_TRUNCATED if it reached the end of the structure
	   block instead of finding a tag.

	- -FDT_BADSTRUCTURE if a bad tag was encountered, or if the
           tag data couldn't be verified with fdt_offset_ptr().

This patch also updates the callers of fdt_next_tag(), where
appropriate, to make use of the new error reporting.

Finally, the prototype for the long gone _fdt_next_tag() is removed
from libfdt_internal.h.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2009-02-06 11:19:14 -06:00
David Gibson
ce4d9c0f74 libfdt: Rework fdt_next_node()
Currently fdt_next_node() will find the next node in the blob
regardless of whether it is above, below or at the same level in the
tree as the starting node - the depth parameter is updated to indicate
which is the case.  When a depth parameter is supplied, this patch
makes it instead terminate immediately when it finds the END_NODE tag
for a node at depth 0.  In this case it returns the offset immediately
past the END_NODE tag.

This has a couple of advantages.  First, this slightly simplifies
fdt_subnode_offset(), which no longer needs to explicitly check that
fdt_next_node()'s iteration hasn't left the starting node.  Second,
this allows fdt_next_node() to be used to implement
_fdt_node_end_offset() considerably simplifying the latter function.

The other users of fdt_next_node() either don't need to iterate out of
the starting node, or don't pass a depth parameter at all.  Any
callers that really need to iterate out of the starting node, but keep
tracking depth can do so by biasing the initial depth value.

This is a semantic change, but I think it's very unlikely to break any
existing library users.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2009-02-06 11:19:10 -06:00
Jon Loeliger
b236893fc4 Fix an overflow case in fdt_offset_ptr() detected by GCC 4.3.
Using Gcc 4.3 detected this problem:

    ../dtc/libfdt/fdt.c: In function 'fdt_next_tag':
    ../dtc/libfdt/fdt.c:82: error: assuming signed overflow does not
    occur when assuming that (X + c) < X is always false

To fix the problem, treat the offset as an unsigned int.

The problem report and proposed fix were provided
by Steve Papacharalambous <stevep@freescale.com>.

Signed-off-by: Jon Loeliger <jdl@freescale.com>
2008-09-25 15:45:48 -05:00
David Gibson
b6d80a20fc libfdt: Increase namespace-pollution paranoia
libfdt is supposed to easy to embed in projects all and sundry.
Often, it won't be practical to separate the embedded libfdt's
namespace from that of the surrounding project.  Which means there can
be namespace conflicts between even libfdt's internal/static functions
and functions or macros coming from the surrounding project's headers
via libfdt_env.h.

This patch, therefore, renames a bunch of libfdt internal functions
and macros and makes a few other chances to reduce the chances of
namespace collisions with embedding projects.  Specifically:
	- Internal functions (even static ones) are now named _fdt_*()

	- The type and (static) global for the error table in
          fdt_strerror() gain an fdt_ prefix

	- The unused macro PALIGN is removed

	- The memeq and streq macros are removed and open-coded in the
          users (they were only used once each)

	- Other macros gain an FDT_ prefix

	- To save some of the bulk from the previous change, an
          FDT_TAGALIGN() macro is introduced, where FDT_TAGALIGN(x) ==
          FDT_ALIGN(x, FDT_TAGSIZE)

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2008-07-14 12:36:27 -05:00
David Gibson
36786db615 dtc: Enable and fix -Wpointer-arith warnings
This patch turns on the -Wpointer-arith option in the dtc Makefile,
and fixes the resulting warnings due to using (void *) in pointer
arithmetic.  While convenient, pointer arithmetic on void * is not
portable, so it's better that we avoid it, particularly in libfdt.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2008-07-14 12:36:08 -05:00
David Gibson
aa1baab3cc libfdt: Several cleanups to parameter checking
This patch makes a couple of small cleanups to parameter checking of
libfdt functions.

	- In several functions which take a node offset, we use an
idiom involving fdt_next_tag() first to check that we have indeed been
given a node offset.  This patch adds a helper function
_fdt_check_node_offset() to encapsulate this usage of fdt_next_tag().

	- In fdt_rw.c in several places we have the expanded version
of the RW_CHECK_HEADER() macro for no particular reason.  This patch
replaces those instances with an invocation of the macro; that's what
it's for.

	- In fdt_sw.c we rename the check_header_sw() function to
sw_check_header() to match the analgous function in fdt_rw.c, and we
provide an SW_CHECK_HEADER() wrapper macro as RW_CHECK_HEADER()
functions in fdt_rw.c

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2008-05-29 08:15:53 -05:00
David Gibson
8a4e75049d libfdt: Trivial cleanup for CHECK_HEADER)
Currently the CHECK_HEADER() macro is defined local to fdt_ro.c.
However, there are a handful of functions (fdt_move, rw_check_header,
fdt_open_into) from other files which could also use it (currently
they open-code something more-or-less identical).  Therefore, this
patch moves CHECK_HEADER() to libfdt_internal.h and uses it in those
places.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2008-02-18 08:27:13 -06:00
David Gibson
fc9769ac2b libfdt: Add and use a node iteration helper function.
This patch adds an fdt_next_node() function which can be used to
iterate through nodes of the tree while keeping track of depth.  This
function is used to simplify the iteration code in a lot of other
functions, and is also exported for use by library users.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2008-02-12 09:11:40 -06:00
David Gibson
3c44c87bde libfdt: Rename and publish _fdt_next_tag()
Although it's a low-level function that shouldn't normally be needed,
there are circumstances where it's useful for users of libfdt to use
the _fdt_next_tag() function.  Therefore, this patch renames it to
fdt_next_tag() and publishes it in libfdt.h.

In addition, this patch adds a new testcase using fdt_next_tag(),
dtbs_equal_ordered.  This testcase tests for structural equality of
two dtbs, including the order of properties and subnodes, but ignoring
NOP tags, the order of the dtb sections and the layout of strings in
the strings block.  This will be useful for testing other dtc
functionality in the future.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2007-10-24 09:56:27 -05:00
David Gibson
96b5fad3a1 libfdt: Rename and publish _fdt_check_header()
It's potentially useful for users of libfdt to sanity check a device
tree (or, rather, a blob of data which may or may not be a device
tree) before processing it in more detail with libfdt.

This patch renames the libfdt internal function _fdt_check_header() to
fdt_check_header() and makes it a published function, so it can now be
used for this purpose.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2007-10-24 07:58:13 -05:00
David Gibson
23cdf2379f Move everything into a subdirectory in preparation for merge into dtc. 2007-06-14 11:58:35 +10:00
Renamed from fdt.c (Browse further)