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>
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>
Enabling -Wcast-qual warnings in dtc shows up a number of places where
we are incorrectly discarding a const qualification. There are also
some places where we are intentionally discarding the 'const', and we
need an ugly cast through uintptr_t to suppress the warning. However,
most of these are pretty well isolated with the *_w() functions. So
in the interests of maximum safety with const qualifications, this
patch enables the warnings and fixes the existing complaints.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
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>
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>
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>
fdt_add_subnode_namelen() has a bug if asked to add a subnode to a
node which has NOP tags interspersed with its properties. In this
case fdt_add_subnode_namelen() will put the new subnode before the
first NOP tag, even if there are properties after it, which will
result in an invalid blob.
This patch fixes the bug, and adds a testcase for it.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
This patch adds an fdt_set_name() function to libfdt, mirroring
fdt_get_name(). This is a r/w function which alters the name of a
given device tree node.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
This patch adds some options to the run_tests.sh script allowing it to
run all the testcases under valgrind to check for pointer corruption
bugs and memory leaks. Invoking "make checkm" will run the testsuite
with valgrind.
It include a mechanism for specifying valgrind errors to be suppressed
on a per-testcase basis, and adds a couple of such suppression files
for the mangle-layout and open_pack testcases which dump for use by
other testcases a buffer which may contain uninitialized sections. We
use suppressions rather than initializing the buffer so that valgrind
will catch any internal access s to the uninitialized data, which
would be a bug.
The patch also fixes one genuine bug caught by valgrind -
_packblocks() in fdt_rw.c was using memcpy() where it should have been
using memmove().
At present the valgrinding won't do anything useful for testcases
invoked via a shell script - which includes all the dtc testcases. I
plan to fix that later.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Currently all the read/write functions in libfdt require that the
given tree be v17, and further, that the tree has the memory
reservation block, structure block and strings block stored in that
physical order.
This patch eases these constraints, by making fdt_open_int() reorder
the blocks, and/or convert the tree to v17, so that it will then be
ready for the other read-write functions.
It also extends fdt_pack() to actually remove any gaps between blocks
that might be present.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
If future dtb version > 17 are defined, that are still backwards
compatible with v16, libfdt will of course be able to read and
understand them. However, when modifying such a tree, it can't
guarantee that it won't clobber additional structure from the new
version which it doesn't know about. Therefore, before making
modifications to a tree of version >17, we must change it's version to
be exactly 17.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
The fdt_set_header() macro casts an arbitrary pointer into (struct
fdt_header *) to set fdt header fields. While we need to change the
type, so that we can use this macro on the usual (void *) used to
represent a device tree blob, the current macro also casts away any
const on the input pointer, which loses an important check.
This patch replaces the fdt_set_header() macro with a set of inline
functions, one for each header field which do a similar thing, but
which won't silently remove const from a given pointer. This approach
is also more in keeping with the individual accessor macros we use for
reading fdt header fields.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
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>
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>
fdt_del_node(), unlike most of the rw functions does not check the
fdt's header with RW_CHECK_HEADER. However, it could make a mess of
things if the conditions in RW_CHECK_HEADER aren't met. So, this
patch adds the omitted check.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
This patch adds functions to libfdt for accessing the memory
reservation map section of a device tree blob. fdt_num_mem_rsv()
retreives the number of reservation entries in a dtb, and
fdt_get_mem_rsv() retreives a specific reservation entry.
fdt_add_mem_rsv() adds a new entry, and fdt_del_mem_rsv() removes a
specific numbered entry.
Testcases for these new functions are also included.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
As a read-only functions, which take a const pointer to the fdt, treat
fdt_get_property() and fdt_getprop() as returning const pointers to
within the blob. fdt_get_property_w() and fdt_getprop_w() versions
are supplied which take a non-const fdt pointer and return a non-const
pointer for the benefit of callers wishing to alter the device tree
contents.
Likewise the lower-level fdt_offset_ptr() and _fdt_offset_ptr()
functions are changed to return const pointers, with *_w() versions
supplied.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
At present, libfdt functions returning a structure offset return a
zero-or-positive offset on success, and return a negative error code
on failure. Functions which only return an error code return a
positive version of the error code, or 0 on success.
This patch improves consistency by always returning negative error
codes on failure, for both types of function. With this change, we do
away with the special fdt_offset_error() macro for checking whether a
returned offset value is an error and extracting the encoded error
value within. Instead an explicit (ret_value < 0) is now the
preferred way of checking return values for both offset-returning and
error-code-returning functions.
The fdt_strerror() function in the test code is updated
correspondingly to make more sense with the new conventions.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
This patch abolishes the non-standard and confusing encoding of errors
into pointer return values. The only functions still returning such a
potentially encoded pointer are fdt_get_property() and fdt_getprop().
Those functions also return a length via an (int *). With this patch
those functions instead now return NULL on any error, and return the
code indicating the type of error in the length paramater.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
At present, the blob containing a device tree is passed to the various
fdt_*() functions as a (struct fdt_header *) i.e. a pointer to the
header structure at the beginning of the blob.
This patch changes all the functions so that they instead take a (void
*) pointing to the blob. Under some circumstances can avoid the need
for the caller to cast a blob pointer into a (struct fdt_header *)
before passing it to the fdt_*() functions.
Using a (void *) also reduce the temptation for users of the library
to directly dereference toe (struct fdt_header *) to access header
fields. Instead they must use the fdt_get_header() or
fdt_set_header() macros, or the fdt_magic(), fdt_totalsize()
etc. wrappers around them which are safer, since they will always
handle endian conversion.
With this change, the whole-tree moving, or manipulating functions:
fdt_move(), fdt_open_into() and fdt_pack() no longer need to return a
pointer to the "new" tree. The given (void *) buffer pointer they
take can instead be used directly by the caller as the new tree.
Those functions are thus changed to instead return an error code
(which in turn reduces the number of functions using the ugly encoding
of error values into pointers).
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Several places in fdt_rw.c incorrectly use fdt_offset_ptr(), using it
as if it returned an encoded error code on errors, instead of
returning NULL on error as it actually does.
In fact, however, in these instances the extra checks in
fdt_offset_ptr() are useless anyway, so we introduce a new (internal
use) _fdt_offset_ptr() and use that without checking.
(cherry picked from 3dffb1808dea6aee6158c92e17faa6ced9b183f2 commit)
fdt_property_offset() is the only function in the library returning a
direct offset to a property, and no function takes such an offset
(they only take offsets to nodes, not properties). Furthermore the
only client uses for this function I can think of involve immediately
translating the offset into a pointer, effectively duplicating the
internal function _fdt_getprop()
This function abolishes fdt_property_offset(), replacing it with
fdt_get_property(), a renamed and now externally visible version of
_fdt_getprop().