Commit graph

778 commits

Author SHA1 Message Date
Greg Kurz
0ac9fdee37 dtc: trivial '-I fs -O dts' test
Some recent changes caused '-I fs -O dts' to crash instantly when
emitting the first property holding actual data, ie, coming from
a non-empty file. This got fixed already by another patch.

This simply adds a test for the original problem.

Signed-off-by: Greg Kurz <groug@kaod.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2018-09-10 12:19:39 +10:00
Dan Horák
0fd1c8c783 pylibfdt: fdt_get_mem_rsv returns 2 uint64_t values
Fix typemap for fdt_get_mem_rsv so it returns 64-bit values.

Fixes https://github.com/dgibson/dtc/issues/15.

Signed-off-by: Dan Horák <dan@danny.cz>
[dwg: Adjusted commit message for typo and context]
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2018-09-02 15:35:59 +10:00
David Gibson
04853cad18 pylibfdt: Don't incorrectly / unnecessarily override uint64_t typemap
In libfdt.i we set the handling of uint64_t parameters to use
PyLong_AsUnsignedLong.  But for 32-bit platforms, where an unsigned long
is 32-bits, this will truncate the value we need.

It turns out swig's default typemapping for uint64_t correctly handles
conversions both to python ints and python longs, so we don't need this
typemap at all.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2018-08-31 11:15:41 +10:00
Greg Kurz
9619c8619c Kill bogus TYPE_BLOB marker type
Since commit 32b9c61307 "Preserve datatype markers when emitting dts
format", we no longer try to guess the value type. Instead, we reuse
the type of the datatype markers when they are present, if the type
is either TYPE_UINT* or TYPE_STRING.

This causes 'dtc -I fs' to crash:

Starting program: /root/dtc -q -f -O dts -I fs /proc/device-tree
/dts-v1/;

/ {

Program received signal SIGSEGV, Segmentation fault.
__strlen_power8 () at ../sysdeps/powerpc/powerpc64/power8/strlen.S:47
47              ld      r12,0(r4)     /* Load doubleword from memory.  */
(gdb) bt
#0  __strlen_power8 () at ../sysdeps/powerpc/powerpc64/power8/strlen.S:47
#1  0x00007ffff7de3d10 in __GI__IO_fputs (str=<optimized out>,
    fp=<optimized out>) at iofputs.c:33
#2  0x000000001000c7a0 in write_propval (prop=0x100525e0,
    f=0x7ffff7f718a0 <_IO_2_1_stdout_>) at treesource.c:245

The offending line is:

                fprintf(f, "%s", delim_start[emit_type]);

where emit_type is TYPE_BLOB and:

static const char *delim_start[] = {
        [TYPE_UINT8] = "[",
        [TYPE_UINT16] = "/bits/ 16 <",
        [TYPE_UINT32] = "<",
        [TYPE_UINT64] = "/bits/ 64 <",
        [TYPE_STRING] = "",
};

/* Data blobs */
enum markertype {
        TYPE_NONE,
        REF_PHANDLE,
        REF_PATH,
        LABEL,
        TYPE_UINT8,
        TYPE_UINT16,
        TYPE_UINT32,
        TYPE_UINT64,
        TYPE_BLOB,
        TYPE_STRING,
};

Because TYPE_BLOB < TYPE_STRING and delim_start[] is a static array,
delim_start[emit_type] is 0x0. The glibc usually prints out "(null)"
when one passes 0x0 to %s, but it seems to call fputs() internally if
the format is exactly "%s", hence the crash.

TYPE_BLOB basically means the data comes from a file and we don't know
its type. We don't care for the former, and the latter is TYPE_NONE.

So let's drop TYPE_BLOB completely and use TYPE_NONE instead when reading
the file. Then, try to guess the data type at emission time, like the
code already does for refs and labels.

Instead of adding yet another check for TYPE_NONE, an helper is introduced
to check if the data marker has type information, ie, >= TYPE_UINT8.

