Compare commits

...

299 commits
v1.6.0 ... main

Author SHA1 Message Date
Adam Lackorzynski
7f3184a6c5 libfdt: Remove old MacOS strnlen workaround
Some checks failed
Build test / build-make (alpine) (push) Has been cancelled
Build test / build-make (archlinux) (push) Has been cancelled
Build test / build-make (fedora) (push) Has been cancelled
Build test / build-make (ubuntu) (push) Has been cancelled
Build test / build-meson (alpine) (push) Has been cancelled
Build test / build-meson (archlinux) (push) Has been cancelled
Build test / build-meson (fedora) (push) Has been cancelled
Build test / build-meson (ubuntu) (push) Has been cancelled
Build test / clang64 (push) Has been cancelled
Build test / mingw32 (push) Has been cancelled
Build test / mingw64 (push) Has been cancelled
Build test / ucrt64 (push) Has been cancelled
The check for the MacOS X version (10.7) is problematic, because it
fails unless _DARWIN_C_SOURCE is defined if also _POSIX_C_SOURCE or
_XOPEN_SOURCE is defined, as then the Darwin version defines are not
defined.  We cannot force _DARWIN_C_SOURCE reliably in the header
either, because we cannot be sure that the libfdt_env.h has not already
been included by another source before.

The check is also only for very old versions of Mac OS X. In the
interest of not replacing strnlen arbitrarily for sources using
libfdt and considering that the last version of OS X 10.6 was
released in 2011 I propose to remove the workaround for that system.

We noticed as compiling fdt_strnlen in C++ environments fails
(missing cast for memchr).

Signed-off-by: Adam Lackorzynski <adam@l4re.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2025-09-30 12:03:03 +10:00
Andrew Davis
9197f1ccd9 checks: Do not check overlays for alias paths
The path given as an alias inside an overlay can be a path to a node
in the base DT. The path check searches only the overlay as that is
the only tree available leading to false check failures.

Skip this check when checking an overlay.

Signed-off-by: Andrew Davis <afd@ti.com>
Message-ID: <20250822171038.190122-1-afd@ti.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2025-08-25 11:39:08 +10:00
Uwe Kleine-König
e1284ee5dc livetree: Add only new data to fixup nodes instead of complete regeneration
Removing the complete __fixups__ and __local_fixups__ tree might delete
data that should better be retained. See the added test for a situation
that was broken before.

Note that without removing /__fixups__ and /__local_fixups__ in
generate_fixups_tree() and generate_local_fixups_tree() respectively
calling build_and_name_child_node() isn't safe as the nodes might
already exist and then a duplicate would be added. So build_root_node()
has to be used which copes correctly here.

Fixes: 915daadbb6 ("Start with empty __local_fixups__ and __fixups__ nodes")
Closes: https://github.com/dgibson/dtc/issues/170
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
Message-ID: <b061ee57157fafbb9d5b9b0b86af760d13a04eda.1755512759.git.u.kleine-koenig@baylibre.com>
[dwg: Use -1 instead of 1 as an error return]
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2025-08-20 21:34:05 +10:00
Niklas Söderlund
cba90ce820 checks: Remove check for graph child addresses
The dtc graph_child_address check can't distinguish between bindings
where there can only be a single endpoint, and cases where there can be
multiple endpoints.

In cases where the bindings allow for multiple endpoints but only one is
described false warnings about unnecessary #address-cells/#size-cells
can be generated, but only if the endpoint described have an address of
0 (A), for single endpoints with a non-zero address (B) no warnings are
generated.

A)
    ports {
	#address-cells = <1>;
	#size-cells = <0>;

	port@0 {
	    #address-cells = <1>;
	    #size-cells = <0>;

	    sourceA: endpoint@0 {
		reg = <0>
	    };
	};
    };

B)
    ports {
	#address-cells = <1>;
	#size-cells = <0>;

	port@0 {
	    #address-cells = <1>;
	    #size-cells = <0>;

	    sourceB: endpoint@1 {
		reg = <1>
	    };
	};
    };

Remove the check as it is somewhat redundant now that we can use schemas
to validate the full node.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
Message-ID: <20250817133733.3483922-1-niklas.soderlund+renesas@ragnatech.se>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2025-08-19 09:33:15 +10:00
Uwe Kleine-König
763c6ab418 livetree: Simplify append_to_property()
The two if branches are quite similar. Build the property first (in case
it doesn't exist) and then the common parts can be done outside the if
block.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
Message-ID: <eef88e559f5b9818c4c2311fa8a75ab6fd4508d5.1755512759.git.u.kleine-koenig@baylibre.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2025-08-19 09:24:37 +10:00
Rob Herring (Arm)
739403f222 libfdt: Drop including string.h from libfdt_internal.h
Commit 0f69cedc08 ("libfdt_internal: fdt_find_string_len_()") added a
string.h include to libfdt_internal.h which introduces a libc dependency
which cannot be overridden. Environments without libc (e.g. Linux
kernel) use a custom libfdt_env.h. string.h is already indirectly
included in libfdt_env.h, so it can be dropped from libfdt_internal.h.

Fixes: 0f69cedc08 ("libfdt_internal: fdt_find_string_len_()")
Signed-off-by: Rob Herring (Arm) <robh@kernel.org>
Message-ID: <20250811130416.2653959-1-robh@kernel.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2025-08-13 11:09:10 +10:00
Colin Finck
1c6c51e51b Consider drive letters when checking for absolute paths on Windows.
This still requires you to specify paths with forward slashes instead of
backslashes on Windows, due to many hardcoded checks for '/'.
Fortunately, the Windows user APIs all support forward slashes too.

Signed-off-by: Colin Finck <mail@colinfinck.de>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2025-08-07 21:42:42 +10:00
David Gibson
617f3d9b60 ci: Add Cirrus CI configuration for FreeBSD testing
Add FreeBSD test coverage with builds on FreeBSD 13.5 and 14.3 using
both make and meson build systems.

Generated-by: Claude Code 1.0.65 (claude-sonnet-4@20250514)
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2025-08-01 15:48:27 +10:00
David Gibson
04f948e83f ci: Add GitLab CI configuration for Linux builds
Add GitLab CI with Linux builds on Alpine, Arch, Fedora, and Ubuntu using
both make and meson build systems.

Generated-by: Claude Code 1.0.65 (claude-sonnet-4@20250514)
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2025-08-01 15:46:48 +10:00
David Gibson
e896802631 ci: Tweaks to GitHub Actions setup
Remove some unnecessary package dependencies.  Also include testing of the
'ci' branch (so as to test in-progress changes to the CI configuration
itself).

Generated-by: Claude Code 1.0.65 (claude-sonnet-4@20250514)
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2025-08-01 15:45:58 +10:00
David Gibson
2ad738722b build: Add FreeBSD and non-GNU linker compatibility
Add compatibility fixes for non-GNU compilers and linkers by testing
versions before using certain flags.  In particular this fixes make build
problems on FreeBSD.

Generated-by: Claude Code 1.0.65 (claude-sonnet-4@20250514)
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2025-08-01 15:43:21 +10:00
David Gibson
4132ac08ba libfdt: Document most remaining functions
Largely an experiment using an AI assistant.  Used Claude to generate
documentation comments for most of the functions in libfdt.h which
currently lack them.  Then hand reviewed and edited.

Or, as Claude describes it:

Add detailed documentation comments for core libfdt functions including:
- Low-level functions (fdt_offset_ptr, fdt_next_tag, fdt_check_full)
- Sequential write functions (fdt_resize, fdt_add_reservemap_entry,
  fdt_finish_reservemap, fdt_begin_node, fdt_property, fdt_end_node, fdt_finish)
- Read-write functions (fdt_create_empty_tree, fdt_open_into, fdt_pack)
- Error handling (fdt_strerror)

Documentation includes parameter descriptions, return value meanings,
and usage notes for proper API usage.

Generated-by: Claude 1.0.64 (claude-sonnet-4@20250514)
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2025-08-01 11:34:18 +10:00
David Gibson
33e66ec845 tests: Add compatibility with uutils
In some places run_tsets.sh needs to get the size of files, which it does
with stat(1).  However the syntax to do this is different between GNU
coreutils stat(1) and BSD's stat(1).  We have some logic that looks for
"GNU" in the version string to figure out the correct version.

This will break upcoming Ubuntu versions which are now using uutils, a Rust
reimplementation of coreutils.  These support the same GNU syntax, but
don't have the "GNU" in the version string.

Update the detection to simply try the GNU version and otherwise assume
BSD.

Link: https://github.com/dgibson/dtc/issues/166

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2025-07-28 16:54:31 +10:00
David Gibson
a0dd7b6081 fdtput: Use strtol() in preference to sscanf()
I find the exact semantics of scanf() always confusing, and mostly we use
strtol() and similar functions instead.  Switch fdtput to using strtol and
similar functions instead of sscanf().

As well as being more in keeping with what we do in other places, this
works around a FreeBSD bug[0], where sscanf(), but not strtol() parses
"003" as having value 0.

[0] https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=288440

Link: https://github.com/dgibson/dtc/issues/165

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2025-07-28 16:42:34 +10:00
David Gibson
5b71660724 tests: Work around limitation in FreeBSD's printf(1)
Some of our testcases check fdtget retreiving string list properties that
include internal \0 characters.  We use printf(1) to generate the expected
value for comparison.

However, on FreeBSD, printf(1)'s %b format option can't handle \0: it will
terminate that argument ignoring it and everything after.  Curiously,
internal \0 *is* ok in the main format string.  So avoid using %b and use
the format string directly instead.

Link: https:/https://github.com/dgibson/dtc/issues/165

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2025-07-25 13:01:41 +10:00
Vivian Wang
52f07dcca4 dtc: Add informative error for stray identifier
When a DTS is preprocessed, sometimes the user fails to include the
correct header files, or make a spelling mistake on a macro name. This
leads to a stray identifier in the DTS, like:

  property = <1 2 FOO BAR(3, 4)>;

Give a more helpful error message than "syntax error" by recognizing and
reporting the identifier, like this:

  Lexical error: <stdin>:2.21-24 Unexpected 'FOO'

Also, treat that identifier as literal, which often helps the parser go
further and may generate more helpful error messages.

Signed-off-by: Vivian Wang <wangruikang@iscas.ac.cn>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2025-07-14 18:32:02 +10:00
Jon Hunter
9cabae6b03 checks: Fix detection of 'i2c-bus' node
If an I2C controller has a 'i2c-bus' child node, then the function
check_i2c_bus_bridge() does not detect this as expected and warnings
such as the following are observed:

 Warning (i2c_bus_bridge): /example-0/i2c@7000c000: \
     incorrect #address-cells for I2C bus
 Warning (i2c_bus_bridge): /example-0/i2c@7000c000: \
     incorrect #size-cells for I2C bus

These warnings occur because the '#address-cells' and '#size-cells' are
not directly present under the I2C controller node but the 'i2c-bus'
child node. The function check_i2c_bus_bridge() does not detect this
because it is using the parent node's 'basenamelen' and not the child
node's 'basenamelen' when comparing the child node name with 'i2c-bus'.
The parent node's 'basenamelen' is shorter ('i2c') than 'i2c-bus' and so
the strprefixeq() test fails. Fix this by using the child node
'basenamelen' when comparing the child node name.

Fixes: 53a1bd5469 ("checks: add I2C bus checks")
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Message-ID: <20250709142452.249492-1-jonathanh@nvidia.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2025-07-10 19:09:39 +10:00
Uwe Kleine-König
605dc044c3 New helper to add markers
The add_marker() function is used to create a new marker and add it at
the right spot to the relevant marker list. Use it in the
add_string_markers() helper (which gets slightly quicker by it).

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2025-07-02 15:46:47 +10:00
Uwe Kleine-König
7da5d106c7 fdtput: Fix documentation about existing nodes
The documentation claims that `-c` would "Create nodes if they don't
already exist". This is true, but suggests that trying to create a node
that already exists is not an error. fdtput however errors out in that
case. Similar `fdtput -d` errors out when called for a non-existing
node.

Drop the "if they [don't] already exist" to make that clearer.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2025-07-01 20:47:15 +10:00
Uwe Kleine-König
53c63dd421 dtdiff: Use input format dtb for dtbo files
The file ending .dtbo is typically used for device tree overlays. These
are in the dtb input format, too. So assume this input format for *.dtbo
as is already done for *.dtb.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2025-07-01 20:42:22 +10:00
Ayush Singh
84d9dd2fcb dtc: Add data_insert_data function
Add helper function to insert a data struct into another.

Signed-off-by: Ayush Singh <ayush@beagleboard.org>
Message-ID: <20250605-previous-value-v3-2-0983d0733a07@beagleboard.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2025-06-12 16:37:31 +10:00
Paolo Bonzini
97011d1f4e meson: use override_find_program/override_dependency
Allow projects that use dtc as a subproject to find the tools and
library via find_program() and dependency().  This way, for those
projects there is no different between system dtc and subproject dtc.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-ID: <20250612053829.1037412-1-pbonzini@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2025-06-12 15:55:00 +10:00
Ayush Singh
b841391bbd srcpos: Define srcpos_free
srcpos can be chained together using srcpos_extend. However, in such
cases, we need to free all the chained nodes.

srcpos_free is a helper to recursively free all the linked srcpos.

Signed-off-by: Ayush Singh <ayush@beagleboard.org>
Message-ID: <20250605-previous-value-v3-1-0983d0733a07@beagleboard.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2025-06-09 22:27:00 +10:00
Ayush Singh
e0b7749c26 Add alloc_marker
- Add helper to allocate new marker

Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Ayush Singh <ayush@beagleboard.org>
Message-ID: <20250311-previous-value-v2-1-e4a8611e956f@beagleboard.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2025-05-28 15:12:50 +10:00
Eli Schwartz
ecb21febfd meson: port python bindings to build natively via meson and meson-python
We get full build parallelism and fewer confusing ancient distutils
paths. The python wheels build fully standalone, including linking
libfdt as a static library.

For convenience, when running pip install a meson option is passed that
prevents building tools or installing headers/pkgconfig files.
meson-python would otherwise include them in the wheel itself, in case
they are needed, but this is essentially a bit useless so don't bother.

The old setuptools-based build is now redundant and goes away.

Signed-off-by: Eli Schwartz <eschwartz@gentoo.org>
Message-ID: <20250430152601.43554-3-eschwartz@gentoo.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2025-05-01 19:27:10 +07:00
Eli Schwartz
7ebfcac852 Makefile: deprecate in favor of Meson
Building the python bindings is complicated and not very practical to do
in a Makefile. The setuptools invocations previously used are confusing
and don't work very well compared to Meson. Having two build systems
that do different things is also confusing though.

Since Meson can do everything that Make can do, but the reverse is not
true, we deprecate the latter and warn when you use it.

GNU Make can emit a $(warning) on every Makefile run, which is a bit
noisy but means we don't need to have every target depend on a PHONY
target (preventing built targets from being seen as up to date).

Signed-off-by: Eli Schwartz <eschwartz@gentoo.org>
Message-ID: <20250430152601.43554-2-eschwartz@gentoo.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2025-05-01 19:27:10 +07:00
Thomas Huth
f4c53f4ebf Use __ASSEMBLER__ instead of __ASSEMBLY__
Both, Clang and GCC define __ASSEMBLER__ automatically when
compiling .S files, so this macro is a much better fit for
fdt.h - programs that want to use it from .S files don't have
to manually #define __ASSEMBLY__ that way.
While we're at it, also change it in testdata.h, then we don't
have to define __ASSEMBLY__ in the Makefile / meson.build file
anymore.

Signed-off-by: Thomas Huth <thuth@redhat.com>
Message-ID: <20250313192718.1561683-1-thuth@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2025-03-14 13:51:31 +11:00
Thomas Huth
205fbef17b Fix some typos
Discovered with the "codespell" utility.

Signed-off-by: Thomas Huth <thuth@redhat.com>
Message-ID: <20250313191607.1556384-1-thuth@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2025-03-14 13:50:32 +11:00
Thomas Huth
da85f91931 Remove duplicated words in documentation and comments
Let's avoid repeating single words here!

Signed-off-by: Thomas Huth <thuth@redhat.com>
Message-ID: <20250313190527.1556019-1-thuth@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2025-03-14 13:48:10 +11:00
Brandon Maier
dd1b3e532d meson: support building libfdt without static library
Some packaging systems like NixOS don't support compiling static
libraries. However libfdt's meson.build uses `both_library()` which
forces the build to always compile shared and static libraries. Removing
`both_library()` will make packaging easier.

libfdt uses `both_libraries()` to support the 'static-build' option.
But we do not need the 'static-build' option as Meson can natively
build static using

> meson setup builddir/ -Dc_link_args='-static' --prefer-static --default-library=static

So drop 'static-build' and then replace `both_libraries()` with
`library()`.

Signed-off-by: Brandon Maier <brandon.maier@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2025-03-13 16:19:27 +11:00
Eli Schwartz
1ccd232709 meson: don't build test programs by default
They are only used when running tests, and are included as depedencies
of the test cases themselves already. Marking them to not build by
default, means that 291 compile edges can be skipped when only running

```
meson setup builddir/
ninja -C builddir/
meson install -C builddir/
```

resulting in an overall much faster build. Instead they will be compiled
on-demand by `meson test`, only for users that actually run the tests.

Signed-off-by: Eli Schwartz <eschwartz@gentoo.org>
Message-ID: <20250302222839.2256985-1-eschwartz@gentoo.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2025-03-03 12:46:55 +11:00
David Gibson
ce1d858888 tests: When building .so from -O asm output mark as non-executable stack
For certain tests, we take the output from dtc -O asm and build it into
a .so shared library which we then dlopen() for further tests.  Because we
don't mark it otherwise, it's treated as requiring an executable stack,
which dlopen() refuses to open as of glibc-2.41.

Of course, the library is pure data, no code, so it certainly doesn't need
an executable stack.  Add the -znoexecstack linker option to avoid the
error.

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

Reported-by: Xi Ruoyao <xry111@xry111.site>
Signed-off-by: David Gibson <david@gibson.dropbear.id.a>
2025-02-05 13:39:43 +11:00
Uwe Kleine-König
915daadbb6 Start with empty __local_fixups__ and __fixups__ nodes
When the meta nodes __local_fixups__ and __fixups__ are generated, and
one of these (or both) already exist, the information contained there
is duplicated at best and stale otherwise. So remove the nodes before
starting to fill them.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2025-01-24 14:15:35 +11:00
Uwe Kleine-König
4ea851f5a4 Let get_subnode() not return deleted nodes
Both current callers actually don't want deleted nodes returned by
get_subnode(). So change semantics of this function to only return
"live" nodes.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2025-01-24 14:14:02 +11:00
Uwe Kleine-König
175d2a564c Use build_root_node() instead of open-coding it
build_root_node() does error checking (which is good!) but otherwise
behaves exactly as the code replaced here.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2025-01-24 14:12:53 +11:00
Marc-André Lureau
18f4f305fd build: fix -Dtools=false build
When configuring the project, meson fails with:
tests/meson.build:107:27: ERROR: Unknown variable "util_dep"

Declare the util_dep dependency regardless if 'tools' are enabled, so
tests can be built with it.

Fixes: bdc5c8793a ("meson: allow disabling tests")
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-12-18 16:12:59 +11:00
Thierry Reding
267efc7d46 checks: Warn about missing #address-cells for interrupt parents
The device tree specification (v0.4) suggests that #address-cells is
mandatory for interrupt parent nodes. If this property is missing, Linux
will default to the value of 0.

A number of device tree files rely on Linux' fallback and don't specify
an explicit #address-cells as suggested by the specification. This can
cause issues when these device trees are passed to software with a more
pedantic interpretation of the DT spec.

Add a warning when this case is detected so that device tree files can
be fixed.

Reported-by: Brad Griffis <bgriffis@nvidia.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
Message-ID: <20241213141438.3616902-1-thierry.reding@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-12-18 15:56:51 +11:00
Ayush Singh
755db11535 libfdt: Add fdt_setprop_namelen_string()
Macro using fdt_setprop_namelen() internally similar to
`fdt_setprop_string()`.

Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Ayush Singh <ayush@beagleboard.org>
Message-ID: <20241205-setprop-namelen-v2-4-0d85a3d2e7b1@beagleboard.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-12-06 16:42:25 +11:00
Ayush Singh
bdca861200 libfdt: Add fdt_setprop_namelen()
Allow specifying name length in setprop similar to
`fdt_get_property_namelen` functions.

Signed-off-by: Ayush Singh <ayush@beagleboard.org>
Message-ID: <20241205-setprop-namelen-v2-3-0d85a3d2e7b1@beagleboard.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-12-06 16:42:25 +11:00
Ayush Singh
0f69cedc08 libfdt_internal: fdt_find_string_len_()
Allow specifying string length to `fdt_find_string_`.
fdt_find_string_() now internally uses this function.

Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Ayush Singh <ayush@beagleboard.org>
Message-ID: <20241205-setprop-namelen-v2-2-0d85a3d2e7b1@beagleboard.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-12-06 16:42:25 +11:00
Ayush Singh
56b2b30c5b libfdt: add fdt_get_property_namelen_w()
Similar to the non-namelen variant, it is implemented in terms of
fdt_get_property_namelen()

Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Ayush Singh <ayush@beagleboard.org>
Message-ID: <20241205-setprop-namelen-v2-1-0d85a3d2e7b1@beagleboard.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-12-06 16:42:25 +11:00
Ayush Singh
1e8c5f60e1 Add clang-format config
Add clang-format config based on Linux kernel clang-format config.
Allows for consistent formatting rules for all future contributions.

Signed-off-by: Ayush Singh <ayush@beagleboard.org>
Message-ID: <20241205-clang-format-v2-1-07d21007bdab@beagleboard.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-12-06 14:44:46 +11:00
Philipp Zabel
6f183c7d92 checks: Relax avoid_unnecessary_addr_size check to allow child ranges properties
Do not fail the unnecessary #address-cells/#size-cells check if any
children of the node have a "ranges" property.

Suggested-by: Rob Herring <robh@kernel.org>
Link: https://lore.kernel.org/all/CAL_JsqKebRL454poAYZ9i=sCsHqGzmocLy0psQcng-79UWJB-A@mail.gmail.com/
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Message-ID: <20241106130108.852323-1-p.zabel@pengutronix.de>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-11-27 12:52:56 +11:00
Brandon Maier
66c7d0e6f4 tests/sw_tree1.c: fix unitialized saveptr
Building the dtc tests on the Conda build system results in the
following error.

> In function '__strtok_r_1c',                                                                                                                                     2024-11-23T19:17:20.7930512Z     inlined from 'main' at ../tests/sw_tree1.c:140:17:
> $BUILD_PREFIX/x86_64-conda-linux-gnu/sysroot/usr/include/bits/string2.h:1177:10: error: 'saveptr' may be used uninitialized [-Werror=maybe-uninitialized]
>  1177 |   while (*__s == __sep)
>       |          ^~~~
> ../tests/sw_tree1.c: In function 'main':
> ../tests/sw_tree1.c:137:39: note: 'saveptr' was declared here
>   137 |                 char *str = argv[2], *saveptr, *tok;
>       |                                       ^~~~~~~
> cc1: all warnings being treated as errors

The manpage `strtok(3)` says the following.

> VERSIONS
>   On some implementations, *saveptr is required to be NULL on the first call to strtok_r() that is being used to parse str.

So set it to NULL.

Signed-off-by: Brandon Maier <brandon.maier@gmail.com>
2024-11-25 12:52:43 +11:00
Brandon Maier
9a969f3b70 pylibfdt/libfdt.i: fix backwards compatibility of return values
When our Python functions wrap `fdt_getprop()` they return a list
containing `[*data, length]`.

In SWIG v4.2 and earlier SWIG would discard `*data` if it is NULL/None.
Causing the return value to just be `length`.

But starting in SWIG v4.3 it no longer discards `*data`. So the return
value is now `[None, length]`.

Handle this compatibility issue in libfdt.i by checking if the return
value looks like the older 4.2 return value, and casting it to the newer
style.

See https://github.com/swig/swig/pull/2907

Signed-off-by: Brandon Maier <brandon.maier@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-11-25 12:43:19 +11:00
Brandon Maier
4292b072a2 .github/workflows: update ubuntu runner to supported version
The Ubuntu runner fails with the following message

> E: The repository 'http://security.ubuntu.com/ubuntu mantic-security Release' does not have a Release file.

Ubuntu 23.10 is end-of-life as of July 2024 anyway. So switch to the
latest Ubuntu tag, which is currently 24.04.

See https://discourse.ubuntu.com/t/edubuntu-23-10-has-reached-end-of-life-eol/46325

Signed-off-by: Brandon Maier <brandon.maier@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-11-25 12:27:23 +11:00
Bingwu Zhang
1c745a9bd1 libfdt: Remove fdt parameter from overlay_fixup_one_phandle
When compiling with -Wall -Wextra, the unused fdt parameter becomes a
warning. With -Werror, it becomes an error and fails the build.

As the parameter is not used in the function, let's remove it.

Signed-off-by: Bingwu Zhang <xtexchooser@duck.com>
Message-ID: <20241123094814.15504-2-xtex@envs.net>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-11-25 12:21:00 +11:00
Richard Hughes
b3bbee6b12 libfdt: Move the SBOM authors section
I was mistaken, and another maintainer pointed out the author-of-this-file
metadata needs to be in a different place. Apologies for the churn.

Signed-off-by: Richard Hughes <richard@hughsie.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-11-20 16:16:57 +11:00
Richard Hughes
d1656730ab Add a SBOM file in CycloneDX format
Improve supply chain security by including a SBOM file with substituted values.

This will be used to construct a composite platform SBOM.

Signed-off-by: Richard Hughes <richard@hughsie.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-11-18 16:24:48 +11:00
Bingwu Zhang
b75515af45 libfdt: Remove extra semi-colons outside functions
When compiling with -Werror -Wpedantic, both GCC and Clang fails, saying
that these semi-colons are redundant, so remove them.

Signed-off-by: Bingwu Zhang <xtexchooser@duck.com>
Message-ID: <20241116101228.164707-6-xtex@envs.net>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-11-18 14:26:34 +11:00
David Gibson
2d10aa2afe Bump version to v1.7.2
Prepare for a new release.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-11-06 14:01:37 +11:00
David Gibson
48795c82bd pylibfdt: Don't emit warnings from swig generate C code
The swig generated code has a heap of warnings with the flags we usually
use.  These aren't helpful, since there's nothing we can do about them from
the dtc side.  So, just disable the warnings flags when compiling the
Python module.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-11-06 14:00:45 +11:00
Amjad Alsharafi
838f11e830 fdtoverlay: provide better error message for missing /__symbols__
This was added because trying to apply overlay on dtb without knowing a lot
about the subject can be frustrating with strange error messages.

Before this, it will tell you:
`Failed to apply 'overlay.dtbo': FDT_ERR_BADOFFSET`

This message is similar to what's shown in `u-boot` when
trying to apply overlay

Signed-off-by: Amjad Alsharafi <amjadsharafi10@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-10-30 16:01:37 +11:00
Markus Volk
d1e2384185 pylibfdt/libfdt.i: Use SWIG_AppendOutput
Swig has changed language specific AppendOutput functions. The helper
macro SWIG_AppendOutput remains unchanged. Use that instead
of SWIG_Python_AppendOutput, which would require an extra parameter
since swig 4.3.0.

| /home/flk/poky/build-hypr/tmp/work/x86_64-linux/python3-dtc-native/1.7.0/git/pylibfdt/libfdt_wrap.c: In function ‘_wrap_fdt_next_node’:
| /home/flk/poky/build-hypr/tmp/work/x86_64-linux/python3-dtc-native/1.7.0/git/pylibfdt/libfdt_wrap.c:5598:17: error: too few arguments to function ‘SWIG_Python_AppendOutput’
|  5598 |     resultobj = SWIG_Python_AppendOutput(resultobj, val);

Signed-off-by: Markus Volk <f_l_k@t-online.de>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-10-30 12:06:50 +11:00
Colin Finck
18aa49a9f6 Escape spaces in depfile with backslashes.
This matches how Linux escapes spaces in paths.
The same syntax is also used by other build tools that output depfiles,
e.g. edd36eba5e/src/cargo/core/compiler/output_depinfo.rs (L19)

Signed-off-by: Colin Finck <mail@colinfinck.de>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-10-24 15:44:47 +11:00
Rasmus Villemoes
f9968fa069 libfdt.h: whitespace consistency fixups
In these cases, spaces are used for indentation/alignment while the
surrounding lines use tab. Fix it up for consistency.

Signed-off-by: Rasmus Villemoes <ravi@prevas.dk>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-10-07 19:59:18 +10:00
Rasmus Villemoes
9b5f65fb3d libfdt.h: typo and consistency fixes
Most of these are plain typos. Exceptions:

- "devicetree" is only used in that form in the grammar and in mailing
  list references; all other instances, in particular all in prose,
  use "device tree".

- I don't know what "nodeequested" was supposed to be, the sentence
  reads just fine without it.

- "inexistant" is a rare form of nonexistent.

Signed-off-by: Rasmus Villemoes <ravi@prevas.dk>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-10-07 19:58:13 +10:00
David Gibson
99031e3a4a Bump version to v1.7.1
Prepare for a new release.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-08-17 18:22:16 +10:00
Simon Glass
3d5e376925 setup: Move setting of srcdir down to the bottom
Put this variable assignment next to the others. Pass it to
get_top_builddir() instead of relying on the global variable.

Signed-off-by: Simon Glass <sjg@chromium.org>
Message-ID: <20240811150248.7537-5-sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-08-12 11:46:30 +10:00
Simon Glass
e277553b98 setup: Collect top-level code together
Move most of the top-level code together, with the classes and functions
above, for easier reading.

The srcdir is left where it is for now.

Signed-off-by: Simon Glass <sjg@chromium.org>
Message-ID: <20240811150248.7537-4-sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-08-12 11:45:25 +10:00
Simon Glass
7e5a889840 setup: Move version and full_description into a function
Do this processing in a function and return the result, to reduce the
amount of code at the top level.

Signed-off-by: Simon Glass <sjg@chromium.org>
Message-ID: <20240811150248.7537-3-sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-08-12 11:45:01 +10:00
Simon Glass
78b6a85c11 Tidy up some pylint warnings
Resolve all the pylint warnings currently in setup.py

Signed-off-by: Simon Glass <sjg@chromium.org>
Message-ID: <20240811150248.7537-2-sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-08-12 11:39:48 +10:00
Simon Glass
3501d373f0 Require Python 3
We don't need to support Python 2 anymore, so drop the comment and add
the minimum required version. Use version 3.8 since I am not sure that
it works on older versions and 3.7 has reached end-of-life.

Signed-off-by: Simon Glass <sjg@chromium.org>
Message-ID: <20240811150248.7537-1-sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-08-12 11:38:41 +10:00
Markus Heidelberg
bcd02b5234 fdtoverlay: remove wrong singular article in a comment
Signed-off-by: Markus Heidelberg <m.heidelberg@cab.de>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-08-11 11:05:29 +10:00
Michael Riesch
84b056a89d checks: relax graph checks for overlays
In device tree overlays, the following patterns occur frequently:

board.dts:
/dts-v1/;

/ {
	display-controller {
		ports {
			#address-cells = <1>;
			#size-cells = <0>;

			vp0: port@0 {
				reg = <0>;

				vp0_out: endpoint {
				};
			};

			vp1: port@1 {
				reg = <1>;
			};
		};
	};
};

overlay-endpoint.dtso:
/dts-v1/;
/plugin/;

&{/} {
	hdmi-tx-connector {
		port {
			hdmi_tx_in: endpoint {
				remote-endpoint = <&vp0_out>;
			};
		};
	};
};

&vp0_out {
	remote-endpoint = <&hdmi_tx_in>;
};

In this case, dtc expects that the node referenced by &vp0_out is
named "endpoint", but the name cannot be inferred. Also, dtc
complains about the connections between the endpoints not being
bidirectional.

Similarly, for a different overlay overlay-port.dtso:
/dts-v1/;
/plugin/;

&{/} {
	panel {
		port {
			panel_in: endpoint {
				remote-endpoint = <&vp1_out>;
			};
		};
	};
};

&vp1 {
	vp1_out: endpoint {
		remote-endpoint = <&panel_in>;
	};
};

dtc expects that the node referenced by &vp1 is named "port", but the
name cannot be inferred.

Relax the corresponding checks and skip the parts that are not reasonable
for device tree overlays.

Signed-off-by: Michael Riesch <michael.riesch@wolfvision.net>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-08-01 12:56:59 +10:00
Dan Horák
1df7b047fe pylibfdt/Makefile.pylibfdt: use project's flags to compile the extension
Seems the project's CFLAGS are not used when compiling the python
extension's C code via the setup.py script. Some default flags are used
instead. Thus pass the CFLAGS explicitly. Unfortunately the SWIG generated
code is not clean and requires -Wno-error override to compile successfully,
because -Werror is used in the project's flags.

Signed-off-by: Dan Horák <dan@danny.cz>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-07-06 15:58:06 +10:00
Uwe Kleine-König
61e88fdcec libfdt: overlay: Fix phandle overwrite check for new subtrees
If the overlay's target is only created in a previous fragment, it
doesn't exist in the unmodified base device tree. For the phandle
overwrite check this can be ignored because in this case the base tree
doesn't contain a phandle that could be overwritten.

Adapt the corresponding check to not error out if that happens but just
continue with the next fragment.

This is currently triggered by
arch/arm64/boot/dts/renesas/salvator-panel-aa104xd12.dtso in the kernel
repository which creates /panel in its first fragment and modifies it in
its second.

Reported-by: Rob Herring <robh@kernel.org>
Link: https://lore.kernel.org/all/CAL_JsqL9MPycDjqQfPNAuGfC6EMrdzUivr+fuOS7YgU3biGd4A@mail.gmail.com/
Fixes: 1fad065080 ("libfdt: overlay: ensure that existing phandles are not overwritten")
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
Message-ID: <20240626075551.2493048-2-u.kleine-koenig@baylibre.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-07-05 21:53:18 +10:00
Brandon Maier
49d3089446 meson: fix installation with meson-python
The meson-python backend fails to map 'dtdiff' install into Python
wheels. Removing the prefix from the install_dir path allows
meson-python to map dtdiff. The install_data(install_dir) documentation
says "If this is a relative path, it is assumed to be relative to the
prefix"[1]. So removing the prefix does not change the installation
behaviour.

[1] https://mesonbuild.com/Reference-manual_functions.html#install_data

Signed-off-by: Brandon Maier <brandon.maier@collins.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-07-01 12:01:52 +10:00
Brandon Maier
d54aaf9367 pylibfdt: clean up python build directory
In commit "pylibfdt/Makefile.pylibfdt: fix Python library being rebuild
during install" the build directory moved to the top level of the repo.

Signed-off-by: Brandon Maier <brandon.maier@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-07-01 11:49:27 +10:00
Brandon Maier
ab86f1e9fd pylibfdt: add VERSION.txt to Python sdist
The VERSION.txt file tells setup.py what library version to use, so we
must include it in the source distrbution.

Signed-off-by: Brandon Maier <brandon.maier@collins.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-07-01 11:43:50 +10:00
Brandon Maier
7b8a30ecea pylibfdt: fix Python version
In commit "pylibfdt: Remove some apparently deprecated options from
setup.py" the scm version tracking was removed. But it was not replaced
with the fixed version. This causes the Python modules to be installed
as version '0.0.0'.

Signed-off-by: Brandon Maier <brandon.maier@collins.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-07-01 11:43:43 +10:00
Brandon Maier
ff4f17eb58 pylibfdt/Makefile.pylibfdt: fix Python library being rebuild during install
The Python module gets built during the 'make install' command even if
'make all' was run prior for build.

This is the same issue as described in the previous commit
"pylibfdt/meson.build: fix Python library being rebuilt during install".
Remove the '--build-lib' flag so setuptools can find the build module.

Signed-off-by: Brandon Maier <brandon.maier@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-06-26 11:38:31 +10:00
Brandon Maier
9e313b14e6 pylibfdt/meson.build: fix Python library being rebuilt during install
User @sharkcz noted that when the '--quiet' flag is removed from
./setup.py, the following can be seen from the `./setup.py install`
stage.

  Running custom install script 'dtc/g/pylibfdt/../setup.py --top-builddir \
    dtc/g/redhat-linux-build install --prefix=/usr/local --root=$DESTDIR'
  running install
  ...
  building '_libfdt' extension
  swigging dtc/g/pylibfdt/../pylibfdt/libfdt.i to \
    dtc/g/pylibfdt/../pylibfdt/libfdt_wrap.c
  swig -python -Idtc/g/pylibfdt/../libfdt -o \
    dtc/g/pylibfdt/../pylibfdt/libfdt_wrap.c dtc/g/pylibfdt/../pylibfdt/libfdt.i
  gcc -fno-strict-overflow -Wsign-compare -DDYNAMIC_ANNOTATIONS_ENABLED=1 \
    -DNDEBUG -fexceptions -fexceptions -fexceptions -fPIC -DPY_SSIZE_T_CLEAN \
    -Idtc/g/pylibfdt/../libfdt -I/usr/include/python3.12 -c \
    dtc/g/pylibfdt/../pylibfdt/libfdt_wrap.c -o \
    build/temp.linux-ppc64le-cpython-312dtc/g/pylibfdt/../pylibfdt/libfdt_wrap.o
  creating build/lib.linux-ppc64le-cpython-312
  gcc -shared build/temp.linux-ppc64le-cpython-312dtc/g/pylibfdt/../pylibfdt/libfdt_wrap.o \
    -Ldtc/g/redhat-linux-build/libfdt -L/usr/lib64 -lfdt -o \
    build/lib.linux-ppc64le-cpython-312/_libfdt.cpython-312-powerpc64le-linux-gnu.so
  copying dtc/g/pylibfdt/../pylibfdt/libfdt.py -> build/lib.linux-ppc64le-cpython-312

Meaning the python library is getting recompiled during the `meson
install` phase. This causes build issues as Meson does not set the
compiler and linker flags during the install phase.

The reason the library is getting rebuilt is during the normal build
with "build_ext", the `--build-lib` flag gets passed which changes the
default output build directory. But there is no equivalent option for
the "install" command. Install instead looks in the default directory
"./build" and so does not find the previously built library.

Since we can't fix the "install" command, drop the --build-lib flag.
This causes setup.py to compile the libraries at
`<meson-build>/build/lib.linux-x86_64-cpython-312/`. We must also then
fix run_tests.sh to find the library build directory as it's
machine-dependent.

Fixes: #135
Signed-off-by: Brandon Maier <brandon.maier@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-06-26 11:38:22 +10:00
Brandon Maier
d598fc3648 tests/run_tests.sh: fix Meson library path being dropped
Meson automatically passes in LD_LIBRARY_PATH pointing at the correct
build directory for libfdt.so. So preserve LD_LIBRARY_PATH if it's
already set.

Signed-off-by: Brandon Maier <brandon.maier@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-06-26 11:27:02 +10:00
Brandon Maier
b98239da2f tests/meson.build: fix python and yaml tests not running
The run-tests.sh script attempts to detect if Python and Yaml support is
enabled in the build. This has caused false-negatives where it fails to
find the Python library even though it was compiled into the build.

Avoid this problem altogether and always set the NO_PYTHON and NO_YAML
to match if the features are enabled in Meson.

Signed-off-by: Brandon Maier <brandon.maier@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-06-24 13:24:13 +10:00
Rob Herring (Arm)
c17d76ab5e checks: Check the overall length of "interrupt-map"
It is possible the overall length of "interrupt-map" is shorter than
expected. A likely scenario is if "#address-cells" in the interrupt
parent is not accounted for and there is only a single map entry. With
multiple entries, one of the other tests would likely fail.

Signed-off-by: Rob Herring (Arm) <robh@kernel.org>
Message-ID: <20240531133149.1498139-1-robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-06-01 18:05:00 +10:00
Zheng Guangyuan
ae26223a05 libfdt: overlay: Refactor overlay_fixup_phandle
Refactored overlay_fixup_phandle to optimize efficiency by moving the
phandle lookup logic based on label outside the overlay_fixup_one_phandle call.
This avoids redundant phandle lookups when a single label is associated with multiple modifications.

Signed-off-by: Zheng Guangyuan <1628513611@qq.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-05-01 16:50:50 +10:00
Zheng Guangyuan
4dd831affd libfdt: tests: Update test case for overlay_bad_fixup
Changed the target DTS from overlay_base_no_symbols.test.dtb to overlay_base_manual_symbols.test.dtb.
This ensures that the test case doesn't exit prematurely due to the absence of label-linked phandle in the symbols node.
The update guarantees that the test case appropriately checks the validity of the fixup string linked to the label, as intended.

Signed-off-by: Zheng Guangyuan <1628513611@qq.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-05-01 16:50:19 +10:00
Zheng Guangyuan
e6d2942008 tests: Remove two_roots and named_root from LIBTREE_TESTS_L and add all dtb filenames generated by dumptrees to TESTS_TREES_L in Makefile.tests
These two binaries are not produced;
two_roots.dtb and named_root.dtb are instead generated in TESTS_TREES.
Redundant file entries eliminated and Ensures that all dtb filenames
generated by dumptrees are now accounted for in the TEST_TREES, addressing previous omissions

Signed-off-by: Zheng Guangyuan <1628513611@qq.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-04-29 11:42:47 +10:00
Brandon Maier
855c934e26 tests: fix tests broken under Meson
Tests running under Meson run from a different working directory then
under Makefile. Some of these tests had not been fixed to work from a
different directory because the tests were testing for an error
condition which is indistinguishable from a missing file.

Signed-off-by: Brandon Maier <brandon.maier@collins.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-03-22 08:56:12 +11:00
Brandon Maier
4fd3f4f0a9 github: enforce testing pylibfdt and yaml support
The Ubuntu runner was not building the yaml support as it's using Ubuntu
22 (jammy) which uses libyaml 0.2.2, but the build requires libyaml
0.2.3. Switch to Ubuntu 23 which has libyaml 0.2.5.

This was not detected by the runner as the Yaml feature defaults to
"auto" which turns off if it fails to find the dependency. In the runner
force yaml to enabled so if it fails to build it will trigger a build
failure.

We also force python support for the same reason.

Signed-off-by: Brandon Maier <brandon.maier@collins.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-03-19 15:31:56 +11:00
Brandon Maier
9ca7d62dbf meson: split run-tests by type
Instead of running run-tests on all tests, split them down into the 9
separate run-tests test types. This provides better granularity of test
results from the Meson test harness.

Signed-off-by: Brandon Maier <brandon.maier@collins.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-03-19 15:26:22 +11:00
Brandon Maier
bb51223083 meson: fix dependencies of tests
If the tests are run without a full compile they will fail. For example
with the following.

> rm -rf build/
> meson setup build/
> meson test -C build/

This is because the tests rely on the devicetree tools and test
executables.

Signed-off-by: Brandon Maier <brandon.maier@collins.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-03-19 15:25:39 +11:00
Brandon Maier
e81900635c meson: fix pylibfdt missing dependency on libfdt
The python library requires libfdt to build. This would intermittently
fail depending on what order targets compiled.

Signed-off-by: Brandon Maier <brandon.maier@collins.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-03-19 15:20:06 +11:00
Brandon Maier
8221238569 pylibfdt: fix get_mem_rsv for newer Python versions
The test for get_mem_rsv fails on newer versions of Python with the
following error.

> Traceback (most recent call last):
>   File "/__w/dtc/dtc/tests/pylibfdt_tests.py", line 421, in testReserveMap
>     self.assertEqual([ 0xdeadbeef00000000, 0x100000],
> AssertionError: Lists differ: [16045690981097406464, 1048576] != [0, 16045690981097406464, 1048576]
>
> First differing element 0:
> 16045690981097406464
> 0
>
> Second list contains 1 additional elements.
> First extra element 2:
> 1048576
>
> - [16045690981097406464, 1048576]
> + [0, 16045690981097406464, 1048576]
> ?  +++

It appears this is because the PyTuple_GET_SIZE() function that was used
to build the fdt_get_mem_rsv() return value has changed. It now is
returning a non-zero value when it's passed an integer, which causes the
SWIG wrapper to append the returned arguments to the return error rather
then ignore them.

This is valid behaviour per Python's documentation, which says it will
"Return the size of the tuple p, which must be non-NULL and point to a
tuple; no error checking is performed"[1]. As passing an integer is not
a tuple, its return value is undefined.

Fix this issue on older and newer versions by avoiding
PyTuple_GET_SIZE() entirely. Always append the arguments to the list,
and instead use the wrapper python function to check the first argument
and then splice the last two arguments as the return value.

[1] https://docs.python.org/3/c-api/tuple.html#c.PyTuple_GET_SIZE

Signed-off-by: Brandon Maier <brandon.maier@collins.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-03-19 15:13:34 +11:00
Uwe Kleine-König
1fad065080 libfdt: overlay: ensure that existing phandles are not overwritten
A phandle in an overlay is not supposed to overwrite a phandle that
already exists in the base dtb as this breaks references to the
respective node in the base.

So add another iteration over the fdto that checks for such overwrites
and fixes the fdto phandle's value to match the fdt's.

A test is added that checks that newly added phandles and existing
phandles work as expected.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Message-ID: <20240225175422.156393-2-u.kleine-koenig@pengutronix.de>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-03-14 20:34:16 +10:00
Marc-André Lureau
b0aacd0a77 github: add windows/msys CI build
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-03-06 22:30:33 +11:00
David Gibson
ae97d97458 github: Don't accidentally suppress test errors
The last commit, displaying the meson testlog if we fail tests had the
accidentaly side effect of not propagating the failure to show up properly
in github's dashboard.  Fix that.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-03-06 15:48:37 +11:00
David Gibson
057a7dbbb7 github: Display meson test logs on failure
Currently the way we integrate the existing tests into meson means meson
test itself doesn't show any detailed logs of the failures, those just go
to the meson testlog file.  As a hack to see what's failing in CI builds,
display that file if the tests fail.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-03-06 15:11:14 +11:00
David Gibson
92b5d4e916 pylibfdt: Remove some apparently deprecated options from setup.py
We seem to get deprecation warnings because of these.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-03-06 15:06:06 +11:00
David Gibson
417e3299db github: Update to newer checkout action
We're getting deprecation warnings about the v3 one.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-03-06 14:46:22 +11:00
Rosen Penev
5e6cefa17e fix MinGW format attribute
Setting -D__USE_MINGW_ANSI_STDIO=1 is wrong and should not be used. MinGW
internally uses a macro to select between gnu_printf and printf. Just use
that instead of using a wrong format under clang backends.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-03-06 14:28:43 +11:00
David Gibson
24f60011fd libfdt: Simplify adjustment of values for local fixups
In a couple of places in fdt_overlay.c we need to adjust a phandle value
in a property (either a node's phandle itself or a reference) by some
delta.  Currently this is done if a fairly convoluted way, open-coding
loading the value and handling of a non-aligned reference, and then using
fdt_setprop_inplace_partial() to replace the value.  This becomes much
simpler if we use fdt_getprop_w() to get a writable pointer to the value
then we can just load/store it with fdt32_{ld,st}().

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-02-23 15:36:00 +11:00
Rosen Penev
da39ee0e68 libfdt: rework shared/static libraries
Instead of creating 2 libraries manualy, just call both_libraries and
link to the appropriate one as requested.

Fixes compilation when passing -Ddefault_libraries=both as the
static_library name is duplicated.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-02-22 16:26:23 +11:00
Samuel Tardieu
a669223f7a Makefile: do not hardcode the install program path
On systems that do not use the FHS, such as NixOS, the `install` program is not
located in `/usr/bin/` as its location is dynamic.

`dtc` can be easily installed on such systems by using the `install` program
available in the `$PATH` with:

    make PREFIX=… INSTALL=install

However, this becomes more difficult when `dtc` is being compiled as part of a
larger toolchain, as the toolchain build scripts will not spontaneously pass
such an argument on the command line. This happens for example when `dtc` is
build as a part of the RTEMS build system.

By not hardcoding a predefined path for `install`, as is done for other
executables, `dtc` will allow the one in the `$PATH` to be used.

Signed-off-by: Samuel Tardieu <sam@rfc1149.net>
Message-ID: <20240208191405.1597654-1-sam@rfc1149.net>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-02-14 19:19:50 +11:00
Alyssa Ross
3fbfdd08af libfdt: fix duplicate meson target
If default_library is set to static, the libfdt target (which just
uses library()) is already static, so we should just use that.

This fixes this Meson error:

	libfdt/meson.build:37:11: ERROR: Tried to create target "fdt", but a target of that name already exists.

Signed-off-by: Alyssa Ross <hi@alyssa.is>
Message-ID: <20240123130742.185409-1-hi@alyssa.is>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-01-25 13:24:40 +11:00
Alyssa Ross
dcef5f834e tests: use correct pkg-config when cross compiling
By convention, the PKG_CONFIG environment variable is used to tell
build systems which pkg-config executable should be used.  This is
often used when cross compiling, where it might be set to something
like "aarch64-unknown-linux-gnu-pkg-config".

Signed-off-by: Alyssa Ross <hi@alyssa.is>
Message-ID: <20240123130409.181128-2-hi@alyssa.is>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-01-25 13:20:58 +11:00
Peter Marko
0b8026ff25 meson: allow building from shallow clones
When building from shallow clone, tag is not available
and version defaults to git hash.
Problem is that some builds check DTC version and fail the comparison.
Example is https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git
Which fails to build with following error:
dtc version too old (039a994), you need at least version 1.4.4

Drop --always from git describe command, see
https://github.com/mesonbuild/meson/blob/1.3.0/mesonbuild/utils/universal.py#L773
This will make it more closer to build via Makefile.

Signed-off-by: Peter Marko <peter.marko@siemens.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-12-18 10:58:31 +11:00
Rob Herring
95c74d71f0 treesource: Restore string list output when no type markers
When the DTS output has no type markers, we have to guess the type. Prior
to commit 32b9c61307 ("Preserve datatype markers when emitting dts
format"), instances of string lists would be delimited. Since then, a
single string with embedded "\0"s are emitted. An embedded "\0" is valid
for DTS files, but that's a rare exception and lists of strings are the
overwhelming majority. Restore the prior behavior.

stringlist.dts is reused for testing this, but needs a couple of tweaks
in order to match the dts output.

Reported-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Rob Herring <robh@kernel.org>
Message-ID: <20231027142901.2536622-1-robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-11-04 12:43:38 +11:00
Pierre-Clément Tosi
2283dd78ef libfdt: fdt_path_offset_namelen: Reject empty path
Reject empty paths and negative lengths, according to the DT spec v0.4:

    The convention for specifying a device path is:
        /node-name-1/node-name-2/node-name-N

    The path to the root node is /.

This prevents the access to path[0] from ever being out-of-bounds.

Signed-off-by: Pierre-Clément Tosi <ptosi@google.com>
Message-ID: <20231010092822.qo2nxc3g47t26dqs@google.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-10-11 11:37:24 +11:00
Pierre-Clément Tosi
79b9e326a1 libfdt: fdt_get_alias_namelen: Validate aliases
Ensure that the alias found matches the device tree specification v0.4:

    Each property of the /aliases node defines an alias. The property
    name specifies the alias name. The property value specifies the full
    path to a node in the devicetree.

This protects against a stack overflow caused by

    fdt_path_offset_namelen(fdt, path, namelen)

calling

    fdt_path_offset(fdt, fdt_get_alias_namelen(fdt, path, namelen))

leading to infinite recursion on DTs with "circular" aliases.

This fix was originally written by Mike McTernan for Android in [1].

[1]: https://android.googlesource.com/platform/external/dtc/+/9308e7f9772bd226fea9925b1fc4d53c127ed4d5

Signed-off-by: Pierre-Clément Tosi <ptosi@google.com>
Acked-by: Mike McTernan <mikemcternan@google.com>
Message-ID: <20231010092725.63h7c45p2fnmj577@google.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-10-11 11:35:08 +11:00
Simon Glass
52157f13ef pylibfdt: Support boolean properties
Boolean properties are unusual in that their presense or absence
indicates the value of the property. This makes them a little painful to
support using the existing getprop() support.

Add new methods to deal with booleans specifically.

Signed-off-by: Simon Glass <sjg@chromium.org>
Message-ID: <20230912182716.248253-1-sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-09-15 16:00:43 +10:00
Charles Perry
d774337275 dtc: fix missing string in usage_opts_help
This fixes the output of the `dtc --help` command as the last few
entries were offset by one.

Signed-off-by: Charles Perry <charles.perry@savoirfairelinux.com>
Message-ID: <20230904143104.1941715-1-charles.perry@savoirfairelinux.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-09-05 11:44:10 +10:00
Pierre-Clément Tosi
ad8bf9f9aa libfdt: Fix fdt_appendprop_addrrange documentation
According to the documentation, the function should default to the very
common property name <reg> when none is "specified". However, neither
passing NULL (ends up calling strlen(NULL) and segfaults) nor ""
(appends a property with an empty name) implements this behavior.

Furthermore, the test case supposed to cover this default value actually
passes the value to the function, somewhat defeating its own purpose:

    /* 2. default property name */

    // ...

    err = fdt_appendprop_addrrange(fdt, 0, offset, "reg", addr, size);
    if (err)
            FAIL("Failed to set \"reg\": %s", fdt_strerror(err));
    check_getprop_addrrange(fdt, 0, offset, "reg", 1);

Finally, nothing in the implementation of the function seems to attempt
to cover that use-case.

As the feature can't ever have been used by clients and as the resulting
reduced readability of the caller seems (IMO) to outweigh any potential
benefit this API would bring, remove the erroneous documentation instead
of trying to fix the function.

Reported-by: Mostafa Saleh <smostafa@google.com>
Signed-off-by: Pierre-Clément Tosi <ptosi@google.com>
Message-ID: <20230831123918.rf54emwkzgtcb7aw@google.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-09-04 15:27:55 +10:00
Brandon Maier
6c5e189fb9 github: add workflow for Meson builds
Signed-off-by: Brandon Maier <brandon.maier@collins.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-09-03 22:20:35 +10:00
Brandon Maier
a3dc9f006a libfdt: rename libfdt-X.Y.Z.so to libfdt.so.X.Y.Z
The Meson build system requires that the generated shared library uses
the libfdt.so.X.Y.Z naming scheme. But the Makefile is generating
libfdt-X.Y.Z.so. We want to keep the output of both systems the same to
avoid issues, so we rename the Makefile to match Meson.

Additionally, Meson generates the base "libfdt.so -> libfdt.so.1"
symlink which the Makefile hasn't been doing, add that as well.

This shouldn't impact existing users as the linker should be looking for
libfdt.so.1 which won't change and will still point to the correct file.

Signed-off-by: Brandon Maier <brandon.maier@collins.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-08-06 14:53:29 +10:00
Brandon Maier
35019949c4 workflows: build: remove setuptools_scm hack
The SETUPTOOLS_SCM_PRETEND_VERSION was needed as ./setup.py would fail
without it. As setuptools_scm will fail if there is not git repo, and
the github workflow container does not include the source code git repo.

A previous commit added "fallback_version" to setuptools_scm which
instructs it to use the version from VERSION.txt when the git repo is
missing. So this hack is no longer needed.

Signed-off-by: Brandon Maier <brandon.maier@collins.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-08-06 14:53:29 +10:00
Brandon Maier
cd3e2304f4 pylibfdt: use fallback version in tarballs
When building pylibfdt from the released tarballs[1] setup.py will fail
with the following.

> LookupError: setuptools-scm was unable to detect version for dtc.
> Make sure you're either building from a fully intact git repository or
> PyPI tarballs. Most other sources (such as GitHub's tarballs, a git
> checkout without the .git folder) don't contain the necessary metadata
> and will not work.

seutptools_scm supports a 'fallback_version' that will use the provided
string as the version when the git repo is not available.

[1] https://www.kernel.org/pub/software/utils/dtc/dtc-1.7.0.tar.xz

Signed-off-by: Brandon Maier <brandon.maier@collins.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-08-06 14:53:29 +10:00
Brandon Maier
0f58645677 move release version into VERSION.txt
To synchronize the release version of the Makefile and Meson build
systems, pull the version info from a shared file.

Meson requires that the shared library version follow the X.Y.Z
numbering scheme. But the Makefile supported building shared libraries
with an EXTRAVERSION appended, for example X.Y.Z-rc1. We want to keep
the output of both systems the same to avoid issues, so we drop support
for the Makefile EXTRAVERSION.

Signed-off-by: Brandon Maier <brandon.maier@collins.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-08-06 14:53:29 +10:00
Brandon Maier
38165954c1 libfdt: add missing version symbols
These symbols were not added to the version script when they were added
to libfdt.

Signed-off-by: Brandon Maier <brandon.maier@collins.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-08-04 18:02:33 +10:00
Brandon Maier
5e98b59793 editorconfig: use tab indentation for version.lds
This file is indented with tabs, but editorconfig defaults all files to
spaces.

Signed-off-by: Brandon Maier <brandon.maier@collins.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-08-04 18:02:21 +10:00
Brandon Maier
d030a893be tests: generate dtbs in Meson build directory
When running under Meson, check_tests() is generating dtb build files in
the source directory. This is because dtb is named by appending
".test.dtb" to the full source file name.

Use basename to extract just the source filename and write it to the
working directory which is the build directory.

Signed-off-by: Brandon Maier <brandon.maier@collins.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-08-04 13:15:08 +10:00
Brandon Maier
8d8372b137 tests: fix use of deprecated meson methods
Fixes the following warnings

> tests/meson.build:123: WARNING: Project targets '>=0.56.0' but uses
  feature deprecated since '0.55.0': ExternalProgram.path. use
  ExternalProgram.full_path() instead
> tests/meson.build:124: WARNING: Project targets '>=0.56.0' but uses
  feature deprecated since '0.56.0': meson.source_root. use
  meson.project_source_root() or meson.global_source_root() instead.

Signed-off-by: Brandon Maier <brandon.maier@collins.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-08-03 12:31:22 +10:00
Brandon Maier
761114effa pylibtfdt: fix use of deprecated meson method
Fixes the following warning

> pylibfdt/meson.build:2: WARNING: Project targets '>=0.56.0' but uses
  feature deprecated since '0.55.0': ExternalProgram.path. use
  ExternalProgram.full_path() instead

Do not use full_path() as suggested. setup_py is being called as a
command by custom_target() which understands how to properly inherit the
object returned by find_program().

Signed-off-by: Brandon Maier <brandon.maier@collins.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-08-03 12:30:55 +10:00
Brandon Maier
bf6377a98d meson: set minimum Meson version to 0.56.0
Set the minimum required version of Meson based on the highest version
feature used, as detected by meson-setup.

* 0.56.0: {'meson.project_build_root'}

Signed-off-by: Brandon Maier <brandon.maier@collins.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-08-02 11:04:09 +10:00
Brandon Maier
4c68e4b16b libfdt: fix library version to match project version
Build the libfdt with the correct version number by pulling the version
from the top-level project.

Change as suggested from https://github.com/dgibson/dtc/pull/95#issuecomment-1546933095

Signed-off-by: Brandon Maier <brandon.maier@collins.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-08-01 13:09:19 +10:00
Otavio Salvador
bdc5c8793a meson: allow disabling tests
The new meson build system support diverges from former build system
where the tests were not built until required.

This has caused an issue in NixOS[1] due to broken build of tests in
Darwin platform, so this patch allows the control if tests should be
build or not.

1. https://github.com/NixOS/nixpkgs/pull/235210

Signed-off-by: Otavio Salvador <otavio@ossystems.com.br>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-07-29 13:28:40 +10:00
Nicolas Escande
f088e381f2 Makefile: allow to install libfdt without building executables
When we only need the libfdt calling the target install-lib also builds the
executables listed in $(BINS) because this target depends on all
Instead lets make install-lib only depend on libfdt.

Signed-off-by: Nicolas Escande <nico.escande@gmail.com>
Message-ID: <20230726144336.677135-1-nico.escande@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-07-29 13:03:56 +10:00
Sebastian Huber
6df5328a90 Fix use of <ctype.h> functions
The value passed to the <ctype.h> functions shall be the value of an unsigned
char or EOF.  It is implementation-defined if the char type is signed or
unsigned.  Cast to unsigned char to avoid undefined behaviour on systems where
char is signed.

This cast is already present in other parts of the code base.

Signed-off-by: Sebastian Huber <sebastian.huber@embedded-brains.de>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-07-28 20:55:34 +10:00
Yan-Jie Wang
ccf1f62d59 libfdt: Fix a typo in libfdt.h
The function mentioned in the comment, fdt_finished(), should be
changed to fdt_finish().

Signed-off-by: Yan-Jie Wang <yanjiewtw@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-06-08 19:47:51 +10:00
Otavio Salvador
71a8b8ef0a libfdt: meson: Fix linking on macOS linker
-undefined error is the equivalent of --no-undefined for the macOS
linker, but -undefined would also be understood as a valid argument for
GNU ld so we use the supported linker variant.

Signed-off-by: Otavio Salvador <otavio@ossystems.com.br>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-06-01 13:42:50 +10:00
Uwe Kleine-König
589d8c7653 dtc: Add an option to generate __local_fixups__ and __fixups__
This records detailed usage of labels in a dtb. This is needed in
overlays (and enabled implicitly for these). For ordinary device trees
it can be used to restore labels when compiling back to dts format.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Message-Id: <20230523080941.419330-1-u.kleine-koenig@pengutronix.de>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-05-26 21:11:32 +10:00
Biswapriyo Nath
e8364666d5 CI: Add build matrix with multiple Linux distributions
set SETUPTOOLS_SCM_PRETEND_VERSION="0" variable because GitHub Actions
does not copy the .git directory into the container. Without that, the
build fails with the following error

LookupError: setuptools-scm was unable to detect version for /__w/dtc/dtc.
Signed-off-by: Biswapriyo Nath <nathbappai@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-05-16 19:30:09 +10:00
David Gibson
3b02a94b48 dtc: Correct invalid dts output with mixed phandles and integers
The handling of "type preservation" dts output is based on the idea of
"phandles with arguments" in properties, which isn't really a thing, other
than a fairly common convention about how bindings are written.  There's
nothing preventing a binding which freely mixes phandles and other integers
in an array of cells.

Currently write_propval() handles this incorrectly: specifically the case
of a phandle which follows a regular integer in a 32-bit cell array, but
without a new '< >' delimited causing an extra TYPE_UINT32 marker to be
inserted.  In this case it omits the necessary space between the integer
and the phandle reference, leading to output which can't be sent back into
dtc and parsed.

Correct this, and update tests to match.  I think this is more or less
correct for now, but really write_propval() is a big mess :(.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-05-14 16:27:27 +10:00
Johannes Beisswenger
d4888958d6 tests: Add additional tests for device graph checks
* bad-graph-child-address.dts: additional child address test since the
    one in bad-graph.dts is now shadowed by its prerequisites also
    failing.
* bad-graph-reg-cells.dts: test warnings produced by check_graph_reg().

Signed-off-by: Johannes Beisswenger <johannes.beisswenger@cetitec.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-05-14 15:22:37 +10:00
Johannes Beisswenger
ea3b9a1d2c checks: Fix crash in graph_child_address if 'reg' cell size != 1
If an endpoint node has a 'reg' property which consists of more than
one cell (4 bytes) and given that matching '#address-cells' and '#size-cells'
properties are specified on the port node an assertion is triggered in
check_graph_child_address() before the relevant diagnostic checks in
check_graph_reg() (called by check_graph_port() and check_graph_endpoint()) are executed.

The issue is fixed by making graph_child_address depend on the
graph_port and graph_endpoint checks.

Additionally the assertion can also be triggered if the length of the
'reg' property is less than 4 bytes e.g. by specifying
'reg = "a";'. In that case however other warnings are produced
highlighting the malformed property before dtc crashes.

Example dts file triggering the issue:

/dts-v1/;
 / {
	bar: bar {
		port {
			bar_con: endpoint {
				remote-endpoint = <&foo_con>;
			};
		};
	};
	foo {
		port {
			#address-cells = <1>;
			#size-cells = <1>; // should always be 0
			foo_con: endpoint@1 {
				reg = <1 2>; // causes assertion failure instead of diagnostic
				remote-endpoint = <&bar_con>;
			};
		};
	};
};

Signed-off-by: Johannes Beisswenger <johannes.beisswenger@cetitec.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-05-14 15:22:22 +10:00
Johannes Beisswenger
b2b9671583 livetree: fix off-by-one in propval_cell_n() bounds check
Signed-off-by: Johannes Beisswenger <johannes.beisswenger@cetitec.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-05-14 15:22:09 +10:00
Uwe Kleine-König
ab481e4830 Add definition for a GitHub Actions CI job
The job just builds the full configuration on latest Ubuntu

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
2023-05-14 15:11:32 +10:00
Uwe Kleine-König
c88038c9b8 Drop obsolete/broken CI definitions
(Free) Travis-ci is gone since November 2020, cirrus seems to be
unreliable showing build breakages unrelated to changes.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
2023-05-14 15:11:32 +10:00
Uwe Kleine-König
0ac8b30ba5 yaml: Depend on libyaml >= 0.2.3
libyaml before 0.2.3 expects non-const string parameters. Supporting
both variants would require either cpp magic or ignoring
"discarded-qualifiers" compiler warnings. For the sake of simplicity
just support libyaml 0.2.3 and newer.

Note that NO_YAML can be overwritten on the make command line.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
2023-05-14 15:11:32 +10:00
Johannes Beisswenger
f1657b2fb5 tests: Add test cases for bad endpoint node and remote-endpoint prop checks
Signed-off-by: Johannes Beisswenger <johannes.beisswenger@cetitec.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-05-07 18:47:40 +10:00
Johannes Beisswenger
44bb89cafd checks: Fix segmentation fault in check_graph_node
Dts files which contain an 'endpoint' node as a direct child of the
root node cause a segmentation fault inside check_graph_node(). This
type of error can easily happen when a 'remote-endpoint' property is
accidentally placed outside the corresponding endpoint and port nodes.

Example with 'endpoint' node:
/dts-v1/;
/ {	endpoint {};  };

Example with remote-endpoint property:
/dts-v1/;
/ {
	foo {
                remote-endpoint = <0xdeadbeef>;
	};
};

Signed-off-by: Johannes Beisswenger <johannes.beisswenger@cetitec.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-05-07 18:47:31 +10:00
Rasmus Villemoes
60bcf1cde1 improve documentation for fdt_path_offset()
The current documentation doesn't mention the possibility of passing a
non-absolute path and having that treated as an alias. Add that
information, along with an example (which will further be expanded in
a subsequent patch), and clarify when -FDT_ERR_BADPATH can be returned.

Signed-off-by: Rasmus Villemoes <rasmus.villemoes@prevas.dk>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-05-03 23:51:15 +10:00
Rasmus Villemoes
a6f997bc77 add fdt_get_symbol() and fdt_get_symbol_namelen() functions
The fdt_get_symbol_namelen() function will be used in a subsequent
patch.

Signed-off-by: Rasmus Villemoes <rasmus.villemoes@prevas.dk>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-05-03 23:51:08 +10:00
Rasmus Villemoes
18f5ec12a1 use fdt_path_getprop_namelen() in fdt_get_alias_namelen()
Simplify the code by making use of the new helper.

Signed-off-by: Rasmus Villemoes <rasmus.villemoes@prevas.dk>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-05-03 23:51:02 +10:00
Rasmus Villemoes
df09327928 add fdt_path_getprop_namelen() helper
Add a wrapper for fdt_getprop_namelen() allowing one to specify the node
by path instead of offset.

Signed-off-by: Rasmus Villemoes <rasmus.villemoes@prevas.dk>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-05-03 23:50:55 +10:00
Uwe Kleine-König
129bb4b78b doc: dt-object-internal: Fix a typo
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Message-Id: <20230428163034.775288-1-u.kleine-koenig@pengutronix.de>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-04-29 11:45:10 +10:00
Uwe Kleine-König
390f481521 fdtoverlay: Drop a a repeated article
Signed-off-by: Uwe Kleine-König <uwe@kleine-koenig.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-04-28 16:26:39 +10:00
Uwe Kleine-König
9f8b382ed4 manual: Fix and improve documentation about -@
Device trees with a /plugin/ tag ("overlays") generate a __fixups__ node
when needed and independent of -q being given or not. The same is true for
__local__fixups__. So don't mention these two nodes in the paragraph about
-@.

To not shorten the description too much, describe the semantic of the
properties contained in the generated __symbols__ node.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-04-28 16:26:02 +10:00
Uwe Kleine-König
2cdf93a6d4 fdtoverlay: Fix usage string to not mention "<type>"
fdtoverlay doesn't have a -t option, so explaining the type formats and
modifier prefixes doesn't make much sense.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Message-Id: <20230315100819.13387-1-u.kleine-koenig@pengutronix.de>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-03-18 12:59:46 +11:00
Marc-André Lureau
72fc810c30 build-sys: add -Wwrite-strings
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-03-01 18:43:15 +11:00
Marc-André Lureau
083ab26da8 tests: fix leaks spotted by ASAN
Always allocate from open_blob_rw(), to simplify memory management.

The fixes are not exhaustive.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-03-01 18:43:15 +11:00
Marc-André Lureau
6f8b28f496 livetree: fix leak spotted by ASAN
./dtc -I dts -O dtb -o overlay_base_manual_symbols.test.dtb /home/elmarco/src/dtc/tests/overlay_base_manual_symbols.dts
../data.c:109:2: runtime error: null pointer passed as argument 2, which is declared to never be null

=================================================================
==933317==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 24 byte(s) in 1 object(s) allocated from:
    #0 0x7f49a2aba6af in __interceptor_malloc (/lib64/libasan.so.8+0xba6af)
    #1 0x43183d in xmalloc ../util.h:45
    #2 0x43482f in data_add_marker ../data.c:230
    #3 0x449bb8 in get_node_phandle ../livetree.c:632
    #4 0x421058 in fixup_phandle_references ../checks.c:627
    #5 0x41b0ba in check_nodes_props ../checks.c:141
    #6 0x41b1c8 in check_nodes_props ../checks.c:144
    #7 0x41b9f1 in run_check ../checks.c:181
    #8 0x430a68 in process_checks ../checks.c:2057
    #9 0x436abd in main ../dtc.c:327
    #10 0x7f49a30d850f in __libc_start_call_main (/lib64/libc.so.6+0x2750f)

Only create data when necessary, and do not alias it.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
[dwg: Small fixup for a slightly different approach to adjacent cleanups]
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-03-01 18:43:15 +11:00
David Gibson
fd68bb8c56 Make name_node() xstrdup its name argument
The name field of 'struct node' was really always supposed to be a
malloc()ed string, that is owned by the structure.  To avoid an extra
strdup() for strings coming up from the lexer, name_node() expects to take
uch an already malloc()ed string, which means it's not correct to pass it
a static string literal.

That's a pretty non-obvious constraint, so a bunch of incorrect uses have
crept in.  Really, avoiding the extra dup from the lexer isn't a big enough
benefit for this demonstrably dangerous interface.  So change it to do the
xstrdup() itself, removing the burden from callers.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-03-01 17:55:35 +11:00
David Gibson
4718189c4c Delay xstrdup() of node and property names coming from a flat tree
The 'name' field of 'struct node' is supposed to be an (individually)
malloc()ed string.  So, when taking a name from a flattened blob we need
to strdup() it.

Currently that happens in flat_read_string() as we take it from the
flattened structure itself.  That obscures what's going on because it's
several steps removed from actually inserting it into node->name.  It also
means we need an additional strdup() and free() for the case of old dtb
formats where we need to extract just the final path component from the
blob for the name.

While we're scanning the blob, we're doing so read-only, so it's fine to
have pointers into it.  Therefore simplify things a bit by delaying the
xstrdup() to the point where we're actually inserting into node->name.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-03-01 17:53:27 +11:00
David Gibson
0b842c3c81 Make build_property() xstrdup its name argument
The name field of 'struct property' was really always supposed to be a
malloc()ed string, that is owned by the structure.  To avoid an extra
strdup() for strings coming up from the lexer, build_property() and
build_property_delete() expect to take such an already malloc()ed string,
which means it's not correct to pass it a static string literal.

That's a pretty non-obvious constraint, so a bunch of incorrect uses have
crept in.  Really, avoiding the extra dup from the lexer isn't a big enough
benefit for this demonstrably dangerous interface.  So change it to do the
xstrdup() itself, removing the burden from callers.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-03-01 17:47:27 +11:00
Matt Ranostay
9cceabea1e checks: correct I2C 10-bit address check
Currently if there is a valid 10-bit address the following warning is
always displayed due to the 7-bit check failing due to reg > 0x7f

"I2C address must be less than 7-bits, got "0x800000a6". Set I2C_TEN_BIT_ADDRESS for 10 bit addresses or fix the property"

Fix this issue by checking if a 10-bit address is expected, and is valid in separate if statements.

Fixes: 8259d59f ("checks: Improve i2c reg property checking")
Signed-off-by: Matt Ranostay <matt.ranostay@konsulko.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-03-01 16:08:28 +11:00
Marc-André Lureau
0d56145938 yamltree.c: fix -Werror=discarded-qualifiers & -Werror=cast-qual
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-03-01 16:02:36 +11:00
Marc-André Lureau
61fa22b05f checks: make check.data const
Fixes:
../checks.c:47:25: error: initialization discards ‘const’ qualifier from pointer target type [-Werror=discarded-qualifiers]

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-03-01 16:01:37 +11:00
Marc-André Lureau
7a1d72a788 checks.c: fix check_msg() leak
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-03-01 15:57:03 +11:00
Marc-André Lureau
ee57999386 checks.c: fix heap-buffer-overflow
./dtc -I dts -O dtb -o aliases.dtb /home/elmarco/src/dtc/tests/aliases.dts
=================================================================
==882911==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000113 at pc 0x7f34ba0abf50 bp 0x7ffc8db22450 sp 0x7ffc8db21c00
READ of size 4 at 0x602000000113 thread T0
    #0 0x7f34ba0abf4f in MemcmpInterceptorCommon(void*, int (*)(void const*, void const*, unsigned long), void const*, void const*, unsigned long) (/lib64/libasan.so.8+0xabf4f)
    #1 0x7f34ba0ac5e8 in memcmp (/lib64/libasan.so.8+0xac5e8)
    #2 0x4282dc in check_spi_bus_bridge ../checks.c:1110
    #3 0x41b08d in check_nodes_props ../checks.c:140
    #4 0x41b9c4 in run_check ../checks.c:180
    #5 0x430a3b in process_checks ../checks.c:2056
    #6 0x436a90 in main ../dtc.c:327
    #7 0x7f34b964a50f in __libc_start_call_main (/lib64/libc.so.6+0x2750f)
    #8 0x7f34b964a5c8 in __libc_start_main@GLIBC_2.2.5 (/lib64/libc.so.6+0x275c8)
    #9 0x4025c4 in _start (/home/elmarco/src/dtc/build/dtc+0x4025c4)

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-03-01 15:56:29 +11:00
Marc-André Lureau
44c9b73801 tests: fix -Wwrite-strings
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-03-01 15:37:19 +11:00
Marc-André Lureau
5b60f5104f srcpos.c: fix -Wwrite-strings
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-03-01 15:36:40 +11:00
David Gibson
32174a66ef meson: Fix cell overflow tests when running from meson
Because meson always builds out-of-tree we need to reference things in the
original source tree via $SRCDIR from run_tests.sh.  We forgot a couple of
cases for the cell overflow tests.  Fix them.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-02-28 10:33:58 +11:00
Nikolay Letov
64a907f08b meson.build: bump version to 1.7.0
[This was botched in the actual 1.7.0 release :( - David Gibson]

Signed-off-by: Nikolay Letov <letov.nikolay@gmail.com>
2023-02-28 09:50:20 +11:00
David Gibson
e3cde0613b Add -Wsuggest-attribute=format warning, correct warnings thus generated
Add this new warning to the default build flags.  It suggests adding
a ((format)) attribute to xavsprintf_append(), so do that.

Suggested-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-02-27 19:18:35 +11:00
Marc-André Lureau
4182182110 Use #ifdef NO_VALGRIND
Using simply #if will fail when NO_VALGRIND is undefined.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
2023-02-27 19:01:23 +11:00
Marc-André Lureau
71c19f20b3 Do not redefine _GNU_SOURCE if already set
Or else, compilation will fail.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
2023-02-27 19:00:17 +11:00
David Gibson
039a99414e Bump version to v1.7.0
It's been rather too long since the last release, and quite a lot of
changes have accumulated.  Finally get around to rolling a release.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-02-09 21:01:35 +11:00
David Gibson
9b62ec84bb Merge remote-tracking branch 'gitlab/main' 2023-02-05 17:34:50 +11:00
Luca Weiss
3f29d6d85c pylibfdt: add size_hint parameter for get_path
This also enables us to test the -NOSPACE condition by adding a test
setting size_hint=1 so this path is taken.

Message-Id: <20230201181112.1644842-1-luca@z3ntu.xyz>
Signed-off-by: Luca Weiss <luca@z3ntu.xyz>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-02-05 17:29:25 +11:00
Qun-Wei Lin
2022bb1087 checks: Update #{size,address}-cells check for 'dma-ranges'
The "dma-ranges" property value is a sequence of
	child-address  parent-address  child-size

The size of each field is determined by taking the child's
"#address-cells" value, the parent's "#address-cells" value,
and the child's "#size-cells" value.

However, in the following example, it gives a false alarm:
+-----------------------------------+---------------------------------------+
| ranges.dts                        | dma-ranges.dts                        |
+-----------------------------------+---------------------------------------+
| /dts-v1/;                         | /dts-v1/;                             |
|                                   |                                       |
| /{                                | /{                                    |
|   #address-cells = <1>;           |   #address-cells = <1>;               |
|                                   |                                       |
|   parent {                        |   parent {                            |
|     #address-cells = <1>;         |     #address-cells = <1>;             |
|     #size-cells = <1>;            |     #size-cells = <1>;                |
|     ranges = <0x0 0xe000 0x1000>; |     dma-ranges = <0x0 0xe000 0x1000>; |
|     child {                       |     child {                           |
|       ...                         |       ...                             |
|     };                            |     };                                |
|   };                              |   };                                  |
| };                                | };                                    |
+-----------------------------------+---------------------------------------+
| no warning                        | Warning (avoid_unnecessary_addr_size) |
+-----------------------------------+---------------------------------------+

Same as "ranges", it should not be reported in this check.

Signed-off-by: Qun-Wei Lin <qun-wei.lin@mediatek.com>
Message-Id: <20230112125654.13390-1-qun-wei.lin@mediatek.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-02-02 17:46:54 +11:00
Rob Herring
abbd523bae pylibfdt: Work-around SWIG limitations with flexible arrays
Commit a41509bea3 ("libfdt: Replace deprecated 0-length arrays with
proper flexible arrays") fails to build pylibfdt:

./pylibfdt/libfdt_wrap.c: In function ‘_wrap_fdt_node_header_name_set’:
./pylibfdt/libfdt_wrap.c:4350:18: error: cast specifies array type
 4350 |     arg1->name = (char [])(char *)memcpy(malloc((size)*sizeof(char)), (const char *)(arg2), sizeof(char)*(size));
      |                  ^
./pylibfdt/libfdt_wrap.c:4350:16: error: invalid use of flexible array member
 4350 |     arg1->name = (char [])(char *)memcpy(malloc((size)*sizeof(char)), (const char *)(arg2), sizeof(char)*(size));
      |                ^
./pylibfdt/libfdt_wrap.c:4352:16: error: invalid use of flexible array member
 4352 |     arg1->name = 0;
      |                ^
./pylibfdt/libfdt_wrap.c: In function ‘_wrap_fdt_property_data_set’:
./pylibfdt/libfdt_wrap.c:4613:18: error: cast specifies array type
 4613 |     arg1->data = (char [])(char *)memcpy(malloc((size)*sizeof(char)), (const char *)(arg2), sizeof(char)*(size));
      |                  ^
./pylibfdt/libfdt_wrap.c:4613:16: error: invalid use of flexible array member
 4613 |     arg1->data = (char [])(char *)memcpy(malloc((size)*sizeof(char)), (const char *)(arg2), sizeof(char)*(size));
      |                ^
./pylibfdt/libfdt_wrap.c:4615:16: error: invalid use of flexible array member
 4615 |     arg1->data = 0;
      |                ^

Turns out this is known issue with SWIG: https://github.com/swig/swig/issues/1699

Implement the work-around to ignore the flexible array member.

Fixes: a41509bea3 ("libfdt: Replace deprecated 0-length arrays with proper flexible arrays")
Cc: Kees Cook <keescook@chromium.org>
Cc: Simon Glass <sjg@chromium.org>
Signed-off-by: Rob Herring <robh@kernel.org>
Message-Id: <20230201224441.305757-1-robh@kernel.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
Tested-by: Simon Glass <sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-02-02 16:32:47 +11:00
Kees Cook
a41509bea3 libfdt: Replace deprecated 0-length arrays with proper flexible arrays
Replace the 0-length arrays in structures with proper flexible
arrays. This will avoid warnings when building under GCC 13 with
-fstrict-flex-arrays, which the Linux kernel will be doing soon:

In file included from ../lib/fdt_ro.c:2:
../lib/../scripts/dtc/libfdt/fdt_ro.c: In function 'fdt_get_name':
../lib/../scripts/dtc/libfdt/fdt_ro.c:319:24: warning: 'strrchr' reading 1 or more bytes from a region of size 0 [-Wstringop-overread]
  319 |                 leaf = strrchr(nameptr, '/');
      |                        ^~~~~~~~~~~~~~~~~~~~~

Signed-off-by: Kees Cook <keescook@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2023-01-29 14:42:57 +11:00
David Gibson
2cd89f862c dtc: Warning rather than error on possible truncation of cell values
We always evaluate integer values in cell arrays as 64-bit quantities, then
truncate to the size of the array cells (32-bit by default).  However to
detect accidental truncation of meaningful values, we give an error if the
truncated portion isn't either all 0 or all 1 bits.  However, this can
still give counterintuitive errors.  For if the user is thinking in 2's
complement 32-bit arithmetic (which would be quite natural), then they'd
expect the expression (-0xffffffff-2) to evaluate to -1 (0xffffffff).
However in 64-bit it evaluates to 0xfffffffeffffffff which does truncate
to the expected value but trips this error message.

Because of this reduce the error to only a warnings, with a somewhat more
helpful message.

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

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2022-11-21 14:18:44 +11:00
Tadeusz Struk
55778a03df libfdt: tests: add get_next_tag_invalid_prop_len
Add a new test get_next_tag_invalid_prop_len, which covers
fdt_next_tag(), when it is passed an corrupted blob, with
invalid property len values. The test runs twice, on a blob
in sw and finished state.

Signed-off-by: Tadeusz Struk <tadeusz.struk@linaro.org>
Message-Id: <20221011182611.116011-2-tadeusz.struk@linaro.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2022-10-12 10:49:36 +11:00
Tadeusz Struk
73590342fc libfdt: prevent integer overflow in fdt_next_tag
Since fdt_next_tag() in a public API function all input parameters,
including the fdt blob should not be trusted. It is possible to forge
a blob with invalid property length that will cause integer overflow
during offset calculation. To prevent that, validate the property length
read from the blob before doing calculations.

Signed-off-by: Tadeusz Struk <tadeusz.struk@linaro.org>
Message-Id: <20221005232931.3016047-1-tadeusz.struk@linaro.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2022-10-12 10:49:36 +11:00
Tadeusz Struk
035fb90d53 libfdt: add fdt_get_property_by_offset_w helper
Add a new fdt_get_property_by_offset_w helper function.
It is a wrapper on fdt_get_property_by_offset that returns
a writable pointer to a property at a given offset.

Signed-off-by: Tadeusz Struk <tadeusz.struk@linaro.org>
Message-Id: <20221011182611.116011-1-tadeusz.struk@linaro.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2022-10-12 10:49:36 +11:00
Sergei Trofimovich
98a07006c4 Makefile: fix infinite recursion by dropping non-existent %.output
Without the change GNU `make-4.4` falls into infinite recursion of trying
to generate %.output files (bison is not passed flags to generate debug
output).

This happens on GNU `make-4.4` only after GNU make change to more eagerly
rebuild all target outputs in multiple targets:
    https://savannah.gnu.org/bugs/index.php?63098

The recursion here is the following:

- Makefile depends on *.d files
- *.d files depend on *.c files
- *.c files are generated by bison
- bison is triggered whenever some of it's multiple targets are missing

In our case `%.output` is always missing and bison is always reran.
*.d files are always regenerated on `make` run. And make is always
restarted as *.d files are always regenerated.

The fix removes infeasible `%.output`.

Signed-off-by: Sergei Trofimovich <slyich@gmail.com>
Message-Id: <20220925104203.648449-2-slyich@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2022-09-26 15:22:05 +10:00
Sergei Trofimovich
a036cc7b0c Makefile: limit make re-execution to avoid infinite spin
make-4.4 became intentionally more eager at rebuilding outdated Makefile
includes. Currently this causes `dtc` to spin infinitely in
parser/dependency loop:

    $ make
    ...
        CHK version_gen.h
         BISON dtc-parser.tab.h
         DEP dtc-lexer.lex.c
         DEP dtc-parser.tab.c
        CHK version_gen.h
         BISON dtc-parser.tab.h
         DEP dtc-lexer.lex.c
         DEP dtc-parser.tab.c
    ... # never stops

After the change build eventually fails when gets into this state:

    $ make
    ...
        CHK version_gen.h
        UPD version_gen.h
         DEP util.c
         BISON dtc-parser.tab.h
         DEP dtc-lexer.lex.c
         DEP dtc-parser.tab.c
        CHK version_gen.h
         BISON dtc-parser.tab.h
         DEP dtc-lexer.lex.c
         DEP dtc-parser.tab.c
    Makefile:394: *** "Make re-executed itself 10 times. Infinite recursion?".  Stop.

The actual recursion will be fixed separately.

Signed-off-by: Sergei Trofimovich <slyich@gmail.com>
Message-Id: <20220925104203.648449-1-slyich@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2022-09-26 15:22:05 +10:00
Jia Xianhua
c6e92108bc libdtc: remove duplicate judgments
There is no need to check the VALID_DTB repeatedly, and can be combined
into one if statement.

Signed-off-by: Jia Xianhua <jiaxianhua@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2022-09-16 19:02:06 +10:00
David Gibson
e37c25677d Don't generate erroneous fixups from reference to path
The dtb overlay format only permits (non local) fixups to reference labels,
not paths.  That's because the fixup target goes into the property name in
the overlay, and property names aren't permitted to include '/' characters.

Stop erroneously generating such fixups, because we didn't check for this
case.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2022-07-31 22:10:05 +10:00
Pierre-Clément Tosi
50454658f2 libfdt: Don't mask fdt_get_name() returned error
Return the error code from fdt_get_name() (contained in len when the
result is NULL) instead of masking it with FDT_ERR_BADSTRUCTURE.

Fixes: fda71da26e ("libfdt: Handle failed get_name() on BEGIN_NODE")
Reported-by: Mike McTernan <mikemcternan@google.com>
Signed-off-by: Pierre-Clément Tosi <ptosi@google.com>
Message-Id: <20220729130019.804288-1-ptosi@google.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2022-07-30 13:52:33 +10:00
Pierre-Clément Tosi
e64a204196 manual.txt: Follow README.md and remove Jon
Following 0ee1d479b2 ("Remove Jon Loeliger from maintainers list"),
make the "Submitting Patches" section of the manual.txt consistent with
the README by requesting patches to only be sent to David.

Cc: Jon Loeliger <loeliger@gmail.com>
Signed-off-by: Pierre-Clément Tosi <ptosi@google.com>
Message-Id: <20220729131019.806164-1-ptosi@google.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2022-07-30 13:50:27 +10:00
Saad Waheed
f508c83fe6 Update README in MANIFEST.in and setup.py to README.md
Signed-off-by: Saad Waheed <saad.waheed@10xengineers.ai>
2022-07-30 13:42:39 +10:00
David Gibson
c2ccf8a77d Add description of Signed-off-by lines
dtc and libfdt have been using Signed-off-by lines (as used in the Linux
kernel) for some time, like a lot of open source projects.  However
Uwe Kleine-König pointed out we never really stated what they mean in our
context.

Add information on what the S-o-b line means in CONTRIBUTING.md - this is
essentially a quote of the same information from the kernel documentation,
with some tweaks to make sense in the new context.

Suggested-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Acked-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
2022-07-29 12:55:15 +10:00
David Gibson
90b9d9de42 Split out information for contributors to CONTRIBUTING.md
README.md covers both general information for people using and building
the software, and more specific information for people contributing to
either dtc or libfdt.  Split out the latter information into its own file
for easier reference.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2022-07-28 16:25:56 +10:00
David Gibson
0ee1d479b2 Remove Jon Loeliger from maintainers list
Jon hasn't been actively working on dtc maintenance for some years.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2022-07-28 16:16:08 +10:00
David Gibson
b33a73c62c Convert README to README.md
Let's move vaguely into the twenty-first century by converting our old
plain text README file to Markdown.  While we're updating the formatting,
make some small polish changes to the content.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2022-07-28 16:15:06 +10:00
Tero Tervala
7ad60734b1 Allow static building with meson
Added "static-build" option in the meson_options.txt.
Setting it to "true" allows static building.

Signed-off-by: Tero Tervala <tero.tervala@unikie.com>
Message-Id: <20220629163557.932298-1-tero.tervala@unikie.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2022-07-27 16:38:45 +10:00
Tero Tervala
fd9b8c96c7 Allow static building with make
Set STATIC_BUILD=1 environment variable to enable static building
when using makefiles.

Signed-off-by: Tero Tervala <tero.tervala@unikie.com>
Message-Id: <20220629163531.932281-1-tero.tervala@unikie.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2022-07-27 16:35:29 +10:00
Pierre-Clément Tosi
fda71da26e libfdt: Handle failed get_name() on BEGIN_NODE
Validate the return value of fdt_get_name() as an ill-formed DT, causing
it to fail, could result in fdt_check_full() dereferencing NULL.

fixes: a2def54799 ("libfdt: Check that the root-node name is empty")
Signed-off-by: Pierre-Clément Tosi <ptosi@google.com>
Message-Id: <20220714083848.958492-1-ptosi@google.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2022-07-26 21:46:18 +10:00
Tero Tervala
c7c7f17a83 Fix test script to run also on dash shell
/bin/sh points to dash instead of bash in some linux distros.
One test would fail if dash was used, this fix will allow all tests
to run properly on dash too.

dash built-in printf does not support "\xNN" -hex escape format.
"\NNN" -octal escape format is supported by both bash and dash printf.

Replaced "$(echo "$expect")" because this actually runs /bin/echo
instead of shell internal echo and in some cases causes "\NNN" escapes
to be printed as the actual characters they represent instead of the
escape sequence itself.

Cosmetic quotes added to make printout a bit clearer.

Signed-off-by: Tero Tervala <tero.tervala@unikie.com>
Message-Id: <20220704073722.1075849-1-tero.tervala@unikie.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2022-07-26 21:39:07 +10:00
Tero Tervala
01f23ffe16 Add missing relref_merge test to meson test list
Will remove one "Strange test result" when running tests with
meson

Signed-off-by: Tero Tervala <tero.tervala@unikie.com>
Message-Id: <20220629163114.932175-1-tero.tervala@unikie.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2022-07-02 16:37:02 +10:00
Luca Weiss
ed310803ea pylibfdt: add FdtRo.get_path()
Add a new Python method wrapping fdt_get_path() from the C API.

Also add a test for the new method.

Signed-off-by: Luca Weiss <luca@z3ntu.xyz>
Message-Id: <20220419194537.63170-1-luca@z3ntu.xyz>
Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2022-04-20 12:55:14 +10:00
Rob Herring
c001fc01a4 pylibfdt: fix swig build in install
A 'pip install' is silently broken unless the tree is dirty and contains
pylibfdt/libfdt.py. The problem is a known issue[1] with SWIG and
setuptools where the 'build_py' stage needing module.py runs before
the 'build_ext' stage which generates it. The work-around is to override
'build_py' to run 'build_ext' first.

[1] https://stackoverflow.com/questions/50239473/building-a-module-with-setuptools-and-swig

Signed-off-by: Rob Herring <robh@kernel.org>
Message-Id: <20220203180408.611645-2-robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2022-02-04 18:52:36 +11:00
Ahmad Fatoum
26c54f840d tests: add test cases for label-relative path references
Newly added &{label/path} feature doesn't yet have any tests. Add some.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
2022-01-25 17:10:47 +11:00
Ahmad Fatoum
ec7986e682 dtc: introduce label relative path references
Reference via label allows extending nodes with compile-time checking of
whether the node being extended exists. This is useful to catch
renamed/removed nodes after an update of the device trees to be extended.

In absence of labels in the original device trees, new style path
references can be used:

  /* upstream device tree */
  / {
	leds: some-non-standard-led-controller-name {
		led-0 {
			default-state = "off";
		};
	};
  };

  /* downstream device tree */
  &{/some-non-standard-led-controller-name/led-0} {
	default-state = "on";
  };

This is a common theme within the barebox bootloader[0], which extends the
upstream (Linux) device trees in that manner. The downside is that,
especially for deep nodes, these references can get quite long and tend to
break often due to upstream rework (e.g. rename to adhere to bindings).

Often there is a label a level or two higher that could be used. This
patch allows combining both a label and a new style path reference to
get a compile-time-checked reference, which allows rewriting the
previous downstream device tree snippet to:

  &{leds/led-0} {
	default-state = "on";
  };

This won't be broken when /some-non-standard-led-controller-name is
renamed or moved while keeping the label. And if led-0 is renamed, we
will get the expected compile-time error.

Overlay support is skipped for now as they require special support: The
label and relative path parts need to be resolved at overlay apply-time,
not at compile-time.

[0]: https://www.barebox.org/doc/latest/devicetree/index.html

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
2022-01-25 17:10:47 +11:00
Ahmad Fatoum
651410e54c util: introduce xstrndup helper
We already have xstrdup, add xstrndup as well to make it
straight-forward to clone part of a string.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
2022-01-25 17:10:47 +11:00
Marc-André Lureau
4048aed12b setup.py: fix out of tree build
Fixes: commit 1cc41b1c9 ("pylibfdt: Add packaging metadata")

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20220103073855.1468799-3-marcandre.lureau@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2022-01-04 10:48:59 +11:00
David Gibson
ff5afb96d0 Handle integer overflow in check_property_phandle_args()
If the corresponding '#xxx-cells' value is much too large, an integer
overflow can prevent the checks in check_property_phandle_args() from
correctly determining that the checked property is too short for the
given cells value.  This leads to an infinite loops.

This patch fixes the bug, and adds a testcase for it.  Further
information in https://github.com/dgibson/dtc/issues/64

Reported-by: Anciety <anciety@pku.edu.cn>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-12-29 17:04:18 +11:00
Simon Glass
ca72944343 README: Explain how to add a new API function
This is not obvious so add a little note about it.

Signed-off-by: Simon Glass <sjg@chromium.org>
Message-Id: <20211107224346.3181320-2-sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-12-28 20:14:05 +11:00
LoveSy
c0c2e115f8 Fix a UB when fdt_get_string return null
When fdt_get_string return null, `namep` is not correctly reset.
From the document of `fdt_getprop_by_offset`, the parameter `namep` will
be always overwritten (that is, it will be overwritten without exception
of error occurance).

As for the caller (like
e097c097fe/native/jni/magiskboot/dtb.cpp (L42)),
the code may be like:
```cpp
size_t size;
const char *name;
auto *value = fdt_getprop_by_offset(fdt, prop, &name, &size);
```
and if `value == nullptr`, `size` is also be overwritten correctly but
`name` is not, which is quite inconsistent.

This commit makes sure `name` and `size` behavior consistently (reset to
reasonable value) when error occurs.

Signed-off-by: LoveSy <shana@zju.edu.cn>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-12-28 20:11:11 +11:00
Ahmad Fatoum
cd5f69cbc0 tests: setprop_inplace: use xstrdup instead of unchecked strdup
This is the only strdup instance we have, all others are xstrdup. As
strdup is _POSIX_C_SOURCE >= v200809L, which we don't require and we
don't check strdup error return here, switch to xstrdup instead. This
aligns the test with others that call xfuncs, mainly xmalloc().

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-12-28 20:10:57 +11:00
Luca Weiss
a04f690250 pylibfdt: add Property.as_*int*_array()
Add new methods to handle decoding of int32, uint32, int64 and uint64
arrays.

Also add tests for the new methods.

Signed-off-by: Luca Weiss <luca@z3ntu.xyz>
Message-Id: <20211225132558.167123-3-luca@z3ntu.xyz>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-12-28 15:30:33 +11:00
Luca Weiss
83102717d7 pylibfdt: add Property.as_stringlist()
Add a new method for decoding a string list property, useful for e.g.
the "reg-names" property.

Also add a test for the new method.

Signed-off-by: Luca Weiss <luca@z3ntu.xyz>
Message-Id: <20211225132558.167123-2-luca@z3ntu.xyz>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-12-28 15:29:31 +11:00
Luca Weiss
d152126bb0 Fix Python crash on getprop deallocation
Fatal Python error: none_dealloc: deallocating None
Python runtime state: finalizing (tstate=0x000055c9bac70920)

Current thread 0x00007fbe34e47740 (most recent call first):
  <no Python frame>
Aborted (core dumped)

This is caused by a missing Py_INCREF on the returned Py_None, as
demonstrated e.g. in https://github.com/mythosil/swig-python-incref or
described at https://edcjones.tripod.com/refcount.html ("Remember to
INCREF Py_None!")

A PoC for triggering this crash is uploaded to
https://github.com/z3ntu/pylibfdt-crash .
With this patch applied to pylibfdt the crash does not happen.

Signed-off-by: Luca Weiss <luca@z3ntu.xyz>
Message-Id: <20211224102811.70695-1-luca@z3ntu.xyz>
Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-12-26 15:44:32 +11:00
Rafał Miłecki
17739b7ef5 Support 'r' format for printing raw bytes with fdtget
FT is sometimes used for storing raw data. That is quite common for
U-Boot FIT images.

Extracting such data is not trivial currently. Using type 's' (string)
will replace every 0x00 (NUL) with 0x20 (space). Using type 'x' will
print bytes but in xxd incompatible format.

This commit adds support for 'r' (raw) format. Example usage:
fdtget -t r firmware.itb /images/foo data > image.raw

Support for encoding isn't added as there isn't any clean way of passing
binary data as command line argument.

Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
Message-Id: <20211209061420.29466-1-zajec5@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-12-09 17:48:58 +11:00
Vikram Garhwal
45f3d1a095 libfdt: overlay: make overlay_get_target() public
This is done to get the target path for the overlay nodes which is very useful
in many cases. For example, Xen hypervisor needs it when applying overlays
because Xen needs to do further processing of the overlay nodes, e.g. mapping of
resources(IRQs and IOMMUs) to other VMs, creation of SMMU pagetables, etc.

Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
Message-Id: <1637204036-382159-2-git-send-email-fnu.vikram@xilinx.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-11-18 16:25:10 +11:00
Elvira Khabirova
c19a4bafa5 libfdt: fix an incorrect integer promotion
UINT32_MAX is an integer of type unsigned int. UINT32_MAX + 1 overflows
unless explicitly computed as unsigned long long. This led to some
invalid addresses being treated as valid.

Cast UINT32_MAX to uint64_t explicitly.

Signed-off-by: Elvira Khabirova <e.khabirova@omp.ru>
2021-11-17 12:22:53 +11:00
Rob Herring
1cc41b1c96 pylibfdt: Add packaging metadata
PyPI expects to have various package metadata including long
description, license, and classifiers. Add them.

Signed-off-by: Rob Herring <robh@kernel.org>
Message-Id: <20211112041633.741598-3-robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-11-12 15:58:23 +11:00
Rob Herring
db72398cd4 README: Update pylibfdt install instructions
Now that pip is supported for installs, update the install instructions to
use it. Using pip over setup.py is generally recommended and simpler.

Also, drop 'SETUP_PREFIX' as it doesn't exist anywhere.

Signed-off-by: Rob Herring <robh@kernel.org>
Message-Id: <20211112041633.741598-2-robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-11-12 15:58:23 +11:00
Ross Burton
383e148b70 pylibfdt: fix with Python 3.10
Since Python 2.5 the argument parsing functions when parsing expressions
such as s# (string plus length) expect the length to be an int or a
ssize_t, depending on whether PY_SSIZE_T_CLEAN is defined or not.

Python 3.8 deprecated the use of int, and with Python 3.10 this symbol
must be defined and ssize_t used[1].

Define the magic symbol when building the extension, and cast the ints
from the libfdt API to ssize_t as appropriate.

[1] https://docs.python.org/3.10/whatsnew/3.10.html#id2

Signed-off-by: Ross Burton <ross.burton@arm.com>
Message-Id: <20211111160536.2516573-1-ross.burton@arm.com>
[dwg: Adjust for new location of setup.py]
Tested-by: Rob Herring <robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-11-12 12:45:46 +11:00
Rob Herring
23b56cb7e1 pylibfdt: Move setup.py to the top level
Using 'pip' and several setup.py sub-commands currently don't work with
pylibfdt. The primary reason is Python packaging has opinions on the
directory structure of repositories and one of those appears to be the
inability to reference source files outside of setup.py's subtree. This
means a sdist cannot be created with all necessary source components
(i.e. libfdt headers). Moving setup.py to the top-level solves these
problems.

With this change. the following commands now work:

Creating packages for pypi.org:
./setup.py sdist bdist_wheel

Using pip for installs:
pip install .
pip install git+http://github.com/robherring/dtc.git@pypi-v2

Signed-off-by: Rob Herring <robh@kernel.org>
Message-Id: <20211111011135.2386773-5-robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-11-11 14:34:51 +11:00
Rob Herring
69a760747d pylibfdt: Split setup.py author name and email
The 'author' field in setup.py is supposed to be just the name. The
email address goes in 'author_email' field.

Cc: Simon Glass <sjg@chromium.org>
Signed-off-by: Rob Herring <robh@kernel.org>
Message-Id: <20211111011135.2386773-4-robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-11-11 14:34:51 +11:00
Rob Herring
0b106a77db pylibfdt: Use setuptools_scm for the version
The DTC version in version_gen.h causes a warning with setuptools:

setuptools/dist.py:501: UserWarning: The version specified ('1.6.1-g5454474d') \
is an invalid version, this may not work as expected with newer versions of \
setuptools, pip, and PyPI. Please see PEP 440 for more details.

It also creates an unnecessary dependency on the rest of the build
system(s). Switch to use setuptools_scm instead to get the version for
pylibfdt.

Signed-off-by: Rob Herring <robh@kernel.org>
Message-Id: <20211111011135.2386773-3-robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-11-11 14:30:33 +11:00
Rob Herring
c691776ddb pylibfdt: Use setuptools instead of distutils
The use of setuptools is favored over distutils. setuptools is needed to
support building Python 'wheels' and for pip support.

Signed-off-by: Rob Herring <robh@kernel.org>
Message-Id: <20211111011135.2386773-2-robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-11-11 14:29:12 +11:00
Rob Herring
5216f3f1bb libfdt: Add static lib to meson build
The meson build is not building the static libfdt, so add it.

Signed-off-by: Rob Herring <robh@kernel.org>
Message-Id: <20211111003329.2347536-1-robh@kernel.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
Tested-by: Simon Glass <sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-11-11 14:27:09 +11:00
Ahmad Fatoum
4eda2590f4 CI: Cirrus: bump used FreeBSD from 12.1 to 13.0
CI freebsd_12 job currently fails to build PRs, because of:
```
ld-elf.so.1: /usr/local/bin/bison: Undefined symbol "fread_unlocked@FBSD_1.6"
```

According to FreeBSD issue tracker[1], the proper solution is to upgrade to a
supported release, so do that for our CI.

[1]: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=253452

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
2021-11-01 14:02:44 +11:00
Rob Herring
0a3a9d3449 checks: Add an interrupt-map check
Add a check for parsing 'interrupt-map' properties. The check primarily
tests parsing 'interrupt-map' properties which depends on and the parent
interrupt controller (or another map) node.

Note that this does not require '#address-cells' in the interrupt-map
parent, but treats missing '#address-cells' as 0 which is how the Linux
kernel parses it. There's numerous cases that expect this behavior.

Cc: Andre Przywara <andre.przywara@arm.com>
Signed-off-by: Rob Herring <robh@kernel.org>
Message-Id: <20211015213527.2237774-1-robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-10-21 15:48:41 +11:00
Rob Herring
8fd24744e3 checks: Ensure '#interrupt-cells' only exists in interrupt providers
The interrupt provider check currently checks if an interrupt provider
has #interrupt-cells, but not whether #interrupt-cells is present
outside of interrupt-providers. Rework the check to cover the latter
case.

Cc: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Rob Herring <robh@kernel.org>
Message-Id: <20211011191245.1009682-4-robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-10-14 14:46:17 +11:00
Rob Herring
d8d1a9a778 checks: Drop interrupt provider '#address-cells' check
'#address-cells' is only needed when parsing 'interrupt-map' properties, so
remove it from the common interrupt-provider test.

Cc: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Rob Herring <robh@kernel.org>
Message-Id: <20211011191245.1009682-3-robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-10-14 14:45:22 +11:00
Rob Herring
52a16fd728 checks: Make interrupt_provider check dependent on interrupts_extended_is_cell
If '#interrupt-cells' doesn't pass checks, no reason to run interrupt
provider check.

Cc: Andre Przywara <andre.przywara@arm.com>
Signed-off-by: Rob Herring <robh@kernel.org>
Message-Id: <20211011191245.1009682-1-robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-10-14 14:35:45 +11:00
Rob Herring
37fd700685 treesource: Maintain phandle label/path on output
The dts output will just output phandle integer values, but often the
necessary markers are present with path or label references. Improve the
output and maintain phandle label or path references when present in dts
output.

Signed-off-by: Rob Herring <robh@kernel.org>
Message-Id: <20210727183023.3212077-6-robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-10-11 16:20:53 +11:00
David Gibson
e33ce1d6a8 flattree: Use '\n', not ';' to separate asm pseudo-ops
The output of -Oasm is peculiar for assembler in that we want its output
to be portable across targets (it consists entirely of pseudo-ops and
labels, no actual instructions).

It turns out that while ';' is a valid instruction/pseudo-op separator
on most targets, it's not correct for all of them - e.g. HP PA-RISC.  So,
switch to using an actual \n instead.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-09-27 11:54:56 +10:00
David Gibson
d24cc189dc asm: Use assembler macros instead of cpp macros
tests/trees.S is a weird thing: a portable aseembler file, used to produce
a specific binary output.  Currently it uses CPP macros quite heavily to
construct the dtbs we want (including some partial and broken trees).

Using cpp has the side effect that we need to use ; separators between
instructions (or, rather, pseudo-ops), because cpp won't expand newlines.
However, it turns out that while ; is a suitable separator on most
targets, it doesn't work for all of them (e.g. HP PA-RISC).

Switch to using the assembler's inbuilt macros rather than CPP, so that we
can use genuine newlines.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-09-27 11:54:56 +10:00
Rob Herring
ff3a30c115 asm: Use .asciz and .ascii instead of .string
We use the .string pseudo-op both in some of our test assembly files
and in our -Oasm output.  We expect this to emit a \0 terminated
string into the .o file.  However for certain targets (e.g. HP
PA-RISC) it doesn't include the \0.  Use .asciz instead, which
explicitly does what we want.

There's also one place we can use .ascii (which explicitly emits a
string *without* \0 termination) instead of multiple .byte directives.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-09-25 16:11:41 +10:00
Marc-André Lureau
5eb5927d81 fdtdump: fix -Werror=int-to-pointer-cast
With mingw64-gcc, the compiler complains with various warnings:
error: cast from pointer to integer of different size [-Werror=pointer-to-int-cast]

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20210825121350.213551-1-marcandre.lureau@redhat.com>
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-08-26 10:58:26 +10:00
Georg Kotheimer
0869f82691 libfdt: Add ALIGNMENT error string
The ALIGNMENT error was missing a string, leading to <unknown error>
being returned.

Signed-off-by: Georg Kotheimer <georg.kotheimer@kernkonzept.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-08-02 12:21:53 +10:00
Thierry Reding
69595a167f checks: Fix bus-range check
The upper limit of the bus-range is specified by the second cell of the
bus-range property.

Signed-off-by: Thierry Reding <treding@nvidia.com>
Message-Id: <20210629114304.2451114-1-thierry.reding@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-06-30 10:32:13 +10:00
Andre Przywara
72d09e2682 Makefile: add -Wsign-compare to warning options
Now that all signedness comparison warnings in the source tree have been
fixed, let's enable the warning option, to avoid them creeping in again.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Message-Id: <20210618172030.9684-6-andre.przywara@arm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-06-21 15:34:49 +10:00
Andre Przywara
b587787ef3 checks: Fix signedness comparisons warnings
With -Wsign-compare, compilers warn about a mismatching signedness in
comparisons in various parts in checks.c.

Fix those by making all affected variables unsigned. This covers return
values of the (unsigned) size_t type, phandles, variables holding sizes
in general and loop counters only ever counting positives values.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Message-Id: <20210618172030.9684-5-andre.przywara@arm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-06-21 15:34:05 +10:00
Andre Przywara
69bed6c241 dtc: Wrap phandle validity check
In several places we check for a returned phandle value to be valid,
for that it must not be 0 or "-1".

Wrap this check in a static inline function in dtc.h, and use ~0U instead
of -1 on the way, to keep everything in the unsigned realm.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Message-Id: <20210618172030.9684-4-andre.przywara@arm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-06-21 15:28:21 +10:00
Andre Przywara
9102211855 fdtget: Fix signedness comparisons warnings
With -Wsign-compare, compilers warn about a mismatching signedness in
the different legs of the conditional operator, in fdtget.c.

In the questionable expression, we are constructing a 16-bit value out of
two unsigned 8-bit values, however are relying on the compiler's
automatic expansion of the uint8_t to a larger type, to survive the left
shift. This larger type happens to be an "int", so this part of the
expression becomes signed.

Fix this by explicitly blowing up the uint8_t to a larger *unsigned* type,
before doing the left shift. And while we are at it, convert the hardly
readable conditional operator usage into a sane switch/case expression.

This fixes "make fdtget", when compiled with -Wsign-compare.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Message-Id: <20210618172030.9684-3-andre.przywara@arm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-06-21 15:27:39 +10:00
Andre Przywara
d966f08fcd tests: Fix signedness comparisons warnings
With -Wsign-compare, compilers warn about a mismatching signedness in
comparisons in various files in the tests/ directory.

For about half of the cases we can simply change the signed variable to
be of an unsigned type, because they will never need to store negative
values (which is the best fix of the problem).

In the remaining cases we can cast the signed variable to an unsigned
type, provided we know for sure it is not negative.
We see two different scenarios here:
- We either just explicitly checked for this variable to be positive
  (if (rc < 0) FAIL();), or
- We rely on a function returning only positive values in the "length"
  pointer if the function returned successfully: which we just checked.

At two occassions we compare with a constant "-1" (even though the
variable is unsigned), so we just change this to ~0U to create an
unsigned comparison value.

Since this is about the tests, let's also add explicit tests for those
values really not being negative.

This fixes "make tests" (but not "make check" yet), when compiled
with -Wsign-compare.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Message-Id: <20210618172030.9684-2-andre.przywara@arm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-06-21 15:25:44 +10:00
Andre Przywara
ecfb438c07 dtc: Fix signedness comparisons warnings: pointer diff
With -Wsign-compare, compilers warn about a mismatching signedness
in comparisons in the function get_node_by_path().

Taking the difference between two pointers results in a signed ptrdiff_t
type, which mismatches the unsigned type returned by strlen().
Since "p" has been returned by a call to strchr() with "path" as its
argument, we know for sure that it's bigger than "path", so the
difference must be positive. So a cast to an unsigned type is valid.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Message-Id: <20210611171040.25524-7-andre.przywara@arm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-06-15 12:49:23 +10:00
Andre Przywara
5bec74a6d1 dtc: Fix signedness comparisons warnings: reservednum
With -Wsign-compare, compilers warn about a mismatching signedness
in comparisons in code using the "reservednum" variable.

There is obviously little sense in having a negative number of reserved
memory entries, so let's make this variable and all its users unsigned.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Message-Id: <20210611171040.25524-6-andre.przywara@arm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-06-15 12:48:25 +10:00
Andre Przywara
24e7f511fd fdtdump: Fix signedness comparisons warnings
With -Wsign-compare, compilers warn about a mismatching signedness in
comparisons in fdtdump.c.

The "len" parameter to valid_header() refers to a memory size, not a
file offset, so the (unsigned) size_t is better fit, and fixes the
warning nicely.

In the main function we compare the difference between two pointers,
which produces a signed ptrdiff_t type. However the while loop above the
comparison makes sure that "p" always points before "endp" (by virtue of
the limit in the memchr() call). This means "endp - p" is never
negative, so we can safely cast this expression to an unsigned type.

This fixes "make fdtdump", when compiled with -Wsign-compare.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Message-Id: <20210611171040.25524-3-andre.przywara@arm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-06-15 12:35:54 +10:00
David Gibson
b6910bec11 Bump version to v1.6.1
A number of fixes have accumulated, so rolling up another release.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-06-08 17:00:49 +10:00
David Gibson
21d61d18f9 Fix CID 1461557
Coverity gets a bit confused by loading fdt_size_dt_strings() and
using it in a memmove().  In fact this is safe because the callers
have verified this information (via FDT_RW_PROBE() in fdt_pack() or
construction in fdt_open_into()).

Passing in strings_size like we already do struct_size seems to get
Coverity to follow what's going on here.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-06-08 16:32:59 +10:00
David Gibson
4c2ef8f4d1 checks: Introduce is_multiple_of()
In a number of places we check if one number is a multiple of another,
using a modulus.  In some of those cases the divisor is potentially zero,
which needs special handling or we could trigger a divide by zero.

Introduce an is_multiple_of() helper to safely handle this case, and use
it in a bunch of places.  This should close Coverity issue 1501687, maybe
others as well.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-06-08 15:17:11 +10:00
David Gibson
e59ca36fb7 Make handling of cpp line information more tolerant
At least some cpp implementations, in at least some circumstances place
multiple numbers after the file name when they put line number information
into the output.  We don't really care what the content of these is, but
we want the dtc lexer not to choke on this, so adjust the rule for handling
cpp line number information accordingly.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-06-08 14:15:25 +10:00
Rob Herring
0c3fd9b6ac checks: Drop interrupt_cells_is_cell check
With the prior commit, this check is now redundant.

Signed-off-by: Rob Herring <robh@kernel.org>
Message-Id: <20210526010335.860787-4-robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-06-08 11:58:43 +10:00
Rob Herring
6b3081abc4 checks: Add check_is_cell() for all phandle+arg properties
There's already a check for '#.*-cells' properties, so let's enable it for
all the ones we already know about.

Signed-off-by: Rob Herring <robh@kernel.org>
Message-Id: <20210526010335.860787-3-robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-06-08 11:57:04 +10:00
Rob Herring
2dffc192a7 yamltree: Remove marker ordering dependency
The check for phandle markers is fragile because the phandle marker must
be after a type marker. The only guarantee for markers is they are in
offset order. The order at a specific offset is undefined.

Rework yaml_propval_int() to get the full marker list, so it can find a
phandle marker no matter the ordering.

Signed-off-by: Rob Herring <robh@kernel.org>
Message-Id: <20210526010335.860787-2-robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-06-08 11:53:19 +10:00
Tom Rini
61e513439e pylibfdt: Rework "avoid unused variable warning" lines
Clang has -Wself-assign enabled by default under -Wall and so when
building with -Werror we would get an error here.  Inspired by Linux
kernel git commit a21151b9d81a ("tools/build: tweak unused value
workaround") make use of the fact that both Clang and GCC support
casting to `void` as the method to note that something is intentionally
unused.

Signed-off-by: Tom Rini <trini@konsulko.com>
Message-Id: <20210524154910.30523-1-trini@konsulko.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-05-25 13:27:00 +10:00
Ilya Lipnitskiy
c8bddd1060 tests: add a positive gpio test case
Ensure that properly named properties don't trigger warnings

Signed-off-by: Ilya Lipnitskiy <ilya.lipnitskiy@gmail.com>
Message-Id: <20210504035944.8453-5-ilya.lipnitskiy@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-05-04 14:45:20 +10:00
Ilya Lipnitskiy
ad4abfadb6 checks: replace strstr and strrchr with strends
Makes the logic more clear

Signed-off-by: Ilya Lipnitskiy <ilya.lipnitskiy@gmail.com>
Message-Id: <20210504035944.8453-4-ilya.lipnitskiy@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-05-04 14:45:20 +10:00
Ilya Lipnitskiy
09c6a6e887 dtc.h: add strends for suffix matching
Logic is similar to strcmp_suffix in <kernel>/drivers/of/property.c with
the exception that strends allows string length to equal suffix length.

Signed-off-by: Ilya Lipnitskiy <ilya.lipnitskiy@gmail.com>
Message-Id: <20210504035944.8453-3-ilya.lipnitskiy@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-05-04 14:45:20 +10:00
Ilya Lipnitskiy
9bb9b8d0b4 checks: tigthen up nr-gpios prop exception
There are no instances of nr-gpio in the Linux kernel tree, only
"[<vendor>,]nr-gpios", so make the check stricter.

nr-gpios without a "vendor," prefix is also invalid, according to the DT
spec[0], and there are no DT files in the Linux kernel tree with
non-vendor nr-gpios. There are some drivers, but they are not DT spec
compliant, so don't suppress the check for them.

[0]:
Link: cb53a16a1e/schemas/gpio/gpio-consumer.yaml (L20)

Signed-off-by: Ilya Lipnitskiy <ilya.lipnitskiy@gmail.com>
Cc: Rob Herring <robh+dt@kernel.org>
Message-Id: <20210504035944.8453-2-ilya.lipnitskiy@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-05-04 14:45:20 +10:00
Rob Herring
b07b62ee33 libfdt: Add FDT alignment check to fdt_check_header()
Only checking the FDT alignment in fdt_ro_probe_() means that
fdt_check_header() can pass, but then subsequent API calls fail on
alignment checks. Let's add an alignment check to fdt_check_header() so
alignment errors are found up front.

Cc: Tom Rini <trini@konsulko.com>
Cc: Frank Rowand <frowand.list@gmail.com>
Signed-off-by: Rob Herring <robh@kernel.org>
Message-Id: <20210406190712.2118098-1-robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-04-07 12:44:19 +10:00
Simon Glass
a2def54799 libfdt: Check that the root-node name is empty
The root node is supposed to have an empty name, but at present this is
not checked. The behaviour of such a tree is not well defined. Most
software rightly assumes that the root node is at offset 0 and does not
check the name. This oddity was discovered as part of a security
investigation into U-Boot verified boot.

Add a check for this to fdt_check_full().

Signed-off-by: Simon Glass <sjg@chromium.org>
Reported-by: Arie Haenel <arie.haenel@intel.com>
Reported-by: Julien Lenoir <julien.lenoir@intel.com>
Message-Id: <20210323010410.3222701-2-sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-03-23 12:13:06 +11:00
Simon Glass
4ca61f84dc libfdt: Check that there is only one root node
At present it is possible to have two root nodes and even access nodes
in the 'second' root. Such trees should not be considered valid. This
was discovered as part of a security investigation into U-Boot verified
boot.

Add a check for this to fdt_check_full().

Signed-off-by: Simon Glass <sjg@chromium.org>
Reported-by: Arie Haenel <arie.haenel@intel.com>
Reported-by: Julien Lenoir <julien.lenoir@intel.com>
Message-Id: <20210323000926.3210733-1-sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-03-23 11:56:34 +11:00
Masahiro Yamada
34d708249a dtc: Remove -O dtbo support
This partially reverts 163f0469bf ("dtc: Allow overlays to have
.dtbo extension").

I think accepting "dtbo" as --out-format is strange. This is not
shown by --help, at least.

*.dtb and *.dtbo should have the same format, "dtb".

Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
Message-Id: <20210311094956.924310-1-masahiroy@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-03-12 12:57:31 +11:00
David Gibson
8e7ff260f7 libfdt: Fix a possible "unchecked return value" warning
Apparently the unchecked return value of the first fdt_next_tag() call in
fdt_add_subnode_namelen() is tripping Coverity Scan in some circumstances,
although it appears not to for the scan on our project itself.

This fdt_next_tag() should always return FDT_BEGIN_NODE, since otherwise
the fdt_subnode_offset_namelen() above would have returned BADOFFSET or
BADSTRUCTURE.

Still, add a check to shut Coverity up, gated by a can_assume() to avoid
bloat in small builds.

Reported-by: Ryan Long <ryan.long@oarcorp.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-03-09 14:49:35 +11:00
Kumar Gala
88875268c0 checks: Warn on node-name and property name being the same
Treat a node-name and property name at the same level of tree as
a warning

Signed-off-by: Kumar Gala <kumar.gala@linaro.org>
Message-Id: <20210210193912.799544-1-kumar.gala@linaro.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-02-15 17:17:36 +11:00
Kumar Gala
9d2279e7e6 checks: Change node-name check to match devicetree spec
The devicetree spec limits the valid character set to:
  A-Z
  a-z
  0-9
  ,._+-

while property can additionally have '?#'.  Change the check to match
the spec.

Signed-off-by: Kumar Gala <kumar.gala@linaro.org>
Message-Id: <20210209184641.63052-1-kumar.gala@linaro.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-02-10 16:29:21 +11:00
Jonathan Gray
f527c867a8 util: limit gnu_printf format attribute to gcc >= 4.4.0
The gnu_printf format attribute was introduced in gcc 4.4.0
https://gcc.gnu.org/legacy-ml/gcc-help/2012-02/msg00225.html.

Use the printf format attribute on earlier versions of gcc and clang
(which claims to be gcc 4.2.1 in builtin defines) to fix the build with
gcc 4.2.1.

Fixes: 588a29f ("util: use gnu_printf format attribute")
Signed-off-by: Jonathan Gray <jsg@jsg.id.au>
Message-Id: <20210206100110.75228-1-jsg@jsg.id.au>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-02-07 14:22:39 +11:00
Viresh Kumar
183df9e9c2 gitignore: Ignore the swp files
Ignore the temporary .*.swp files.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Message-Id: <15496f8669ac2bb3b4b61a1a7c978947623cb7c3.1612346186.git.viresh.kumar@linaro.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-02-03 21:19:53 +11:00
Viresh Kumar
0db6d09584 gitignore: Add cscope files
Add cscope files in gitignore.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Message-Id: <3c39a6324ef2be64f839e6e6205f4afc63486216.1612338199.git.viresh.kumar@linaro.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-02-03 21:17:58 +11:00
David Gibson
307afa1a7b Update Jon Loeliger's email
At Jon's request update to a more current address.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-01-28 11:24:20 +11:00
David Gibson
ca16a723fa fdtdump: Fix gcc11 warning
In one place, fdtdump abuses fdt_set_magic(), passing it just a small char
array instead of the full fdt header it expects.  That's relying on the
fact that in fact fdt_set_magic() will only actually access the first 4
bytes of the buffer.

This trips a new warning in GCC 11 - and it's entirely possible it was
always UB.  So, don't do that.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-01-15 16:58:40 +11:00
Ignacy Kuchciński
64990a272e srcpos: increase MAX_SRCFILE_DEPTH
Some kernels require the MAX_SRCFILE_DEPTH to be bigger than 100, and
since it's just a sanity check to detect infinite recursion it shouldn't
hurt increasing it to 200.

Signed-off-by: Ignacy Kuchciński <ignacykuchcinski@gmail.com>
Message-Id: <CAJq_QG0BHBQYT4RnVi0QSxM_vFK2K-5k1eTpJnwZQtWbKnCBJA@mail.gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-01-13 12:05:26 +11:00
Viresh Kumar
163f0469bf dtc: Allow overlays to have .dtbo extension
Allow the overlays to have .dtbo extension instead of just .dtb. This
allows them to be identified easily by tools as well as humans.

Allow the dtbo outform in dtc.c for the same.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>

Message-Id: <30fd0e5f2156665c713cf191c5fea9a5548360c0.1609926856.git.viresh.kumar@linaro.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-01-11 21:55:55 +11:00
Justin Covell
3b01518e68 Set last_comp_version correctly in new dtb and fix potential version issues in fdt_open_into
Changes in v3:
- Remove noop version sets
- Set version correctly on loaded fdt in fdt_open_into

Fixes: f1879e1a50 ("Add limited read-only support for older (V2 and V3) device tree to libfdt.")

Signed-off-by: Justin Covell <jujugoboom@gmail.com>

Message-Id: <20201229041749.2187-1-jujugoboom@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2021-01-04 12:26:37 +11:00
Paul Barker
f7e5737f26 tests: Fix overlay_overlay_nosugar test case
This test was accidentally skipped as the wrong test dts file was built.
The fragment numbering in this sugar-free test case needed adjusting to
match the numbering generated by dtc for overlay_overlay.dts.

Signed-off-by: Paul Barker <pbarker@konsulko.com>
Message-Id: <20201219143521.2118-1-pbarker@konsulko.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-12-22 20:45:42 +11:00
David Gibson
7cd5d5fe43 libfdt: Tweak description of assume-aligned load helpers
There's a small inaccuracy in the comment describing these new helpers.
This corrects it, and reformats while we're there.

Fixes: f98f28ab ("libfdt: Internally perform potentially unaligned loads")
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-12-16 16:52:17 +11:00
Tom Rini
a7c4040993 libfdt: Internally perform potentially unaligned loads
Commits 6dcb8ba4 "libfdt: Add helpers for accessing unaligned words"
introduced changes to support unaligned reads for ARM platforms and
11738cf01f "libfdt: Don't use memcpy to handle unaligned reads on ARM"
improved the performance of these helpers.

On further discussion, while there are potential cases where we could be
used on platforms that do not fixup unaligned reads for us, making this
choice the default is very expensive in terms of binary size and access
time.  To address this, introduce and use new fdt{32,64}_ld_ functions
that call fdt{32,64}_to_cpu() as was done prior to the above mentioned
commits.  Leave the existing load functions as unaligned-safe and
include comments in both cases.

Reviewed-by: Rob Herring <robh@kernel.org>
Signed-off-by: Tom Rini <trini@konsulko.com>
Message-Id: <20201211022736.31657-1-trini@konsulko.com>
Tested-by: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-12-16 16:52:05 +11:00
Marc-André Lureau
bab85e48a6 meson: increase default timeout for tests
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20201207130055.462734-4-marcandre.lureau@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-12-08 15:30:28 +11:00
Marc-André Lureau
f8b4609882 meson: do not assume python is installed, skip tests
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20201207130055.462734-3-marcandre.lureau@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-12-08 15:30:28 +11:00
Marc-André Lureau
30a56bce4f meson: fix -Wall warning
Meson already handles Wall via the built-in warning_level option.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20201207130055.462734-2-marcandre.lureau@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-12-08 15:30:28 +11:00
Tom Rini
5e735860c4 libfdt: Check for 8-byte address alignment in fdt_ro_probe_()
The device tree must be loaded in to memory at an 8-byte aligned
address.  Add a check for this condition in fdt_ro_probe_() and a new
error code to return if we are not.

Signed-off-by: Tom Rini <trini@konsulko.com>
Message-Id: <20201104130605.28874-1-trini@konsulko.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-11-24 16:41:45 +11:00
Marc-André Lureau
67849a3279 build-sys: add meson build
The meson build system allows projects to "vendor" dtc easily, thanks to
subproject(). QEMU has recently switched to meson, and adding meson
support to dtc will help to handle the QEMU submodule.

meson rules are arguably simpler to write and maintain than
the hand-crafted/custom Makefile. meson support various backends, and
default build options (including coverage, sanitizer, debug/release
etc, see: https://mesonbuild.com/Builtin-options.html)

Compare to the Makefiles, the same build targets should be built and
installed and the same tests should be run ("meson test" can be provided
extra test arguments for running the equivalent of checkm/checkv).

There is no support EXTRAVERSION/LOCAL_VERSION/CONFIG_LOCALVERSION,
instead the version is simply set with project(), and vcs_tag() is
used for git/dirty version reporting (This is most common and is
hopefully enough. If necessary, configure-time options could be added
for extra versioning.).

libfdt shared library is build following regular naming conventions:
instead of libfdt.so.1 -> libfdt-1.6.0.so (with current build-sys),
libfdt.so.1 -> libfdt.so.1.6.0. I am not sure why the current build
system use an uncommon naming pattern. I also included a libfdt.pc
pkg-config file, as convenience.

Both Linux native build and mingw cross-build pass. CI pass. Tests are
only run on native build.

The current Makefiles are left in-tree, and make/check still work.
Eventually, the Makefiles could be marked as deprecated, to start a
transition period and avoid having to maintain 2 build systems in the
near future.

(run_tests.sh could eventually be replaced by the meson test runner,
which would have several advantages in term of flexibility/features,
but this is left for another day)

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20201012073405.1682782-3-marcandre.lureau@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-10-21 14:36:07 +11:00
Marc-André Lureau
05874d0821 pylibfdt: allow build out of tree
With meson, we have to support out-of-tree build.

Introduce a --top-builddir option, which will default to the current
directory to lookup generated filed such as version_gen.h and output
directories.

Other source paths are derived from the location of the setup.py script
in the source tree.

--build-lib is changed to be relative to the current directory, instead
of relative to setup.py. This has less surprising results!

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20201012073405.1682782-2-marcandre.lureau@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-10-21 14:35:17 +11:00
Andre Przywara
3bc3a6b9fe dtc: Fix signedness comparisons warnings: Wrap (-1)
With -Wsign-compare, compilers warn about a mismatching signedness
in a comparison in dtc's data_copy_file().

Even though maxlen is of an unsigned type, we compare against "-1",
which is passed in from the parser to indicate an unknown size.

Cast the "-1" to an unsigned size to make the comparison match.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Message-Id: <20201012161948.23994-9-andre.przywara@arm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-10-13 15:58:53 +11:00
Andre Przywara
e1147b159e dtc: Fix signedness comparisons warnings: change types
With -Wsign-compare, compilers warn about a mismatching signedness in
comparisons in various parts of dtc.

Many variables are using signed types unnecessarily, as we never use
negative value in them.
Change their types to be unsigned, to prevent issues with comparisons.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Message-Id: <20201012161948.23994-7-andre.przywara@arm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-10-13 15:56:53 +11:00
Andre Przywara
04cf1fdc0f convert-dtsv0: Fix signedness comparisons warning
With -Wsign-compare, compilers warn about a mismatching signedness in
comparisons in the generated lexer code.

In this case we walk over an array, and never use negative indicies, so
we can change the loop counter variable to be unsigned.

This fixes "make convert-dtsv0", when compiled with -Wsign-compare.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Message-Id: <20201012161948.23994-3-andre.przywara@arm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-10-13 15:48:40 +11:00
Andre Przywara
b30013edb8 libfdt: Fix kernel-doc comments
The API documentation in libfdt.h seems to follow the Linux kernel's
kernel-doc format[1].

Running "scripts/kernel-doc -v -none" on the file reports some problems,
mostly missing return values and missing parameter descriptions.

Fix those up by providing the missing bits, and fixing the other small
issues reported by the script.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>

[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/doc-guide/kernel-doc.rst
Message-Id: <20201012165331.25016-1-andre.przywara@arm.com>

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-10-13 15:46:44 +11:00
Rob Herring
cbca977ea1 checks: Allow PCI bridge child nodes without an address
Some PCI bridge nodes have child nodes such as an interrupt controller
which are not PCI devices. Allow these nodes which don't have a
unit-address.

Signed-off-by: Rob Herring <robh@kernel.org>
Message-Id: <20200928201942.3242124-1-robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-10-02 13:30:24 +10:00
Andre Przywara
73e0f143b7 libfdt: fdt_strerror(): Fix comparison warning
With -Wsign-compare, compilers warn about a mismatching signedness
in a comparison in fdt_strerror().

Force FDT_ERRTABSIZE to be signed (it's surely small enough to fit), so
that the types match. Also move the minus sign to errval, as this is
actually what we use in the next line.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Message-Id: <20201001164630.4980-7-andre.przywara@arm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-10-02 10:34:18 +10:00
Andre Przywara
6c2be7d853 libfdt: fdt_get_string(): Fix sequential write comparison warnings
With -Wsign-compare, compilers warn about a mismatching signedness in
comparisons in fdt_get_string().

Introduce a new usigned variable, which holds the actual (negated)
stroffset value, so we avoid negating all the other variables and have
proper types everywhere.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Message-Id: <20201001164630.4980-6-andre.przywara@arm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-10-02 10:33:01 +10:00
Andre Przywara
82525f41d5 libfdt: libfdt_wip: Fix comparison warning
With -Wsign-compare, compilers warn about a mismatching signedness
in a comparison in fdt_setprop_inplace_namelen_partial().

fdt_getprop_namelen() will only return negative error values in "proplen"
if the return value is NULL. So we can rely on "proplen" being positive
in our case and can safely cast it to an unsigned type.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Message-Id: <20201001164630.4980-5-andre.przywara@arm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-10-02 10:30:07 +10:00
Andre Przywara
fb1f65f158 libfdt: fdt_create_with_flags(): Fix comparison warning
With -Wsign-compare, compilers warn about a mismatching signedness
in a comparison in fdt_create_with_flags().

By making hdrsize a signed integer (we are sure it's a very small
number), we avoid all the casts and have matching types.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Message-Id: <20201001164630.4980-4-andre.przywara@arm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-10-02 10:29:27 +10:00
Andre Przywara
f28aa27100 libfdt: fdt_move(): Fix comparison warnings
With -Wsign-compare, compilers warn about a mismatching signedness
in comparisons in fdt_move().

This stems from "bufsize" being passed in as a signed integer, even
though we would expect a buffer size to be positive.

Short of changing the prototype, check that bufsize is not negative, and
cast it to an unsigned type in the comparison.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Message-Id: <20201001164630.4980-3-andre.przywara@arm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-10-02 10:28:36 +10:00
Andre Przywara
3d7c6f4419 libfdt: fdt_add_string_(): Fix comparison warning
With -Wsign-compare, compilers warn about a mismatching signedness
in a comparison in fdt_add_string_().

Make all variables unsigned, and express the negative offset trick via
subtractions in the code.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Message-Id: <20201001164630.4980-2-andre.przywara@arm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-10-02 10:22:37 +10:00
Andre Przywara
10f682788c libfdt: fdt_node_offset_by_phandle(): Fix comparison warning
With -Wsign-compare, compilers warn about a mismatching signedness
in a comparison in fdt_node_offset_by_phandle().

Uses a better suited bitwise NOT operator to denote the special value of
-1, which automatically results in an unsigned type.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Message-Id: <20200921165303.9115-14-andre.przywara@arm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-09-25 14:09:41 +10:00
Andre Przywara
07158f4cf2 libfdt: overlay: Fix comparison warning
With -Wsign-compare, compilers warn about a mismatching signedness in
a comparison in overlay_update_local_node_references().

This happens because the division of a signed int by an unsigned int
promotes the dividend to unsigned first (ANSI C standard 6.1.3.8).

As in this case we basically just divide by 4, we can do the division
separately earlier, which preserves the original type.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Message-Id: <20200921165303.9115-12-andre.przywara@arm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-09-25 14:05:51 +10:00
Andre Przywara
ce9e1f25a7 libfdt: fdt_resize(): Fix comparison warning
With -Wsign-compare, compilers warn about a mismatching signedness
in a comparison in fdt_resize().

A negative buffer size will surely do us no good, so let's rule this
case out first.
In the actual comparison we then know that a cast to an unsigned type is
safe.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Message-Id: <20200921165303.9115-10-andre.przywara@arm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-09-24 14:43:02 +10:00
Andre Przywara
faa76fc10b libfdt: fdt_splice_(): Fix comparison warning
With -Wsign-compare, compilers warn about a mismatching signedness
in a comparison in fdt_splice_().

Since we just established that oldlen is not negative, we can safely
cast it to an unsigned type.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Message-Id: <20200921165303.9115-8-andre.przywara@arm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-09-24 11:07:27 +10:00
Simon Glass
54dca09853 libfdt: fdt_get_string(): Fix comparison warnings
With -Wsign-compare, compilers warn about a mismatching signedness in
comparisons in fdt_get_string().

In the first two cases, we have just established that the signed values
are not negative, so it's safe to cast the values to an unsigned type.

Signed-off-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Message-Id: <20200921165303.9115-7-andre.przywara@arm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-09-24 11:06:30 +10:00
Andre Przywara
f8e11e6162 libfdt: fdt_grab_space_(): Fix comparison warning
With -Wsign-compare, compilers warn about a mismatching signedness
in a comparison in fdt_grab_space_().

All the involved values cannot be negative, so let's switch the types of
the local variables to unsigned to make the compiler happy.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Message-Id: <20200921165303.9115-4-andre.przywara@arm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-09-23 21:50:50 +10:00
Andre Przywara
0c43d4d7bf libfdt: fdt_mem_rsv(): Fix comparison warnings
With -Wsign-compare, compilers warn about a mismatching signedness
in comparisons in fdt_mem_rsv().

Since all involved values must be positive, change the used types to be
unsigned.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Message-Id: <20200921165303.9115-3-andre.przywara@arm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-09-23 21:50:17 +10:00
Andre Przywara
442ea3dd15 libfdt: fdt_offset_ptr(): Fix comparison warnings
With -Wsign-compare, compilers warn about mismatching signedness in
comparisons in fdt_offset_ptr().

This mostly stems from "offset" being passed in as a signed integer,
even though the function would not really tolerate negative values.

Short of changing the prototype, check that offset is not negative, and
use an unsigned type internally.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Message-Id: <20200921165303.9115-2-andre.przywara@arm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-09-23 21:47:35 +10:00
Emmanuel Vadot
ca19c3db2b Makefile: Specify cflags for libyaml
Some systems don't install third party software includes in a default
path (like FreeBSD), add yaml cflags to fix compilation.

Signed-off-by: Emmanuel Vadot <manu@FreeBSD.org>
2020-08-25 12:34:18 +02:00
Frank Mehnert
7bb86f1c09 libfdt: fix fdt_check_node_offset_ w/ VALID_INPUT
fdt_check_node_offset_() checks for a valid offset but also changes the
offset by calling fdt_next_tag(). Hence, do not skip this function if
ASSUME_VALID_INPUT is set but only omit the initial offset check in that
case.

As this function works very similar to fdt_check_prop_offset_(), do the
offset check there as well depending on ASSUME_VALID_INPUT.
Message-Id: <1913141.TlUzK5foHS@noys4>

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-08-14 13:16:22 +10:00
Andrei Ziureaev
3d522abc75 dtc: Include stdlib.h in util.h
If used on its own, util.h needs stdlib.h for exit(), malloc() and
realloc().

Signed-off-by: Andrei Ziureaev <andrei.ziureaev@arm.com>
Message-Id: <20200721155900.9147-2-andrei.ziureaev@arm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-07-22 16:41:28 +10:00
Andrei Ziureaev
808cdaaf52 dtc: Avoid UB when shifting
Prevent undefined behavior when shifting by a number that's bigger than
or equal to the width of the first operand.

Signed-off-by: Andrei Ziureaev <andrei.ziureaev@arm.com>
Message-Id: <20200714154542.18064-2-andrei.ziureaev@arm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-07-15 20:40:54 +10:00
Patrick Oppenlander
3e3138b4a9 libfdt: fix fdt_check_full buffer overrun
fdt_check_header assumes that its argument points to a complete header
and can read data beyond the FDT_V1_SIZE bytes which fdt_check_full
can provide.

fdt_header_size can safely return a header size with FDT_V1_SIZE bytes
available and will return a usable value even for a corrupted header.

Signed-off-by: Patrick Oppenlander <patrick.oppenlander@gmail.com>
Message-Id: <20200709041451.338548-1-patrick.oppenlander@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-07-10 19:55:36 +10:00
Geert Uytterhoeven
9d7888cbf1 dtc: Consider one-character strings as strings
When using overlays, a target-path property pointing to the root node is
quite common.  However, "dtc -O dts" prints it as a byte array:

    target-path = [2f 00];

instead of a string:

    target-path = "/";

For guess_value_type() to consider a value to be a string, it must
contain less nul bytes than non-nul bytes, thus ruling out strings
containing only a single character.  Allow printing such strings by
relaxing the condition slightly.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Message-Id: <20200623094343.26010-1-geert+renesas@glider.be>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-06-24 16:11:55 +10:00
Joel Stanley
8259d59f59 checks: Improve i2c reg property checking
The i2c bindings in the kernel tree describe support for 10 bit
addressing, which must be indicated with the I2C_TEN_BIT_ADDRESS flag.
When this is set the address can be up to 10 bits. When it is not set
the address is a maximum of 7 bits.

See Documentation/devicetree/bindings/i2c/i2c.txt.

Take into account this flag when checking the address is valid.

Signed-off-by: Joel Stanley <joel@jms.id.au>
Message-Id: <20200622031005.1890039-3-joel@jms.id.au>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-06-22 17:52:50 +10:00
Joel Stanley
fdabcf2980 checks: Remove warning for I2C_OWN_SLAVE_ADDRESS
dtc does a sanity check on reg properties that they are within the 10
bit address range for i2c slave addresses. In the case of multi-master
buses or devices that act as a slave, the binding may describe an
address that the bus will listen on as a device. Do not warn when this
flag is set.

See Documentation/devicetree/bindings/i2c/i2c.txt.

This fixes the following build warnings reported by Stephen and by Arnd:

arch/arm/boot/dts/aspeed-bmc-facebook-yosemitev2.dts:126.11-130.4:
  Warning (i2c_bus_reg): /ahb/apb/bus@1e78a000/i2c-bus@80/ipmb1@10:
    I2C bus unit address format error, expected "40000010"
arch/arm/boot/dts/aspeed-bmc-facebook-yosemitev2.dts:128.3-30:
  Warning (i2c_bus_reg): /ahb/apb/bus@1e78a000/i2c-bus@80/ipmb1@10:reg:
    I2C address must be less than 10-bits, got "0x40000010"

Reported-by: Stephen Rothwell <sfr@canb.auug.org.au>
Reported-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Joel Stanley <joel@jms.id.au>
Message-Id: <20200622031005.1890039-2-joel@jms.id.au>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-06-22 17:52:50 +10:00
Patrick Oppenlander
2478b1652c libfdt: add extern "C" for C++
Signed-off-by: Patrick Oppenlander <patrick.oppenlander@gmail.com>
Message-Id: <20200616011217.15253-1-patrick.oppenlander@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-06-19 09:52:41 +10:00
Patrick Oppenlander
f68bfc2668 libfdt: trivial typo fix
Signed-off-by: Patrick Oppenlander <patrick.oppenlander@gmail.com>
Message-Id: <20200618042117.131731-1-patrick.oppenlander@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-06-18 16:26:37 +10:00
Simon Glass
7be250b4d0 libfdt: Correct condition for reordering blocks
This condition uses bitwise OR but should be logical OR. Fix it.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reported-by: kernel test robot <lkp@intel.com>
Message-Id: <20200615160033.87328-1-sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-06-16 13:12:43 +10:00
Andre Przywara
81e0919a3e checks: Add interrupt provider test
An interrupt provider (an actual interrupt-controller node or an
interrupt nexus) should have both #address-cells and #interrupt-cells
properties explicitly defined.

Add an extra test for this. We check for the #interrupt-cells property
already, but this does not cover every controller so far, only those that
get referenced by an interrupts property in some node. Also we miss
interrupt nexus nodes.

A missing #address-cells property is less critical, but creates
ambiguities when used in interrupt-map properties, so warn about this as
well now.
This removes the now redundant warning in the existing interrupts test.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Message-Id: <20200515141827.27957-2-andre.przywara@arm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-05-18 14:26:12 +10:00
Claudio Fontana
85e5d83984 Makefile: when building libfdt only, do not add unneeded deps
implemented originally for the QEMU consumer of libfdt.

Signed-off-by: Claudio Fontana <cfontana@suse.de>
Message-Id: <20200512103315.1926-1-cfontana@suse.de>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-05-14 17:11:53 +10:00
David Gibson
b28464a550 Fix some potential unaligned accesses in dtc
Because of the convention of packed representations in property layouts,
it's not uncommon to have integer values in properties which aren't
naturally aligned.  Thus, there are several places in the dtc code where we
cast a potentially unaligned byte pointer into an integer pointer and load
it directly.  On a number of architectures (including sparc64 and arm) this
won't work and will cause a fault.  In some cases it may be trapped and
emulated by the kernel, but not always.

Therefore, replace such direct unaligned reads with a helper which will
handle unaligned data reads (a variant on the fdtXX_ld() functions already
used in libfdt).

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-04-14 15:02:51 +10:00
Arkadiusz Drabczyk
87a656ae5f check: Inform about missing ranges
In check_unit_address_vs_reg() warning message already says 'reg _or_
ranges' when reg or ranges are present but unit name is missing.  Add
this message for compatibility to say "reg _or_ ranges" when unit name
is present but neither reg nor ranges are present.

Signed-off-by: Arkadiusz Drabczyk <arkadiusz@drabczyk.org>
Message-Id: <20200308165643.19281-1-arkadiusz@drabczyk.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-03-10 11:44:23 +11:00
Jan Beulich
73d6e9ecb4 libfdt: fix undefined behaviour in fdt_splice_()
libfdt: fix undefined behaviour in fdt_splice_()

Along the lines of commit d0b3ab0a0f ("libfdt: Fix undefined behaviour
in fdt_offset_ptr()"), fdt_splice_() similarly may not use pointer
arithmetic to do overflow checks. (The left side of the checks added by
d4c7c25c9e ["libfdt: check for potential overrun in _fdt_splice()"]
doesn't really lend itself to similar replacement though.)

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Message-Id: <f2d09e81-7cb8-c5cc-9699-1ac05b0626ff@suse.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-03-06 12:58:54 +11:00
129 changed files with 4319 additions and 1274 deletions

View file

@ -1,23 +1,39 @@
env:
CIRRUS_CLONE_DEPTH: 1
freebsd_12_task:
# FreeBSD build with multiple versions
freebsd_versions_task:
name: FreeBSD $FREEBSD_VERSION make build
freebsd_instance:
image: freebsd-12-1-release-amd64
image_family: $FREEBSD_IMAGE
matrix:
- env:
FREEBSD_VERSION: "13.5"
FREEBSD_IMAGE: freebsd-13-5
- env:
FREEBSD_VERSION: "14.3"
FREEBSD_IMAGE: freebsd-14-3
install_script:
pkg install -y bison gmake pkgconf
- pkg install -y git gmake flex bison python3 py312-setuptools swig libyaml pkgconf
build_script:
gmake
test_script:
gmake check
- gmake
check_script:
- gmake check
linux_gcc_task:
container:
image: gcc:latest
# FreeBSD meson builds with multiple versions
freebsd_meson_versions_task:
name: FreeBSD $FREEBSD_VERSION meson build
freebsd_instance:
image_family: $FREEBSD_IMAGE
matrix:
- env:
FREEBSD_VERSION: "13.5"
FREEBSD_IMAGE: freebsd-13-5
- env:
FREEBSD_VERSION: "14.3"
FREEBSD_IMAGE: freebsd-14-3
install_script:
- apt-get update
- apt-get -y install bison flex
- pkg install -y git meson ninja flex bison python3 py312-setuptools swig libyaml pkgconf
setup_script:
- meson setup -D python=enabled -D yaml=enabled build
build_script:
- make
- meson compile -C build
test_script:
- make check
- if ! meson test -C build; then cat build/meson-logs/testlog.txt; false; fi

135
.clang-format Normal file
View file

@ -0,0 +1,135 @@
# SPDX-License-Identifier: GPL-2.0
#
# clang-format configuration file. Intended for clang-format >= 11.
#
# For more information, see:
#
# Documentation/dev-tools/clang-format.rst
# https://clang.llvm.org/docs/ClangFormat.html
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
#
---
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Left
AlignOperands: true
AlignTrailingComments: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: false
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: true
AfterNamespace: true
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
BreakBeforeInheritanceComma: false
BreakBeforeTernaryOperators: false
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeComma
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: false
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 8
ContinuationIndentWidth: 8
Cpp11BracedListStyle: false
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: false
# Taken from:
# git grep -h '^#define [^[:space:]]*for_each[^[:space:]]*(' \
# | sed "s,^#define \([^[:space:]]*for_each[^[:space:]]*\)(.*$, - '\1'," \
# | LC_ALL=C sort -u
ForEachMacros:
- 'fdt_for_each_property_offset'
- 'fdt_for_each_subnode'
- 'for_each_child'
- 'for_each_child_withdel'
- 'for_each_label'
- 'for_each_label_withdel'
- 'for_each_marker'
- 'for_each_marker_of_type'
- 'for_each_property'
- 'for_each_property_withdel'
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '.*'
Priority: 1
IncludeIsMainRegex: '(Test)?$'
IndentCaseLabels: false
IndentGotoLabels: false
IndentPPDirectives: None
IndentWidth: 8
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 8
ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: true
# Taken from git's rules
PenaltyBreakAssignment: 10
PenaltyBreakBeforeFirstCallParameter: 30
PenaltyBreakComment: 10
PenaltyBreakFirstLessLess: 0
PenaltyBreakString: 10
PenaltyExcessCharacter: 100
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
ReflowComments: false
SortIncludes: false
SortUsingDeclarations: false
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatementsExceptForEachMacros
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: false
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp03
TabWidth: 8
UseTab: Always
...

View file

@ -28,3 +28,6 @@ indent_size = 4
[meson.build]
indent_style = space
indent_size = 2
[*.lds]
indent_style = tab

114
.github/workflows/build.yml vendored Normal file
View file

@ -0,0 +1,114 @@
---
name: Build test
'on':
push:
branches:
- main
- ci
pull_request:
branches:
- main
# ensure that the workflow is only triggered once per PR, subsequent pushes to the PR will cancel
# and restart the workflow. See https://docs.github.com/en/actions/using-jobs/using-concurrency
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
build-make:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
os: [ "alpine", "archlinux", "fedora", "ubuntu" ]
container:
image: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Dependencies
run: |
./scripts/install-deps.sh
- name: Build
run: |
make
- name: Run check
run: |
make check
build-meson:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
os: [ "alpine", "archlinux", "fedora", "ubuntu" ]
container:
image: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Dependencies
run: |
./scripts/install-deps.sh
- name: Setup
run: meson setup -D python=enabled -D yaml=enabled build
- name: Build
run: meson compile -C build
- name: Run check
run: if ! meson test -C build; then cat build/meson-logs/testlog.txt; false; fi
build-windows:
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
include:
- { sys: mingw32 }
- { sys: mingw64 }
- { sys: ucrt64 }
- { sys: clang64 }
name: ${{ matrix.sys }}
defaults:
run:
shell: msys2 {0}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup MSYS2
uses: msys2/setup-msys2@v2
with:
msystem: ${{matrix.sys}}
update: true
install: >-
git
flex
bison
pacboy: >-
toolchain:p
meson:p
ninja:p
libyaml:p
swig:p
python-setuptools-scm:p
- name: '🚧 Build'
run: |
meson setup -Dtools=true -Dtests=false build
meson compile -C build

11
.gitignore vendored
View file

@ -3,11 +3,13 @@
*.a
*.patch
*.so
*.so.*
*~
*.bak
*.tab.[ch]
lex.yy.c
*.lex.c
.*.swp
/dtc
/fdtdump
/convert-dtsv0
@ -17,3 +19,12 @@ lex.yy.c
/fdtoverlay
/patches
/.pc
# cscope files
cscope.*
ncscope.*
.eggs/
build/
dist/
*.egg-info/

65
.gitlab-ci.yml Normal file
View file

@ -0,0 +1,65 @@
stages:
- build
variables:
GIT_DEPTH: 1
workflow:
rules:
- if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "main"
- if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "ci"
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
# Linux builds with make
.build-make-template: &build-make-template
stage: build
before_script:
- ./scripts/install-deps.sh
script:
- make
- make check
interruptible: true
build-make-alpine:
<<: *build-make-template
image: alpine:latest
build-make-archlinux:
<<: *build-make-template
image: archlinux:latest
build-make-fedora:
<<: *build-make-template
image: fedora:latest
build-make-ubuntu:
<<: *build-make-template
image: ubuntu:latest
# Linux builds with meson
.build-meson-template: &build-meson-template
stage: build
before_script:
- ./scripts/install-deps.sh
script:
- meson setup -D python=enabled -D yaml=enabled build
- meson compile -C build
- if ! meson test -C build; then cat build/meson-logs/testlog.txt; false; fi
interruptible: true
build-meson-alpine:
<<: *build-meson-template
image: alpine:latest
build-meson-archlinux:
<<: *build-meson-template
image: archlinux:latest
build-meson-fedora:
<<: *build-meson-template
image: fedora:latest
build-meson-ubuntu:
<<: *build-meson-template
image: ubuntu:latest

View file

@ -1,65 +0,0 @@
language: c
# Coverity Scan uploads
env:
global:
# COVERITY_SCAN_TOKEN (dgibson/dtc)
- secure: "vlHvXe618//IM9LQaKzqsrUbjs7ng0L9UCST4kJbJnFQDXvVe5JiSmJGd4ef7mm0NUv5bMRl2W3xCiu6BYAu/NvU3tMNHoLG+JgCJs0+wLJXbWOwji/NmH7olqgJG+CmpaCMXjARF6+nrTnBYHJL6cYyf4KVoV4B0I/hLUW91+s="
matrix:
include:
- addons:
apt:
packages:
- swig
- python-dev
- valgrind
- libyaml-0-2
coverity_scan:
project:
name: dtc
description: Device Tree Compiler
notification_email: david@gibson.dropbear.id.au
build_command: make
branch_pattern: coverity_scan
script:
- make
- make check && make checkm
# Check it builds properly without optional packages:
# python, valgrind, libyaml
- script:
- make
- make check
- arch: arm64
addons:
apt_packages:
- swig
- python-dev
- valgrind
- libyaml-0-2
script:
- make
- make check checkm
- arch: ppc64le
addons:
apt_packages:
- swig
- python-dev
- libyaml-0-2
script:
- make
- make check
- arch: s390x
addons:
apt_packages:
- swig
- python-dev
- valgrind
- libyaml-0-2
script:
- make
- make check checkm

79
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,79 @@
# Contributing to dtc or libfdt
There are two ways to submit changes for dtc or libfdt:
* Post patches directly to the
[devicetree-compiler](mailto:devicetree-compiler@vger.kernel.org)
mailing list.
* Submit pull requests via
[Github](https://github.com/dgibson/dtc/pulls)
## Adding a new function to libfdt.h
The shared library uses `libfdt/version.lds` to list the exported
functions, so add your new function there. Check that your function
works with pylibfdt. If it cannot be supported, put the declaration in
`libfdt.h` behind `#ifndef SWIG` so that swig ignores it.
## Tests
Test files are kept in the `tests/` directory. Use `make check` to build and run
all tests.
If you want to adjust a test file, be aware that `tree_tree1.dts` is compiled
and checked against a binary tree from assembler macros in `trees.S`. So
if you change that file you must change `tree.S` also.
## Developer's Certificate of Origin
Like many other projects, dtc and libfdt have adopted the "Developer's
Certificate of Origin" (Signed-off-by) process created by the Linux
kernel community to improve tracking of who did what. Here's how it
works (this is a very slight modification of the description from
`Documentation/process/submitting-patches.rst` in the kernel tree):
The sign-off is a simple line at the end of the explanation for the
patch, which certifies that you wrote it or otherwise have the right
to pass it on as an open-source patch. The rules are pretty simple:
if you can certify the below:
Developer's Certificate of Origin 1.1
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I
have the right to submit it under the open source license
indicated in the file; or
(b) The contribution is based upon previous work that, to the best
of my knowledge, is covered under an appropriate open source
license and I have the right under that license to submit that
work with modifications, whether created in whole or in part
by me, under the same open source license (unless I am
permitted to submit under a different license), as indicated
in the file; or
(c) The contribution was provided directly to me by some other
person who certified (a), (b) or (c) and I have not modified
it.
(d) I understand and agree that this project and the contribution
are public and that a record of the contribution (including all
personal information I submit with it, including my sign-off) is
maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved.
then you just add a line saying::
Signed-off-by: Random J Developer <random@developer.example.org>
using your real name (sorry, no pseudonyms or anonymous
contributions.) This will be done for you automatically if you use
`git commit -s`. Reverts should also include "Signed-off-by". `git
revert -s` does that for you.
Any further SoBs (Signed-off-by:'s) following the author's SoB are
from people handling and transporting the patch, but were not involved
in its development. SoB chains should reflect the **real** route a
patch took as it was propagated to the maintainers, with the first SoB
entry signalling primary authorship of a single author.

View file

@ -6,7 +6,7 @@ the hardware capabilities. This is insufficient for platforms
that need to dynamically insert Device Tree fragments into the
live tree.
This document explains the the Device Tree object format and
This document explains the Device Tree object format and
modifications made to the Device Tree compiler, which make it possible.
1. Simplified Problem Definition
@ -35,7 +35,7 @@ We have a number of peripherals that after probing (using some undefined method)
should result in different Device Tree configuration.
We cannot boot with this static tree because due to the configuration of the
foo platform there exist multiple conficting peripherals DT fragments.
foo platform there exist multiple conflicting peripherals DT fragments.
So for the bar peripheral we would have this:

View file

@ -43,9 +43,8 @@ The gitweb interface for the upstream repository is:
1.1) Submitting Patches
Patches should be sent to the maintainers:
Patches should be sent to the maintainer:
David Gibson <david@gibson.dropbear.id.au>
Jon Loeliger <jdl@jdl.com>
and CCed to <devicetree-compiler@vger.kernel.org>.
2) Description
@ -123,12 +122,24 @@ Options:
Relevant for dtb and asm output only.
-@
Generates a __symbols__ node at the root node of the resulting blob
for any node labels used, and for any local references using phandles
it also generates a __local_fixups__ node that tracks them.
Generates a __symbols__ node at the root node. This node contains a
property for each label. The property's name is the label name and the
value is the path of the labeled node.
When using the /plugin/ tag all unresolved label references to
be tracked in the __fixups__ node, making dynamic resolution possible.
-L
Possibly generates a __local_fixups__ and a __fixups__ node at the root node.
For each property that contains a phandle reference using a locally
defined phandle, the __local_fixups__ node contains a property (at path
/__local_fixups__/$a if $a is the path of the node). Its value is a list
of offsets that are phandle values. If there are no such properties, no
__local_fixups__ node is generated.
For each undefined label used in at least one reference, the __fixups__
node contains a property. Its name is the label name, its value is a
list of locations where the label is used in a reference in the format
"path:property:offset". If there is no undefined label, no __fixups__
nodes is generated.
Enabled by default for compiling overlays (i.e. dts files with a
/plugin/ tag).
-A
Generate automatically aliases for all node labels. This is similar to
@ -712,7 +723,7 @@ The syntax of the fdtget command is:
where options are:
<type> s=string, i=int, u=unsigned, x=hex
<type> s=string, i=int, u=unsigned, x=hex, r=raw
Optional modifier prefix:
hh or b=byte, h=2 byte, l=4 byte (default)

116
Makefile
View file

@ -3,16 +3,17 @@
# Device Tree Compiler
#
$(warning WARNING: Building dtc using make is deprecated, in favour of using Meson (https://mesonbuild.com))
$(warning )
$(warning Use `meson setup builddir/ && meson compile -C builddir/` to build, `meson test -C builddir/` to test, or `meson configure` to see build options.)
#
# Version information will be constructed in this order:
# EXTRAVERSION might be "-rc", for example.
# DTC_VERSION release version as MAJOR.MINOR.PATCH
# LOCAL_VERSION is likely from command line.
# CONFIG_LOCALVERSION from some future config system.
#
VERSION = 1
PATCHLEVEL = 6
SUBLEVEL = 0
EXTRAVERSION =
DTC_VERSION = $(shell cat VERSION.txt)
LOCAL_VERSION =
CONFIG_LOCALVERSION =
@ -21,17 +22,20 @@ CONFIG_LOCALVERSION =
ASSUME_MASK ?= 0
CPPFLAGS = -I libfdt -I . -DFDT_ASSUME_MASK=$(ASSUME_MASK)
WARNINGS = -Wall -Wpointer-arith -Wcast-qual -Wnested-externs \
-Wstrict-prototypes -Wmissing-prototypes -Wredundant-decls -Wshadow
WARNINGS = -Wall -Wpointer-arith -Wcast-qual -Wnested-externs -Wsign-compare \
-Wstrict-prototypes -Wmissing-prototypes -Wredundant-decls -Wshadow \
-Wwrite-strings
ifeq ($(shell $(CC) --version | grep -q gcc && echo gcc),gcc)
WARNINGS += -Wsuggest-attribute=format
endif
CFLAGS = -g -Os $(SHAREDLIB_CFLAGS) -Werror $(WARNINGS) $(EXTRA_CFLAGS)
BISON = bison
LEX = flex
SWIG = swig
PKG_CONFIG ?= pkg-config
PYTHON ?= python3
INSTALL = /usr/bin/install
INSTALL = install
INSTALL_PROGRAM = $(INSTALL)
INSTALL_LIB = $(INSTALL)
INSTALL_DATA = $(INSTALL) -m 644
@ -45,8 +49,6 @@ INCLUDEDIR = $(PREFIX)/include
HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \
sed -e 's/\(cygwin\|msys\).*/\1/')
NO_PYTHON ?= 0
NO_VALGRIND := $(shell $(PKG_CONFIG) --exists valgrind; echo $$?)
ifeq ($(NO_VALGRIND),1)
CPPFLAGS += -DNO_VALGRIND
@ -54,13 +56,20 @@ else
CFLAGS += $(shell $(PKG_CONFIG) --cflags valgrind)
endif
NO_YAML := $(shell $(PKG_CONFIG) --exists yaml-0.1; echo $$?)
# libyaml before version 0.2.3 expects non-const string parameters. Supporting
# both variants would require either cpp magic or passing
# -Wno-error=discarded-qualifiers to the compiler. For the sake of simplicity
# just support libyaml >= 0.2.3.
NO_YAML := $(shell $(PKG_CONFIG) --atleast-version 0.2.3 yaml-0.1; echo $$?)
ifeq ($(NO_YAML),1)
CFLAGS += -DNO_YAML
else
LDLIBS_dtc += $(shell $(PKG_CONFIG) --libs yaml-0.1)
CFLAGS += $(shell $(PKG_CONFIG) --cflags yaml-0.1)
endif
HAS_VERSION_SCRIPT := $(shell echo 'int main(){}' | $(CC) -Wl,--version-script=/dev/null -x c - -o /dev/null 2>/dev/null && echo y)
ifeq ($(HOSTOS),darwin)
SHAREDLIB_EXT = dylib
SHAREDLIB_CFLAGS = -fPIC
@ -68,11 +77,15 @@ SHAREDLIB_LDFLAGS = -fPIC -dynamiclib -Wl,-install_name -Wl,
else ifeq ($(HOSTOS),$(filter $(HOSTOS),msys cygwin))
SHAREDLIB_EXT = so
SHAREDLIB_CFLAGS =
SHAREDLIB_LDFLAGS = -shared -Wl,--version-script=$(LIBFDT_version) -Wl,-soname,
SHAREDLIB_LDFLAGS = -shared -Wl,-soname,
else
SHAREDLIB_EXT = so
SHAREDLIB_CFLAGS = -fPIC
SHAREDLIB_LDFLAGS = -fPIC -shared -Wl,--version-script=$(LIBFDT_version) -Wl,-soname,
SHAREDLIB_LDFLAGS = -fPIC -shared -Wl,-soname,
endif
ifeq ($(HAS_VERSION_SCRIPT),y)
SHAREDLIB_LDFLAGS += -Wl,--version-script=$(LIBFDT_version)
endif
#
@ -97,7 +110,6 @@ endif
# Rules for versioning
#
DTC_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
VERSION_FILE = version_gen.h
CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
@ -152,30 +164,8 @@ SCRIPTS = dtdiff
all: $(BIN) libfdt
# We need both Python and swig to build/install pylibfdt.
# This builds the given make ${target} if those deps are found.
check_python_deps = \
if $(PKG_CONFIG) --cflags $(PYTHON) >/dev/null 2>&1; then \
if which swig >/dev/null 2>&1; then \
can_build=yes; \
fi; \
fi; \
if [ "$${can_build}" = "yes" ]; then \
$(MAKE) $${target}; \
else \
echo "\#\# Skipping pylibfdt (install python dev and swig to build)"; \
fi ;
.PHONY: maybe_pylibfdt
maybe_pylibfdt: FORCE
target=pylibfdt; $(check_python_deps)
ifeq ($(NO_PYTHON),0)
all: maybe_pylibfdt
endif
ifneq ($(DEPTARGETS),)
ifneq ($(MAKECMDGOALS),libfdt)
-include $(DTC_OBJS:%.o=%.d)
-include $(CONVERT_OBJS:%.o=%.d)
-include $(FDTDUMP_OBJS:%.o=%.d)
@ -183,6 +173,7 @@ ifneq ($(DEPTARGETS),)
-include $(FDTPUT_OBJS:%.o=%.d)
-include $(FDTOVERLAY_OBJS:%.o=%.d)
endif
endif
@ -195,6 +186,13 @@ LIBFDT_lib = $(LIBFDT_dir)/$(LIBFDT_LIB)
LIBFDT_include = $(addprefix $(LIBFDT_dir)/,$(LIBFDT_INCLUDES))
LIBFDT_version = $(addprefix $(LIBFDT_dir)/,$(LIBFDT_VERSION))
ifeq ($(STATIC_BUILD),1)
CFLAGS += -static
LIBFDT_dep = $(LIBFDT_archive)
else
LIBFDT_dep = $(LIBFDT_lib)
endif
include $(LIBFDT_dir)/Makefile.libfdt
.PHONY: libfdt
@ -207,6 +205,7 @@ $(LIBFDT_lib): $(addprefix $(LIBFDT_dir)/,$(LIBFDT_OBJS)) $(LIBFDT_version)
$(CC) $(LDFLAGS) $(SHAREDLIB_LDFLAGS)$(LIBFDT_soname) -o $(LIBFDT_lib) \
$(addprefix $(LIBFDT_dir)/,$(LIBFDT_OBJS))
ln -sf $(LIBFDT_LIB) $(LIBFDT_dir)/$(LIBFDT_soname)
ln -sf $(LIBFDT_soname) $(LIBFDT_dir)/$(LIBFDT_so)
ifneq ($(DEPTARGETS),)
-include $(LIBFDT_OBJS:%.o=$(LIBFDT_dir)/%.d)
@ -223,7 +222,7 @@ install-bin: all $(SCRIPTS)
$(INSTALL_PROGRAM) $(BIN) $(DESTDIR)$(BINDIR)
$(INSTALL_SCRIPT) $(SCRIPTS) $(DESTDIR)$(BINDIR)
install-lib: all
install-lib: libfdt
@$(VECHO) INSTALL-LIB
$(INSTALL) -d $(DESTDIR)$(LIBDIR)
$(INSTALL_LIB) $(LIBFDT_lib) $(DESTDIR)$(LIBDIR)
@ -238,14 +237,6 @@ install-includes:
install: install-bin install-lib install-includes
.PHONY: maybe_install_pylibfdt
maybe_install_pylibfdt: FORCE
target=install_pylibfdt; $(check_python_deps)
ifeq ($(NO_PYTHON),0)
install: maybe_install_pylibfdt
endif
$(VERSION_FILE): Makefile FORCE
$(call filechk,version)
@ -258,11 +249,11 @@ convert-dtsv0: $(CONVERT_OBJS)
fdtdump: $(FDTDUMP_OBJS)
fdtget: $(FDTGET_OBJS) $(LIBFDT_lib)
fdtget: $(FDTGET_OBJS) $(LIBFDT_dep)
fdtput: $(FDTPUT_OBJS) $(LIBFDT_lib)
fdtput: $(FDTPUT_OBJS) $(LIBFDT_dep)
fdtoverlay: $(FDTOVERLAY_OBJS) $(LIBFDT_lib)
fdtoverlay: $(FDTOVERLAY_OBJS) $(LIBFDT_dep)
dist:
git archive --format=tar --prefix=dtc-$(dtc_version)/ HEAD \
@ -271,16 +262,6 @@ dist:
gzip -9 > ../dtc-$(dtc_version).tar.gz
#
# Rules for pylibfdt
#
PYLIBFDT_dir = pylibfdt
include $(PYLIBFDT_dir)/Makefile.pylibfdt
.PHONY: pylibfdt
pylibfdt: $(PYLIBFDT_dir)/_libfdt.so
#
# Release signing and uploading
# This is for maintainer convenience, don't try this at home.
@ -314,11 +295,10 @@ TESTS_BIN += fdtput
TESTS_BIN += fdtget
TESTS_BIN += fdtdump
TESTS_BIN += fdtoverlay
ifeq ($(NO_PYTHON),0)
TESTS_PYLIBFDT += maybe_pylibfdt
endif
ifneq ($(MAKECMDGOALS),libfdt)
include tests/Makefile.tests
endif
#
# Clean rules
@ -326,7 +306,7 @@ include tests/Makefile.tests
STD_CLEANFILES = *~ *.o *.$(SHAREDLIB_EXT) *.d *.a *.i *.s core a.out vgcore.* \
*.tab.[ch] *.lex.c *.output
clean: libfdt_clean pylibfdt_clean tests_clean
clean: libfdt_clean tests_clean
@$(VECHO) CLEAN
rm -f $(STD_CLEANFILES)
rm -f $(VERSION_FILE)
@ -346,7 +326,7 @@ clean: libfdt_clean pylibfdt_clean tests_clean
%.o: %.S
@$(VECHO) AS $@
$(CC) $(CPPFLAGS) $(AFLAGS) -D__ASSEMBLY__ -o $@ -c $<
$(CC) $(CPPFLAGS) $(AFLAGS) -o $@ -c $<
%.d: %.c
@$(VECHO) DEP $<
@ -372,8 +352,12 @@ clean: libfdt_clean pylibfdt_clean tests_clean
@$(VECHO) LEX $@
$(LEX) -o$@ $<
%.tab.c %.tab.h %.output: %.y
%.tab.c %.tab.h: %.y
@$(VECHO) BISON $@
$(BISON) -b $(basename $(basename $@)) -d $<
FORCE:
ifeq ($(MAKE_RESTARTS),10)
$(error "Make re-executed itself $(MAKE_RESTARTS) times. Infinite recursion?")
endif

91
README
View file

@ -1,91 +0,0 @@
The source tree contains the Device Tree Compiler (dtc) toolchain for
working with device tree source and binary files and also libfdt, a
utility library for reading and manipulating the binary format.
DTC and LIBFDT are maintained by:
David Gibson <david@gibson.dropbear.id.au>
Jon Loeliger <jdl@jdl.com>
Python library
--------------
A Python library is also available. To build this you will need to install
swig and Python development files. On Debian distributions:
sudo apt-get install swig python3-dev
The library provides an Fdt class which you can use like this:
$ PYTHONPATH=../pylibfdt python3
>>> import libfdt
>>> fdt = libfdt.Fdt(open('test_tree1.dtb', mode='rb').read())
>>> node = fdt.path_offset('/subnode@1')
>>> print(node)
124
>>> prop_offset = fdt.first_property_offset(node)
>>> prop = fdt.get_property_by_offset(prop_offset)
>>> print('%s=%s' % (prop.name, prop.as_str()))
compatible=subnode1
>>> node2 = fdt.path_offset('/')
>>> print(fdt.getprop(node2, 'compatible').as_str())
test_tree1
You will find tests in tests/pylibfdt_tests.py showing how to use each
method. Help is available using the Python help command, e.g.:
$ cd pylibfdt
$ python3 -c "import libfdt; help(libfdt)"
If you add new features, please check code coverage:
$ sudo apt-get install python3-coverage
$ cd tests
# It's just 'coverage' on most other distributions
$ python3-coverage run pylibfdt_tests.py
$ python3-coverage html
# Open 'htmlcov/index.html' in your browser
To install the library via the normal setup.py method, use:
./pylibfdt/setup.py install [--prefix=/path/to/install_dir]
If --prefix is not provided, the default prefix is used, typically '/usr'
or '/usr/local'. See Python's distutils documentation for details. You can
also install via the Makefile if you like, but the above is more common.
To install both libfdt and pylibfdt you can use:
make install [SETUP_PREFIX=/path/to/install_dir] \
[PREFIX=/path/to/install_dir]
To disable building the python library, even if swig and Python are available,
use:
make NO_PYTHON=1
More work remains to support all of libfdt, including access to numeric
values.
Tests
-----
Test files are kept in the tests/ directory. Use 'make check' to build and run
all tests.
If you want to adjust a test file, be aware that tree_tree1.dts is compiled
and checked against a binary tree from assembler macros in trees.S. So
if you change that file you must change tree.S also.
Mailing list
------------
The following list is for discussion about dtc and libfdt implementation
mailto:devicetree-compiler@vger.kernel.org
Core device tree bindings are discussed on the devicetree-spec list:
mailto:devicetree-spec@vger.kernel.org

View file

@ -28,7 +28,7 @@ tools. Allowing libfdt to be used under the terms of the BSD license
makes that it easier for vendors or authors of such software to do so.
This does mean that libfdt code could be "stolen" - say, included in a
proprietary fimware and extended without contributing those extensions
proprietary firmware and extended without contributing those extensions
back to the libfdt mainline. While I hope that doesn't happen, I
believe the goal of allowing libfdt to be widely used is more
important than avoiding that. libfdt is quite small, and hardly

100
README.md Normal file
View file

@ -0,0 +1,100 @@
# Device Tree Compiler and libfdt
The source tree contains the Device Tree Compiler (dtc) toolchain for
working with device tree source and binary files and also libfdt, a
utility library for reading and manipulating the binary format.
dtc and libfdt are maintained by:
* [David Gibson `<david@gibson.dropbear.id.au>`](mailto:david@gibson.dropbear.id.au)
## Python library
A Python library wrapping libfdt is also available. To build this you
will need to install `swig` and Python development files. On Debian
distributions:
```
$ sudo apt-get install swig python3-dev
```
The library provides an `Fdt` class which you can use like this:
```
$ PYTHONPATH=../pylibfdt python3
>>> import libfdt
>>> fdt = libfdt.Fdt(open('test_tree1.dtb', mode='rb').read())
>>> node = fdt.path_offset('/subnode@1')
>>> print(node)
124
>>> prop_offset = fdt.first_property_offset(node)
>>> prop = fdt.get_property_by_offset(prop_offset)
>>> print('%s=%s' % (prop.name, prop.as_str()))
compatible=subnode1
>>> node2 = fdt.path_offset('/')
>>> print(fdt.getprop(node2, 'compatible').as_str())
test_tree1
```
You will find tests in `tests/pylibfdt_tests.py` showing how to use each
method. Help is available using the Python help command, e.g.:
```
$ cd pylibfdt
$ python3 -c "import libfdt; help(libfdt)"
```
If you add new features, please check code coverage:
```
$ sudo apt-get install python3-coverage
$ cd tests
# It's just 'coverage' on most other distributions
$ python3-coverage run pylibfdt_tests.py
$ python3-coverage html
# Open 'htmlcov/index.html' in your browser
```
The library can be installed with pip from a local source tree:
```
$ pip install . [--user|--prefix=/path/to/install_dir]
```
Or directly from a remote git repo:
```
$ pip install git+git://git.kernel.org/pub/scm/utils/dtc/dtc.git@main
```
The install depends on libfdt shared library being installed on the
host system first. Generally, using `--user` or `--prefix` is not
necessary and pip will use the default location for the Python
installation which varies if the user is root or not.
You can also install everything via make if you like, but pip is
recommended.
To install both libfdt and pylibfdt you can use:
```
$ make install [PREFIX=/path/to/install_dir]
```
To disable building the python library, even if swig and Python are available,
use:
```
$ make NO_PYTHON=1
```
More work remains to support all of libfdt, including access to numeric
values.
## Mailing lists
* The [devicetree-compiler](mailto:devicetree-compiler@vger.kernel.org)
list is for discussion about dtc and libfdt implementation.
* Core device tree bindings are discussed on the
[devicetree-spec](mailto:devicetree-spec@vger.kernel.org) list.

1
VERSION.txt Normal file
View file

@ -0,0 +1 @@
1.7.2

366
checks.c
View file

@ -31,7 +31,7 @@ typedef void (*check_fn)(struct check *c, struct dt_info *dti, struct node *node
struct check {
const char *name;
check_fn fn;
void *data;
const void *data;
bool warn, error;
enum checkstatus status;
bool inprogress;
@ -114,6 +114,7 @@ static inline void PRINTF(5, 6) check_msg(struct check *c, struct dt_info *dti,
}
fputs(str, stderr);
free(str);
}
#define FAIL(c, dti, node, ...) \
@ -143,6 +144,14 @@ static void check_nodes_props(struct check *c, struct dt_info *dti, struct node
check_nodes_props(c, dti, child);
}
static bool is_multiple_of(int multiple, int divisor)
{
if (divisor == 0)
return multiple == 0;
else
return (multiple % divisor) == 0;
}
static bool run_check(struct check *c, struct dt_info *dti)
{
struct node *dt = dti->dt;
@ -199,7 +208,7 @@ static void check_is_string(struct check *c, struct dt_info *dti,
struct node *node)
{
struct property *prop;
char *propname = c->data;
const char *propname = c->data;
prop = get_property(node, propname);
if (!prop)
@ -218,7 +227,7 @@ static void check_is_string_list(struct check *c, struct dt_info *dti,
{
int rem, l;
struct property *prop;
char *propname = c->data;
const char *propname = c->data;
char *str;
prop = get_property(node, propname);
@ -246,7 +255,7 @@ static void check_is_cell(struct check *c, struct dt_info *dti,
struct node *node)
{
struct property *prop;
char *propname = c->data;
const char *propname = c->data;
prop = get_property(node, propname);
if (!prop)
@ -297,19 +306,20 @@ ERROR(duplicate_property_names, check_duplicate_property_names, NULL);
#define LOWERCASE "abcdefghijklmnopqrstuvwxyz"
#define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
#define DIGITS "0123456789"
#define PROPNODECHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-"
#define NODECHARS LOWERCASE UPPERCASE DIGITS ",._+-@"
#define PROPCHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-"
#define PROPNODECHARSSTRICT LOWERCASE UPPERCASE DIGITS ",-"
static void check_node_name_chars(struct check *c, struct dt_info *dti,
struct node *node)
{
int n = strspn(node->name, c->data);
size_t n = strspn(node->name, c->data);
if (n < strlen(node->name))
FAIL(c, dti, node, "Bad character '%c' in node name",
node->name[n]);
}
ERROR(node_name_chars, check_node_name_chars, PROPNODECHARS "@");
ERROR(node_name_chars, check_node_name_chars, NODECHARS);
static void check_node_name_chars_strict(struct check *c, struct dt_info *dti,
struct node *node)
@ -330,6 +340,20 @@ static void check_node_name_format(struct check *c, struct dt_info *dti,
}
ERROR(node_name_format, check_node_name_format, NULL, &node_name_chars);
static void check_node_name_vs_property_name(struct check *c,
struct dt_info *dti,
struct node *node)
{
if (!node->parent)
return;
if (get_property(node->parent, node->name)) {
FAIL(c, dti, node, "node name and property name conflict");
}
}
WARNING(node_name_vs_property_name, check_node_name_vs_property_name,
NULL, &node_name_chars);
static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti,
struct node *node)
{
@ -352,7 +376,7 @@ static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti,
FAIL(c, dti, node, "node has a reg or ranges property, but no unit name");
} else {
if (unitname[0])
FAIL(c, dti, node, "node has a unit name, but no reg property");
FAIL(c, dti, node, "node has a unit name, but no reg or ranges property");
}
}
WARNING(unit_address_vs_reg, check_unit_address_vs_reg, NULL);
@ -363,14 +387,14 @@ static void check_property_name_chars(struct check *c, struct dt_info *dti,
struct property *prop;
for_each_property(node, prop) {
int n = strspn(prop->name, c->data);
size_t n = strspn(prop->name, c->data);
if (n < strlen(prop->name))
FAIL_PROP(c, dti, node, prop, "Bad character '%c' in property name",
prop->name[n]);
}
}
ERROR(property_name_chars, check_property_name_chars, PROPNODECHARS);
ERROR(property_name_chars, check_property_name_chars, PROPCHARS);
static void check_property_name_chars_strict(struct check *c,
struct dt_info *dti,
@ -380,7 +404,7 @@ static void check_property_name_chars_strict(struct check *c,
for_each_property(node, prop) {
const char *name = prop->name;
int n = strspn(name, c->data);
size_t n = strspn(name, c->data);
if (n == strlen(prop->name))
continue;
@ -497,7 +521,7 @@ static cell_t check_phandle_prop(struct check *c, struct dt_info *dti,
phandle = propval_cell(prop);
if ((phandle == 0) || (phandle == -1)) {
if (!phandle_is_valid(phandle)) {
FAIL_PROP(c, dti, node, prop, "bad value (0x%x) in %s property",
phandle, prop->name);
return 0;
@ -556,7 +580,7 @@ static void check_name_properties(struct check *c, struct dt_info *dti,
if (!prop)
return; /* No name property, that's fine */
if ((prop->val.len != node->basenamelen+1)
if ((prop->val.len != node->basenamelen + 1U)
|| (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) {
FAIL(c, dti, node, "\"name\" property is incorrect (\"%s\" instead"
" of base node name)", prop->val.val);
@ -657,7 +681,6 @@ ERROR(omit_unused_nodes, fixup_omit_unused_nodes, NULL, &phandle_references, &pa
*/
WARNING_IF_NOT_CELL(address_cells_is_cell, "#address-cells");
WARNING_IF_NOT_CELL(size_cells_is_cell, "#size-cells");
WARNING_IF_NOT_CELL(interrupt_cells_is_cell, "#interrupt-cells");
WARNING_IF_NOT_STRING(device_type_is_string, "device_type");
WARNING_IF_NOT_STRING(model_is_string, "model");
@ -672,8 +695,7 @@ static void check_names_is_string_list(struct check *c, struct dt_info *dti,
struct property *prop;
for_each_property(node, prop) {
const char *s = strrchr(prop->name, '-');
if (!s || !streq(s, "-names"))
if (!strends(prop->name, "-names"))
continue;
c->data = prop->name;
@ -696,11 +718,14 @@ static void check_alias_paths(struct check *c, struct dt_info *dti,
continue;
}
if (!prop->val.val || !get_node_by_path(dti->dt, prop->val.val)) {
/* This check does not work for overlays with external paths */
if (!(dti->dtsflags & DTSF_PLUGIN) &&
(!prop->val.val || !get_node_by_path(dti->dt, prop->val.val))) {
FAIL_PROP(c, dti, node, prop, "aliases property is not a valid node (%s)",
prop->val.val);
continue;
}
if (strspn(prop->name, LOWERCASE DIGITS "-") != strlen(prop->name))
FAIL(c, dti, node, "aliases property name must include only lowercase and '-'");
}
@ -753,7 +778,7 @@ static void check_reg_format(struct check *c, struct dt_info *dti,
size_cells = node_size_cells(node->parent);
entrylen = (addr_cells + size_cells) * sizeof(cell_t);
if (!entrylen || (prop->val.len % entrylen) != 0)
if (!is_multiple_of(prop->val.len, entrylen))
FAIL_PROP(c, dti, node, prop, "property has invalid length (%d bytes) "
"(#address-cells == %d, #size-cells == %d)",
prop->val.len, addr_cells, size_cells);
@ -794,7 +819,7 @@ static void check_ranges_format(struct check *c, struct dt_info *dti,
"#size-cells (%d) differs from %s (%d)",
ranges, c_size_cells, node->parent->fullpath,
p_size_cells);
} else if ((prop->val.len % entrylen) != 0) {
} else if (!is_multiple_of(prop->val.len, entrylen)) {
FAIL_PROP(c, dti, node, prop, "\"%s\" property has invalid length (%d bytes) "
"(parent #address-cells == %d, child #address-cells == %d, "
"#size-cells == %d)", ranges, prop->val.len,
@ -871,7 +896,7 @@ static void check_pci_device_bus_num(struct check *c, struct dt_info *dti, struc
} else {
cells = (cell_t *)prop->val.val;
min_bus = fdt32_to_cpu(cells[0]);
max_bus = fdt32_to_cpu(cells[0]);
max_bus = fdt32_to_cpu(cells[1]);
}
if ((bus_num < min_bus) || (bus_num > max_bus))
FAIL_PROP(c, dti, node, prop, "PCI bus number %d out of range, expected (%d - %d)",
@ -891,10 +916,8 @@ static void check_pci_device_reg(struct check *c, struct dt_info *dti, struct no
return;
prop = get_property(node, "reg");
if (!prop) {
FAIL(c, dti, node, "missing PCI reg property");
if (!prop)
return;
}
cells = (cell_t *)prop->val.val;
if (cells[1] || cells[2])
@ -1004,7 +1027,7 @@ static void check_i2c_bus_bridge(struct check *c, struct dt_info *dti, struct no
} else if (strprefixeq(node->name, node->basenamelen, "i2c")) {
struct node *child;
for_each_child(node, child) {
if (strprefixeq(child->name, node->basenamelen, "i2c-bus"))
if (strprefixeq(child->name, child->basenamelen, "i2c-bus"))
return;
}
node->bus = &i2c_bus;
@ -1022,6 +1045,9 @@ static void check_i2c_bus_bridge(struct check *c, struct dt_info *dti, struct no
}
WARNING(i2c_bus_bridge, check_i2c_bus_bridge, NULL, &addr_size_cells);
#define I2C_OWN_SLAVE_ADDRESS (1U << 30)
#define I2C_TEN_BIT_ADDRESS (1U << 31)
static void check_i2c_bus_reg(struct check *c, struct dt_info *dti, struct node *node)
{
struct property *prop;
@ -1044,6 +1070,8 @@ static void check_i2c_bus_reg(struct check *c, struct dt_info *dti, struct node
}
reg = fdt32_to_cpu(*cells);
/* Ignore I2C_OWN_SLAVE_ADDRESS */
reg &= ~I2C_OWN_SLAVE_ADDRESS;
snprintf(unit_addr, sizeof(unit_addr), "%x", reg);
if (!streq(unitname, unit_addr))
FAIL(c, dti, node, "I2C bus unit address format error, expected \"%s\"",
@ -1051,10 +1079,16 @@ static void check_i2c_bus_reg(struct check *c, struct dt_info *dti, struct node
for (len = prop->val.len; len > 0; len -= 4) {
reg = fdt32_to_cpu(*(cells++));
if (reg > 0x3ff)
FAIL_PROP(c, dti, node, prop, "I2C address must be less than 10-bits, got \"0x%x\"",
reg);
/* Ignore I2C_OWN_SLAVE_ADDRESS */
reg &= ~I2C_OWN_SLAVE_ADDRESS;
if (reg & I2C_TEN_BIT_ADDRESS) {
if ((reg & ~I2C_TEN_BIT_ADDRESS) > 0x3ff)
FAIL_PROP(c, dti, node, prop, "I2C address must be less than 10-bits, got \"0x%x\"",
reg);
} else if (reg > 0x7f)
FAIL_PROP(c, dti, node, prop, "I2C address must be less than 7-bits, got \"0x%x\". Set I2C_TEN_BIT_ADDRESS for 10 bit addresses or fix the property",
reg);
}
}
WARNING(i2c_bus_reg, check_i2c_bus_reg, NULL, &reg_format, &i2c_bus_bridge);
@ -1079,7 +1113,7 @@ static void check_spi_bus_bridge(struct check *c, struct dt_info *dti, struct no
for_each_child(node, child) {
struct property *prop;
for_each_property(child, prop) {
if (strprefixeq(prop->name, 4, "spi-")) {
if (strstarts(prop->name, "spi-")) {
node->bus = &spi_bus;
break;
}
@ -1151,7 +1185,7 @@ static void check_unit_address_format(struct check *c, struct dt_info *dti,
/* skip over 0x for next test */
unitname += 2;
}
if (unitname[0] == '0' && isxdigit(unitname[1]))
if (unitname[0] == '0' && isxdigit((unsigned char)unitname[1]))
FAIL(c, dti, node, "unit name should not have leading 0s");
}
WARNING(unit_address_format, check_unit_address_format, NULL,
@ -1186,24 +1220,27 @@ WARNING(avoid_default_addr_size, check_avoid_default_addr_size, NULL,
static void check_avoid_unnecessary_addr_size(struct check *c, struct dt_info *dti,
struct node *node)
{
struct property *prop;
struct node *child;
bool has_reg = false;
if (!node->parent || node->addr_cells < 0 || node->size_cells < 0)
return;
if (get_property(node, "ranges") || !node->children)
if (get_property(node, "ranges") || get_property(node, "dma-ranges") || !node->children)
return;
for_each_child(node, child) {
prop = get_property(child, "reg");
if (prop)
has_reg = true;
/*
* Even if the child devices' address space is not mapped into
* the parent bus (no 'ranges' property on node), children can
* still have registers on a local bus, or map local addresses
* to another subordinate address space. The properties on the
* child nodes then make #address-cells/#size-cells necessary:
*/
if (get_property(child, "reg") || get_property(child, "ranges"))
return;
}
if (!has_reg)
FAIL(c, dti, node, "unnecessary #address-cells/#size-cells without \"ranges\" or child \"reg\" property");
FAIL(c, dti, node, "unnecessary #address-cells/#size-cells without \"ranges\", \"dma-ranges\" or child \"reg\" or \"ranges\" property");
}
WARNING(avoid_unnecessary_addr_size, check_avoid_unnecessary_addr_size, NULL, &avoid_default_addr_size);
@ -1353,15 +1390,15 @@ struct provider {
};
static void check_property_phandle_args(struct check *c,
struct dt_info *dti,
struct node *node,
struct property *prop,
const struct provider *provider)
struct dt_info *dti,
struct node *node,
struct property *prop,
const struct provider *provider)
{
struct node *root = dti->dt;
int cell, cellsize = 0;
unsigned int cell, cellsize = 0;
if (prop->val.len % sizeof(cell_t)) {
if (!is_multiple_of(prop->val.len, sizeof(cell_t))) {
FAIL_PROP(c, dti, node, prop,
"property size (%d) is invalid, expected multiple of %zu",
prop->val.len, sizeof(cell_t));
@ -1371,14 +1408,15 @@ static void check_property_phandle_args(struct check *c,
for (cell = 0; cell < prop->val.len / sizeof(cell_t); cell += cellsize + 1) {
struct node *provider_node;
struct property *cellprop;
int phandle;
cell_t phandle;
unsigned int expected;
phandle = propval_cell_n(prop, cell);
/*
* Some bindings use a cell value 0 or -1 to skip over optional
* entries when each index position has a specific definition.
*/
if (phandle == 0 || phandle == -1) {
if (!phandle_is_valid(phandle)) {
/* Give up if this is an overlay with external references */
if (dti->dtsflags & DTSF_PLUGIN)
break;
@ -1421,10 +1459,12 @@ static void check_property_phandle_args(struct check *c,
break;
}
if (prop->val.len < ((cell + cellsize + 1) * sizeof(cell_t))) {
expected = (cell + cellsize + 1) * sizeof(cell_t);
if ((expected <= cell) || prop->val.len < expected) {
FAIL_PROP(c, dti, node, prop,
"property size (%d) too small for cell size %d",
"property size (%d) too small for cell size %u",
prop->val.len, cellsize);
break;
}
}
}
@ -1433,7 +1473,7 @@ static void check_provider_cells_property(struct check *c,
struct dt_info *dti,
struct node *node)
{
struct provider *provider = c->data;
const struct provider *provider = c->data;
struct property *prop;
prop = get_property(node, provider->prop_name);
@ -1444,7 +1484,8 @@ static void check_provider_cells_property(struct check *c,
}
#define WARNING_PROPERTY_PHANDLE_CELLS(nm, propname, cells_name, ...) \
static struct provider nm##_provider = { (propname), (cells_name), __VA_ARGS__ }; \
WARNING(nm##_property, check_provider_cells_property, &nm##_provider, &phandle_references);
WARNING_IF_NOT_CELL(nm##_is_cell, cells_name); \
WARNING(nm##_property, check_provider_cells_property, &nm##_provider, &nm##_is_cell, &phandle_references);
WARNING_PROPERTY_PHANDLE_CELLS(clocks, "clocks", "#clock-cells");
WARNING_PROPERTY_PHANDLE_CELLS(cooling_device, "cooling-device", "#cooling-cells");
@ -1465,24 +1506,17 @@ WARNING_PROPERTY_PHANDLE_CELLS(thermal_sensors, "thermal-sensors", "#thermal-sen
static bool prop_is_gpio(struct property *prop)
{
char *str;
/*
* *-gpios and *-gpio can appear in property names,
* so skip over any false matches (only one known ATM)
*/
if (strstr(prop->name, "nr-gpio"))
if (strends(prop->name, ",nr-gpios"))
return false;
str = strrchr(prop->name, '-');
if (str)
str++;
else
str = prop->name;
if (!(streq(str, "gpios") || streq(str, "gpio")))
return false;
return true;
return strends(prop->name, "-gpios") ||
streq(prop->name, "gpios") ||
strends(prop->name, "-gpio") ||
streq(prop->name, "gpio");
}
static void check_gpios_property(struct check *c,
@ -1517,13 +1551,10 @@ static void check_deprecated_gpio_property(struct check *c,
struct property *prop;
for_each_property(node, prop) {
char *str;
if (!prop_is_gpio(prop))
continue;
str = strstr(prop->name, "gpio");
if (!streq(str, "gpio"))
if (!strends(prop->name, "gpio"))
continue;
FAIL_PROP(c, dti, node, prop,
@ -1547,6 +1578,121 @@ static bool node_is_interrupt_provider(struct node *node)
return false;
}
static void check_interrupt_provider(struct check *c,
struct dt_info *dti,
struct node *node)
{
struct property *prop;
bool irq_provider = node_is_interrupt_provider(node);
prop = get_property(node, "#interrupt-cells");
if (irq_provider && !prop) {
FAIL(c, dti, node,
"Missing '#interrupt-cells' in interrupt provider");
return;
}
if (!irq_provider && prop) {
FAIL(c, dti, node,
"'#interrupt-cells' found, but node is not an interrupt provider");
return;
}
}
WARNING(interrupt_provider, check_interrupt_provider, NULL, &interrupts_extended_is_cell);
static void check_interrupt_map(struct check *c,
struct dt_info *dti,
struct node *node)
{
struct node *root = dti->dt;
struct property *prop, *irq_map_prop;
size_t cellsize, cell, map_cells;
irq_map_prop = get_property(node, "interrupt-map");
if (!irq_map_prop)
return;
if (node->addr_cells < 0) {
FAIL(c, dti, node,
"Missing '#address-cells' in interrupt-map provider");
return;
}
cellsize = node_addr_cells(node);
cellsize += propval_cell(get_property(node, "#interrupt-cells"));
prop = get_property(node, "interrupt-map-mask");
if (prop && (prop->val.len != (cellsize * sizeof(cell_t))))
FAIL_PROP(c, dti, node, prop,
"property size (%d) is invalid, expected %zu",
prop->val.len, cellsize * sizeof(cell_t));
if (!is_multiple_of(irq_map_prop->val.len, sizeof(cell_t))) {
FAIL_PROP(c, dti, node, irq_map_prop,
"property size (%d) is invalid, expected multiple of %zu",
irq_map_prop->val.len, sizeof(cell_t));
return;
}
map_cells = irq_map_prop->val.len / sizeof(cell_t);
for (cell = 0; cell < map_cells; ) {
struct node *provider_node;
struct property *cellprop;
int phandle;
size_t parent_cellsize;
if ((cell + cellsize) >= map_cells) {
FAIL_PROP(c, dti, node, irq_map_prop,
"property size (%d) too small, expected > %zu",
irq_map_prop->val.len, (cell + cellsize) * sizeof(cell_t));
break;
}
cell += cellsize;
phandle = propval_cell_n(irq_map_prop, cell);
if (!phandle_is_valid(phandle)) {
/* Give up if this is an overlay with external references */
if (!(dti->dtsflags & DTSF_PLUGIN))
FAIL_PROP(c, dti, node, irq_map_prop,
"Cell %zu is not a phandle(%d)",
cell, phandle);
break;
}
provider_node = get_node_by_phandle(root, phandle);
if (!provider_node) {
FAIL_PROP(c, dti, node, irq_map_prop,
"Could not get phandle(%d) node for (cell %zu)",
phandle, cell);
break;
}
cellprop = get_property(provider_node, "#interrupt-cells");
if (cellprop) {
parent_cellsize = propval_cell(cellprop);
} else {
FAIL(c, dti, node, "Missing property '#interrupt-cells' in node %s or bad phandle (referred from interrupt-map[%zu])",
provider_node->fullpath, cell);
break;
}
cellprop = get_property(provider_node, "#address-cells");
if (cellprop)
parent_cellsize += propval_cell(cellprop);
else
FAIL_PROP(c, dti, node, irq_map_prop,
"Missing property '#address-cells' in node %s, using 0 as fallback",
provider_node->fullpath);
cell += 1 + parent_cellsize;
if (cell > map_cells)
FAIL_PROP(c, dti, node, irq_map_prop,
"property size (%d) mismatch, expected %zu",
irq_map_prop->val.len, cell * sizeof(cell_t));
}
}
WARNING(interrupt_map, check_interrupt_map, NULL, &phandle_references, &addr_size_cells, &interrupt_provider);
static void check_interrupts_property(struct check *c,
struct dt_info *dti,
struct node *node)
@ -1554,13 +1700,13 @@ static void check_interrupts_property(struct check *c,
struct node *root = dti->dt;
struct node *irq_node = NULL, *parent = node;
struct property *irq_prop, *prop = NULL;
int irq_cells, phandle;
cell_t irq_cells, phandle;
irq_prop = get_property(node, "interrupts");
if (!irq_prop)
return;
if (irq_prop->val.len % sizeof(cell_t))
if (!is_multiple_of(irq_prop->val.len, sizeof(cell_t)))
FAIL_PROP(c, dti, node, irq_prop, "size (%d) is invalid, expected multiple of %zu",
irq_prop->val.len, sizeof(cell_t));
@ -1573,7 +1719,7 @@ static void check_interrupts_property(struct check *c,
prop = get_property(parent, "interrupt-parent");
if (prop) {
phandle = propval_cell(prop);
if ((phandle == 0) || (phandle == -1)) {
if (!phandle_is_valid(phandle)) {
/* Give up if this is an overlay with
* external references */
if (dti->dtsflags & DTSF_PLUGIN)
@ -1604,12 +1750,12 @@ static void check_interrupts_property(struct check *c,
prop = get_property(irq_node, "#interrupt-cells");
if (!prop) {
FAIL(c, dti, irq_node, "Missing #interrupt-cells in interrupt-parent");
/* We warn about that already in another test. */
return;
}
irq_cells = propval_cell(prop);
if (irq_prop->val.len % (irq_cells * sizeof(cell_t))) {
if (!is_multiple_of(irq_prop->val.len, irq_cells * sizeof(cell_t))) {
FAIL_PROP(c, dti, node, prop,
"size is (%d), expected multiple of %d",
irq_prop->val.len, (int)(irq_cells * sizeof(cell_t)));
@ -1635,6 +1781,11 @@ static void check_graph_nodes(struct check *c, struct dt_info *dti,
get_property(child, "remote-endpoint")))
continue;
/* The root node cannot be a port */
if (!node->parent) {
FAIL(c, dti, node, "root node contains endpoint node '%s', potentially misplaced remote-endpoint property", child->name);
continue;
}
node->bus = &graph_port_bus;
/* The parent of 'port' nodes can be either 'ports' or a device */
@ -1648,31 +1799,6 @@ static void check_graph_nodes(struct check *c, struct dt_info *dti,
}
WARNING(graph_nodes, check_graph_nodes, NULL);
static void check_graph_child_address(struct check *c, struct dt_info *dti,
struct node *node)
{
int cnt = 0;
struct node *child;
if (node->bus != &graph_ports_bus && node->bus != &graph_port_bus)
return;
for_each_child(node, child) {
struct property *prop = get_property(child, "reg");
/* No error if we have any non-zero unit address */
if (prop && propval_cell(prop) != 0)
return;
cnt++;
}
if (cnt == 1 && node->addr_cells != -1)
FAIL(c, dti, node, "graph node has single child node '%s', #address-cells/#size-cells are not necessary",
node->children->name);
}
WARNING(graph_child_address, check_graph_child_address, NULL, &graph_nodes);
static void check_graph_reg(struct check *c, struct dt_info *dti,
struct node *node)
{
@ -1710,17 +1836,21 @@ static void check_graph_port(struct check *c, struct dt_info *dti,
if (node->bus != &graph_port_bus)
return;
check_graph_reg(c, dti, node);
/* skip checks below for overlays */
if (dti->dtsflags & DTSF_PLUGIN)
return;
if (!strprefixeq(node->name, node->basenamelen, "port"))
FAIL(c, dti, node, "graph port node name should be 'port'");
check_graph_reg(c, dti, node);
}
WARNING(graph_port, check_graph_port, NULL, &graph_nodes);
static struct node *get_remote_endpoint(struct check *c, struct dt_info *dti,
struct node *endpoint)
{
int phandle;
cell_t phandle;
struct node *node;
struct property *prop;
@ -1730,7 +1860,7 @@ static struct node *get_remote_endpoint(struct check *c, struct dt_info *dti,
phandle = propval_cell(prop);
/* Give up if this is an overlay with external references */
if (phandle == 0 || phandle == -1)
if (!phandle_is_valid(phandle))
return NULL;
node = get_node_by_phandle(dti->dt, phandle);
@ -1748,11 +1878,15 @@ static void check_graph_endpoint(struct check *c, struct dt_info *dti,
if (!node->parent || node->parent->bus != &graph_port_bus)
return;
check_graph_reg(c, dti, node);
/* skip checks below for overlays */
if (dti->dtsflags & DTSF_PLUGIN)
return;
if (!strprefixeq(node->name, node->basenamelen, "endpoint"))
FAIL(c, dti, node, "graph endpoint node name should be 'endpoint'");
check_graph_reg(c, dti, node);
remote_node = get_remote_endpoint(c, dti, node);
if (!remote_node)
return;
@ -1766,7 +1900,7 @@ WARNING(graph_endpoint, check_graph_endpoint, NULL, &graph_nodes);
static struct check *check_table[] = {
&duplicate_node_names, &duplicate_property_names,
&node_name_chars, &node_name_format, &property_name_chars,
&name_is_string, &name_properties,
&name_is_string, &name_properties, &node_name_vs_property_name,
&duplicate_label,
@ -1774,7 +1908,7 @@ static struct check *check_table[] = {
&phandle_references, &path_references,
&omit_unused_nodes,
&address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell,
&address_cells_is_cell, &size_cells_is_cell,
&device_type_is_string, &model_is_string, &status_is_string,
&label_is_string,
@ -1809,29 +1943,47 @@ static struct check *check_table[] = {
&chosen_node_is_root, &chosen_node_bootargs, &chosen_node_stdout_path,
&clocks_property,
&clocks_is_cell,
&cooling_device_property,
&cooling_device_is_cell,
&dmas_property,
&dmas_is_cell,
&hwlocks_property,
&hwlocks_is_cell,
&interrupts_extended_property,
&interrupts_extended_is_cell,
&io_channels_property,
&io_channels_is_cell,
&iommus_property,
&iommus_is_cell,
&mboxes_property,
&mboxes_is_cell,
&msi_parent_property,
&msi_parent_is_cell,
&mux_controls_property,
&mux_controls_is_cell,
&phys_property,
&phys_is_cell,
&power_domains_property,
&power_domains_is_cell,
&pwms_property,
&pwms_is_cell,
&resets_property,
&resets_is_cell,
&sound_dai_property,
&sound_dai_is_cell,
&thermal_sensors_property,
&thermal_sensors_is_cell,
&deprecated_gpio_property,
&gpios_property,
&interrupts_property,
&interrupt_provider,
&interrupt_map,
&alias_paths,
&graph_nodes, &graph_child_address, &graph_port, &graph_endpoint,
&graph_nodes, &graph_port, &graph_endpoint,
&always_fail,
};
@ -1851,7 +2003,7 @@ static void enable_warning_error(struct check *c, bool warn, bool error)
static void disable_warning_error(struct check *c, bool warn, bool error)
{
int i;
unsigned int i;
/* Lowering level, also lower it for things this is the prereq
* for */
@ -1872,7 +2024,7 @@ static void disable_warning_error(struct check *c, bool warn, bool error)
void parse_checks_option(bool warn, bool error, const char *arg)
{
int i;
unsigned int i;
const char *name = arg;
bool enable = true;
@ -1899,7 +2051,7 @@ void parse_checks_option(bool warn, bool error, const char *arg)
void process_checks(bool force, struct dt_info *dti)
{
int i;
unsigned int i;
int error = 0;
for (i = 0; i < ARRAY_SIZE(check_table); i++) {

View file

@ -94,7 +94,7 @@ static const struct {
<INITIAL>[0-9a-fA-F]+ {
unsigned long long val;
int obase = 16, width = 0;
int i;
unsigned int i;
val = strtoull(yytext, NULL, cbase);

53
data.c
View file

@ -21,10 +21,10 @@ void data_free(struct data d)
free(d.val);
}
struct data data_grow_for(struct data d, int xlen)
struct data data_grow_for(struct data d, unsigned int xlen)
{
struct data nd;
int newsize;
unsigned int newsize;
if (xlen == 0)
return d;
@ -84,7 +84,7 @@ struct data data_copy_file(FILE *f, size_t maxlen)
while (!feof(f) && (d.len < maxlen)) {
size_t chunksize, ret;
if (maxlen == -1)
if (maxlen == (size_t)-1)
chunksize = 4096;
else
chunksize = maxlen - d.len;
@ -228,11 +228,7 @@ struct data data_add_marker(struct data d, enum markertype type, char *ref)
{
struct marker *m;
m = xmalloc(sizeof(*m));
m->offset = d.len;
m->type = type;
m->ref = ref;
m->next = NULL;
m = alloc_marker(d.len, type, ref);
return data_append_markers(d, m);
}
@ -254,3 +250,44 @@ bool data_is_one_string(struct data d)
return true;
}
struct data data_insert_data(struct data d, struct marker *m, struct data old)
{
unsigned int offset = m->offset;
struct marker *next = m->next;
struct marker *marker;
struct data new_data;
char *ref;
new_data = data_insert_at_marker(d, m, old.val, old.len);
/* Copy all markers from old value */
marker = old.markers;
for_each_marker(marker) {
ref = NULL;
if (marker->ref)
ref = xstrdup(marker->ref);
m->next = alloc_marker(marker->offset + offset, marker->type,
ref);
m = m->next;
}
m->next = next;
return new_data;
}
struct marker *alloc_marker(unsigned int offset, enum markertype type,
char *ref)
{
struct marker *m;
m = xmalloc(sizeof(*m));
m->offset = offset;
m->type = type;
m->ref = ref;
m->next = NULL;
return m;
}

View file

@ -57,7 +57,7 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
push_input_file(name);
}
<*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)? {
<*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)* {
char *line, *fnstart, *fnend;
struct data fn;
/* skip text before line # */
@ -151,6 +151,21 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
return DT_LABEL;
}
<V1>{LABEL} {
/* Missed includes or macro definitions while
* preprocessing can lead to unexpected identifiers in
* the input. Report a slightly more informative error
* in this case */
lexical_error("Unexpected '%s'", yytext);
/* Treat it as a literal which often generates further
* useful error messages */
yylval.integer = 0;
return DT_LITERAL;
}
<V1>([0-9]+|0[xX][0-9a-fA-F]+)(U|L|UL|LL|ULL)? {
char *e;
DPRINT("Integer Literal: '%s'\n", yytext);
@ -200,7 +215,7 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
return DT_LABEL_REF;
}
<*>"&{/"{PATHCHAR}*\} { /* new-style path reference */
<*>"&{"{PATHCHAR}*\} { /* new-style path reference */
yytext[yyleng-1] = '\0';
DPRINT("Ref: %s\n", yytext+2);
yylval.labelref = xstrdup(yytext+2);

View file

@ -23,6 +23,12 @@ extern void yyerror(char const *s);
extern struct dt_info *parser_output;
extern bool treesource_error;
static bool is_ref_relative(const char *ref)
{
return ref[0] != '/' && strchr(&ref[1], '/');
}
%}
%union {
@ -169,6 +175,8 @@ devicetree:
*/
if (!($<flags>-1 & DTSF_PLUGIN))
ERROR(&@2, "Label or path %s not found", $1);
else if (is_ref_relative($1))
ERROR(&@2, "Label-relative reference %s not supported in plugin", $1);
$$ = add_orphan_node(
name_node(build_node(NULL, NULL, NULL),
""),
@ -178,6 +186,9 @@ devicetree:
{
struct node *target = get_node_by_ref($1, $3);
if (($<flags>-1 & DTSF_PLUGIN) && is_ref_relative($3))
ERROR(&@2, "Label-relative reference %s not supported in plugin", $3);
if (target) {
add_label(&target->labels, $2);
merge_nodes(target, $4);
@ -193,6 +204,8 @@ devicetree:
* so $-1 is what we want (plugindecl)
*/
if ($<flags>-1 & DTSF_PLUGIN) {
if (is_ref_relative($2))
ERROR(&@2, "Label-relative reference %s not supported in plugin", $2);
add_orphan_node($1, $3, $2);
} else {
struct node *target = get_node_by_ref($1, $2);
@ -271,14 +284,17 @@ propdef:
DT_PROPNODENAME '=' propdata ';'
{
$$ = build_property($1, $3, &@$);
free($1);
}
| DT_PROPNODENAME ';'
{
$$ = build_property($1, empty_data, &@$);
free($1);
}
| DT_DEL_PROP DT_PROPNODENAME ';'
{
$$ = build_property_delete($2);
free($2);
}
| DT_LABEL propdef
{
@ -391,9 +407,14 @@ arrayprefix:
* within the mask to one (i.e. | in the
* mask), all bits are one.
*/
if (($2 > mask) && (($2 | mask) != -1ULL))
ERROR(&@2, "Value out of range for"
" %d-bit array element", $1.bits);
if (($2 > mask) && (($2 | mask) != -1ULL)) {
char *loc = srcpos_string(&@2);
fprintf(stderr,
"WARNING: %s: Value 0x%016" PRIx64
" truncated to 0x%0*" PRIx64 "\n",
loc, $2, $1.bits / 4, ($2 & mask));
free(loc);
}
}
$$.data = data_append_integer($1.data, $2, $1.bits);
@ -476,8 +497,8 @@ integer_rela:
;
integer_shift:
integer_shift DT_LSHIFT integer_add { $$ = $1 << $3; }
| integer_shift DT_RSHIFT integer_add { $$ = $1 >> $3; }
integer_shift DT_LSHIFT integer_add { $$ = ($3 < 64) ? ($1 << $3) : 0; }
| integer_shift DT_RSHIFT integer_add { $$ = ($3 < 64) ? ($1 >> $3) : 0; }
| integer_add
;
@ -552,10 +573,12 @@ subnode:
DT_PROPNODENAME nodedef
{
$$ = name_node($2, $1);
free($1);
}
| DT_DEL_NODE DT_PROPNODENAME ';'
{
$$ = name_node(build_node_delete(&@$), $2);
free($2);
}
| DT_OMIT_NO_REF subnode
{

21
dtc.c
View file

@ -12,10 +12,10 @@
* Command line options
*/
int quiet; /* Level of quietness */
int reservenum; /* Number of memory reservation slots */
unsigned int reservenum;/* Number of memory reservation slots */
int minsize; /* Minimum blob size */
int padsize; /* Additional padding to blob */
int alignsize; /* Additional padding to blob accroding to the alignsize */
int alignsize; /* Additional padding to blob according to the alignsize */
int phandle_format = PHANDLE_EPAPR; /* Use linux,phandle or phandle properties */
int generate_symbols; /* enable symbols & fixup support */
int generate_fixups; /* suppress generation of fixups on symbol support */
@ -47,7 +47,7 @@ static void fill_fullpaths(struct node *tree, const char *prefix)
/* Usage related data. */
static const char usage_synopsis[] = "dtc [options] <input file>";
static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@AThv";
static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@LAThv";
static struct option const usage_long_opts[] = {
{"quiet", no_argument, NULL, 'q'},
{"in-format", a_argument, NULL, 'I'},
@ -67,6 +67,7 @@ static struct option const usage_long_opts[] = {
{"warning", a_argument, NULL, 'W'},
{"error", a_argument, NULL, 'E'},
{"symbols", no_argument, NULL, '@'},
{"local-fixups", no_argument, NULL, 'L'},
{"auto-alias", no_argument, NULL, 'A'},
{"annotate", no_argument, NULL, 'T'},
{"help", no_argument, NULL, 'h'},
@ -104,6 +105,7 @@ static const char * const usage_opts_help[] = {
"\n\tEnable/disable warnings (prefix with \"no-\")",
"\n\tEnable/disable errors (prefix with \"no-\")",
"\n\tEnable generation of symbols",
"\n\tPossibly generates a __local_fixups__ and a __fixups__ node at the root node",
"\n\tEnable auto-alias of labels",
"\n\tAnnotate output .dts with input source file and line (-T -T for more details)",
"\n\tPrint this help and exit",
@ -122,6 +124,8 @@ static const char *guess_type_by_name(const char *fname, const char *fallback)
return "dts";
if (!strcasecmp(s, ".yaml"))
return "yaml";
if (!strcasecmp(s, ".dtbo"))
return "dtb";
if (!strcasecmp(s, ".dtb"))
return "dtb";
return fallback;
@ -195,7 +199,7 @@ int main(int argc, char *argv[])
depname = optarg;
break;
case 'R':
reservenum = strtol(optarg, NULL, 0);
reservenum = strtoul(optarg, NULL, 0);
break;
case 'S':
minsize = strtol(optarg, NULL, 0);
@ -250,6 +254,11 @@ int main(int argc, char *argv[])
case '@':
generate_symbols = 1;
break;
case 'L':
generate_fixups = 1;
break;
case 'A':
auto_label_aliases = 1;
break;
@ -280,7 +289,9 @@ int main(int argc, char *argv[])
if (!depfile)
die("Couldn't open dependency file %s: %s\n", depname,
strerror(errno));
fprintf(depfile, "%s:", outname);
fprint_path_escaped(depfile, outname);
fputc(':', depfile);
}
if (inform == NULL)

96
dtc.h
View file

@ -35,10 +35,10 @@
* Command line options
*/
extern int quiet; /* Level of quietness */
extern int reservenum; /* Number of memory reservation slots */
extern unsigned int reservenum; /* Number of memory reservation slots */
extern int minsize; /* Minimum blob size */
extern int padsize; /* Additional padding to blob */
extern int alignsize; /* Additional padding to blob accroding to the alignsize */
extern int alignsize; /* Additional padding to blob according to the alignsize */
extern int phandle_format; /* Use linux,phandle or phandle properties */
extern int generate_symbols; /* generate symbols for nodes with labels */
extern int generate_fixups; /* generate fixups */
@ -51,10 +51,56 @@ extern int annotate; /* annotate .dts with input source location */
typedef uint32_t cell_t;
static inline bool phandle_is_valid(cell_t phandle)
{
return phandle != 0 && phandle != ~0U;
}
static inline uint16_t dtb_ld16(const void *p)
{
const uint8_t *bp = (const uint8_t *)p;
return ((uint16_t)bp[0] << 8)
| bp[1];
}
static inline uint32_t dtb_ld32(const void *p)
{
const uint8_t *bp = (const uint8_t *)p;
return ((uint32_t)bp[0] << 24)
| ((uint32_t)bp[1] << 16)
| ((uint32_t)bp[2] << 8)
| bp[3];
}
static inline uint64_t dtb_ld64(const void *p)
{
const uint8_t *bp = (const uint8_t *)p;
return ((uint64_t)bp[0] << 56)
| ((uint64_t)bp[1] << 48)
| ((uint64_t)bp[2] << 40)
| ((uint64_t)bp[3] << 32)
| ((uint64_t)bp[4] << 24)
| ((uint64_t)bp[5] << 16)
| ((uint64_t)bp[6] << 8)
| bp[7];
}
#define streq(a, b) (strcmp((a), (b)) == 0)
#define strstarts(s, prefix) (strncmp((s), (prefix), strlen(prefix)) == 0)
#define strprefixeq(a, n, b) (strlen(b) == (n) && (memcmp(a, b, n) == 0))
static inline bool strends(const char *str, const char *suffix)
{
unsigned int len, suffix_len;
len = strlen(str);
suffix_len = strlen(suffix);
if (len < suffix_len)
return false;
return streq(str + len - suffix_len, suffix);
}
#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
@ -70,17 +116,23 @@ enum markertype {
TYPE_UINT64,
TYPE_STRING,
};
static inline bool is_type_marker(enum markertype type)
{
return type >= TYPE_UINT8;
}
extern const char *markername(enum markertype markertype);
struct marker {
enum markertype type;
int offset;
unsigned int offset;
char *ref;
struct marker *next;
};
struct data {
int len;
unsigned int len;
char *val;
struct marker *markers;
};
@ -94,11 +146,26 @@ struct data {
for_each_marker(m) \
if ((m)->type == (t))
size_t type_marker_length(struct marker *m);
static inline struct marker *next_type_marker(struct marker *m)
{
for_each_marker(m)
if (is_type_marker(m->type))
break;
return m;
}
static inline size_t type_marker_length(struct marker *m)
{
struct marker *next = next_type_marker(m->next);
if (next)
return next->offset - m->offset;
return 0;
}
void data_free(struct data d);
struct data data_grow_for(struct data d, int xlen);
struct data data_grow_for(struct data d, unsigned int xlen);
struct data data_copy_mem(const char *mem, int len);
struct data data_copy_escape_string(const char *s, int len);
@ -115,7 +182,10 @@ struct data data_append_addr(struct data d, uint64_t addr);
struct data data_append_byte(struct data d, uint8_t byte);
struct data data_append_zeroes(struct data d, int len);
struct data data_append_align(struct data d, int align);
struct data data_insert_data(struct data d, struct marker *m, struct data old);
struct marker *alloc_marker(unsigned int offset, enum markertype type,
char *ref);
struct data data_add_marker(struct data d, enum markertype type, char *ref);
bool data_is_one_string(struct data d);
@ -193,16 +263,16 @@ struct node {
void add_label(struct label **labels, char *label);
void delete_labels(struct label **labels);
struct property *build_property(char *name, struct data val,
struct property *build_property(const char *name, struct data val,
struct srcpos *srcpos);
struct property *build_property_delete(char *name);
struct property *build_property_delete(const char *name);
struct property *chain_property(struct property *first, struct property *list);
struct property *reverse_properties(struct property *first);
struct node *build_node(struct property *proplist, struct node *children,
struct srcpos *srcpos);
struct node *build_node_delete(struct srcpos *srcpos);
struct node *name_node(struct node *node, char *name);
struct node *name_node(struct node *node, const char *name);
struct node *omit_node_if_unused(struct node *node);
struct node *reference_node(struct node *node);
struct node *chain_node(struct node *first, struct node *list);
@ -222,7 +292,7 @@ void append_to_property(struct node *node,
const char *get_unitname(struct node *node);
struct property *get_property(struct node *node, const char *propname);
cell_t propval_cell(struct property *prop);
cell_t propval_cell_n(struct property *prop, int n);
cell_t propval_cell_n(struct property *prop, unsigned int n);
struct property *get_property_by_label(struct node *tree, const char *label,
struct node **node);
struct marker *get_marker_label(struct node *tree, const char *label,
@ -269,9 +339,9 @@ struct dt_info *build_dt_info(unsigned int dtsflags,
struct reserve_info *reservelist,
struct node *tree, uint32_t boot_cpuid_phys);
void sort_tree(struct dt_info *dti);
void generate_label_tree(struct dt_info *dti, char *name, bool allocph);
void generate_fixups_tree(struct dt_info *dti, char *name);
void generate_local_fixups_tree(struct dt_info *dti, char *name);
void generate_label_tree(struct dt_info *dti, const char *name, bool allocph);
void generate_fixups_tree(struct dt_info *dti, const char *name);
void generate_local_fixups_tree(struct dt_info *dti, const char *name);
/* Checks */

2
dtdiff
View file

@ -17,7 +17,7 @@ source_and_sort () {
*.dts)
IFORMAT=dts
;;
*.dtb)
*.dtb|*.dtbo)
IFORMAT=dtb
;;
esac

View file

@ -18,10 +18,10 @@
#include "util.h"
#define FDT_MAGIC_SIZE 4
#define MAX_VERSION 17
#define MAX_VERSION 17U
#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
#define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a))))
#define PALIGN(p, a) ((void *)(ALIGN((uintptr_t)(p), (a))))
#define GET_CELL(p) (p += 4, *((const fdt32_t *)(p-4)))
static const char *tagname(uint32_t tag)
@ -163,7 +163,7 @@ static const char * const usage_opts_help[] = {
USAGE_COMMON_OPTS_HELP
};
static bool valid_header(char *p, off_t len)
static bool valid_header(char *p, size_t len)
{
if (len < sizeof(struct fdt_header) ||
fdt_magic(p) != FDT_MAGIC ||
@ -217,7 +217,7 @@ int main(int argc, char *argv[])
char *p = buf;
char *endp = buf + len;
fdt_set_magic(smagic, FDT_MAGIC);
fdt32_st(smagic, FDT_MAGIC);
/* poor man's memmem */
while ((endp - p) >= FDT_MAGIC_SIZE) {
@ -235,7 +235,7 @@ int main(int argc, char *argv[])
}
++p;
}
if (!p || endp - p < sizeof(struct fdt_header))
if (!p || (size_t)(endp - p) < sizeof(struct fdt_header))
die("%s: could not locate fdt magic\n", file);
printf("%s: found fdt at offset %#tx\n", file, p - buf);
buf = p;

View file

@ -62,8 +62,14 @@ static int show_cell_list(struct display_info *disp, const char *data, int len,
for (i = 0; i < len; i += size, p += size) {
if (i)
printf(" ");
value = size == 4 ? fdt32_ld((const fdt32_t *)p) :
size == 2 ? (*p << 8) | p[1] : *p;
switch (size) {
case 4: value = fdt32_ld((const fdt32_t *)p); break;
case 2: value = fdt16_ld((const fdt16_t *)p); break;
case 1:
default:
value = *p;
break;
}
printf(fmt, value);
}
@ -91,6 +97,11 @@ static int show_data(struct display_info *disp, const char *data, int len)
if (len == 0)
return 0;
if (disp->type == 'r') {
fwrite(data, 1, len, stdout);
return 0;
}
is_string = (disp->type) == 's' ||
(!disp->type && util_is_printable_string(data, len));
if (is_string) {

View file

@ -23,9 +23,7 @@
/* Usage related data. */
static const char usage_synopsis[] =
"apply a number of overlays to a base blob\n"
" fdtoverlay <options> [<overlay.dtbo> [<overlay.dtbo>]]\n"
"\n"
USAGE_TYPE_MSG;
" fdtoverlay <options> [<overlay.dtbo> [<overlay.dtbo>]]";
static const char usage_short_opts[] = "i:o:v" USAGE_COMMON_SHORT_OPTS;
static struct option const usage_long_opts[] = {
{"input", required_argument, NULL, 'i'},
@ -48,9 +46,10 @@ static void *apply_one(char *base, const char *overlay, size_t *buf_len,
char *tmp = NULL;
char *tmpo;
int ret;
bool has_symbols;
/*
* We take a copies first, because a a failed apply can trash
* We take copies first, because a failed apply can trash
* both the base blob and the overlay
*/
tmpo = xmalloc(fdt_totalsize(overlay));
@ -64,6 +63,8 @@ static void *apply_one(char *base, const char *overlay, size_t *buf_len,
fdt_strerror(ret));
goto fail;
}
ret = fdt_path_offset(tmp, "/__symbols__");
has_symbols = ret >= 0;
memcpy(tmpo, overlay, fdt_totalsize(overlay));
@ -76,6 +77,11 @@ static void *apply_one(char *base, const char *overlay, size_t *buf_len,
if (ret) {
fprintf(stderr, "\nFailed to apply '%s': %s\n",
name, fdt_strerror(ret));
if (!has_symbols) {
fprintf(stderr,
"base blob does not have a '/__symbols__' node, "
"make sure you have compiled the base blob with '-@' option\n");
}
goto fail;
}

View file

@ -9,6 +9,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <libfdt.h>
@ -64,16 +65,12 @@ static int encode_value(struct display_info *disp, char **arg, int arg_count,
int len; /* length of this cell/string/byte */
int ival;
int upto; /* the number of bytes we have written to buf */
char fmt[3];
upto = 0;
if (disp->verbose)
fprintf(stderr, "Decoding value:\n");
fmt[0] = '%';
fmt[1] = disp->type ? disp->type : 'd';
fmt[2] = '\0';
for (; arg_count > 0; arg++, arg_count--, upto += len) {
/* assume integer unless told otherwise */
if (disp->type == 's')
@ -94,7 +91,34 @@ static int encode_value(struct display_info *disp, char **arg, int arg_count,
fprintf(stderr, "\tstring: '%s'\n", ptr);
} else {
fdt32_t *iptr = (fdt32_t *)ptr;
sscanf(*arg, fmt, &ival);
char *endptr;
errno = 0;
switch (disp->type) {
case 'x':
ival = strtoul(*arg, &endptr, 16);
break;
case 'o':
ival = strtoul(*arg, &endptr, 8);
break;
case 'i':
ival = strtol(*arg, &endptr, 0);
break;
case 'u':
ival = strtoul(*arg, &endptr, 0);
break;
default: /* 0 or 'd' */
ival = strtol(*arg, &endptr, 10);
}
if (*endptr != '\0' || errno) {
if (disp->verbose) {
fprintf(stderr,
"Couldn't parse \"%s\" as an integer\n",
*arg);
}
return -1;
}
if (len == 4)
*iptr = cpu_to_fdt32(ival);
else
@ -389,8 +413,8 @@ static struct option const usage_long_opts[] = {
USAGE_COMMON_LONG_OPTS,
};
static const char * const usage_opts_help[] = {
"Create nodes if they don't already exist",
"Delete nodes (and any subnodes) if they already exist",
"Create nodes",
"Delete nodes (and any subnodes)",
"Delete properties if they already exist",
"Automatically create nodes as needed for the node path",
"Type of data",
@ -433,6 +457,8 @@ int main(int argc, char *argv[])
if (utilfdt_decode_type(optarg, &disp.type,
&disp.size))
usage("Invalid type string");
if (disp.type == 'r')
usage("Unsupported raw data type");
break;
case 'v':

View file

@ -124,7 +124,8 @@ static void asm_emit_cell(void *e, cell_t val)
{
FILE *f = e;
fprintf(f, "\t.byte 0x%02x; .byte 0x%02x; .byte 0x%02x; .byte 0x%02x\n",
fprintf(f, "\t.byte\t0x%02x\n" "\t.byte\t0x%02x\n"
"\t.byte\t0x%02x\n" "\t.byte\t0x%02x\n",
(val >> 24) & 0xff, (val >> 16) & 0xff,
(val >> 8) & 0xff, val & 0xff);
}
@ -134,9 +135,9 @@ static void asm_emit_string(void *e, const char *str, int len)
FILE *f = e;
if (len != 0)
fprintf(f, "\t.string\t\"%.*s\"\n", len, str);
fprintf(f, "\t.asciz\t\"%.*s\"\n", len, str);
else
fprintf(f, "\t.string\t\"%s\"\n", str);
fprintf(f, "\t.asciz\t\"%s\"\n", str);
}
static void asm_emit_align(void *e, int a)
@ -149,14 +150,14 @@ static void asm_emit_align(void *e, int a)
static void asm_emit_data(void *e, struct data d)
{
FILE *f = e;
int off = 0;
unsigned int off = 0;
struct marker *m = d.markers;
for_each_marker_of_type(m, LABEL)
emit_offset_label(f, m->ref, m->offset);
while ((d.len - off) >= sizeof(uint32_t)) {
asm_emit_cell(e, fdt32_to_cpu(*((fdt32_t *)(d.val+off))));
asm_emit_cell(e, dtb_ld32(d.val + off));
off += sizeof(uint32_t);
}
@ -219,7 +220,7 @@ static struct emitter asm_emitter = {
static int stringtable_insert(struct data *d, const char *str)
{
int i;
unsigned int i;
/* FIXME: do this more efficiently? */
@ -295,7 +296,7 @@ static struct data flatten_reserve_list(struct reserve_info *reservelist,
{
struct reserve_info *re;
struct data d = empty_data;
int j;
unsigned int j;
for (re = reservelist; re; re = re->next) {
d = data_append_re(d, re->address, re->size);
@ -345,7 +346,7 @@ static void make_fdt_header(struct fdt_header *fdt,
void dt_to_blob(FILE *f, struct dt_info *dti, int version)
{
struct version_info *vi = NULL;
int i;
unsigned int i;
struct data blob = empty_data;
struct data reservebuf = empty_data;
struct data dtbuf = empty_data;
@ -438,7 +439,7 @@ static void dump_stringtable_asm(FILE *f, struct data strbuf)
while (p < (strbuf.val + strbuf.len)) {
len = strlen(p);
fprintf(f, "\t.string \"%s\"\n", p);
fprintf(f, "\t.asciz \"%s\"\n", p);
p += len+1;
}
}
@ -446,7 +447,7 @@ static void dump_stringtable_asm(FILE *f, struct data strbuf)
void dt_to_asm(FILE *f, struct dt_info *dti, int version)
{
struct version_info *vi = NULL;
int i;
unsigned int i;
struct data strbuf = empty_data;
struct reserve_info *re;
const char *symprefix = "dt";
@ -502,7 +503,7 @@ void dt_to_asm(FILE *f, struct dt_info *dti, int version)
* Reserve map entries.
* Align the reserve map to a doubleword boundary.
* Each entry is an (address, size) pair of u64 values.
* Always supply a zero-sized temination entry.
* Always supply a zero-sized termination entry.
*/
asm_emit_align(f, 8);
emit_label(f, symprefix, "reserve_map");
@ -603,11 +604,11 @@ static void flat_realign(struct inbuf *inb, int align)
die("Premature end of data parsing flat device tree\n");
}
static char *flat_read_string(struct inbuf *inb)
static const char *flat_read_string(struct inbuf *inb)
{
int len = 0;
const char *p = inb->ptr;
char *str;
const char *str;
do {
if (p >= inb->limit)
@ -615,7 +616,7 @@ static char *flat_read_string(struct inbuf *inb)
len++;
} while ((*p++) != '\0');
str = xstrdup(inb->ptr);
str = inb->ptr;
inb->ptr += len;
@ -710,7 +711,7 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb)
}
static char *nodename_from_path(const char *ppath, const char *cpath)
static const char *nodename_from_path(const char *ppath, const char *cpath)
{
int plen;
@ -724,7 +725,7 @@ static char *nodename_from_path(const char *ppath, const char *cpath)
if (!streq(ppath, "/"))
plen++;
return xstrdup(cpath + plen);
return cpath + plen;
}
static struct node *unflatten_tree(struct inbuf *dtbuf,
@ -732,7 +733,7 @@ static struct node *unflatten_tree(struct inbuf *dtbuf,
const char *parent_flatname, int flags)
{
struct node *node;
char *flatname;
const char *flatname;
uint32_t val;
node = build_node(NULL, NULL, NULL);
@ -740,9 +741,10 @@ static struct node *unflatten_tree(struct inbuf *dtbuf,
flatname = flat_read_string(dtbuf);
if (flags & FTF_FULLPATH)
node->name = nodename_from_path(parent_flatname, flatname);
node->name = xstrdup(nodename_from_path(parent_flatname,
flatname));
else
node->name = flatname;
node->name = xstrdup(flatname);
do {
struct property *prop;
@ -784,10 +786,6 @@ static struct node *unflatten_tree(struct inbuf *dtbuf,
}
} while (val != FDT_END_NODE);
if (node->name != flatname) {
free(flatname);
}
return node;
}

View file

@ -43,7 +43,7 @@ static struct node *read_fstree(const char *dirname)
"WARNING: Cannot open %s: %s\n",
tmpname, strerror(errno));
} else {
prop = build_property(xstrdup(de->d_name),
prop = build_property(de->d_name,
data_copy_file(pfile,
st.st_size),
NULL);

View file

@ -4,15 +4,19 @@
# This is not a complete Makefile of itself. Instead, it is designed to
# be easily embeddable into other systems of Makefiles.
#
LIBFDT_so = libfdt.$(SHAREDLIB_EXT)
LIBFDT_soname = libfdt.$(SHAREDLIB_EXT).1
LIBFDT_INCLUDES = fdt.h libfdt.h libfdt_env.h
LIBFDT_VERSION = version.lds
LIBFDT_SRCS = 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 fdt_check.c
LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
LIBFDT_LIB = libfdt-$(DTC_VERSION).$(SHAREDLIB_EXT)
LIBFDT_LIB = libfdt.$(SHAREDLIB_EXT).$(DTC_VERSION)
libfdt_clean:
@$(VECHO) CLEAN "(libfdt)"
rm -f $(STD_CLEANFILES:%=$(LIBFDT_dir)/%)
rm -f $(LIBFDT_dir)/$(LIBFDT_so)
rm -f $(LIBFDT_dir)/$(LIBFDT_soname)
rm -f $(LIBFDT_dir)/$(LIBFDT_LIB)

View file

@ -1,3 +1,2 @@
- Tree traversal functions
- Graft function
- Complete libfdt.h documenting comments

View file

@ -22,6 +22,10 @@ int32_t fdt_ro_probe_(const void *fdt)
if (can_assume(VALID_DTB))
return totalsize;
/* The device tree must be at an 8-byte aligned address */
if ((uintptr_t)fdt & 7)
return -FDT_ERR_ALIGNMENT;
if (fdt_magic(fdt) == FDT_MAGIC) {
/* Complete tree */
if (!can_assume(LATEST)) {
@ -86,6 +90,10 @@ int fdt_check_header(const void *fdt)
{
size_t hdrsize;
/* The device tree must be at an 8-byte aligned address */
if ((uintptr_t)fdt & 7)
return -FDT_ERR_ALIGNMENT;
if (fdt_magic(fdt) != FDT_MAGIC)
return -FDT_ERR_BADMAGIC;
if (!can_assume(LATEST)) {
@ -98,7 +106,6 @@ int fdt_check_header(const void *fdt)
}
hdrsize = fdt_header_size(fdt);
if (!can_assume(VALID_DTB)) {
if ((fdt_totalsize(fdt) < hdrsize)
|| (fdt_totalsize(fdt) > INT_MAX))
return -FDT_ERR_TRUNCATED;
@ -107,9 +114,7 @@ int fdt_check_header(const void *fdt)
if (!check_off_(hdrsize, fdt_totalsize(fdt),
fdt_off_mem_rsvmap(fdt)))
return -FDT_ERR_TRUNCATED;
}
if (!can_assume(VALID_DTB)) {
/* Bounds check structure block */
if (!can_assume(LATEST) && fdt_version(fdt) < 17) {
if (!check_off_(hdrsize, fdt_totalsize(fdt),
@ -134,16 +139,20 @@ int fdt_check_header(const void *fdt)
const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
{
unsigned absoffset = offset + fdt_off_dt_struct(fdt);
unsigned int uoffset = offset;
unsigned int absoffset = offset + fdt_off_dt_struct(fdt);
if (offset < 0)
return NULL;
if (!can_assume(VALID_INPUT))
if ((absoffset < offset)
if ((absoffset < uoffset)
|| ((absoffset + len) < absoffset)
|| (absoffset + len) > fdt_totalsize(fdt))
return NULL;
if (can_assume(LATEST) || fdt_version(fdt) >= 0x11)
if (((offset + len) < offset)
if (((uoffset + len) < uoffset)
|| ((offset + len) > fdt_size_dt_struct(fdt)))
return NULL;
@ -153,7 +162,7 @@ const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
{
const fdt32_t *tagp, *lenp;
uint32_t tag;
uint32_t tag, len, sum;
int offset = startoffset;
const char *p;
@ -179,12 +188,19 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
if (!can_assume(VALID_DTB) && !lenp)
return FDT_END; /* premature end */
len = fdt32_to_cpu(*lenp);
sum = len + offset;
if (!can_assume(VALID_DTB) &&
(INT_MAX <= sum || sum < (uint32_t) offset))
return FDT_END; /* premature end */
/* skip-name offset, length and value */
offset += sizeof(struct fdt_property) - FDT_TAGSIZE
+ fdt32_to_cpu(*lenp);
offset += sizeof(struct fdt_property) - FDT_TAGSIZE + len;
if (!can_assume(LATEST) &&
fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 &&
((offset - fdt32_to_cpu(*lenp)) % 8) != 0)
fdt_version(fdt) < 0x10 && len >= 8 &&
((offset - len) % 8) != 0)
offset += 4;
break;
@ -206,10 +222,11 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
int fdt_check_node_offset_(const void *fdt, int offset)
{
if (can_assume(VALID_INPUT))
return offset;
if ((offset < 0) || (offset % FDT_TAGSIZE)
|| (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE))
if (!can_assume(VALID_INPUT)
&& ((offset < 0) || (offset % FDT_TAGSIZE)))
return -FDT_ERR_BADOFFSET;
if (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE)
return -FDT_ERR_BADOFFSET;
return offset;
@ -217,8 +234,11 @@ int fdt_check_node_offset_(const void *fdt, int offset)
int fdt_check_prop_offset_(const void *fdt, int offset)
{
if ((offset < 0) || (offset % FDT_TAGSIZE)
|| (fdt_next_tag(fdt, offset, &offset) != FDT_PROP))
if (!can_assume(VALID_INPUT)
&& ((offset < 0) || (offset % FDT_TAGSIZE)))
return -FDT_ERR_BADOFFSET;
if (fdt_next_tag(fdt, offset, &offset) != FDT_PROP)
return -FDT_ERR_BADOFFSET;
return offset;
@ -292,23 +312,26 @@ int fdt_next_subnode(const void *fdt, int offset)
return offset;
}
const char *fdt_find_string_(const char *strtab, int tabsize, const char *s)
const char *fdt_find_string_len_(const char *strtab, int tabsize, const char *s,
int slen)
{
int len = strlen(s) + 1;
const char *last = strtab + tabsize - len;
const char *last = strtab + tabsize - (slen + 1);
const char *p;
for (p = strtab; p <= last; p++)
if (memcmp(p, s, len) == 0)
if (memcmp(p, s, slen) == 0 && p[slen] == '\0')
return p;
return NULL;
}
int fdt_move(const void *fdt, void *buf, int bufsize)
{
if (!can_assume(VALID_INPUT) && bufsize < 0)
return -FDT_ERR_NOSPACE;
FDT_RO_PROBE(fdt);
if (fdt_totalsize(fdt) > bufsize)
if (fdt_totalsize(fdt) > (unsigned int)bufsize)
return -FDT_ERR_NOSPACE;
memmove(buf, fdt, fdt_totalsize(fdt));

View file

@ -7,7 +7,7 @@
* Copyright 2012 Kim Phillips, Freescale Semiconductor.
*/
#ifndef __ASSEMBLY__
#ifndef __ASSEMBLER__
struct fdt_header {
fdt32_t magic; /* magic word FDT_MAGIC */
@ -35,17 +35,17 @@ struct fdt_reserve_entry {
struct fdt_node_header {
fdt32_t tag;
char name[0];
char name[];
};
struct fdt_property {
fdt32_t tag;
fdt32_t len;
fdt32_t nameoff;
char data[0];
char data[];
};
#endif /* !__ASSEMBLY */
#endif /* !__ASSEMBLER__ */
#define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */
#define FDT_TAGSIZE sizeof(fdt32_t)

View file

@ -73,7 +73,7 @@ int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset,
/* check validity of address */
prop = data;
if (addr_cells == 1) {
if ((addr > UINT32_MAX) || ((UINT32_MAX + 1 - addr) < size))
if ((addr > UINT32_MAX) || (((uint64_t) UINT32_MAX + 1 - addr) < size))
return -FDT_ERR_BADVALUE;
fdt32_st(prop, (uint32_t)addr);

View file

@ -19,9 +19,12 @@ int fdt_check_full(const void *fdt, size_t bufsize)
unsigned int depth = 0;
const void *prop;
const char *propname;
bool expect_end = false;
if (bufsize < FDT_V1_SIZE)
return -FDT_ERR_TRUNCATED;
if (bufsize < fdt_header_size(fdt))
return -FDT_ERR_TRUNCATED;
err = fdt_check_header(fdt);
if (err != 0)
return err;
@ -39,6 +42,10 @@ int fdt_check_full(const void *fdt, size_t bufsize)
if (nextoffset < 0)
return nextoffset;
/* If we see two root nodes, something is wrong */
if (expect_end && tag != FDT_END)
return -FDT_ERR_BADSTRUCTURE;
switch (tag) {
case FDT_NOP:
break;
@ -52,12 +59,27 @@ int fdt_check_full(const void *fdt, size_t bufsize)
depth++;
if (depth > INT_MAX)
return -FDT_ERR_BADSTRUCTURE;
/* The root node must have an empty name */
if (depth == 1) {
const char *name;
int len;
name = fdt_get_name(fdt, offset, &len);
if (!name)
return len;
if (*name || len)
return -FDT_ERR_BADSTRUCTURE;
}
break;
case FDT_END_NODE:
if (depth == 0)
return -FDT_ERR_BADSTRUCTURE;
depth--;
if (depth == 0)
expect_end = true;
break;
case FDT_PROP:

View file

@ -40,37 +40,22 @@ static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
return fdt32_to_cpu(*val);
}
/**
* overlay_get_target - retrieves the offset of a fragment's target
* @fdt: Base device tree blob
* @fdto: Device tree overlay blob
* @fragment: node offset of the fragment in the overlay
* @pathp: pointer which receives the path of the target (or NULL)
*
* overlay_get_target() retrieves the target offset in the base
* device tree of a fragment, no matter how the actual targeting is
* done (through a phandle or a path)
*
* returns:
* the targeted node offset in the base device tree
* Negative error code on error
*/
static int overlay_get_target(const void *fdt, const void *fdto,
int fragment, char const **pathp)
int fdt_overlay_target_offset(const void *fdt, const void *fdto,
int fragment_offset, char const **pathp)
{
uint32_t phandle;
const char *path = NULL;
int path_len = 0, ret;
/* Try first to do a phandle based lookup */
phandle = overlay_get_target_phandle(fdto, fragment);
phandle = overlay_get_target_phandle(fdto, fragment_offset);
if (phandle == (uint32_t)-1)
return -FDT_ERR_BADPHANDLE;
/* no phandle, try path */
if (!phandle) {
/* And then a path based lookup */
path = fdt_getprop(fdto, fragment, "target-path", &path_len);
path = fdt_getprop(fdto, fragment_offset, "target-path", &path_len);
if (path)
ret = fdt_path_offset(fdt, path);
else
@ -116,26 +101,22 @@ static int overlay_get_target(const void *fdt, const void *fdto,
static int overlay_phandle_add_offset(void *fdt, int node,
const char *name, uint32_t delta)
{
const fdt32_t *val;
uint32_t adj_val;
fdt32_t *valp, val;
int len;
val = fdt_getprop(fdt, node, name, &len);
if (!val)
valp = fdt_getprop_w(fdt, node, name, &len);
if (!valp)
return len;
if (len != sizeof(*val))
if (len != sizeof(val))
return -FDT_ERR_BADPHANDLE;
adj_val = fdt32_to_cpu(*val);
if ((adj_val + delta) < adj_val)
val = fdt32_ld(valp);
if (val + delta < val || val + delta == (uint32_t)-1)
return -FDT_ERR_NOPHANDLES;
adj_val += delta;
if (adj_val == (uint32_t)-1)
return -FDT_ERR_NOPHANDLES;
return fdt_setprop_inplace_u32(fdt, node, name, adj_val);
fdt32_st(valp, val + delta);
return 0;
}
/**
@ -228,8 +209,8 @@ static int overlay_update_local_node_references(void *fdto,
fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) {
const fdt32_t *fixup_val;
const char *tree_val;
const char *name;
char *tree_val;
int fixup_len;
int tree_len;
int i;
@ -241,8 +222,9 @@ static int overlay_update_local_node_references(void *fdto,
if (fixup_len % sizeof(uint32_t))
return -FDT_ERR_BADOVERLAY;
fixup_len /= sizeof(uint32_t);
tree_val = fdt_getprop(fdto, tree_node, name, &tree_len);
tree_val = fdt_getprop_w(fdto, tree_node, name, &tree_len);
if (!tree_val) {
if (tree_len == -FDT_ERR_NOTFOUND)
return -FDT_ERR_BADOVERLAY;
@ -250,34 +232,16 @@ static int overlay_update_local_node_references(void *fdto,
return tree_len;
}
for (i = 0; i < (fixup_len / sizeof(uint32_t)); i++) {
fdt32_t adj_val;
uint32_t poffset;
for (i = 0; i < fixup_len; i++) {
fdt32_t *refp;
poffset = fdt32_to_cpu(fixup_val[i]);
refp = (fdt32_t *)(tree_val + fdt32_ld_(fixup_val + i));
/*
* phandles to fixup can be unaligned.
*
* Use a memcpy for the architectures that do
* not support unaligned accesses.
* phandles to fixup can be unaligned, so use
* fdt32_{ld,st}() to read/write them.
*/
memcpy(&adj_val, tree_val + poffset, sizeof(adj_val));
adj_val = cpu_to_fdt32(fdt32_to_cpu(adj_val) + delta);
ret = fdt_setprop_inplace_namelen_partial(fdto,
tree_node,
name,
strlen(name),
poffset,
&adj_val,
sizeof(adj_val));
if (ret == -FDT_ERR_NOSPACE)
return -FDT_ERR_BADOVERLAY;
if (ret)
return ret;
fdt32_st(refp, fdt32_ld(refp) + delta);
}
}
@ -343,7 +307,6 @@ static int overlay_update_local_references(void *fdto, uint32_t delta)
/**
* overlay_fixup_one_phandle - Set an overlay phandle to the base one
* @fdt: Base Device Tree blob
* @fdto: Device tree overlay blob
* @symbols_off: Node offset of the symbols node in the base device tree
* @path: Path to a node holding a phandle in the overlay
@ -351,7 +314,7 @@ static int overlay_update_local_references(void *fdto, uint32_t delta)
* @name: Name of the property holding the phandle reference in the overlay
* @name_len: number of name characters to consider
* @poffset: Offset within the overlay property where the phandle is stored
* @label: Label of the node referenced by the phandle
* @phandle: Phandle referencing the node
*
* overlay_fixup_one_phandle() resolves an overlay phandle pointing to
* a node in the base device tree.
@ -364,34 +327,17 @@ static int overlay_update_local_references(void *fdto, uint32_t delta)
* 0 on success
* Negative error code on failure
*/
static int overlay_fixup_one_phandle(void *fdt, void *fdto,
int symbols_off,
static int overlay_fixup_one_phandle(void *fdto, int symbols_off,
const char *path, uint32_t path_len,
const char *name, uint32_t name_len,
int poffset, const char *label)
int poffset, uint32_t phandle)
{
const char *symbol_path;
uint32_t phandle;
fdt32_t phandle_prop;
int symbol_off, fixup_off;
int prop_len;
int fixup_off;
if (symbols_off < 0)
return symbols_off;
symbol_path = fdt_getprop(fdt, symbols_off, label,
&prop_len);
if (!symbol_path)
return prop_len;
symbol_off = fdt_path_offset(fdt, symbol_path);
if (symbol_off < 0)
return symbol_off;
phandle = fdt_get_phandle(fdt, symbol_off);
if (!phandle)
return -FDT_ERR_NOTFOUND;
fixup_off = fdt_path_offset_namelen(fdto, path, path_len);
if (fixup_off == -FDT_ERR_NOTFOUND)
return -FDT_ERR_BADOVERLAY;
@ -403,7 +349,7 @@ static int overlay_fixup_one_phandle(void *fdt, void *fdto,
name, name_len, poffset,
&phandle_prop,
sizeof(phandle_prop));
};
}
/**
* overlay_fixup_phandle - Set an overlay phandle to the base one
@ -430,6 +376,10 @@ static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
const char *value;
const char *label;
int len;
const char *symbol_path;
int prop_len;
int symbol_off;
uint32_t phandle;
value = fdt_getprop_by_offset(fdto, property,
&label, &len);
@ -440,6 +390,18 @@ static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
return len;
}
symbol_path = fdt_getprop(fdt, symbols_off, label, &prop_len);
if (!symbol_path)
return prop_len;
symbol_off = fdt_path_offset(fdt, symbol_path);
if (symbol_off < 0)
return symbol_off;
phandle = fdt_get_phandle(fdt, symbol_off);
if (!phandle)
return -FDT_ERR_NOTFOUND;
do {
const char *path, *name, *fixup_end;
const char *fixup_str = value;
@ -479,9 +441,9 @@ static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
if ((*endptr != '\0') || (endptr <= (sep + 1)))
return -FDT_ERR_BADOVERLAY;
ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off,
ret = overlay_fixup_one_phandle(fdto, symbols_off,
path, path_len, name, name_len,
poffset, label);
poffset, phandle);
if (ret)
return ret;
} while (len > 0);
@ -534,6 +496,255 @@ static int overlay_fixup_phandles(void *fdt, void *fdto)
return 0;
}
/**
* overlay_adjust_local_conflicting_phandle: Changes a phandle value
* @fdto: Device tree overlay
* @node: The node the phandle is set for
* @fdt_phandle: The new value for the phandle
*
* returns:
* 0 on success
* Negative error code on failure
*/
static int overlay_adjust_local_conflicting_phandle(void *fdto, int node,
uint32_t fdt_phandle)
{
const fdt32_t *php;
int len, ret;
php = fdt_getprop(fdto, node, "phandle", &len);
if (php && len == sizeof(*php)) {
ret = fdt_setprop_inplace_u32(fdto, node, "phandle", fdt_phandle);
if (ret)
return ret;
}
php = fdt_getprop(fdto, node, "linux,phandle", &len);
if (php && len == sizeof(*php)) {
ret = fdt_setprop_inplace_u32(fdto, node, "linux,phandle", fdt_phandle);
if (ret)
return ret;
}
return 0;
}
/**
* overlay_update_node_conflicting_references - Recursively replace phandle values
* @fdto: Device tree overlay blob
* @tree_node: Node to recurse into
* @fixup_node: Node offset of the matching local fixups node
* @fdt_phandle: Value to replace phandles with
* @fdto_phandle: Value to be replaced
*
* Replaces all phandles with value @fdto_phandle by @fdt_phandle.
*
* returns:
* 0 on success
* Negative error code on failure
*/
static int overlay_update_node_conflicting_references(void *fdto, int tree_node,
int fixup_node,
uint32_t fdt_phandle,
uint32_t fdto_phandle)
{
int fixup_prop;
int fixup_child;
int ret;
fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) {
const fdt32_t *fixup_val;
const char *name;
char *tree_val;
int fixup_len;
int tree_len;
int i;
fixup_val = fdt_getprop_by_offset(fdto, fixup_prop,
&name, &fixup_len);
if (!fixup_val)
return fixup_len;
if (fixup_len % sizeof(uint32_t))
return -FDT_ERR_BADOVERLAY;
fixup_len /= sizeof(uint32_t);
tree_val = fdt_getprop_w(fdto, tree_node, name, &tree_len);
if (!tree_val) {
if (tree_len == -FDT_ERR_NOTFOUND)
return -FDT_ERR_BADOVERLAY;
return tree_len;
}
for (i = 0; i < fixup_len; i++) {
fdt32_t *refp;
uint32_t valp;
refp = (fdt32_t *)(tree_val + fdt32_ld_(fixup_val + i));
valp = fdt32_ld(refp);
if (valp == fdto_phandle)
fdt32_st(refp, fdt_phandle);
}
}
fdt_for_each_subnode(fixup_child, fdto, fixup_node) {
const char *fixup_child_name = fdt_get_name(fdto, fixup_child, NULL);
int tree_child;
tree_child = fdt_subnode_offset(fdto, tree_node, fixup_child_name);
if (tree_child == -FDT_ERR_NOTFOUND)
return -FDT_ERR_BADOVERLAY;
if (tree_child < 0)
return tree_child;
ret = overlay_update_node_conflicting_references(fdto, tree_child,
fixup_child,
fdt_phandle,
fdto_phandle);
if (ret)
return ret;
}
return 0;
}
/**
* overlay_update_local_conflicting_references - Recursively replace phandle values
* @fdto: Device tree overlay blob
* @fdt_phandle: Value to replace phandles with
* @fdto_phandle: Value to be replaced
*
* Replaces all phandles with value @fdto_phandle by @fdt_phandle.
*
* returns:
* 0 on success
* Negative error code on failure
*/
static int overlay_update_local_conflicting_references(void *fdto,
uint32_t fdt_phandle,
uint32_t fdto_phandle)
{
int fixups;
fixups = fdt_path_offset(fdto, "/__local_fixups__");
if (fixups == -FDT_ERR_NOTFOUND)
return 0;
if (fixups < 0)
return fixups;
return overlay_update_node_conflicting_references(fdto, 0, fixups,
fdt_phandle,
fdto_phandle);
}
/**
* overlay_prevent_phandle_overwrite_node - Helper function for overlay_prevent_phandle_overwrite
* @fdt: Base Device tree blob
* @fdtnode: Node in fdt that is checked for an overwrite
* @fdto: Device tree overlay blob
* @fdtonode: Node in fdto matching @fdtnode
*
* returns:
* 0 on success
* Negative error code on failure
*/
static int overlay_prevent_phandle_overwrite_node(void *fdt, int fdtnode,
void *fdto, int fdtonode)
{
uint32_t fdt_phandle, fdto_phandle;
int fdtochild;
fdt_phandle = fdt_get_phandle(fdt, fdtnode);
fdto_phandle = fdt_get_phandle(fdto, fdtonode);
if (fdt_phandle && fdto_phandle) {
int ret;
ret = overlay_adjust_local_conflicting_phandle(fdto, fdtonode,
fdt_phandle);
if (ret)
return ret;
ret = overlay_update_local_conflicting_references(fdto,
fdt_phandle,
fdto_phandle);
if (ret)
return ret;
}
fdt_for_each_subnode(fdtochild, fdto, fdtonode) {
const char *name = fdt_get_name(fdto, fdtochild, NULL);
int fdtchild;
int ret;
fdtchild = fdt_subnode_offset(fdt, fdtnode, name);
if (fdtchild == -FDT_ERR_NOTFOUND)
/*
* no further overwrites possible here as this node is
* new
*/
continue;
ret = overlay_prevent_phandle_overwrite_node(fdt, fdtchild,
fdto, fdtochild);
if (ret)
return ret;
}
return 0;
}
/**
* overlay_prevent_phandle_overwrite - Fixes overlay phandles to not overwrite base phandles
* @fdt: Base Device Tree blob
* @fdto: Device tree overlay blob
*
* Checks recursively if applying fdto overwrites phandle values in the base
* dtb. When such a phandle is found, the fdto is changed to use the fdt's
* phandle value to not break references in the base.
*
* returns:
* 0 on success
* Negative error code on failure
*/
static int overlay_prevent_phandle_overwrite(void *fdt, void *fdto)
{
int fragment;
fdt_for_each_subnode(fragment, fdto, 0) {
int overlay;
int target;
int ret;
overlay = fdt_subnode_offset(fdto, fragment, "__overlay__");
if (overlay == -FDT_ERR_NOTFOUND)
continue;
if (overlay < 0)
return overlay;
target = fdt_overlay_target_offset(fdt, fdto, fragment, NULL);
if (target == -FDT_ERR_NOTFOUND)
/*
* The subtree doesn't exist in the base, so nothing
* will be overwritten.
*/
continue;
else if (target < 0)
return target;
ret = overlay_prevent_phandle_overwrite_node(fdt, target,
fdto, overlay);
if (ret)
return ret;
}
return 0;
}
/**
* overlay_apply_node - Merges a node into the base device tree
* @fdt: Base Device Tree blob
@ -635,7 +846,7 @@ static int overlay_merge(void *fdt, void *fdto)
if (overlay < 0)
return overlay;
target = overlay_get_target(fdt, fdto, fragment, NULL);
target = fdt_overlay_target_offset(fdt, fdto, fragment, NULL);
if (target < 0)
return target;
@ -778,7 +989,7 @@ static int overlay_symbol_update(void *fdt, void *fdto)
return -FDT_ERR_BADOVERLAY;
/* get the target of the fragment */
ret = overlay_get_target(fdt, fdto, fragment, &target_path);
ret = fdt_overlay_target_offset(fdt, fdto, fragment, &target_path);
if (ret < 0)
return ret;
target = ret;
@ -800,7 +1011,7 @@ static int overlay_symbol_update(void *fdt, void *fdto)
if (!target_path) {
/* again in case setprop_placeholder changed it */
ret = overlay_get_target(fdt, fdto, fragment, &target_path);
ret = fdt_overlay_target_offset(fdt, fdto, fragment, &target_path);
if (ret < 0)
return ret;
target = ret;
@ -838,18 +1049,26 @@ int fdt_overlay_apply(void *fdt, void *fdto)
if (ret)
goto err;
/* Increase all phandles in the fdto by delta */
ret = overlay_adjust_local_phandles(fdto, delta);
if (ret)
goto err;
/* Adapt the phandle values in fdto to the above increase */
ret = overlay_update_local_references(fdto, delta);
if (ret)
goto err;
/* Update fdto's phandles using symbols from fdt */
ret = overlay_fixup_phandles(fdt, fdto);
if (ret)
goto err;
/* Don't overwrite phandles in fdt */
ret = overlay_prevent_phandle_overwrite(fdt, fdto);
if (ret)
goto err;
ret = overlay_merge(fdt, fdto);
if (ret)
goto err;

View file

@ -53,7 +53,7 @@ const char *fdt_get_string(const void *fdt, int stroffset, int *lenp)
err = -FDT_ERR_BADOFFSET;
absoffset = stroffset + fdt_off_dt_strings(fdt);
if (absoffset >= totalsize)
if (absoffset >= (unsigned)totalsize)
goto fail;
len = totalsize - absoffset;
@ -61,17 +61,19 @@ const char *fdt_get_string(const void *fdt, int stroffset, int *lenp)
if (stroffset < 0)
goto fail;
if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
if (stroffset >= fdt_size_dt_strings(fdt))
if ((unsigned)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)))
unsigned int sw_stroffset = -stroffset;
if ((stroffset >= 0) ||
(sw_stroffset > fdt_size_dt_strings(fdt)))
goto fail;
if ((-stroffset) < len)
len = -stroffset;
if (sw_stroffset < len)
len = sw_stroffset;
} else {
err = -FDT_ERR_INTERNAL;
goto fail;
@ -157,8 +159,8 @@ int fdt_generate_phandle(const void *fdt, uint32_t *phandle)
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;
unsigned int offset = n * sizeof(struct fdt_reserve_entry);
unsigned int absoffset = fdt_off_mem_rsvmap(fdt) + offset;
if (!can_assume(VALID_INPUT)) {
if (absoffset < fdt_off_mem_rsvmap(fdt))
@ -179,8 +181,8 @@ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
if (!can_assume(VALID_INPUT) && !re)
return -FDT_ERR_BADOFFSET;
*address = fdt64_ld(&re->address);
*size = fdt64_ld(&re->size);
*address = fdt64_ld_(&re->address);
*size = fdt64_ld_(&re->size);
return 0;
}
@ -190,7 +192,7 @@ int fdt_num_mem_rsv(const void *fdt)
const struct fdt_reserve_entry *re;
for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) {
if (fdt64_ld(&re->size) == 0)
if (fdt64_ld_(&re->size) == 0)
return i;
}
return -FDT_ERR_TRUNCATED;
@ -253,6 +255,9 @@ int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen)
FDT_RO_PROBE(fdt);
if (!can_assume(VALID_INPUT) && namelen <= 0)
return -FDT_ERR_BADPATH;
/* see if we have an alias */
if (*path != '/') {
const char *q = memchr(path, '/', end - p);
@ -368,7 +373,7 @@ static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt,
prop = fdt_offset_ptr_(fdt, offset);
if (lenp)
*lenp = fdt32_ld(&prop->len);
*lenp = fdt32_ld_(&prop->len);
return prop;
}
@ -406,7 +411,7 @@ static const struct fdt_property *fdt_get_property_namelen_(const void *fdt,
offset = -FDT_ERR_INTERNAL;
break;
}
if (fdt_string_eq_(fdt, fdt32_ld(&prop->nameoff),
if (fdt_string_eq_(fdt, fdt32_ld_(&prop->nameoff),
name, namelen)) {
if (poffset)
*poffset = offset;
@ -459,7 +464,7 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
/* Handle realignment */
if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
(poffset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
(poffset + sizeof(*prop)) % 8 && fdt32_ld_(&prop->len) >= 8)
return prop->data + 4;
return prop->data;
}
@ -477,22 +482,22 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
int namelen;
if (!can_assume(VALID_INPUT)) {
name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff),
name = fdt_get_string(fdt, fdt32_ld_(&prop->nameoff),
&namelen);
*namep = name;
if (!name) {
if (lenp)
*lenp = namelen;
return NULL;
}
*namep = name;
} else {
*namep = fdt_string(fdt, fdt32_ld(&prop->nameoff));
*namep = fdt_string(fdt, fdt32_ld_(&prop->nameoff));
}
}
/* Handle realignment */
if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
(offset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
(offset + sizeof(*prop)) % 8 && fdt32_ld_(&prop->len) >= 8)
return prop->data + 4;
return prop->data;
}
@ -517,19 +522,34 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
return 0;
}
return fdt32_ld(php);
return fdt32_ld_(php);
}
static const void *fdt_path_getprop_namelen(const void *fdt, const char *path,
const char *propname, int propnamelen,
int *lenp)
{
int offset = fdt_path_offset(fdt, path);
if (offset < 0)
return NULL;
return fdt_getprop_namelen(fdt, offset, propname, propnamelen, lenp);
}
const char *fdt_get_alias_namelen(const void *fdt,
const char *name, int namelen)
{
int aliasoffset;
int len;
const char *alias;
aliasoffset = fdt_path_offset(fdt, "/aliases");
if (aliasoffset < 0)
alias = fdt_path_getprop_namelen(fdt, "/aliases", name, namelen, &len);
if (!can_assume(VALID_DTB) &&
!(alias && len > 0 && alias[len - 1] == '\0' && *alias == '/'))
return NULL;
return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL);
return alias;
}
const char *fdt_get_alias(const void *fdt, const char *name)
@ -537,6 +557,17 @@ const char *fdt_get_alias(const void *fdt, const char *name)
return fdt_get_alias_namelen(fdt, name, strlen(name));
}
const char *fdt_get_symbol_namelen(const void *fdt,
const char *name, int namelen)
{
return fdt_path_getprop_namelen(fdt, "/__symbols__", name, namelen, NULL);
}
const char *fdt_get_symbol(const void *fdt, const char *name)
{
return fdt_get_symbol_namelen(fdt, name, strlen(name));
}
int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
{
int pdepth = 0, p = 0;
@ -680,7 +711,7 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
{
int offset;
if ((phandle == 0) || (phandle == -1))
if ((phandle == 0) || (phandle == ~0U))
return -FDT_ERR_BADPHANDLE;
FDT_RO_PROBE(fdt);

View file

@ -46,7 +46,7 @@ static int fdt_rw_probe_(void *fdt)
return err_; \
}
static inline int fdt_data_size_(void *fdt)
static inline unsigned int fdt_data_size_(void *fdt)
{
return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
}
@ -54,15 +54,16 @@ static inline int fdt_data_size_(void *fdt)
static int fdt_splice_(void *fdt, void *splicepoint, int oldlen, int newlen)
{
char *p = splicepoint;
char *end = (char *)fdt + fdt_data_size_(fdt);
unsigned int dsize = fdt_data_size_(fdt);
size_t soff = p - (char *)fdt;
if (((p + oldlen) < p) || ((p + oldlen) > end))
if ((oldlen < 0) || (soff + oldlen < soff) || (soff + oldlen > dsize))
return -FDT_ERR_BADOFFSET;
if ((p < (char *)fdt) || ((end - oldlen + newlen) < (char *)fdt))
if ((p < (char *)fdt) || (dsize + newlen < (unsigned)oldlen))
return -FDT_ERR_BADOFFSET;
if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt)))
if (dsize - oldlen + newlen > fdt_totalsize(fdt))
return -FDT_ERR_NOSPACE;
memmove(p + newlen, p + oldlen, end - p - oldlen);
memmove(p + newlen, p + oldlen, ((char *)fdt + dsize) - (p + oldlen));
return 0;
}
@ -123,31 +124,33 @@ static int fdt_splice_string_(void *fdt, int newlen)
* allocated. Ignored if can_assume(NO_ROLLBACK)
* @return offset of string in the string table (whether found or added)
*/
static int fdt_find_add_string_(void *fdt, const char *s, int *allocated)
static int fdt_find_add_string_(void *fdt, const char *s, int slen,
int *allocated)
{
char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);
const char *p;
char *new;
int len = strlen(s) + 1;
int err;
if (!can_assume(NO_ROLLBACK))
*allocated = 0;
p = fdt_find_string_(strtab, fdt_size_dt_strings(fdt), s);
p = fdt_find_string_len_(strtab, fdt_size_dt_strings(fdt), s, slen);
if (p)
/* found it */
return (p - strtab);
new = strtab + fdt_size_dt_strings(fdt);
err = fdt_splice_string_(fdt, len);
err = fdt_splice_string_(fdt, slen + 1);
if (err)
return err;
if (!can_assume(NO_ROLLBACK))
*allocated = 1;
memcpy(new, s, len);
memcpy(new, s, slen);
new[slen] = '\0';
return (new - strtab);
}
@ -180,13 +183,15 @@ int fdt_del_mem_rsv(void *fdt, int n)
return fdt_splice_mem_rsv_(fdt, re, 1, 0);
}
static int fdt_resize_property_(void *fdt, int nodeoffset, const char *name,
static int fdt_resize_property_(void *fdt, int nodeoffset,
const char *name, int namelen,
int len, struct fdt_property **prop)
{
int oldlen;
int err;
*prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
*prop = fdt_get_property_namelen_w(fdt, nodeoffset, name, namelen,
&oldlen);
if (!*prop)
return oldlen;
@ -199,7 +204,7 @@ static int fdt_resize_property_(void *fdt, int nodeoffset, const char *name,
}
static int fdt_add_property_(void *fdt, int nodeoffset, const char *name,
int len, struct fdt_property **prop)
int namelen, int len, struct fdt_property **prop)
{
int proplen;
int nextoffset;
@ -210,7 +215,7 @@ static int fdt_add_property_(void *fdt, int nodeoffset, const char *name,
if ((nextoffset = fdt_check_node_offset_(fdt, nodeoffset)) < 0)
return nextoffset;
namestroff = fdt_find_add_string_(fdt, name, &allocated);
namestroff = fdt_find_add_string_(fdt, name, namelen, &allocated);
if (namestroff < 0)
return namestroff;
@ -254,17 +259,18 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name)
return 0;
}
int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name,
int len, void **prop_data)
int fdt_setprop_placeholder_namelen(void *fdt, int nodeoffset, const char *name,
int namelen, int len, void **prop_data)
{
struct fdt_property *prop;
int err;
FDT_RW_PROBE(fdt);
err = fdt_resize_property_(fdt, nodeoffset, name, len, &prop);
err = fdt_resize_property_(fdt, nodeoffset, name, namelen, len, &prop);
if (err == -FDT_ERR_NOTFOUND)
err = fdt_add_property_(fdt, nodeoffset, name, len, &prop);
err = fdt_add_property_(fdt, nodeoffset, name, namelen, len,
&prop);
if (err)
return err;
@ -272,13 +278,14 @@ int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name,
return 0;
}
int fdt_setprop(void *fdt, int nodeoffset, const char *name,
const void *val, int len)
int fdt_setprop_namelen(void *fdt, int nodeoffset, const char *name,
int namelen, const void *val, int len)
{
void *prop_data;
int err;
err = fdt_setprop_placeholder(fdt, nodeoffset, name, len, &prop_data);
err = fdt_setprop_placeholder_namelen(fdt, nodeoffset, name, namelen,
len, &prop_data);
if (err)
return err;
@ -306,7 +313,8 @@ int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
prop->len = cpu_to_fdt32(newlen);
memcpy(prop->data + oldlen, val, len);
} else {
err = fdt_add_property_(fdt, nodeoffset, name, len, &prop);
err = fdt_add_property_(fdt, nodeoffset, name, strlen(name),
len, &prop);
if (err)
return err;
memcpy(prop->data, val, len);
@ -348,7 +356,10 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
return offset;
/* Try to place the new node after the parent's properties */
fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */
tag = fdt_next_tag(fdt, parentoffset, &nextoffset);
/* the fdt_subnode_offset_namelen() should ensure this never hits */
if (!can_assume(LIBFDT_FLAWLESS) && (tag != FDT_BEGIN_NODE))
return -FDT_ERR_INTERNAL;
do {
offset = nextoffset;
tag = fdt_next_tag(fdt, offset, &nextoffset);
@ -390,7 +401,9 @@ int fdt_del_node(void *fdt, int nodeoffset)
}
static void fdt_packblocks_(const char *old, char *new,
int mem_rsv_size, int struct_size)
int mem_rsv_size,
int struct_size,
int strings_size)
{
int mem_rsv_off, struct_off, strings_off;
@ -405,8 +418,7 @@ static void fdt_packblocks_(const char *old, char *new,
fdt_set_off_dt_struct(new, struct_off);
fdt_set_size_dt_struct(new, struct_size);
memmove(new + strings_off, old + fdt_off_dt_strings(old),
fdt_size_dt_strings(old));
memmove(new + strings_off, old + fdt_off_dt_strings(old), strings_size);
fdt_set_off_dt_strings(new, strings_off);
fdt_set_size_dt_strings(new, fdt_size_dt_strings(old));
}
@ -427,15 +439,17 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
struct_size = fdt_size_dt_struct(fdt);
} else {
} else if (fdt_version(fdt) == 16) {
struct_size = 0;
while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END)
;
if (struct_size < 0)
return struct_size;
} else {
return -FDT_ERR_BADVERSION;
}
if (can_assume(LIBFDT_ORDER) |
if (can_assume(LIBFDT_ORDER) ||
!fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) {
/* no further work necessary */
err = fdt_move(fdt, buf, bufsize);
@ -464,7 +478,8 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
return -FDT_ERR_NOSPACE;
}
fdt_packblocks_(fdt, tmp, mem_rsv_size, struct_size);
fdt_packblocks_(fdt, tmp, mem_rsv_size, struct_size,
fdt_size_dt_strings(fdt));
memmove(buf, tmp, newsize);
fdt_set_magic(buf, FDT_MAGIC);
@ -484,7 +499,8 @@ int fdt_pack(void *fdt)
mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
* sizeof(struct fdt_reserve_entry);
fdt_packblocks_(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt));
fdt_packblocks_(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt),
fdt_size_dt_strings(fdt));
fdt_set_totalsize(fdt, fdt_data_size_(fdt));
return 0;

View file

@ -39,8 +39,9 @@ static struct fdt_errtabent fdt_errtable[] = {
FDT_ERRTABENT(FDT_ERR_BADOVERLAY),
FDT_ERRTABENT(FDT_ERR_NOPHANDLES),
FDT_ERRTABENT(FDT_ERR_BADFLAGS),
FDT_ERRTABENT(FDT_ERR_ALIGNMENT),
};
#define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0]))
#define FDT_ERRTABSIZE ((int)(sizeof(fdt_errtable) / sizeof(fdt_errtable[0])))
const char *fdt_strerror(int errval)
{
@ -48,7 +49,7 @@ const char *fdt_strerror(int errval)
return "<valid offset/length>";
else if (errval == 0)
return "<no error>";
else if (errval > -FDT_ERRTABSIZE) {
else if (-errval < FDT_ERRTABSIZE) {
const char *s = fdt_errtable[-errval].str;
if (s)

View file

@ -32,7 +32,7 @@ static int fdt_sw_probe_(void *fdt)
/* 'memrsv' state: Initial state after fdt_create()
*
* Allowed functions:
* fdt_add_reservmap_entry()
* fdt_add_reservemap_entry()
* fdt_finish_reservemap() [moves to 'struct' state]
*/
static int fdt_sw_probe_memrsv_(void *fdt)
@ -93,8 +93,8 @@ static inline uint32_t sw_flags(void *fdt)
static void *fdt_grab_space_(void *fdt, size_t len)
{
int offset = fdt_size_dt_struct(fdt);
int spaceleft;
unsigned int offset = fdt_size_dt_struct(fdt);
unsigned int spaceleft;
spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt)
- fdt_size_dt_strings(fdt);
@ -108,8 +108,8 @@ static void *fdt_grab_space_(void *fdt, size_t len)
int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags)
{
const size_t hdrsize = FDT_ALIGN(sizeof(struct fdt_header),
sizeof(struct fdt_reserve_entry));
const int hdrsize = FDT_ALIGN(sizeof(struct fdt_header),
sizeof(struct fdt_reserve_entry));
void *fdt = buf;
if (bufsize < hdrsize)
@ -152,6 +152,9 @@ int fdt_resize(void *fdt, void *buf, int bufsize)
FDT_SW_PROBE(fdt);
if (bufsize < 0)
return -FDT_ERR_NOSPACE;
headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
tailsize = fdt_size_dt_strings(fdt);
@ -159,7 +162,7 @@ int fdt_resize(void *fdt, void *buf, int bufsize)
headsize + tailsize > fdt_totalsize(fdt))
return -FDT_ERR_INTERNAL;
if ((headsize + tailsize) > bufsize)
if ((headsize + tailsize) > (unsigned)bufsize)
return -FDT_ERR_NOSPACE;
oldtail = (char *)fdt + fdt_totalsize(fdt) - tailsize;
@ -247,18 +250,18 @@ int fdt_end_node(void *fdt)
static int fdt_add_string_(void *fdt, const char *s)
{
char *strtab = (char *)fdt + fdt_totalsize(fdt);
int strtabsize = fdt_size_dt_strings(fdt);
int len = strlen(s) + 1;
int struct_top, offset;
unsigned int strtabsize = fdt_size_dt_strings(fdt);
unsigned int len = strlen(s) + 1;
unsigned int struct_top, offset;
offset = -strtabsize - len;
offset = strtabsize + len;
struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
if (fdt_totalsize(fdt) + offset < struct_top)
if (fdt_totalsize(fdt) - offset < struct_top)
return 0; /* no more room :( */
memcpy(strtab + offset, s, len);
memcpy(strtab - offset, s, len);
fdt_set_size_dt_strings(fdt, strtabsize + len);
return offset;
return -offset;
}
/* Must only be used to roll back in case of error */
@ -374,7 +377,7 @@ int fdt_finish(void *fdt)
fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
/* And fix up fields that were keeping intermediate state. */
fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
fdt_set_last_comp_version(fdt, FDT_LAST_COMPATIBLE_VERSION);
fdt_set_magic(fdt, FDT_MAGIC);
return 0;

View file

@ -23,7 +23,7 @@ int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
if (!propval)
return proplen;
if (proplen < (len + idx))
if ((unsigned)proplen < (len + idx))
return -FDT_ERR_NOSPACE;
memcpy((char *)propval + idx, val, len);

File diff suppressed because it is too large Load diff

View file

@ -66,31 +66,4 @@ static inline fdt64_t cpu_to_fdt64(uint64_t x)
#undef CPU_TO_FDT16
#undef EXTRACT_BYTE
#ifdef __APPLE__
#include <AvailabilityMacros.h>
/* strnlen() is not available on Mac OS < 10.7 */
# if !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED < \
MAC_OS_X_VERSION_10_7)
#define strnlen fdt_strnlen
/*
* fdt_strnlen: returns the length of a string or max_count - which ever is
* smallest.
* Input 1 string: the string whose size is to be determined
* Input 2 max_count: the maximum value returned by this function
* Output: length of the string or max_count (the smallest of the two)
*/
static inline size_t fdt_strnlen(const char *string, size_t max_count)
{
const char *p = memchr(string, 0, max_count);
return p ? p - string : max_count;
}
#endif /* !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED <
MAC_OS_X_VERSION_10_7) */
#endif /* __APPLE__ */
#endif /* LIBFDT_ENV_H */

View file

@ -20,7 +20,15 @@ int32_t fdt_ro_probe_(const void *fdt);
int fdt_check_node_offset_(const void *fdt, int offset);
int fdt_check_prop_offset_(const void *fdt, int offset);
const char *fdt_find_string_(const char *strtab, int tabsize, const char *s);
const char *fdt_find_string_len_(const char *strtab, int tabsize, const char *s,
int s_len);
static inline const char *fdt_find_string_(const char *strtab, int tabsize,
const char *s)
{
return fdt_find_string_len_(strtab, tabsize, s, strlen(s));
}
int fdt_node_end_offset_(void *fdt, int nodeoffset);
static inline const void *fdt_offset_ptr_(const void *fdt, int offset)
@ -46,6 +54,25 @@ static inline struct fdt_reserve_entry *fdt_mem_rsv_w_(void *fdt, int n)
return (void *)(uintptr_t)fdt_mem_rsv_(fdt, n);
}
/*
* Internal helpers to access structural elements of the device tree
* blob (rather than for example reading integers from within property
* values). We assume that we are either given a naturally aligned
* address for the platform or if we are not, we are on a platform
* where unaligned memory reads will be handled in a graceful manner.
* If not the external helpers fdtXX_ld() from libfdt.h can be used
* instead.
*/
static inline uint32_t fdt32_ld_(const fdt32_t *p)
{
return fdt32_to_cpu(*p);
}
static inline uint64_t fdt64_ld_(const fdt64_t *p)
{
return fdt64_to_cpu(*p);
}
#define FDT_SW_MAGIC (~FDT_MAGIC)
/**********************************************************************/

63
libfdt/meson.build Normal file
View file

@ -0,0 +1,63 @@
version_script = '-Wl,--version-script=@0@'.format(meson.current_source_dir() / 'version.lds')
if not cc.has_link_argument(version_script)
version_script = []
endif
sources = files(
'fdt.c',
'fdt_addresses.c',
'fdt_check.c',
'fdt_empty_tree.c',
'fdt_overlay.c',
'fdt_ro.c',
'fdt_rw.c',
'fdt_strerror.c',
'fdt_sw.c',
'fdt_wip.c',
)
link_args = []
if cc.has_link_argument('-Wl,--no-undefined')
link_args += '-Wl,--no-undefined'
else
# -undefined error is the equivalent of --no-undefined for the macOS linker,
# but -undefined would also be understood as a valid argument for GNU ld!
link_args += cc.get_supported_link_arguments('-Wl,-undefined,error')
endif
link_args += version_script
libfdt = library(
'fdt', sources,
version: meson.project_version(),
link_args: link_args,
link_depends: 'version.lds',
install: get_option('default_library') != 'static' or not wheel_only,
)
libfdt_inc = include_directories('.')
libfdt_dep = declare_dependency(
include_directories: libfdt_inc,
link_with: libfdt,
)
meson.override_dependency('libfdt', libfdt_dep)
if not wheel_only
install_headers(
files(
'fdt.h',
'libfdt.h',
'libfdt_env.h',
)
)
pkgconfig = import('pkgconfig')
pkgconfig.generate(
libraries: libfdt,
version: meson.project_version(),
filebase: 'libfdt',
name: 'libfdt',
description: 'Flat Device Tree manipulation',
)
endif

43
libfdt/sbom.cdx.json Normal file
View file

@ -0,0 +1,43 @@
{
"bomFormat": "CycloneDX",
"specVersion": "1.6",
"version": 1,
"metadata": {
"authors": [
{
"name": "@VCS_SBOM_AUTHORS@"
}
]
},
"components": [
{
"type": "library",
"bom-ref": "pkg:github/dgibson/libfdt@@VCS_TAG@",
"cpe": "cpe:2.3:a:dgibson:libfdt:@VCS_TAG@:*:*:*:*:*:*:*",
"name": "libfdt",
"version": "@VCS_VERSION@",
"description": "Utility library for reading and manipulating the FDT binary format",
"supplier": {
"name": "libfdt developers"
},
"licenses": [
{
"license": {
"id": "BSD-2-Clause"
}
},
{
"license": {
"id": "GPL-2.0-or-later"
}
}
],
"externalReferences": [
{
"type": "vcs",
"url": "https://github.com/dgibson/dtc"
}
]
}
]
}

View file

@ -20,7 +20,7 @@ LIBFDT_1.2 {
fdt_get_alias_namelen;
fdt_get_alias;
fdt_get_path;
fdt_header_size;
fdt_header_size;
fdt_supernode_atdepth_offset;
fdt_node_depth;
fdt_parent_offset;
@ -43,6 +43,7 @@ LIBFDT_1.2 {
fdt_add_mem_rsv;
fdt_del_mem_rsv;
fdt_set_name;
fdt_setprop_namelen;
fdt_setprop;
fdt_delprop;
fdt_add_subnode_namelen;
@ -71,12 +72,16 @@ LIBFDT_1.2 {
fdt_find_max_phandle;
fdt_generate_phandle;
fdt_check_full;
fdt_setprop_placeholder_namelen;
fdt_setprop_placeholder;
fdt_property_placeholder;
fdt_header_size_;
fdt_appendprop_addrrange;
fdt_setprop_inplace_namelen_partial;
fdt_create_with_flags;
fdt_overlay_target_offset;
fdt_get_symbol;
fdt_get_symbol_namelen;
local:
*;
};

View file

@ -36,27 +36,27 @@ void delete_labels(struct label **labels)
label->deleted = 1;
}
struct property *build_property(char *name, struct data val,
struct property *build_property(const char *name, struct data val,
struct srcpos *srcpos)
{
struct property *new = xmalloc(sizeof(*new));
memset(new, 0, sizeof(*new));
new->name = name;
new->name = xstrdup(name);
new->val = val;
new->srcpos = srcpos_copy(srcpos);
return new;
}
struct property *build_property_delete(char *name)
struct property *build_property_delete(const char *name)
{
struct property *new = xmalloc(sizeof(*new));
memset(new, 0, sizeof(*new));
new->name = name;
new->name = xstrdup(name);
new->deleted = 1;
return new;
@ -116,11 +116,11 @@ struct node *build_node_delete(struct srcpos *srcpos)
return new;
}
struct node *name_node(struct node *node, char *name)
struct node *name_node(struct node *node, const char *name)
{
assert(node->name == NULL);
node->name = name;
node->name = xstrdup(name);
return node;
}
@ -174,7 +174,7 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
old_prop->val = new_prop->val;
old_prop->deleted = 0;
free(old_prop->srcpos);
srcpos_free(old_prop->srcpos);
old_prop->srcpos = new_prop->srcpos;
free(new_prop);
new_prop = NULL;
@ -250,6 +250,7 @@ struct node * add_orphan_node(struct node *dt, struct node *new_node, char *ref)
name_node(new_node, "__overlay__");
node = build_node(p, new_node, NULL);
name_node(node, name);
free(name);
add_child(dt, node);
return dt;
@ -339,20 +340,73 @@ void append_to_property(struct node *node,
char *name, const void *data, int len,
enum markertype type)
{
struct data d;
struct property *p;
p = get_property(node, name);
if (!p) {
p = build_property(name, empty_data, NULL);
add_property(node, p);
}
p->val = data_add_marker(p->val, type, name);
p->val = data_append_data(p->val, data, len);
}
static int append_unique_str_to_property(struct node *node,
char *name, const char *data, int len)
{
struct property *p;
p = get_property(node, name);
if (p) {
d = data_add_marker(p->val, type, name);
d = data_append_data(d, data, len);
p->val = d;
const char *s;
if (p->val.len && p->val.val[p->val.len - 1] != '\0')
/* The current content doesn't look like a string */
return -1;
for (s = p->val.val; s < p->val.val + p->val.len; s = strchr(s, '\0') + 1) {
if (strcmp(data, s) == 0)
/* data already contained in node.name */
return 0;
}
} else {
d = data_add_marker(empty_data, type, name);
d = data_append_data(d, data, len);
p = build_property(name, d, NULL);
p = build_property(name, empty_data, NULL);
add_property(node, p);
}
p->val = data_add_marker(p->val, TYPE_STRING, name);
p->val = data_append_data(p->val, data, len);
return 0;
}
static int append_unique_u32_to_property(struct node *node, char *name, fdt32_t value)
{
struct property *p;
p = get_property(node, name);
if (p) {
const fdt32_t *v, *val_end = (const fdt32_t *)p->val.val + p->val.len / 4;
if (p->val.len % 4 != 0)
/* The current content doesn't look like a u32 array */
return -1;
for (v = (const void *)p->val.val; v < val_end; v++) {
if (*v == value)
/* value already contained */
return 0;
}
} else {
p = build_property(name, empty_data, NULL);
add_property(node, p);
}
p->val = data_add_marker(p->val, TYPE_UINT32, name);
p->val = data_append_data(p->val, &value, 4);
return 0;
}
struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)
@ -438,9 +492,9 @@ cell_t propval_cell(struct property *prop)
return fdt32_to_cpu(*((fdt32_t *)prop->val.val));
}
cell_t propval_cell_n(struct property *prop, int n)
cell_t propval_cell_n(struct property *prop, unsigned int n)
{
assert(prop->val.len / sizeof(cell_t) >= n);
assert(prop->val.len / sizeof(cell_t) > n);
return fdt32_to_cpu(*((fdt32_t *)prop->val.val + n));
}
@ -503,7 +557,7 @@ struct node *get_subnode(struct node *node, const char *nodename)
struct node *child;
for_each_child(node, child)
if (streq(child->name, nodename))
if (streq(child->name, nodename) && !child->deleted)
return child;
return NULL;
@ -526,7 +580,7 @@ struct node *get_node_by_path(struct node *tree, const char *path)
p = strchr(path, '/');
for_each_child(tree, child) {
if (p && strprefixeq(path, p - path, child->name))
if (p && strprefixeq(path, (size_t)(p - path), child->name))
return get_node_by_path(child, p+1);
else if (!p && streq(path, child->name))
return child;
@ -559,7 +613,7 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
{
struct node *child, *node;
if ((phandle == 0) || (phandle == -1)) {
if (!phandle_is_valid(phandle)) {
assert(generate_fixups);
return NULL;
}
@ -581,20 +635,62 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
struct node *get_node_by_ref(struct node *tree, const char *ref)
{
struct node *target = tree;
const char *label = NULL, *path = NULL;
if (streq(ref, "/"))
return tree;
else if (ref[0] == '/')
return get_node_by_path(tree, ref);
if (ref[0] == '/')
path = ref;
else
return get_node_by_label(tree, ref);
label = ref;
if (label) {
const char *slash = strchr(label, '/');
char *buf = NULL;
if (slash) {
buf = xstrndup(label, slash - label);
label = buf;
path = slash + 1;
}
target = get_node_by_label(tree, label);
free(buf);
if (!target)
return NULL;
}
if (path)
target = get_node_by_path(target, path);
return target;
}
static void add_phandle_property(struct node *node,
const char *name, int format)
{
struct data d;
if (!(phandle_format & format))
return;
if (get_property(node, name))
return;
d = data_add_marker(empty_data, TYPE_UINT32, NULL);
d = data_append_cell(d, node->phandle);
add_property(node, build_property(name, d, NULL));
}
cell_t get_node_phandle(struct node *root, struct node *node)
{
static cell_t phandle = 1; /* FIXME: ick, static local */
struct data d = empty_data;
if ((node->phandle != 0) && (node->phandle != -1))
if (phandle_is_valid(node->phandle))
return node->phandle;
while (get_node_by_phandle(root, phandle))
@ -602,16 +698,8 @@ cell_t get_node_phandle(struct node *root, struct node *node)
node->phandle = phandle;
d = data_add_marker(d, TYPE_UINT32, NULL);
d = data_append_cell(d, phandle);
if (!get_property(node, "linux,phandle")
&& (phandle_format & PHANDLE_LEGACY))
add_property(node, build_property("linux,phandle", d, NULL));
if (!get_property(node, "phandle")
&& (phandle_format & PHANDLE_EPAPR))
add_property(node, build_property("phandle", d, NULL));
add_phandle_property(node, "linux,phandle", PHANDLE_LEGACY);
add_phandle_property(node, "phandle", PHANDLE_EPAPR);
/* If the node *does* have a phandle property, we must
* be dealing with a self-referencing phandle, which will be
@ -781,18 +869,18 @@ void sort_tree(struct dt_info *dti)
}
/* utility helper to avoid code duplication */
static struct node *build_and_name_child_node(struct node *parent, char *name)
static struct node *build_and_name_child_node(struct node *parent, const char *name)
{
struct node *node;
node = build_node(NULL, NULL, NULL);
name_node(node, xstrdup(name));
name_node(node, name);
add_child(parent, node);
return node;
}
static struct node *build_root_node(struct node *dt, char *name)
static struct node *build_root_node(struct node *dt, const char *name)
{
struct node *an;
@ -883,47 +971,61 @@ static bool any_fixup_tree(struct dt_info *dti, struct node *node)
return false;
}
static void add_fixup_entry(struct dt_info *dti, struct node *fn,
struct node *node, struct property *prop,
struct marker *m)
static int add_fixup_entry(struct dt_info *dti, struct node *fn,
struct node *node, struct property *prop,
struct marker *m)
{
char *entry;
int ret;
/* m->ref can only be a REF_PHANDLE, but check anyway */
assert(m->type == REF_PHANDLE);
/* The format only permits fixups for references to label, not
* references to path */
if (strchr(m->ref, '/'))
die("Can't generate fixup for reference to path &{%s}\n",
m->ref);
/* there shouldn't be any ':' in the arguments */
if (strchr(node->fullpath, ':') || strchr(prop->name, ':'))
die("arguments should not contain ':'\n");
xasprintf(&entry, "%s:%s:%u",
node->fullpath, prop->name, m->offset);
append_to_property(fn, m->ref, entry, strlen(entry) + 1, TYPE_STRING);
ret = append_unique_str_to_property(fn, m->ref, entry, strlen(entry) + 1);
free(entry);
return ret;
}
static void generate_fixups_tree_internal(struct dt_info *dti,
struct node *fn,
struct node *node)
static int generate_fixups_tree_internal(struct dt_info *dti,
struct node *fn,
struct node *node)
{
struct node *dt = dti->dt;
struct node *c;
struct property *prop;
struct marker *m;
struct node *refnode;
int ret = 0;
for_each_property(node, prop) {
m = prop->val.markers;
for_each_marker_of_type(m, REF_PHANDLE) {
refnode = get_node_by_ref(dt, m->ref);
if (!refnode)
add_fixup_entry(dti, fn, node, prop, m);
if (add_fixup_entry(dti, fn, node, prop, m))
ret = -1;
}
}
for_each_child(node, c)
generate_fixups_tree_internal(dti, fn, c);
if (generate_fixups_tree_internal(dti, fn, c))
ret = -1;
return ret;
}
static bool any_local_fixup_tree(struct dt_info *dti, struct node *node)
@ -948,7 +1050,7 @@ static bool any_local_fixup_tree(struct dt_info *dti, struct node *node)
return false;
}
static void add_local_fixup_entry(struct dt_info *dti,
static int add_local_fixup_entry(struct dt_info *dti,
struct node *lfn, struct node *node,
struct property *prop, struct marker *m,
struct node *refnode)
@ -973,41 +1075,44 @@ static void add_local_fixup_entry(struct dt_info *dti,
/* walk the path components creating nodes if they don't exist */
for (wn = lfn, i = 1; i < depth; i++, wn = nwn) {
/* if no node exists, create it */
nwn = get_subnode(wn, compp[i]);
if (!nwn)
nwn = build_and_name_child_node(wn, compp[i]);
nwn = build_root_node(wn, compp[i]);
}
free(compp);
value_32 = cpu_to_fdt32(m->offset);
append_to_property(wn, prop->name, &value_32, sizeof(value_32), TYPE_UINT32);
return append_unique_u32_to_property(wn, prop->name, value_32);
}
static void generate_local_fixups_tree_internal(struct dt_info *dti,
struct node *lfn,
struct node *node)
static int generate_local_fixups_tree_internal(struct dt_info *dti,
struct node *lfn,
struct node *node)
{
struct node *dt = dti->dt;
struct node *c;
struct property *prop;
struct marker *m;
struct node *refnode;
int ret = 0;
for_each_property(node, prop) {
m = prop->val.markers;
for_each_marker_of_type(m, REF_PHANDLE) {
refnode = get_node_by_ref(dt, m->ref);
if (refnode)
add_local_fixup_entry(dti, lfn, node, prop, m, refnode);
if (add_local_fixup_entry(dti, lfn, node, prop, m, refnode))
ret = -1;
}
}
for_each_child(node, c)
generate_local_fixups_tree_internal(dti, lfn, c);
if (generate_local_fixups_tree_internal(dti, lfn, c))
ret = -1;
return ret;
}
void generate_label_tree(struct dt_info *dti, char *name, bool allocph)
void generate_label_tree(struct dt_info *dti, const char *name, bool allocph)
{
if (!any_label_tree(dti, dti->dt))
return;
@ -1015,18 +1120,22 @@ void generate_label_tree(struct dt_info *dti, char *name, bool allocph)
dti->dt, allocph);
}
void generate_fixups_tree(struct dt_info *dti, char *name)
void generate_fixups_tree(struct dt_info *dti, const char *name)
{
if (!any_fixup_tree(dti, dti->dt))
return;
generate_fixups_tree_internal(dti, build_root_node(dti->dt, name),
dti->dt);
if (generate_fixups_tree_internal(dti, build_root_node(dti->dt, name), dti->dt))
fprintf(stderr,
"Warning: Preexisting data in %s malformed, some content could not be added.\n",
name);
}
void generate_local_fixups_tree(struct dt_info *dti, char *name)
void generate_local_fixups_tree(struct dt_info *dti, const char *name)
{
if (!any_local_fixup_tree(dti, dti->dt))
return;
generate_local_fixups_tree_internal(dti, build_root_node(dti->dt, name),
dti->dt);
if (generate_local_fixups_tree_internal(dti, build_root_node(dti->dt, name), dti->dt))
fprintf(stderr,
"Warning: Preexisting data in %s malformed, some content could not be added.\n",
name);
}

131
meson.build Normal file
View file

@ -0,0 +1,131 @@
project('dtc', 'c',
version: files('VERSION.txt'),
license: ['GPL2+', 'BSD-2'],
default_options: ['werror=true', 'default_library=both'],
meson_version: '>=0.57.0'
)
cc = meson.get_compiler('c')
add_project_arguments(
cc.get_supported_arguments([
'-Wpointer-arith',
'-Wcast-qual',
'-Wnested-externs',
'-Wstrict-prototypes',
'-Wmissing-prototypes',
'-Wredundant-decls',
'-Wshadow',
'-Wsuggest-attribute=format',
'-Wwrite-strings',
]),
language: 'c'
)
add_project_arguments(
'-DFDT_ASSUME_MASK=' + get_option('assume-mask').to_string(),
language: 'c'
)
yamltree = 'yamltree.c'
yaml = dependency('yaml-0.1', version: '>=0.2.3', required: get_option('yaml'))
if not yaml.found()
add_project_arguments('-DNO_YAML', language: 'c')
yamltree = []
endif
valgrind = dependency('valgrind', required: get_option('valgrind'))
if not valgrind.found()
add_project_arguments('-DNO_VALGRIND', language: 'c')
endif
py = import('python')
py = py.find_installation(required: get_option('python'))
swig = find_program('swig', required: get_option('python'))
pylibfdt_enabled = not meson.is_cross_build() and py.found() and swig.found() ? true : false
wheel_only = get_option('wheel-only')
version_gen_h = vcs_tag(
command: ['git', 'describe', '--dirty=+'],
input: 'version_gen.h.in',
output: 'version_gen.h',
)
subdir('libfdt')
dtc_tools = []
util_dep = declare_dependency(
sources: ['util.c', version_gen_h],
include_directories: '.',
dependencies: libfdt_dep
)
if get_option('tools') and not wheel_only
flex = find_program('flex', required: true)
bison = find_program('bison', required: true)
lgen = generator(
flex,
output: '@PLAINNAME@.lex.c',
arguments: ['-o', '@OUTPUT@', '@INPUT@'],
)
pgen = generator(
bison,
output: ['@BASENAME@.tab.c', '@BASENAME@.tab.h'],
arguments: ['@INPUT@', '--defines=@OUTPUT1@', '--output=@OUTPUT0@'],
)
if cc.check_header('fnmatch.h')
dtc_tools += executable(
'convert-dtsv0',
[
lgen.process('convert-dtsv0-lexer.l'),
'srcpos.c',
],
dependencies: util_dep,
install: true,
)
endif
dtc_tools += executable(
'dtc',
[
lgen.process('dtc-lexer.l'),
pgen.process('dtc-parser.y'),
'checks.c',
'data.c',
'dtc.c',
'flattree.c',
'fstree.c',
'livetree.c',
'srcpos.c',
'treesource.c',
yamltree,
],
dependencies: [util_dep, yaml],
install: true,
)
foreach e: ['fdtdump', 'fdtget', 'fdtput', 'fdtoverlay']
dtc_tools += executable(e, files(e + '.c'), dependencies: util_dep, install: true)
endforeach
install_data(
'dtdiff',
install_dir: get_option('bindir'),
install_mode: 'rwxr-xr-x',
)
endif
foreach e: dtc_tools
meson.override_find_program(e.name(), e)
endforeach
if pylibfdt_enabled
subdir('pylibfdt')
endif
if get_option('tests')
subdir('tests')
endif

14
meson_options.txt Normal file
View file

@ -0,0 +1,14 @@
option('tools', type: 'boolean', value: true,
description: 'Build tools')
option('assume-mask', type: 'integer', value: 0,
description: 'Control the assumptions made (e.g. risking security issues) in the code.')
option('yaml', type: 'feature', value: 'auto',
description: 'YAML support')
option('valgrind', type: 'feature', value: 'auto',
description: 'Valgrind support')
option('python', type: 'feature', value: 'auto',
description: 'Build pylibfdt Python library')
option('tests', type: 'boolean', value: true,
description: 'Build tests')
option('wheel-only', type: 'boolean', value: false,
description: 'building from meson-python')

View file

@ -1,30 +0,0 @@
# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
# Makefile.pylibfdt
#
PYLIBFDT_srcs = $(PYLIBFDT_dir)/libfdt.i
PYMODULE = $(PYLIBFDT_dir)/_libfdt.so
PYLIBFDT_CLEANFILES_L = libfdt_wrap.c libfdt.py *.pyc *.so
PYLIBFDT_CLEANFILES = $(PYLIBFDT_CLEANFILES_L:%=$(PYLIBFDT_dir)/%)
PYLIBFDT_CLEANDIRS_L = build __pycache__
PYLIBFDT_CLEANDIRS = $(PYLIBFDT_CLEANDIRS_L:%=$(PYLIBFDT_dir)/%)
SETUP = $(PYLIBFDT_dir)/setup.py
SETUPFLAGS =
ifndef V
SETUPFLAGS += --quiet
endif
$(PYMODULE): $(PYLIBFDT_srcs) $(LIBFDT_archive) $(SETUP) $(VERSION_FILE)
@$(VECHO) PYMOD $@
$(PYTHON) $(SETUP) $(SETUPFLAGS) build_ext --build-lib=../$(PYLIBFDT_dir)
install_pylibfdt: $(PYMODULE)
@$(VECHO) INSTALL-PYLIB
$(PYTHON) $(SETUP) $(SETUPFLAGS) install --prefix=$(PREFIX)
pylibfdt_clean:
@$(VECHO) CLEAN "(pylibfdt)"
rm -f $(PYLIBFDT_CLEANFILES)
rm -rf $(PYLIBFDT_CLEANDIRS)

View file

@ -114,11 +114,14 @@ def check_err_null(val, quiet=()):
FdtException if val indicates an error was reported and the error
is not in @quiet.
"""
# Normally a list is returned which contains the data and its length.
# If we get just an integer error code, it means the function failed.
# Compatibility for SWIG v4.2 and earlier. SWIG 4.2 would drop the first
# item from the list if it was None, returning only the second item.
if not isinstance(val, list):
if -val not in quiet:
raise FdtException(val)
val = [None, val]
if val[0] is None:
if -val[1] not in quiet:
raise FdtException(val[1])
return val
class FdtRo(object):
@ -159,7 +162,7 @@ class FdtRo(object):
quiet: Errors to ignore (empty to raise on all errors)
Returns:
Typle:
Tuple:
Offset of the next node, if any, else a -ve error
Depth of the returned node, if any, else undefined
@ -295,7 +298,9 @@ class FdtRo(object):
Returns:
Number of memory reserve-map records
"""
return check_err(fdt_get_mem_rsv(self._fdt, index), quiet)
val = fdt_get_mem_rsv(self._fdt, index)
check_err(val[0], quiet)
return val[1:]
def subnode_offset(self, parentoffset, name, quiet=()):
"""Get the offset of a named subnode
@ -393,8 +398,8 @@ class FdtRo(object):
"""
pdata = check_err_null(
fdt_get_property_by_offset(self._fdt, prop_offset), quiet)
if isinstance(pdata, (int)):
return pdata
if pdata[0] is None:
return pdata[1]
return Property(pdata[0], pdata[1])
def getprop(self, nodeoffset, prop_name, quiet=()):
@ -415,10 +420,39 @@ class FdtRo(object):
"""
pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name),
quiet)
if isinstance(pdata, (int)):
return pdata
if pdata[0] is None:
return pdata[1]
return Property(prop_name, bytearray(pdata[0]))
def hasprop(self, nodeoffset, prop_name, quiet=()):
"""Check if a node has a property
This can be used to check boolean properties
Args:
nodeoffset: Node offset containing property to check
prop_name: Name of property to check
quiet: Errors to ignore (empty to raise on all errors). Note that
NOTFOUND is added internally by this function so need not be
provided
Returns:
True if the property exists in the node, else False. If an error
other than -NOTFOUND is returned by fdt_getprop() then the error
is return (-ve integer)
Raises:
FdtError if any error occurs other than NOTFOUND (e.g. the
nodeoffset is invalid)
"""
pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name),
quiet + (NOTFOUND,))
if pdata[0] is None:
if pdata[1] == -NOTFOUND:
return False
return pdata[1]
return True
def get_phandle(self, nodeoffset):
"""Get the phandle of a node
@ -443,6 +477,29 @@ class FdtRo(object):
"""
return fdt_get_alias(self._fdt, name)
def get_path(self, nodeoffset, size_hint=1024, quiet=()):
"""Get the full path of a node
Args:
nodeoffset: Node offset to check
size_hint: Hint for size of returned string
Returns:
Full path to the node
Raises:
FdtException if an error occurs
"""
while True:
ret, path = fdt_get_path(self._fdt, nodeoffset, size_hint)
if ret == -NOSPACE:
size_hint *= 2
continue
err = check_err(ret, quiet)
if err:
return err
return path
def parent_offset(self, nodeoffset, quiet=()):
"""Get the offset of a node's parent
@ -582,6 +639,32 @@ class Fdt(FdtRo):
return check_err(fdt_setprop(self._fdt, nodeoffset, prop_name, val,
len(val)), quiet)
def setprop_bool(self, nodeoffset, prop_name, val, quiet=()):
"""Set the boolean value of a property
Either:
adds the property if not already present; or
deletes the property if present
Args:
nodeoffset: Node offset containing the property to create/delete
prop_name: Name of property
val: Boolean value to write (i.e. True or False)
quiet: Errors to ignore (empty to raise on all errors)
Returns:
Error code, or 0 if OK
Raises:
FdtException if no parent found or other error occurs
"""
exists = self.hasprop(nodeoffset, prop_name, quiet)
if val != exists:
if val:
return self.setprop(nodeoffset, prop_name, b'', quiet=quiet)
else:
return self.delprop(nodeoffset, prop_name, quiet=quiet)
def setprop_u32(self, nodeoffset, prop_name, val, quiet=()):
"""Set the value of a property
@ -716,6 +799,21 @@ class Property(bytearray):
def as_int64(self):
return self.as_cell('q')
def as_list(self, fmt):
return list(map(lambda x: x[0], struct.iter_unpack('>' + fmt, self)))
def as_uint32_list(self):
return self.as_list('L')
def as_int32_list(self):
return self.as_list('l')
def as_uint64_list(self):
return self.as_list('Q')
def as_int64_list(self):
return self.as_list('q')
def as_str(self):
"""Unicode is supported by decoding from UTF-8"""
if self[-1] != 0:
@ -724,6 +822,13 @@ class Property(bytearray):
raise ValueError('Property contains embedded nul characters')
return self[:-1].decode('utf-8')
def as_stringlist(self):
"""Unicode is supported by decoding from UTF-8"""
if self[-1] != 0:
raise ValueError('Property lacks nul termination')
parts = self[:-1].split(b'\x00')
return list(map(lambda x: x.decode('utf-8'), parts))
class FdtSw(FdtRo):
"""Software interface to create a device tree from scratch
@ -991,6 +1096,9 @@ class NodeAdder():
%rename(fdt_property) fdt_property_func;
%immutable fdt_property::data;
%immutable fdt_node_header::name;
/*
* fdt32_t is a big-endian 32-bit value defined to uint32_t in libfdt_env.h
* so use the same type here.
@ -1009,7 +1117,7 @@ typedef uint32_t fdt32_t;
}
$1 = (void *)PyByteArray_AsString($input);
fdt = $1;
fdt = fdt; /* avoid unused variable warning */
(void)fdt; /* avoid unused variable warning */
}
/* Some functions do change the device tree, so use void * */
@ -1020,7 +1128,7 @@ typedef uint32_t fdt32_t;
}
$1 = PyByteArray_AsString($input);
fdt = $1;
fdt = fdt; /* avoid unused variable warning */
(void)fdt; /* avoid unused variable warning */
}
/* typemap used for fdt_get_property_by_offset() */
@ -1032,7 +1140,7 @@ typedef uint32_t fdt32_t;
fdt_string(fdt1, fdt32_to_cpu($1->nameoff)));
buff = PyByteArray_FromStringAndSize(
(const char *)($1 + 1), fdt32_to_cpu($1->len));
resultobj = SWIG_Python_AppendOutput(resultobj, buff);
resultobj = SWIG_AppendOutput(resultobj, buff);
}
}
@ -1040,14 +1148,16 @@ typedef uint32_t fdt32_t;
/* typemap used for fdt_getprop() */
%typemap(out) (const void *) {
if (!$1)
if (!$1) {
$result = Py_None;
else
Py_INCREF($result);
} else {
%#if PY_VERSION_HEX >= 0x03000000
$result = Py_BuildValue("y#", $1, *arg4);
$result = Py_BuildValue("y#", $1, (Py_ssize_t)*arg4);
%#else
$result = Py_BuildValue("s#", $1, *arg4);
$result = Py_BuildValue("s#", $1, (Py_ssize_t)*arg4);
%#endif
}
}
/* typemap used for fdt_setprop() */
@ -1071,7 +1181,7 @@ typedef uint32_t fdt32_t;
%typemap(argout) int *depth {
PyObject *val = Py_BuildValue("i", *arg$argnum);
resultobj = SWIG_Python_AppendOutput(resultobj, val);
resultobj = SWIG_AppendOutput(resultobj, val);
}
%apply int *depth { int *depth };
@ -1083,14 +1193,14 @@ typedef uint32_t fdt32_t;
%typemap(argout) uint64_t * {
PyObject *val = PyLong_FromUnsignedLongLong(*arg$argnum);
if (!result) {
if (PyTuple_GET_SIZE(resultobj) == 0)
resultobj = val;
else
resultobj = SWIG_Python_AppendOutput(resultobj, val);
}
resultobj = SWIG_AppendOutput(resultobj, val);
}
%include "cstring.i"
%cstring_output_maxsize(char *buf, int buflen);
int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen);
/* We have both struct fdt_property and a function fdt_property() */
%warnfilter(302) fdt_property;

21
pylibfdt/meson.build Normal file
View file

@ -0,0 +1,21 @@
libfdt_c = custom_target(
'swig',
input: 'libfdt.i',
output: ['libfdt.c', 'libfdt.py'],
install: true,
install_dir: [false, py.get_install_dir(pure: false)],
command: [swig, '-python', '-I'+meson.current_source_dir() / '../libfdt', '-o', '@OUTPUT0@', '@INPUT@']
)
nowarn_gen = cc.get_supported_arguments(
'-Wno-cast-qual',
'-Wno-missing-prototypes',
'-Wno-redundant-decls',
)
pylibfdt = py.extension_module(
'_libfdt',
libfdt_c,
c_args: ['-DPY_SSIZE_T_CLEAN'] + nowarn_gen,
dependencies: [libfdt_dep, py.dependency()],
install: true,
)

View file

@ -1,48 +0,0 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
# While Python 3 is the default, it's also possible to invoke
# this setup.py script with Python 2.
"""
setup.py file for SWIG libfdt
Copyright (C) 2017 Google, Inc.
Written by Simon Glass <sjg@chromium.org>
"""
from distutils.core import setup, Extension
import os
import re
import sys
VERSION_PATTERN = '^#define DTC_VERSION "DTC ([^"]*)"$'
def get_version():
version_file = "../version_gen.h"
f = open(version_file, 'rt')
m = re.match(VERSION_PATTERN, f.readline())
return m.group(1)
setupdir = os.path.dirname(os.path.abspath(sys.argv[0]))
os.chdir(setupdir)
libfdt_module = Extension(
'_libfdt',
sources=['libfdt.i'],
include_dirs=['../libfdt'],
libraries=['fdt'],
library_dirs=['../libfdt'],
swig_opts=['-I../libfdt'],
)
setup(
name='libfdt',
version=get_version(),
author='Simon Glass <sjg@chromium.org>',
description='Python binding for libfdt',
ext_modules=[libfdt_module],
py_modules=['libfdt'],
)

33
pyproject.toml Normal file
View file

@ -0,0 +1,33 @@
[build-system]
build-backend = 'mesonpy'
requires = ['meson-python']
[project]
name = 'libfdt'
authors = [
{name = 'Simon Glass', email = 'sjg@chromium.org'},
]
classifiers = [
'Programming Language :: Python :: 3',
'License :: OSI Approved :: BSD License',
'License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)',
'Operating System :: OS Independent',
]
description = 'Python binding for libfdt'
readme = 'README.md'
requires-python = '>=3.8'
dynamic = ['version']
[project.urls]
'homepage' = 'https://git.kernel.org/pub/scm/utils/dtc/dtc.git'
# These arguments are applied only when building a redistributable binary wheel
# for uploading to PyPI. We don't want to install libraries (or headers /
# pkgconfig files / executables) that clash with system C installs, so we
# disable everything other than the python bindings themselves, and build the
# python C-API extension using static linkage to avoid juggling "libdir" /
# LD_LIBRARY_PATH / RPATH around. When building both the C library and the
# python bindings for a distro, `meson setup` will still default to shared
# libraries.
[tool.meson-python.args]
setup = ['-Ddefault_library=static', '-Dwheel-only=true']

32
scripts/install-deps.sh Executable file
View file

@ -0,0 +1,32 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-or-later
if [ -f /etc/os-release ]
then
. /etc/os-release
else
echo "ERROR: OS name is not provided."
exit 1
fi
if [ "$NAME" = "Arch Linux" ]
then
pacman -Syu --needed --noconfirm bison diffutils flex gcc git libyaml \
make meson pkgconf python python-setuptools-scm swig
elif [ "$NAME" = "Alpine Linux" ]
then
apk add build-base bison flex git yaml yaml-dev python3-dev \
meson py3-setuptools_scm swig
elif [ "$NAME" = "Fedora Linux" ]
then
dnf install -y bison diffutils flex gcc git libyaml libyaml-devel \
make meson python3-devel python3-setuptools swig
elif [ "$NAME" = "Ubuntu" ]
then
apt update
apt install -yq build-essential bison flex git libyaml-dev pkg-config \
meson python3-dev python3-setuptools python3-setuptools-scm swig
else
echo "ERROR: OS name is not provided."
exit 1
fi

View file

@ -3,7 +3,9 @@
* Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc.
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stdio.h>
@ -20,7 +22,7 @@ struct search_path {
static struct search_path *search_path_head, **search_path_tail;
/* Detect infinite include recursion. */
#define MAX_SRCFILE_DEPTH (100)
#define MAX_SRCFILE_DEPTH (200)
static int srcfile_depth; /* = 0 */
static char *get_dirname(const char *path)
@ -86,6 +88,26 @@ static char *shorten_to_initial_path(char *fname)
return NULL;
}
/**
* Returns true if the given path is an absolute one.
*
* On Windows, it either needs to begin with a forward slash or with a drive
* letter (e.g. "C:").
* On all other operating systems, it must begin with a forward slash to be
* considered an absolute path.
*/
static bool is_absolute_path(const char *path)
{
#ifdef WIN32
return (
path[0] == '/' ||
(((path[0] >= 'A' && path[0] <= 'Z') || (path[0] >= 'a' && path[0] <= 'z')) && path[1] == ':')
);
#else
return (path[0] == '/');
#endif
}
/**
* Try to open a file in a given directory.
*
@ -101,7 +123,7 @@ static char *try_open(const char *dirname, const char *fname, FILE **fp)
{
char *fullname;
if (!dirname || fname[0] == '/')
if (!dirname || is_absolute_path(fname))
fullname = xstrdup(fname);
else
fullname = join_path(dirname, fname);
@ -158,8 +180,10 @@ FILE *srcfile_relative_open(const char *fname, char **fullnamep)
strerror(errno));
}
if (depfile)
fprintf(depfile, " %s", fullname);
if (depfile) {
fputc(' ', depfile);
fprint_path_escaped(depfile, fullname);
}
if (fullnamep)
*fullnamep = fullname;
@ -283,6 +307,17 @@ struct srcpos *srcpos_extend(struct srcpos *pos, struct srcpos *newtail)
return pos;
}
void srcpos_free(struct srcpos *pos)
{
struct srcpos *p_next;
while (pos) {
p_next = pos->next;
free(pos);
pos = p_next;
}
}
char *
srcpos_string(struct srcpos *pos)
{
@ -311,8 +346,8 @@ srcpos_string(struct srcpos *pos)
static char *
srcpos_string_comment(struct srcpos *pos, bool first_line, int level)
{
char *pos_str, *fname, *first, *rest;
bool fresh_fname = false;
char *pos_str, *fresh_fname = NULL, *first, *rest;
const char *fname;
if (!pos) {
if (level > 1) {
@ -330,9 +365,9 @@ srcpos_string_comment(struct srcpos *pos, bool first_line, int level)
else if (level > 1)
fname = pos->file->name;
else {
fname = shorten_to_initial_path(pos->file->name);
if (fname)
fresh_fname = true;
fresh_fname = shorten_to_initial_path(pos->file->name);
if (fresh_fname)
fname = fresh_fname;
else
fname = pos->file->name;
}
@ -346,7 +381,7 @@ srcpos_string_comment(struct srcpos *pos, bool first_line, int level)
first_line ? pos->first_line : pos->last_line);
if (fresh_fname)
free(fname);
free(fresh_fname);
if (pos->next != NULL) {
rest = srcpos_string_comment(pos->next, first_line, level);

View file

@ -88,6 +88,7 @@ extern void srcpos_update(struct srcpos *pos, const char *text, int len);
extern struct srcpos *srcpos_copy(struct srcpos *pos);
extern struct srcpos *srcpos_extend(struct srcpos *new_srcpos,
struct srcpos *old_srcpos);
extern void srcpos_free(struct srcpos *pos);
extern char *srcpos_string(struct srcpos *pos);
extern char *srcpos_string_first(struct srcpos *pos, int level);
extern char *srcpos_string_last(struct srcpos *pos, int level);

2
tests/.gitignore vendored
View file

@ -54,6 +54,7 @@ tmp.*
/property_iterate
/propname_escapes
/references
/relref_merge
/root_node
/rw_tree1
/rw_oom
@ -73,3 +74,4 @@ tmp.*
/truncated_memrsv
/utilfdt_test
/value-labels
/get_next_tag_invalid_prop_len

View file

@ -4,7 +4,7 @@ LIB_TESTS_L = get_mem_rsv \
get_path supernode_atdepth_offset parent_offset \
node_offset_by_prop_value node_offset_by_phandle \
node_check_compatible node_offset_by_compatible \
get_alias \
get_alias get_next_tag_invalid_prop_len \
char_literal \
sized_cells \
notfound \
@ -18,7 +18,7 @@ LIB_TESTS_L = get_mem_rsv \
open_pack rw_tree1 rw_oom set_name setprop del_property del_node \
appendprop1 appendprop2 propname_escapes \
string_escapes references path-references phandle_format \
boot-cpuid incbin \
boot-cpuid incbin relref_merge \
extra-terminating-null \
dtbs_equal_ordered \
dtb_reverse dtbs_equal_unordered \
@ -33,14 +33,19 @@ LIB_TESTS_L = get_mem_rsv \
LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%)
LIBTREE_TESTS_L = truncated_property truncated_string truncated_memrsv
LIBTREE_TESTS = $(LIBTREE_TESTS_L:%=$(TESTS_PREFIX)%)
DL_LIB_TESTS_L = asm_tree_dump value-labels
DL_LIB_TESTS = $(DL_LIB_TESTS_L:%=$(TESTS_PREFIX)%)
ifneq ($(STATIC_BUILD),1)
DL_LIB_TESTS_L = asm_tree_dump value-labels
DL_LIB_TESTS = $(DL_LIB_TESTS_L:%=$(TESTS_PREFIX)%)
endif
TESTS = $(LIB_TESTS) $(LIBTREE_TESTS) $(DL_LIB_TESTS)
TESTS_TREES_L = test_tree1.dtb
TESTS_TREES_L = test_tree1.dtb bad_node_char.dtb bad_node_format.dtb \
bad_prop_char.dtb ovf_size_strings.dtb truncated_property.dtb \
truncated_string.dtb truncated_memrsv.dtb two_roots.dtb named_root.dtb
TESTS_TREES = $(TESTS_TREES_L:%=$(TESTS_PREFIX)%)
TESTS_TARGETS = $(TESTS) $(TESTS_TREES)
@ -58,17 +63,17 @@ TESTS_CLEANDIRS = $(TESTS_CLEANDIRS_L:%=$(TESTS_PREFIX)%)
.PHONY: tests
tests: $(TESTS) $(TESTS_TREES)
$(LIB_TESTS): %: $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_lib)
$(LIB_TESTS): %: $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_dep)
# Not necessary on all platforms; allow -ldl to be excluded instead of forcing
# other platforms to patch it out.
LIBDL = -ldl
$(DL_LIB_TESTS): %: %.o $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_lib)
$(DL_LIB_TESTS): %: %.o $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_dep)
@$(VECHO) LD [libdl] $@
$(LINK.c) -o $@ $^ $(LIBDL)
$(LIBTREE_TESTS): %: $(TESTS_PREFIX)testutils.o $(TESTS_PREFIX)trees.o \
util.o $(LIBFDT_lib)
util.o $(LIBFDT_dep)
$(TESTS_PREFIX)dumptrees: $(TESTS_PREFIX)trees.o

View file

@ -5,6 +5,10 @@
#size-cells = <0>;
aliases {
empty = "";
loop = "loop";
nonull = [626164];
relative = "s1/subsubnode";
s1 = &sub1;
ss1 = &subsub1;
sss1 = &subsubsub1;

View file

@ -36,6 +36,7 @@ int main(int argc, char *argv[])
buf = xmalloc(SPACE);
CHECK(fdt_open_into(fdt, buf, SPACE));
free(fdt);
fdt = buf;
CHECK(fdt_appendprop(fdt, 0, "prop-bytes", bytes, sizeof(bytes)));

View file

@ -36,7 +36,7 @@ int main(int argc, char *argv[])
err = fdt_open_into(fdt, buf, 0x1000);
if (err)
FAIL("fdt_open_into(): %s", fdt_strerror(err));
free(fdt);
fdt = buf;
/* Set up */

View file

@ -0,0 +1,22 @@
/dts-v1/;
/ {
bar: bar {
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
bar_con: endpoint {
remote-endpoint = <&foo_con>;
};
};
};
};
foo {
port {
foo_con: endpoint {
remote-endpoint = <&bar_con>;
};
};
};
};

View file

@ -0,0 +1,36 @@
/dts-v1/;
/ {
bar: bar {
ports {
#address-cells = <1>;
#size-cells = <1>; // should always be 0
port@1 {
reg = <1 2>; // should always contain only a single cell
bar_con: endpoint {
remote-endpoint = <&foo_con>;
};
};
port@2 {
reg = <2>;
bar_con2: endpoint {
remote-endpoint = <&foo_con2>;
};
};
};
};
foo {
port {
#address-cells = <1>;
#size-cells = <1>; // should always be 0
foo_con: endpoint@1 {
reg = <1 2>; // should always contain only a single cell
remote-endpoint = <&bar_con>;
};
foo_con2: endpoint@2 {
reg = <2>;
remote-endpoint = <&bar_con2>;
};
};
};
};

View file

@ -0,0 +1,7 @@
/dts-v1/;
/ {
foo {
remote-endpoint = <0xdeadbeef>;
};
};

View file

@ -0,0 +1,2 @@
/dts-v1/;
/ { endpoint {}; };

14
tests/bad-graph-root3.dts Normal file
View file

@ -0,0 +1,14 @@
/dts-v1/;
/ {
bar: bar {
port {
bar_con: endpoint {
remote-endpoint = <&foo_con>;
};
};
};
foo_con: endpoint {
remote-endpoint = <&bar_con>;
};
};

19
tests/bad-graph-root4.dts Normal file
View file

@ -0,0 +1,19 @@
/dts-v1/;
/ {
bar: bar {
port {
bar_con: endpoint {
remote-endpoint = <&foo_con>;
};
};
};
foo {
remote-endpoint = <&bar_con>; // misplaced remote-endpoint property
port {
foo_con: endpoint {
};
};
};
};

View file

@ -0,0 +1,7 @@
/dts-v1/;
/ {
intc: interrupt-controller {
interrupt-controller;
};
};

View file

@ -0,0 +1,20 @@
/dts-v1/;
/ {
interrupt-parent = <&intc>;
intc: interrupt-controller {
#interrupt-cells = <3>;
interrupt-controller;
};
node {
#address-cells = <0>;
#interrupt-cells = <1>;
interrupt-map = <1 &intc 1 2 3>;
interrupt-map-mask = <0 0>;
child {
interrupts = <1>;
};
};
};

View file

@ -0,0 +1,17 @@
/dts-v1/;
/ {
interrupt-parent = <&intc>;
intc: interrupt-controller {
};
node {
#address-cells = <0>;
#interrupt-cells = <1>;
interrupt-map = <1 &intc 1 2 3>;
child {
interrupts = <1>;
};
};
};

View file

@ -0,0 +1,19 @@
/dts-v1/;
/ {
interrupt-parent = <&intc>;
intc: interrupt-controller {
#interrupt-cells = <3>;
interrupt-controller;
};
node {
/* Missing #address-cells = <0>; */
#interrupt-cells = <1>;
interrupt-map = <1 &intc 1 2 3>;
child {
interrupts = <1>;
};
};
};

View file

@ -32,7 +32,7 @@ _dt_reserve_map:
dt_struct_start:
_dt_struct_start:
.long OF_DT_BEGIN_NODE
.string ""
.asciz ""
.balign 4
.long OF_DT_PROP
.long 0xa
@ -58,7 +58,7 @@ _dt_struct_start:
.long 0x2
.balign 4
.long OF_DT_BEGIN_NODE
.string "memory@0"
.asciz "memory@0"
.balign 4
.long OF_DT_PROP
.long 0x7
@ -77,7 +77,7 @@ _dt_struct_start:
.balign 4
.long OF_DT_END_NODE
.long OF_DT_BEGIN_NODE
.string "cpus"
.asciz "cpus"
.balign 4
.long OF_DT_PROP
.long 0x4
@ -151,22 +151,22 @@ _dt_struct_end:
.globl dt_strings_start
dt_strings_start:
_dt_strings_start:
.string "model"
.string "compatible"
.string "#address-cells"
.string "#size-cells"
.string "device_type"
.string "reg"
.string "d10"
.string "d23"
.string "b101"
.string "o17"
.string "hd00d"
.string "stuff"
.string "bad-d-1"
.string "bad-d-2"
.string "bad-o-1"
.string "bad-o-2"
.asciz "model"
.asciz "compatible"
.asciz "#address-cells"
.asciz "#size-cells"
.asciz "device_type"
.asciz "reg"
.asciz "d10"
.asciz "d23"
.asciz "b101"
.asciz "o17"
.asciz "hd00d"
.asciz "stuff"
.asciz "bad-d-1"
.asciz "bad-d-2"
.asciz "bad-o-1"
.asciz "bad-o-2"
.globl dt_strings_end
dt_strings_end:
_dt_strings_end:

View file

@ -0,0 +1,7 @@
/dts-v1/;
/ {
prop1 = < 0 >;
prop2 = < 0xffffffff >;
prop3 = < 0 >;
};

7
tests/cell-overflow.dts Normal file
View file

@ -0,0 +1,7 @@
/dts-v1/;
/ {
prop1 = < (-0xffffffff - 1) >;
prop2 = < (-0xffffffff - 2) >;
prop3 = < ((-0xffffffff - 1) * 2) >;
};

View file

@ -32,6 +32,7 @@ static void *open_dt(char *path)
* Resize our DTs to 4k so that we have room to operate on
*/
CHECK(fdt_open_into(dt, copy, FDT_COPY_SIZE));
free(dt);
return copy;
}

View file

@ -25,7 +25,7 @@
prop7;
/* yet
* another
* multline
* multiline
* comment
*/
prop8;

View file

@ -18,15 +18,16 @@
int main(int argc, char *argv[])
{
void *fdt;
void *fdt, *blob;
int subnode1_offset, subnode2_offset, subsubnode2_offset;
int err;
int oldsize, delsize, newsize;
test_init(argc, argv);
fdt = load_blob_arg(argc, argv);
blob = load_blob_arg(argc, argv);
fdt = open_blob_rw(fdt);
fdt = open_blob_rw(blob);
free(blob);
oldsize = fdt_totalsize(fdt);

View file

@ -18,16 +18,17 @@
int main(int argc, char *argv[])
{
void *fdt;
void *fdt, *blob;
const uint32_t *intp;
const char *strp;
int err, lenerr;
int oldsize, delsize, newsize;
test_init(argc, argv);
fdt = load_blob_arg(argc, argv);
blob = load_blob_arg(argc, argv);
fdt = open_blob_rw(fdt);
fdt = open_blob_rw(blob);
free(blob);
oldsize = fdt_totalsize(fdt);
@ -73,5 +74,6 @@ int main(int argc, char *argv[])
if (newsize >= oldsize)
FAIL("Tree failed to shrink after deletions");
free(fdt);
PASS();
}

View file

@ -24,13 +24,15 @@ static struct {
TREE(ovf_size_strings),
TREE(truncated_property), TREE(truncated_string),
TREE(truncated_memrsv),
TREE(two_roots),
TREE(named_root)
};
#define NUM_TREES (sizeof(trees) / sizeof(trees[0]))
int main(int argc, char *argv[])
{
int i;
unsigned int i;
if (argc != 2) {
fprintf(stderr, "Missing output directory argument\n");

View file

@ -9,7 +9,7 @@ rm -f $LOG $EXPECT
trap "rm -f $LOG $EXPECT" 0
expect="$1"
printf '%b\n' "$expect" > $EXPECT
printf "$expect\n" > $EXPECT
shift
verbose_run_log_check "$LOG" $VALGRIND $DTGET "$@"

View file

@ -0,0 +1,6 @@
/dts-v1/;
/plugin/;
/ {
prop = < &{/path/to/node} >;
};

View file

@ -54,7 +54,7 @@ static void mkfile(const char *name, void *data, size_t len)
rc = write(fd, data, len);
if (rc < 0)
FAIL("write(\"%s\"): %s", name, strerror(errno));
if (rc != len)
if ((unsigned)rc != len)
FAIL("write(\"%s\"): short write", name);
rc = close(fd);

View file

@ -21,9 +21,16 @@ static void check_alias(void *fdt, const char *path, const char *alias)
aliaspath = fdt_get_alias(fdt, alias);
if (path && !aliaspath)
if (!path && !aliaspath)
return;
if (!aliaspath)
FAIL("fdt_get_alias(%s) failed\n", alias);
if (!path)
FAIL("fdt_get_alias(%s) returned %s instead of NULL",
alias, aliaspath);
if (strcmp(aliaspath, path) != 0)
FAIL("fdt_get_alias(%s) returned %s instead of %s\n",
alias, aliaspath, path);
@ -36,9 +43,14 @@ int main(int argc, char *argv[])
test_init(argc, argv);
fdt = load_blob_arg(argc, argv);
check_alias(fdt, NULL, "empty");
check_alias(fdt, NULL, "nonull");
check_alias(fdt, NULL, "relative");
check_alias(fdt, "/subnode@1", "s1");
check_alias(fdt, "/subnode@1/subsubnode", "ss1");
check_alias(fdt, "/subnode@1/subsubnode/subsubsubnode", "sss1");
check_alias(fdt, NULL, "loop"); // Might trigger a stack overflow
PASS();
}

View file

@ -34,12 +34,14 @@ static void check_name(void *fdt, const char *path)
offset, getname, len);
if (!getname)
FAIL("fdt_get_name(%d): %s", offset, fdt_strerror(len));
if (len < 0)
FAIL("negative name length (%d) for returned node name\n", len);
if (strcmp(getname, checkname) != 0)
FAIL("fdt_get_name(%s) returned \"%s\" instead of \"%s\"",
path, getname, checkname);
if (len != strlen(getname))
if ((unsigned)len != strlen(getname))
FAIL("fdt_get_name(%s) returned length %d instead of %zd",
path, len, strlen(getname));

View file

@ -0,0 +1,100 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for fdt_next_tag()
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <libfdt.h>
#include "tests.h"
#include "testdata.h"
#define FDT_SIZE 65536
#define CHECK_ERR(err) \
({ if (err) \
FAIL("%s: %d: %s", __FILE__, __LINE__, fdt_strerror(err)); \
})
static void fdt_next_tag_test(bool fdt_finished)
{
struct fdt_property *prp;
void *fdt;
int nextoff = 0, offset, err;
uint32_t tag;
fdt = malloc(FDT_SIZE);
if (!fdt)
FAIL("Can't allocate memory");
err = fdt_create(fdt, FDT_SIZE);
CHECK_ERR(err);
err = fdt_finish_reservemap(fdt);
CHECK_ERR(err);
/* Create a root node and add two properties */
err = fdt_begin_node(fdt, "");
CHECK_ERR(err);
err = fdt_property_u32(fdt, "prop-int-32", 0x1234);
CHECK_ERR(err);
err = fdt_property_u32(fdt, "prop2-int-32", 0x4321);
CHECK_ERR(err);
err = fdt_end_node(fdt);
CHECK_ERR(err);
if (fdt_finished) {
/* Call fdt_finish to set the correct fdt state. */
err = fdt_finish(fdt);
CHECK_ERR(err);
}
offset = fdt_first_property_offset(fdt, 0);
if (offset <= 0)
FAIL("Invalid offset %x, expected value greater than 0, finished=%d\n",
offset, fdt_finished);
/* Normal case */
tag = fdt_next_tag(fdt, offset, &nextoff);
if (tag != FDT_PROP)
FAIL("Invalid tag %x, expected FDT_PROP, finished=%d\n",
tag, fdt_finished);
if (nextoff <= 0)
FAIL("Invalid nextoff %d, expected value greater than 0, finished=%d",
nextoff, fdt_finished);
/* Get a writable ptr to the first property and corrupt the length */
prp = fdt_get_property_by_offset_w(fdt, offset, NULL);
if (!prp)
FAIL("Bad property pointer, finished=%d", fdt_finished);
/* int overflow case */
prp->len = cpu_to_fdt32(0xFFFFFFFA);
tag = fdt_next_tag(fdt, offset, &nextoff);
if (tag != FDT_END)
FAIL("Invalid tag %x, expected premature FDT_END, finished=%d",
tag, fdt_finished);
if (nextoff != -FDT_ERR_BADSTRUCTURE)
FAIL("Invalid nextoff, expected error -FDT_ERR_BADSTRUCTURE, finished=%d",
fdt_finished);
/* negative offset case */
prp->len = cpu_to_fdt32(0x7FFFFFFA);
tag = fdt_next_tag(fdt, offset, &nextoff);
if (tag != FDT_END)
FAIL("Invalid tag %x, expected premature FDT_END, finished=%d",
tag, fdt_finished);
if (nextoff != -FDT_ERR_BADSTRUCTURE)
FAIL("Invalid nextoff, expected -FDT_ERR_BADSTRUCTURE, finished=%d",
fdt_finished);
free(fdt);
}
int main(int argc, char *argv[])
{
test_init(argc, argv);
fdt_next_tag_test(false);
fdt_next_tag_test(true);
PASS();
}

12
tests/good-gpio.dts Normal file
View file

@ -0,0 +1,12 @@
/dts-v1/;
/ {
gpio: gpio-controller {
#gpio-cells = <3>;
};
node {
foo,nr-gpios = <1>;
foo-gpios = <&gpio 1 2 3>;
};
};

View file

@ -59,7 +59,7 @@ int main(int argc, char *argv[])
void *fdt;
const fdt32_t *res;
int reslen;
int i;
unsigned int i;
test_init(argc, argv);

163
tests/meson.build Normal file
View file

@ -0,0 +1,163 @@
trees = static_library('trees', files('trees.S'),
build_by_default: false,
include_directories: libfdt_inc)
dumptrees = executable('dumptrees', files('dumptrees.c'),
build_by_default: false,
link_with: trees, dependencies: libfdt_dep)
dumptrees_dtb = custom_target(
'dumptrees',
command: [dumptrees, meson.current_build_dir()],
output: [
'test_tree1.dtb',
'bad_node_char.dtb',
'bad_node_format.dtb',
'bad_prop_char.dtb',
'ovf_size_strings.dtb',
'truncated_property.dtb',
'truncated_string.dtb',
'truncated_memrsv.dtb',
]
)
testutil_dep = declare_dependency(sources: ['testutils.c'], link_with: trees)
tests = [
'add_subnode_with_nops',
'addr_size_cells',
'addr_size_cells2',
'appendprop1',
'appendprop2',
'appendprop_addrrange',
'boot-cpuid',
'char_literal',
'check_full',
'check_header',
'check_path',
'del_node',
'del_property',
'dtb_reverse',
'dtbs_equal_ordered',
'dtbs_equal_unordered',
'extra-terminating-null',
'find_property',
'fs_tree1',
'get_alias',
'get_mem_rsv',
'get_name',
'get_path',
'get_phandle',
'get_prop_offset',
'get_next_tag_invalid_prop_len',
'getprop',
'incbin',
'integer-expressions',
'mangle-layout',
'move_and_save',
'node_check_compatible',
'node_offset_by_compatible',
'node_offset_by_phandle',
'node_offset_by_prop_value',
'nop_node',
'nop_property',
'nopulate',
'notfound',
'open_pack',
'overlay',
'overlay_bad_fixup',
'parent_offset',
'path-references',
'path_offset',
'path_offset_aliases',
'phandle_format',
'property_iterate',
'propname_escapes',
'references',
'relref_merge',
'root_node',
'rw_oom',
'rw_tree1',
'set_name',
'setprop',
'setprop_inplace',
'sized_cells',
'string_escapes',
'stringlist',
'subnode_iterate',
'subnode_offset',
'supernode_atdepth_offset',
'sw_states',
'sw_tree1',
'utilfdt_test',
]
tests += [
'truncated_memrsv',
'truncated_property',
'truncated_string',
]
test_deps = [testutil_dep, util_dep, libfdt_dep]
dl = cc.find_library('dl', required: false)
if dl.found()
tests += [
'asm_tree_dump',
'value-labels',
]
test_deps += [dl]
endif
tests_exe = []
foreach t: tests
tests_exe += executable(t, files(t + '.c'), dependencies: test_deps, build_by_default: false)
endforeach
run_tests = find_program('run_tests.sh')
env = []
if not py.found()
env += 'NO_PYTHON=1'
else
env += [
'PYTHON=' + py.full_path(),
'PYTHONPATH=' + meson.project_source_root() / 'pylibfdt',
'NO_PYTHON=0',
]
endif
if not yaml.found()
env += 'NO_YAML=1'
else
env += 'NO_YAML=0'
endif
run_test_types = [
'libfdt',
'utilfdt',
'dtc',
'dtbs_equal',
'fdtget',
'fdtput',
'fdtdump',
'fdtoverlay'
]
run_test_deps = [
dtc_tools, dumptrees_dtb, tests_exe
]
if pylibfdt_enabled
run_test_types += 'pylibfdt'
run_test_deps += pylibfdt
endif
foreach test_type : run_test_types
test(
test_type,
run_tests,
args: ['-t', test_type],
is_parallel: false,
workdir: meson.current_build_dir(),
depends: run_test_deps,
env: env,
timeout: 1800, # mostly for valgrind
)
endforeach

View file

@ -43,7 +43,8 @@ static int nopulate_struct(char *buf, const char *fdt)
int main(int argc, char *argv[])
{
char *fdt, *fdt2, *buf;
int newsize, struct_start, struct_end_old, struct_end_new, delta;
int newsize, struct_end_old, struct_end_new, delta;
unsigned int struct_start;
const char *inname;
char outname[PATH_MAX];
@ -64,7 +65,7 @@ int main(int argc, char *argv[])
verbose_printf("Nopulated structure block has new size %d\n", newsize);
/* Replace old strcutre block with the new */
/* Replace old structure block with the new */
fdt2 = xmalloc(fdt_totalsize(fdt) + newsize);

View file

@ -35,7 +35,11 @@ static int fdt_getprop_u32_by_poffset(void *fdt, const char *path,
return node_off;
val = fdt_getprop(fdt, node_off, name, &len);
if (!val || (len < (sizeof(uint32_t) * (poffset + 1))))
if (val && len < 0)
FAIL("fdt_getprop() returns negative length");
if (!val && len < 0)
return len;
if (!val || ((unsigned)len < (sizeof(uint32_t) * (poffset + 1))))
return -FDT_ERR_NOTFOUND;
*out = fdt32_to_cpu(*(val + poffset));
@ -182,6 +186,7 @@ static void *open_dt(char *path)
* Resize our DTs to 4k so that we have room to operate on
*/
CHECK(fdt_open_into(dt, copy, FDT_COPY_SIZE));
free(dt);
return copy;
}

View file

@ -0,0 +1,21 @@
/*
* Copyright (c) 2024 Uwe Kleine-König
*
* SPDX-License-Identifier: GPL-2.0+
*/
/dts-v1/;
/ {
node_a: a {
value = <17>;
};
node_b: b {
a = <&node_a>;
};
node_d: d {
b = <&node_b>;
};
};

View file

@ -46,3 +46,7 @@
new-sub-test-property;
};
};
&{/new-local-node} {
another-new-property;
};

View file

@ -72,6 +72,14 @@
};
};
fragment@7 {
target-path = "/new-local-node";
__overlay__ {
another-new-property;
};
};
__local_fixups__ {
fragment@5 {
__overlay__ {

View file

@ -48,7 +48,7 @@
};
};
fragment@5 {
fragment@4 {
target = <&test>;
__overlay__ {
@ -58,7 +58,7 @@
};
};
fragment@6 {
fragment@5 {
target = <&test>;
__overlay__ {
@ -66,7 +66,7 @@
};
};
fragment@7 {
fragment@6 {
target = <&test>;
__overlay__ {
@ -74,7 +74,7 @@
};
};
fragment@8 {
fragment@7 {
target = <&test>;
__overlay__ {

View file

@ -0,0 +1,34 @@
/*
* Copyright (c) 2024 Uwe Kleine-König
*
* SPDX-License-Identifier: GPL-2.0+
*/
/dts-v1/;
/plugin/;
&{/} {
/*
* /b already has a label "node_b" in the base dts, also b is already
* referenced in the base, so both the base's b and this b have a
* phandle value.
*/
node_b2: b {
value = <42>;
d = <&node_d>;
};
node_c: c {
value = <23>;
b = <&node_b2>;
};
d {
a = <&node_a>;
c = <&node_c>;
};
};
&node_a {
value = <32>;
};

View file

@ -53,7 +53,7 @@ int main(int argc, char *argv[])
void *fdt;
const char *p;
int len, multilen;
int n1, n2, n3, n4;
int n1, n2, n3, n4, n5;
test_init(argc, argv);
fdt = load_blob_arg(argc, argv);
@ -89,6 +89,12 @@ int main(int argc, char *argv[])
check_ref(fdt, n3, "/foobar/baz");
check_ref(fdt, n4, "/foo/baz");
n5 = fdt_path_offset(fdt, "/bar/baz");
if (n5 < 0)
FAIL("fdt_path_offset(/bar/baz): %s", fdt_strerror(n5));
check_ref(fdt, n5, "/bar/baz");
check_rref(fdt);
PASS();

View file

@ -25,4 +25,13 @@
lref = &n3;
};
};
n5: bar {
baz {
};
};
};
n6: &{n5/baz} {
ref = &{n6/};
lref = &{n5/baz};
};

View file

@ -41,22 +41,25 @@ static int check_subnode(void *fdt, int parent, const char *name)
return offset;
}
static void check_path_offset(void *fdt, char *path, int offset)
static void check_path_offset(void *fdt, const char *path, int offset)
{
int rc;
verbose_printf("Checking offset of \"%s\" is %d...\n", path, offset);
rc = fdt_path_offset(fdt, path);
if (rc == offset)
return;
if (rc < 0)
FAIL("fdt_path_offset(\"%s\") failed: %s",
path, fdt_strerror(rc));
if (rc != offset)
else
FAIL("fdt_path_offset(\"%s\") returned incorrect offset"
" %d instead of %d", path, rc, offset);
}
static void check_path_offset_namelen(void *fdt, char *path, int namelen,
static void check_path_offset_namelen(void *fdt, const char *path, int namelen,
int offset)
{
int rc;
@ -102,6 +105,7 @@ int main(int argc, char *argv[])
check_path_offset(fdt, "/subnode@2/subsubnode", subsubnode2_offset2);
/* Test paths with extraneous separators */
check_path_offset(fdt, "", -FDT_ERR_BADPATH);
check_path_offset(fdt, "//", 0);
check_path_offset(fdt, "///", 0);
check_path_offset(fdt, "//subnode@1", subnode1_offset);
@ -110,6 +114,8 @@ int main(int argc, char *argv[])
check_path_offset(fdt, "/subnode@2////subsubnode", subsubnode2_offset2);
/* Test fdt_path_offset_namelen() */
check_path_offset_namelen(fdt, "/subnode@1", -1, -FDT_ERR_BADPATH);
check_path_offset_namelen(fdt, "/subnode@1", 0, -FDT_ERR_BADPATH);
check_path_offset_namelen(fdt, "/subnode@1", 1, 0);
check_path_offset_namelen(fdt, "/subnode@1/subsubnode", 10, subnode1_offset);
check_path_offset_namelen(fdt, "/subnode@1/subsubnode", 11, subnode1_offset);

Some files were not shown because too many files have changed in this diff Show more