Fixes: 32b9c61307
Suggested-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Greg Kurz <groug@kaod.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2018-08-31 11:13:33 +10:00
Rob Herring
ac68ff92ae parser: add TYPE_STRING marker to path references
Path references are also a string, so add TYPE_STRING marker in addition
to REF_PATH.

Signed-off-by: Rob Herring <robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2018-08-01 10:02:38 +10:00
Rob Herring
90a190eb04 checks: add SPI bus checks
Add SPI bus type detection and checks. The node name is the
preferred way to find SPI buses as there is no common compatible or
property which can be used. There are a few common properties used in
child nodes, so they can be used as a fallback detection method. This
lets us warn if the SPI controller is not properly named 'spi@...'.

Signed-off-by: Rob Herring <robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2018-07-27 13:42:50 +10:00
Rob Herring
53a1bd5469 checks: add I2C bus checks
Add I2C bus type detection and checks. The node name is used to find I2C
buses as there is no common compatible or property which can be used to
identify I2C controllers/buses. There are some common I2C properties,
but they are not used frequently enough to match on.

Signed-off-by: Rob Herring <robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2018-07-27 13:42:50 +10:00
David Gibson
88f18909db dtc: Bump version to v1.4.7
We've accumulated a bunch of bugfixes, including considerable improvements
to libfdt's memory safety, so get ready for another release.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2018-07-23 13:00:50 +10:00
David Gibson
85bce8b2f0 tests: Correction to vg_prepare_blob()
vg_prepare_blob() assumes a valid return from fdt_num_mem_rsv() in order
to make sensible initialization of the valgrind mem checker.  Usually
that's fine, but it breaks down on the (deliberately corrupted)
truncated_memrsv testcase.

That led to marking a negative-size (== enormously sized once cast to
size_t) as defined with VALGRIND_MAKE_MEM_DEFINED, which casued valgrind
to freeze up and consume ludicrous amounts of memory until OOMing.

This correction makes us robust in that case.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2018-07-23 12:16:09 +10:00
David Gibson
57f7f9e7bc tests: Don't call memcmp() with NULL arguments
You're not supposed to pass NULL to memcmp(), and some sanitizers complain
about it, even when the length is zero.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2018-07-20 14:35:12 +10:00
Sebastian Huber
c12b2b0c20 libfdt: fdt_address_cells() and fdt_size_cells()
Add internal fdt_cells() to avoid copy and paste.  Test error cases and
default values.  Fix typo in fdt_size_cells() documentation comment.

Signed-off-by: Sebastian Huber <sebastian.huber@embedded-brains.de>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2018-07-20 11:56:49 +10:00
Rob Herring
3fe0eeda0b livetree: Set phandle properties type to uint32
Generated phandle property values are a single cell, so set the type
marker to uint32. Otherwise, we default to uint8.

Signed-off-by: Rob Herring <robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2018-07-13 10:38:25 +10:00
Simon Glass
853649acce pylibfdt: Support the sequential-write interface
It is useful to be able to create a device tree from scratch using
software. This is supported in libfdt but not currently available in the
Python bindings.

Add a new FdtSw class to handle this, with various methods corresponding
to the libfdt functions. When the tree is complete, calling AsFdt() will
return the completed device-tree object.

Signed-off-by: Simon Glass <sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2018-07-11 16:21:20 +10:00
David Gibson
9b0e4fe260 tests: Improve fdt_resize() tests
We primarily test fdt_resize() in the sw_tree1 testcase, but it has
some deficiencies:

  - It didn't check for errors actually originating in fdt_resize(),
    just for errors before and after

  - It only tested cases where the resized buffer was at the same
    address as the original one, whereas fdt_resize() is also supposed
    to work if the new buffer is entirely separate, or partly
    overlapping

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2018-07-09 15:03:14 +10:00
David Gibson
1087504bb3 libfdt: Add necessary header padding in fdt_create()
At present fdt_create() will succeed if there is exactly enough space to
put in the fdt header.  However, it sets the off_mem_rsvmap field, a few
bytes past that in order to align the memory reservation block.

Having block pointers pointing past the end of the fdt is pretty ugly, even
if it is just a transient state.  Worse, if fdt_resize() is called at
exactly the wrong time, it can end up accessing data past the blob's
allocated space because of this.

So, correct fdt_create() to ensure that there is sufficient space for the
alignment padding as well as the plain header.  For paranoia, also add a
check in fdt_resize() to make sure we don't copy data from outside the
blob's bounds.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2018-07-09 15:03:14 +10:00
Simon Glass
c72fa777e6 libfdt: Copy the struct region in fdt_resize()
At present this function appears to copy only the data before the struct
region and the data in the string region. It does not seem to copy the
struct region itself.

From the arguments of this function it seems that it should support fdt
and buf being different. This patch attempts to fix this problem.

Signed-off-by: Simon Glass <sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2018-07-09 15:03:14 +10:00
Grant Likely
32b9c61307 Preserve datatype markers when emitting dts format
If datatype markers are present in the property value, use them to
output the data in the correct format instead of trying to guess the
datatype. This also will preserve data grouping, such as in an
interrupts list.

This is a step forward for preserving and using datatype information
when processing DTS/DTB files. Schema validation tools can use the
datatype information to make sure a DT is correctly formed and
intepreted.

Signed-off-by: Grant Likely <grant.likely@arm.com>
[robh: rework marker handling and fix label output]
Signed-off-by: Rob Herring <robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2018-06-29 11:06:49 +10:00
David Gibson
6dcb8ba408 libfdt: Add helpers for accessing unaligned words
This adds some helpers to load (32 or 64 bit) words from an fdt blob, even
if they're unaligned and we're on a platform that doesn't like plain
unaligned loads and stores.  We then use the helpers in a number of places.
There are two purposes for this:

1) This makes libfdt more robust against a blob loaded at an unaligned
   address.  It's usually good practice to load a blob at a 64-bit
   alignment, but it's nice to work even then.

2) Users can use these helpers to load integer values from within property
   values.  These can often be unaligned, even if the blob as a whole is
   aligned, since some property encodings have integers and strings mixed
   together without any alignment gaps.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2018-06-26 15:09:46 +10:00
Rob Herring
42607f21d4 tests: Fix incorrect check name 'prop_name_chars'
'prop_name_chars' is not a valid check name, but the test was passing due
to a bug in dtc-checkfails.sh. Fix it to be the correct name,
'property_name_chars'.

Signed-off-by: Rob Herring <robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2018-06-17 21:39:37 +10:00
Rob Herring
9d78c33bf8 tests: fix grep for checks error messages
I noticed the error type passed in didn't matter for check tests to pass.
There's a couple of problems with the grep regex. The error/warning
messages begin with the output filename now, so "ERROR" or "Warning" is not
at the beginning of the line. Secondly, the parentheses seem to be wrong.
It's not clear to me what was intended.

Signed-off-by: Rob Herring <robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2018-06-17 21:39:07 +10:00
Simon Glass
b770f3d1c1 pylibfdt: Support setting the name of a node
Add a method to call fdt_set_name().

Signed-off-by: Simon Glass <sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2018-06-14 14:08:32 +10:00
Simon Glass
2f0d07e678 pylibfdt: Add functions to set and get properties as strings
It is common to want to set a property to a nul-terminated string in a
device tree. Add python methods to handle this.

Signed-off-by: Simon Glass <sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2018-06-14 14:07:40 +10:00
Simon Glass
354d3dc559 pylibfdt: Update the bytearray size with pack()
At present pack() calls fdt_pack() which may well reduce the size of the
device-tree data. However this does not currently update the size of the
bytearray to take account of any reduction. This means that there may be
unused data at the end of the bytearray and any users of as_bytearray()
will see this extra data.

Fix this by resizing the bytearray after packing.

Signed-off-by: Simon Glass <sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2018-06-13 22:02:06 +10:00
Simon Glass
3c374d46ac pylibfdt: Allow reading integer values from properties
Extend the Properties class with some functions to read a single integer
property. Add a new getprop_obj() function to return a Property object
instead of the raw data.

This suggested approach can be extended to handle other types, as well as
arrays.

Signed-off-by: Simon Glass <sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2018-06-13 16:59:18 +10:00
Simon Glass
49d32ce40b pylibfdt: Use an unsigned type for fdt32_t
The members of struct fdt_header are declared as fdt32_t which is a
32-bit, big-endian, unsigned integer. These fields are accessed by macros
in libfdt.h so no return type is declared. But the correct return type is
uint32_t, not fdt32_t, since the endianness conversion is done within the
macro before returning the value.

The macros are re-declared as normal functions in pylibfdt since swig does
not support macros. The return type is currently int. Change it to
uint32_t, which allows us to drop the work-around mask in Fdt.magic().

Also change the typedef for fdt32_t to uint32_t. The currently has no
obvious effect, since use of big-endian values should always be internal
to pylibfdt, but it is more correct.

Signed-off-by: Simon Glass <sjg@chromium.org>
Suggested-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2018-06-13 16:32:55 +10:00
Simon Glass
481246a0c1 pylibfdt: Avoid accessing the internal _fdt member in tests
We can use the accessor now, so do so.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2018-06-12 15:05:05 +10:00
Simon Glass
9aafa33d99 pylibfdt: Add functions to update properties
Allow updating and creating properties, including special methods for
integers.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2018-06-12 14:44:20 +10:00
Simon Glass
5a598671fd pylibfdt: Support device-tree creation/expansion
Add support for fdt_open_into() and fdt_create_empty_tree() from the
Python library. The former is named resize() since it better fits with
what the Python binding actually does.

Signed-off-by: Simon Glass <sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2018-06-09 23:36:33 +10:00
Simon Glass
483e170625 pylibfdt: Add support for reading the memory reserve map
Add a way to access this information from Python.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2018-06-09 23:35:35 +10:00
Simon Glass
29bb05aa42 pylibfdt: Add support for the rest of the header functions
Export all of these through Python.

Signed-off-by: Simon Glass <sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2018-06-09 23:33:41 +10:00
Simon Glass
582a7159a5 pylibfdt: Add support for fdt_next_node()
This function requires a bit of typemap effort to get the depth parameter
to work correctly. Add support for it, along with a test.

Signed-off-by: Simon Glass <sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2018-06-08 22:26:03 +10:00
Simon Glass
f0f8c91698 pylibfdt: Reorder functions to match libfdt.h
The ordering of the Python functions loosely matches the corresponding
function in the C header file, but not exactly. As we add more functions
it is easier to track what is missing if they are in the same order.

Move some functions around to achieve this.

Signed-off-by: Simon Glass <sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2018-06-08 22:25:02 +10:00
Simon Glass
64a69d1239 pylibfdt: Return string instead of bytearray from getprop()
The return value is not actually mutable, so it seems more correct to
return bytes rather than a bytearray.

Suggested-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Simon Glass <sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2018-06-08 13:43:52 +10:00
Simon Glass
4d09a83420 fdtput: Add documentation
This is missing at present and the fdtput tool could use a litle more
information than just its help text.

This might be useful for distributions which want to provide a man page.

Signed-off-by: Simon Glass <sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2018-06-07 21:54:38 +10:00
Simon Glass
e617cbe1bd fdtget: Add documentation
This is missing at present and the fdtget tool is no-longer trivial. Add
a little bit of information.

This might be useful for distributions which want to provide a man page.

Signed-off-by: Simon Glass <sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2018-06-07 21:54:38 +10:00
David Gibson
180a939240 Use <inttypes.h> format specifiers in a bunch of places we should
Rather than assuming that uint32_t is the same thing as unsigned.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2018-06-07 11:49:17 +10:00
nixiaoming
b9af3b3965 scripts/dtc: Fixed format mismatch in fprintf
format specifier "d" need arg type "int" , but the according arg
"fdt32_to_cpu(xxx)" has type "unsigned int"

Signed-off-by: nixiaoming <nixiaoming@huawei.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2018-06-07 11:49:17 +10:00
David Gibson
4b8fcc3d01 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>
2018-06-07 11:49:17 +10:00
David Gibson
c14223fb22 tests: Use valgrind client requests for better checking
libfdt is never supposed to access memory outside the the blob, or outside
the sub-blocks within it, even if the blob is badly corrupted.

We can leverage valgrind's client requests to do better testing of this.
This adds a vg_prepare_blob() function which marks just the valid parts of
an fdt blob as properly initialized, explicitly marking the rest as
uninitialized.  This means valgrind should catch any bad accesses.

We add a call to vg_prepare_blob() to load_blob() so that lots of the
existing testcases will benefit from the extra checking.

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:49:17 +10:00
David Gibson
5b67d2b955 tests: Better handling of valgrind errors saving blobs
Currently we have 3 valgrind suppression files in the tests, all of which
are to handle memcheck errors that originate from saving entire buffers
containing blobs where the gaps between sub-blocks might not be
initialized.

We can more simply suppress those errors by having the save_blob() helper
use valgrind's client interface to mark the data as initialized before we
write it out.

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:49:17 +10:00
David Gibson
e2556aaeb5 tests: Remove unused #define
This was leftover from an earlier implementation of load_blob().

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:17 +10:00
David Gibson
fb9c6abdda Use size_t for blob lengths in utilfdt_read*
It's more appropriate than off_t since it is, after all, a size not an
offset.

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:17 +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
6473a21d8b Consolidate utilfdt_read_len() variants
There are no less than _four_ variants on utilfdt_read() which is a bit
excessive.  The _len() variants are particularly pointless, since we can
achieve the same thing with very little extra verbosity by using the usual
convention of ignoring return parameters if they're NULL.  So, get rid of
them (we keep the shorter names without _len, but add now-optional len
parameters).

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:48:20 +10:00
David Gibson
d5db5382c5 libfdt: Safer access to memory reservations
fdt_num_mem_rsv() and fdt_get_mem_rsv() currently don't sanity check their
parameters, or the memory reserve section offset in the header.  That means
that on a corrupted blob they could access outside of the range of memory
that they should.

This improves their safety checking, meaning they shouldn't access outside
the blob's bounds, even if its contents are badly corrupted.

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:48:20 +10:00
David Gibson
719d582e98 libfdt: Propagate name errors in fdt_getprop_by_offset()
fdt_getprop_by_offset() doesn't check for errors from fdt_string() - after
all, until very recently it couldn't fail.  Now it can, so we need to
propagate errors up to the caller.

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:48:20 +10:00
David Gibson
70166d62a2 libfdt: Safer access to strings section
fdt_string() is used to retrieve strings from a DT blob's strings section.
It's rarely used directly, but is widely used internally.

However, it doesn't do any bounds checking, which means in the case of a
corrupted blob it could access bad memory, which libfdt is supposed to
avoid.

This write a safe alternative to fdt_string, fdt_get_string().  It checks
both that the given offset is within the string section and that the string
it points to is properly \0 terminated within the section.  It also returns
the string's length as a convenience (since it needs to determine to do the
checks anyway).

fdt_string() is rewritten in terms of fdt_get_string() for compatibility.

Most of the diff here is actually testing infrastructure.

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:48:20 +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
899d6fad93 libfdt: Improve sequential write state checking
When creating a tree with the sequential write functions, certain things
have to be done in a certain order.  You must create the memory reserve map
and only then can you create the actual tree structure.

The -FDT_ERR_BADSTATE return code is for if you try to do things out of
order.  However, we weren't checking that very thoroughly, so it was
possible to generate a corrupted blob if, for example, you started calling
fdt_begin_node() etc. before calling fdt_finish_reservemap().

This makes the state checking more thorough disallow that.

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:45:48 +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