Compare commits

...

376 Commits

Author SHA1 Message Date
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]: 9308e7f977

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
David Gibson 2525da3dba Bump version to v1.6.0
We've accumulated some new features and a bunch of fixes.  Also the
versioning on v1.5.1 was messed up :(.  Prepare for another release.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-03-04 17:14:58 +11:00
David Gibson 62cb4ad286 Execute tests on FreeBSD with Cirrus CI
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-03-04 16:40:00 +11:00
David Gibson 1f9a417508 tests: Allow running the testsuite on already installed binary / libraries
Currently the test runner script always expects to be run from within the
tests/ subdirectory of a dtc source tree: it looks for dtc and other
binaries in the parent of the current directory and for the libfdt shared
library in ../libfdt.

That works great with make check and for testing a build you've just made.
However, sometimes it's useful to test a dtc & libfdt which have already
been installed on the system, or which for whatever reason are located
somewhere else.

This patch allows the test runner script to do this when TEST_BINDIR and/or
TEST_LIBDIR environment variables are set.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-03-04 16:38:04 +11:00
David Gibson c5995ddf4c tests: Honour NO_YAML make variable
Support for YAML output in dtc is optional (to cover systems that don't
have libyaml).  Currently the tests for yaml output test if the libyaml
package is locally installed.

That duplicates similar logic in the Makefile, and worse it will cause
failed tests if the user explicitly disables YAML support, rather than
simply not having libyaml installed.

Fix this by having the test script use the NO_YAML variable exported by
make.  Fall back to the current test if the variable isn't set, such as
when running the script manually.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-03-04 16:10:06 +11:00
David Gibson e4ce227e89 tests: Properly clean up .bak file from tests
One of our testcases creates a .bak file from invoking sed.  Fix that to be
removed by make clean, and also ignore it in git to avoid clutter.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-03-04 16:05:31 +11:00
David Gibson 9b75292c33 tests: Honour $(NO_PYTHON) flag from Makefile in run_tests.sh
Currently the test script bases whether to run the Python tests on whether
it can see a built Python module.  That can easily be fooled if there is
a stale module there.

Instead, have it actually look at the NO_PYTHON variable exported from the
Makefile.  If the variable doesn't exist (such as if we're running the
script manually) fall back on the old logic.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-03-04 16:03:28 +11:00
David Gibson 6c253afd07 Encode $(NO_PYTHON) consistently with other variables
We have several $(NO_*) variables used to disable optional features.
$(NO_PYTHON) is encoded as empty for "include Python support" and anything
else for "disable Python support".

However the other variables - $(NO_YAML) and $(NO_VALGRIND) - use 0 for
"include" and 1 for "disable".  Change $(NO_PYTHON) to work consistently
with the others.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-03-04 15:44:00 +11:00
David Gibson 95ec8ef706 tests: No need to explicitly pass $PYTHON from Make to run_tests.sh
Make automatically passes its variables through the environment, so
we don't need to explicitly copy this one into the test script.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-03-04 15:38:48 +11:00
David Gibson 2b5f62d109 tests: Let run_tests.sh run Python tests without Makefile assistance
Currently run_tests.sh needs the $PYTHON environment variable set to
correctly run pylibfdt tests.  The Makefile does this for make check, but
it breaks if the script is run manually.  Add a fallback to handle that
case.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-03-04 15:32:47 +11:00
Rob Herring 76b43dcbd1 checks: Add 'dma-ranges' check
Generalize the existing 'ranges' check to also work for 'dma-ranges'
which has the same parsing requirements.

Signed-off-by: Rob Herring <robh@kernel.org>
Message-Id: <20200303193931.1653-1-robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-03-04 10:30:12 +11:00
Simon Glass e5c92a4780 libfdt: Use VALID_INPUT for FDT_ERR_BADSTATE checks
This error indicates a logic bug in the code calling libfdt, so VALID_DTB
is not really the right check. Update it to use VALID_INPUT instead.

Signed-off-by: Simon Glass <sjg@chromium.org>
Suggested-by: David Gibson <david@gibson.dropbear.id.au>
Message-Id: <20200302190255.51426-4-sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-03-03 09:59:55 +11:00
Simon Glass e5cc26b68b libfdt: Add support for disabling internal checks
If libfdt returns -FDT_ERR_INTERNAL that generally indicates a bug in the
library. Add a new assumption for these cases since it should be save to
disable these checks regardless of the input.

Signed-off-by: Simon Glass <sjg@chromium.org>
Suggested-by: David Gibson <david@gibson.dropbear.id.au>
Message-Id: <20200302190255.51426-3-sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-03-03 09:59:55 +11:00
Simon Glass 28fd7590aa libfdt: Improve comments in some of the assumptions
Add a little more detail in a few of these comments.

Signed-off-by: Simon Glass <sjg@chromium.org>
Suggested-by: David Gibson <david@gibson.dropbear.id.au>
Message-Id: <20200302190255.51426-2-sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-03-03 09:59:55 +11:00
Simon Glass fc207c3234 libfdt: Fix a few typos
Fix 'saftey' and 'additional' typos noticed in the assumption series.
Reword the ASSUME_NO_ROLLBACK slightly to improve clarity.

Signed-off-by: Simon Glass <sjg@chromium.org>
Suggested-by: David Gibson <david@gibson.dropbear.id.au>
Message-Id: <20200302190255.51426-1-sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-03-03 09:59:55 +11:00
Simon Glass 0f61c72ded libfdt: Allow exclusion of fdt_check_full()
This function is used to perform a full check of the device tree. Allow
it to be excluded if all assumptions are enabled.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Message-Id: <20200220214557.176528-9-sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-02-24 13:38:44 +11:00
Simon Glass f270f45fd5 libfdt: Add support for disabling ordering check/fixup
Add a way to remove this check and the reordering code, which is
unnecessary if the dtb is known to be correctly ordered.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Message-Id: <20200220214557.176528-8-sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-02-24 13:38:44 +11:00
Simon Glass c18bae9a4c libfdt: Add support for disabling version checks
Allow enabling FDT_ASSUME_LATEST to disable version checks.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Message-Id: <20200220214557.176528-7-sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-02-24 13:38:44 +11:00
Simon Glass fc03c4a2e0 libfdt: Add support for disabling rollback handling
Allow enabling FDT_ASSUME_NO_ROLLBACK to disable rolling back after a
failed operation.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Message-Id: <20200220214557.176528-6-sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-02-24 13:38:44 +11:00
Simon Glass 77563ae72b libfdt: Add support for disabling sanity checks
Allow enabling ASSUME_VALID_INPUT to disable sanity checks on the device
tree and the parameters to libfdt. This assumption covers that cases where
the problem could be with either.

Signed-off-by: Simon Glass <sjg@chromium.org>
Message-Id: <20200220214557.176528-5-sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-02-24 13:38:44 +11:00
Simon Glass 57bc6327b8 libfdt: Add support for disabling dtb checks
Support ASSUME_VALID_DTB to disable some sanity checks

If we assume that the DTB itself is valid then we can skip some checks and
save code space. Add various conditions to handle this.

Signed-off-by: Simon Glass <sjg@chromium.org>
Message-Id: <20200220214557.176528-4-sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-02-24 13:38:44 +11:00
Simon Glass 464962489d Add a way to control the level of checks in the code
Add a new ASSUME_MASK option, which allows for some control over the
checks used in libfdt. With all assumptions enabled, libfdt assumes that
the input data and parameters are all correct and that internal errors
cannot happen.

By default no assumptions are made and all checks are enabled.

Signed-off-by: Simon Glass <sjg@chromium.org>
Message-Id: <20200220214557.176528-3-sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-02-24 13:38:44 +11:00
Simon Glass 0c5326cb28 libfdt: De-inline fdt_header_size()
There does not seem to be a strong reason to inline this function. Also
we are about to add some extra code to it which will increase its size.

Move it into fdt.c and use a simple declaration in libfdt.h

Signed-off-by: Simon Glass <sjg@chromium.org>
Message-Id: <20200220214557.176528-2-sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-02-24 13:38:44 +11:00
Rob Herring cc6a5a0715 Revert "yamltree: Ensure consistent bracketing of properties with phandles"
This reverts commit 18d7b2f4ee.

This doesn't work for properties such as 'interrupt-map' that has
phandle in the middle of an entry. It would also not work for a 0 or -1
phandle value that acts as a NULL.

Signed-off-by: Rob Herring <robh@kernel.org>
Message-Id: <20200124144657.29749-1-robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-01-29 14:41:33 +11:00
Dirk Mueller 0e9225eb0d Remove redundant YYLOC global declaration
gcc 10 will default to -fno-common, which causes this error at link
time:

  (.text+0x0): multiple definition of `yylloc'; dtc-lexer.lex.o (symbol from plugin):(.text+0x0): first defined here

This is because both dtc-lexer as well as dtc-parser define the same
global symbol yyloc. Before with -fcommon those were merged into one
defintion. The proper solution would be to to mark this as "extern",
however that leads to:

  dtc-lexer.l:26:16: error: redundant redeclaration of 'yylloc' [-Werror=redundant-decls]
   26 | extern YYLTYPE yylloc;
      |                ^~~~~~
In file included from dtc-lexer.l:24:
dtc-parser.tab.h:127:16: note: previous declaration of 'yylloc' was here
  127 | extern YYLTYPE yylloc;
      |                ^~~~~~
cc1: all warnings being treated as errors

which means the declaration is completely redundant and can just be
dropped.

Signed-off-by: Dirk Mueller <dmueller@suse.com>
Message-Id: <20200114175341.2994-1-dmueller@suse.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-01-16 11:00:19 +10:00
David Gibson cab09eedd6 Move -DNO_VALGRIND into CPPFLAGS
Since -D sets preprocessor directives, it applies for the preprocessor not
just the C compiler proper and so belongs in CPPFLAGS rather than CFLAGS.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-12-19 13:14:45 +11:00
Ed Maste 0eb1cb0b53 Makefile: pass $(CFLAGS) also during dependency generation
When Valgrind is not available NO_VALGRIND is set in CFLAGS, and this
is needed during dependency generation as well as compilation.
Message-Id: <20191210163033.9888-1-emaste@freefall.freebsd.org>

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-12-17 12:34:46 +11:00
Thomas Huth c40aeb60b4 travis.yml: Run tests on the non-x86 builders, too
Travis recently added the possibility to compile on aarch64, ppc64le
and s390x hosts, so let's add this possibility to the dtc CI, too.
Unfortunately, there are some weird valgrind errors when running
on ppc64le (which rather look like a problem on the valgrind side to
me, and not in dtc), so we can not use "checkm" on ppc64le yet.

Signed-off-by: Thomas Huth <thuth@redhat.com>
Message-Id: <20191203122020.14442-1-thuth@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-12-04 16:54:04 +11:00
Ed Maste 9f86aff444 Add .cirrus.yml for FreeBSD build
Right now this is just a build test for FreeBSD, along with a Linux build
and "make check."  A later change will add "gmake check" for FreeBSD.

Signed-off-by: Ed Maste <emaste@freebsd.org>
Message-Id: <20191120211133.69281-1-emaste@freefall.freebsd.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-11-21 12:33:24 +11:00
Ed Maste 34c82275ba Avoid gnu_printf attribute when using Clang
Clang does not support gnu_printf, so just use printf when using it to
compile.

Signed-off-by: Ed Maste <emaste@freebsd.org>
Message-Id: <20191120210422.61327-1-emaste@freefall.freebsd.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-11-21 12:31:36 +11:00
Ed Maste 743000931b tests: default to 'cc' if CC not set
By default FreeBSD does not have 'gcc' in the PATH (on common platforms).
As on Linux 'cc' is available as a link to the default compiler (Clang or
GCC), so just use 'cc'.

Signed-off-by: Ed Maste <emaste@freebsd.org>
Message-Id: <20191115155108.39488-1-emaste@freefall.freebsd.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-11-16 09:16:28 +11:00
Stefan Mavrodiev adcd676491 Add test-case for trailing zero
If there is trailing zero, fdtget adds extra chacarter to the
property value. Thus comparing the expected with the actual
value, an error is emitted.

Signed-off-by: Stefan Mavrodiev <stefan@olimex.com>
Message-Id: <20191111080444.9819-3-stefan@olimex.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-11-15 20:42:47 +11:00
Stefan Mavrodiev d9c55f855b Remove trailing zero from the overlay path
The overlay path ends with trailing zero. When adding this path
as property value, this character should be removed. This is the case
when the overlay adds a node with an alias.

Signed-off-by: Stefan Mavrodiev <stefan@olimex.com>
Message-Id: <20191111080444.9819-2-stefan@olimex.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-11-15 20:42:47 +11:00
Simon Glass 7a22132c79 pylibfdt: Adjust for deprecated test methods
Python recently deprecated some test methods in favour of others. Adjust
the code to avoid warnings.

Signed-off-by: Simon Glass <sjg@chromium.org>
Message-Id: <20191113012410.62550-1-sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-11-15 20:21:21 +11:00
Ed Maste dbe80d577e tests: add extension to sed -i for GNU/BSD sed compatibility
BSD sed requires that an extension is provided to the -i (in-place edit)
flag, which may immediately follow the -i or may be separated by a space -
sed -i .bak and sed -i.bak are equivalent.  The extension is optional with
GNU sed, but if provided must immediately follow the -i.  Thus, sed -i.bak
behaves identically with both GNU and BSD sed.

Signed-off-by: Ed Maste <emaste@freebsd.org>
Message-Id: <20191114203615.2866-1-emaste@freefall.freebsd.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-11-15 20:08:25 +11:00
David Gibson af57d440d8 libfdt: Correct prototype for fdt_ro_probe_()
This function returns an int32_t, however the prototype in
libfdt_internal.h shows it returning an int.  We haven't caught this before
because they're the same type on nearly all platforms this gets built on.
Apparently it's not the case on FreeRTOS, so someone hit this mismatch
building for that platform.

Reported-by: dharani kumar <dharanikumarsrvn@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-11-08 14:42:53 +00:00
David Gibson 6ce585ac15 Use correct inttypes.h format specifier
The type here is uint32_t which should use PRIx32, not plain %x which is
for an int, we've just gotten away with it so far.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-11-07 17:46:43 +01:00
Ethan Sommer 7150286225 support byacc in addition to bison
Use -b to explicitly set file prefix, so that byacc generates files with
the same names as bison.

Add %locations to dtc-parser.y to explicitly enable location tracking
for byacc, and define YYERROR_CALL to prevent byacc from defining it to
call yyerror with 2 parameters because of the locations directive,
because dtc-parser.y defines yyerror to accept one parameter.

Signed-off-by: Ethan Sommer <e5ten.arch@gmail.com>
Message-Id: <20191029162619.32561-1-e5ten.arch@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-11-03 20:20:22 +01:00
Simon Glass fdf3f6d897 pylibfdt: Correct the type for fdt_property_stub()
This function should use a void * type, not char *. This causes an error:

TypeError: in method 'fdt_property_stub', argument 3 of type 'char const *'

Fix it and update the tests.

Signed-off-by: Simon Glass <sjg@chromium.org>
Message-Id: <20191025010226.34378-1-sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-10-27 17:50:53 +01:00
Marc-André Lureau 430419c281 tests: fix some python warnings
Fixes:
ResourceWarning: unclosed file <_io.BufferedReader name='test_tree1.dtb'>

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20191009102025.10179-9-marcandre.lureau@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-10-14 17:09:13 +11:00
Marc-André Lureau 588a29ff2e util: use gnu_printf format attribute
dtc uses non-portable formats. Using gnu_printf attributes (for
warnings) in combination with __USE_MINGW_ANSI_STDIO allows to build
for win32.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20191009102025.10179-8-marcandre.lureau@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-10-14 17:07:46 +11:00
Marc-André Lureau bc876708ab fstree: replace lstat with stat
Fixes mingw cross-compilation. lstat() doesn't exist on win32.

It seems to me that stat() is the right function there, to return
informations about the file it refers to.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20191009102025.10179-7-marcandre.lureau@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-10-14 17:07:10 +11:00
Marc-André Lureau 4c3c4ccb99 dumptrees: pass outputdir as first argument
Instead of outputing files to current directory, allow to specificy an
output directory. This helps with meson build system out-of-tree support.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20191009102025.10179-4-marcandre.lureau@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-10-14 16:20:32 +11:00
Marc-André Lureau aa522da9ff tests: allow out-of-tree test run
meson runs out-of-tree, add absolute path location where necessary.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20191009102025.10179-3-marcandre.lureau@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-10-14 16:19:29 +11:00
Valter Minute 0d0d0fa51b fdtoverlay: Return non-zero exit code if overlays can't be applied
At present the tool terminates its execution if one of the overlays passed
as command-line arguments can't be successfully read or applied, but the exit
code of the process is zero, making failures hard to detect inside scripts.

Signed-off-by: Valter Minute <valter.minute@toradex.com>
Message-Id: <20191009123256.14248-1-valter.minute@toradex.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-10-11 15:58:18 +11:00
Marc-André Lureau 4605eb047b Add .editorconfig
Set code style for various editors.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20191009102025.10179-2-marcandre.lureau@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-10-09 22:41:44 +11:00
Rob Herring 18d7b2f4ee yamltree: Ensure consistent bracketing of properties with phandles
The dts syntax allows for '<>' around phandles and arg cells or not
which it didn't matter until adding type information. However, the YAML
encoding expects each phandle + args to be bracketed.

If TYPE_UINT32 markers are not present before each REF_PHANDLE, fix up
the markers and add the TYPE_UINT32 markers. This allows the subsequent
YAML emitting code to work as-is.

Adding the markers at an earlier stage doesn't work because of
possible labels in dts output. We'd have to define the ordering of
labels and brackets. Also, it is probably best to have dts output match
the input.

Signed-off-by: Rob Herring <robh@kernel.org>
Message-Id: <20190918183534.24205-1-robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-09-25 11:48:50 +10:00
Luc Michel 67f790c1ad libfdt.h: add explicit cast from void* to uint8_t* in fdt(32|64)_st
Including libfdt.h in a C++ project fails during compilation with recent
version of GCC or Clang.

This simple example:

extern "C" {
 #include <libfdt.h>
}

int main(void) { return 0; }

leads to the following errors with GCC 9.1.0:

/usr/include/libfdt.h: In function ‘void fdt32_st(void*, uint32_t)’:
/usr/include/libfdt.h:139:16: error: invalid conversion from ‘void*’ to ‘uint8_t*’ {aka ‘unsigned char*’} [-fpermissive]
  139 |  uint8_t *bp = property;
      |                ^~~~~~~~
      |                |
      |                void*
/usr/include/libfdt.h: In function ‘void fdt64_st(void*, uint64_t)’:
/usr/include/libfdt.h:163:16: error: invalid conversion from ‘void*’ to ‘uint8_t*’ {aka ‘unsigned char*’} [-fpermissive]
  163 |  uint8_t *bp = property;
      |                ^~~~~~~~
      |                |
      |                void*

This commit adds an explicit cast to uint8_t* to fix this issue.

Signed-off-by: Luc Michel <luc.michel@greensocs.com>
Message-Id: <20190910104824.1321594-1-luc.michel@greensocs.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-09-10 23:11:40 +10:00
Luca Weiss b111122ea5 pylibfdt: use python3 shebang
The default Python version for pylibfdt is already Python 3 but if
called without specifiying an interpreter, the setup.py script gets
called with Python 2.

It's of course still possible to call setup.py with python2 directly.

Signed-off-by: Luca Weiss <luca@z3ntu.xyz>
Message-Id: <20190907152530.25102-1-luca@z3ntu.xyz>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-09-09 15:20:55 +10:00
David Gibson 60e0db3d65 Ignore phandle properties in /aliases
The 'alias_paths' check verifies that each property in /aliases is a valid
path to another node.  However this can cans false positives trees where
the /aliases node has a phandle property, which isn't in this format but
is allowed.  In particular this situation can be common with trees dumped
from some real OF systems (which typically generate a phandle for every
node).

Special case this to avoid the spurious error.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-09-04 14:58:28 +10:00
Luca Weiss 95ce19c140 README: update for Python 3
Convert the usage to be compatible with Python 3 and the current API.

Signed-off-by: Luca Weiss <luca@z3ntu.xyz>
Message-Id: <20190817212532.15661-2-luca@z3ntu.xyz>
Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-08-29 11:06:11 +10:00
Denis Efremov 5345db19f6 livetree: simplify condition in get_node_by_path
The "strlen && strprefixeq" check in get_node_by_path is
excessive, since strlen is checked in strprefixeq macro
internally. Thus, "strlen(child->name) == p-path"
conjunct duplicates after macro expansion and could
be removed.

Signed-off-by: Denis Efremov <efremov@linux.com>
Message-Id: <20190827204148.20604-1-efremov@linux.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-08-28 13:57:27 +10:00
David Gibson b8d6eca782 libfdt: Allow #size-cells of 0
c12b2b0c20 "libfdt: fdt_address_cells() and fdt_size_cells()" introduced
a bug as it consolidated code between the helpers for getting
#address-cells and #size-cells.  Specifically #size-cells is allowed to
be 0, and is frequently found so in practice for /cpus.  IEEE1275 only
requires implementations to handle 1..4 for #address-cells, although one
could make a case for #address-cells == #size-cells == 0 being used to
represent a bridge with a single port.

While we're there, it's not totally obvious that the existing implicit
cast of a u32 to int will give the correct results according to strict C,
although it does work in practice.  Straighten that up to cast only after
we've made our range checks.

Reported-by: yonghuhaige via https://github.com/dgibson/dtc/issues/28
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-07-28 16:31:44 +10:00
Joel Stanley 184f510994 Makefile: Add EXTRA_CFLAGS variable
Distributions packaging dtc may need to set extra flags. Currently when
they do that it overrides the ones set by the makefile. This is
particularly problematic when compiling without yaml, as the yaml
detection is ignored.

 ld: dtc.o: in function `main':
 dtc.c:(.text.startup+0x718): undefined reference to `dt_to_yaml'

This patch provides a EXTRA_CFLAGS variable that is added to the list of
CFLAGS, and can be set on the command line when packaging.

Signed-off-by: Joel Stanley <joel@jms.id.au>
Message-Id: <20190722030244.9580-1-joel@jms.id.au>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-07-22 13:13:24 +10:00
David Gibson 812b1956a0 libfdt: Tweak data handling to satisfy Coverity
In libfdt we often sanity test fdt_totalsize(fdt) fairly early, then
trust it (but *only* that header field) for the remainder of our work.
However, Coverity gets confused by this - it sees the byteswap in
fdt32_ld() and assumes that means it is coming from an untrusted source
everytime, resulting in many tainted data warnings.

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

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

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

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-07-05 15:31:12 +10:00
David Gibson 5c715a4477 fdtoverlay: Ignore symbols in overlays which don't apply to the target tree
Symbols from overlays are merged into the target tree, and are required to
have the form:
	/fragment@XXX/__overlay__/...
If any symbols don't have this form, the overlay is rejected.

But there's not really anything wrong with an overlay having "local"
labels referring to a fragment node or some other metadata, that's not
expected to end up in a target tree.

So change our overlay application to simply ignore such symbols rather than
fail.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-07-04 15:10:01 +10:00
David Gibson b993534748 fdtoverlay: Allow adding labels to __overlay__ nodes in overlays
When applying overlays, we merge symbols from the overlay into the target
tree.  At the moment the logic for this assumes all symbols in the overlay
are attached to a node of the form:
	/fragment@XXX/__overlay__/relative/path

And will end up applied to the relative/path node under the fragment's
target.

However, this disallows the case of a symbol in the form just:
	/fragment@XXX/__overlay__

This does have a pretty obvious sensible meaning: attach the new symbol
directly to the fragment's target, but we don't currently do that.

It's pretty easy to workaround this limitation in one's overlays, but it's
also easy to handle in the overlay applying code, so we might as well
extend it to cover this case.

Reported-by: Christophe Braillon
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-07-04 14:39:02 +10:00
Appana Durga Kedareswara rao d6de81b81b pylibfdt: Add support for fdt_get_alias()
Add this into the class to simplify use of this function.

Signed-off-by: Appana Durga Kedareswara rao <appana.durga.rao@xilinx.com>
Message-Id: <1562130487-27028-1-git-send-email-appana.durga.rao@xilinx.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-07-04 12:56:47 +10:00
Simon Glass 1c17714dbb pylibfdt: Correct the FdtSw example
At present this example is incorrect since it is missing the call to
finish_reservemap() and does not add a root node. Fix these problems.

Signed-off-by: Simon Glass <sjg@chromium.org>
Message-Id: <20190703000815.102459-1-sjg@chromium.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-07-03 10:23:21 +10:00
Fabrice Gasnier ad57e4574a tests: Add a failed test case for 'fdtoverlay' with long target path
This adds a test case to demonstrate some issue seen when applying
overlays using 'fdtoverlay'. It fails with FDT_ERR_NOSPACE:
- with long target path
- symbols in order to use these nodes in possible subsequent overlay.

This is seen with this patch, by running:
$ make check # Reports a failed test
$ ./fdtoverlay -i tests/overlay_base.test.dtb -o out.dtb \
  tests/overlay_overlay_long_path.fdoverlay.test.dtb
  Failed to apply tests/overlay_overlay_long_path.fdoverlay.test.dtb (-3)

This overlay fails to apply, because dtb size is close to modulo 1024
bytes chunk: utilfdt_read() -> utilfdt_read_err() -> bufsize = 1024.

As there is not much extra space in the blob to resolve symbols (long
target path), it fails with FDT_ERR_NOSPACE. In fdtoverlay, size is :
 /* grow the blob to worst case */
 blob_len = fdt_totalsize(blob) + total_len;

I can see assumption is made that result should be lower than:
- base fdt size + overlay size. Is there a simple way to find to know
what the final size is?
I'm not sure what the correct fix might be, for such (worst) case?
Similar issue is also seen in u-boot/common/image-fit.c that implements
similar approach (e.g. base fdt size + overlay size).

Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
Message-Id: <1538553302-1353-1-git-send-email-fabrice.gasnier@st.com>
[dwg: To avoid breaking bisection, I committed this after a fix, so
 the "failed" description is no longer accurate]
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-06-30 15:48:40 +10:00
David Gibson bbe3b36f54 fdtoverlay: Rework output allocation
At present the fdtoverlay tool allocates space for its output based on a
calculation of the worse case size based on the size of the input blobs.

Except.. that certain edge cases with very long target paths can actually
exceed that "worst case" calculation.

This reworks the code to instead dynamically reallocate the output buffer
if we run out of space at any point.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-06-30 15:47:50 +10:00
David Gibson 6c2e61f083 fdtoverlay: Improve error messages
Make several improvements to the error messages from the fdtoverlay helper
program: improve brevity, consistently quote filenames and print symbolic
errors from libfdt rather than a raw error number.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-06-30 15:47:50 +10:00
David Gibson 297f5abb36 fdtoverlay: Check for truncated overlay blobs
The fdtoverlay helper program checks if it has read a base blob which is
incomplete: that is, where the amount of data read in is less that the
declared size of the blob.

This applies the same check for safety to each overlay blob as well.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-06-30 15:47:50 +10:00
Rob Herring 702c1b6c0e README.license: Update to reflect SPDX tag usage
Update README.license since files now have SPDX tags rather than license
text. Adding a copy of BSD-2-Clause license since that no longer exists
within the project.

Signed-off-by: Rob Herring <robh@kernel.org>
Message-Id: <20190620211944.9378-8-robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-06-21 21:06:10 +10:00
Rob Herring 4097bbffcf dtc: Add GPLv2 SPDX tags to files missing license text
A couple of dtc files are missing licenses. Add GPL-2.0-or-later SPDX
tag to them.

Signed-off-by: Rob Herring <robh@kernel.org>
Message-Id: <20190620211944.9378-7-robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-06-21 21:06:10 +10:00
Rob Herring 94f87cd5b7 libfdt: Add dual GPL/BSD SPDX tags to files missing license text
A couple of libfdt files are missing licenses. Add (GPL-2.0-or-later OR
BSD-2-Clause) SPDX tag to them.

Signed-off-by: Rob Herring <robh@kernel.org>
Message-Id: <20190620211944.9378-6-robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-06-21 21:06:10 +10:00
Rob Herring c4ffc05574 tests: Replace license boilerplate with SPDX tags
Replace instances in tests of mostly LGPL-2.1 license boilerplate
with SPDX tags.

Signed-off-by: Rob Herring <robh@kernel.org>
Message-Id: <20190620211944.9378-5-robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-06-21 21:06:10 +10:00
Rob Herring a5ac29baac pylibfdt: Replace dual GPLv2/BSD license boilerplate with SPDX tags
Replace pylibfdt GPLv2/BSD license boilerplate and add missing license
with SPDX tags.

Signed-off-by: Rob Herring <robh@kernel.org>
Message-Id: <20190620211944.9378-4-robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-06-21 21:06:10 +10:00
Rob Herring 7fb0f4db2e libfdt: Replace GPL/BSD boilerplate/reference with SPDX tags
Replace instances of dual GPLv2 or BSD license boilerplate with SPDX tags.

Signed-off-by: Rob Herring <robh@kernel.org>
Message-Id: <20190620211944.9378-3-robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-06-21 21:06:10 +10:00
Rob Herring acfe84f2c4 dtc: Replace GPLv2 boilerplate/reference with SPDX tags
Replace instances of GPLv2 or later boilerplate with SPDX tags.

Signed-off-by: Rob Herring <robh@kernel.org>
Message-Id: <20190620211944.9378-2-robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-06-21 21:06:10 +10:00
Rob Herring 87963ee206 livetree: add missing type markers in generated overlay properties
The YAML output fails for overlays and when symbol generation are enabled
due to missing markers in the generated properties.

Add type markers when generating properties under '__symbols__' and
'__fixups__' nodes as well as target-path properties. As a side effect of
append_to_property() changes, this also sets type markers in
'__local_fixups__' node properties.

Signed-off-by: Rob Herring <robh@kernel.org>
Message-Id: <20190517202804.9084-1-robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-06-12 16:01:16 +10:00
Thomas Huth 825146d13d Fix typos in various documentation and source files
The typos have been discovered with the "codespell" utility.

Signed-off-by: Thomas Huth <thuth@redhat.com>
Message-Id: <20190520081209.20415-1-thuth@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-05-21 10:01:01 +10:00
Thomas Huth 25bb080c18 Update the GPL2 text to the latest revision
This patch replaces the GPL2 text with the latest one from:

 https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt

The FSF moved to a different location quite a while ago already, and
the latest revision recommends to use the LGPL-2.1 ("Lesser" license)
instead of the LGPL-2.0 ("Library" license) in certain cases.

Signed-off-by: Thomas Huth <thuth@redhat.com>
Message-Id: <20190520072720.14755-1-thuth@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-05-21 09:58:37 +10:00
David Gibson 243176c4ce Fix bogus error on rebuild
Currently if a file is touched requiring libfdt.so rebuild, it will fail
because the ln -s command will attempt to replace an already existing link
an error.  Correct this by using ln -sf.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-05-10 11:57:19 +10:00
Nicholas Piggin ce01b21098 libfdt: Add FDT_CREATE_FLAG_NO_NAME_DEDUP flag that trades size for speed
Searching for duplicate names scales O(n^2) with the number of names
added to a fdt, which can cause a noticable slowdown with larger device
trees and very slow CPU cores.

Add FDT_CREATE_FLAG_NO_NAME_DEDUP that allow the caller to trade fdt size
for speed in the creation process.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Message-Id: <20190509094122.834-4-npiggin@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-05-10 11:53:10 +10:00
Nicholas Piggin fbb62754ce libfdt: Introduce fdt_create_with_flags()
There is a need to be able to specify some options when building an FDT
with the SW interface. This can be accomplished with minimal changes by
storing intermediate data in the fdt header itself, in fields that are
not otherwise needed during the creation process and can be set by
fdt_finish().

The fdt.magic field is already used exactly this way, as a state to
check with callers that the FDT has been created but not yet finished.

fdt.version and fdt.last_comp_version are used to make room for more
intermediate state. These are adjacent and unused during the building
process. last_comp_version is not yet used for intermediate state, but
it is zeroed and treated as used, so as to allow future growth easily.

A new interface, fdt_create_with_flags() is added, which takes 32-bit
flag value to control creation.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Message-Id: <20190509094122.834-3-npiggin@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-05-10 11:53:10 +10:00
Nicholas Piggin 228a44cce8 libfdt: Ensure fdt_add_property frees allocated name string on failure
If fdt_add_property or fdt_property_placeholder fail after allocating
a string for the name, they return without freeing that string. This
does not change the structure of the tree, but in very specific cases
it could lead to undesirable space consumption.

Fix this by rolling back the string allocation in this situation.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Message-Id: <20190509094122.834-2-npiggin@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-05-10 11:53:10 +10:00
David Gibson 8f69567622 Avoid assertion in check_interrupts_property()
If running on a tree with an 'interrupt-parent' property which contains
an invalid phandle (0 or -1, not merely for a node which doesn't exist),
then check_interrupts_property() will trip the assertion in
get_node_by_phandle().

There's logic that almost detects this, but it only handles the overlay
case, where we can't fully check because the links will be fixed up later.

For the non-overlay case, this is definitely a bad property, but we
shouldn't crash.  Fix it by failing the check early.

Fixes: c1e55a5513 ("checks: fix handling of unresolved phandles for dts plugins")
Fixes: ee3d26f696 ("checks: add interrupts property check")
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-05-06 17:00:07 +10:00
David Gibson 5c3513f689 Link tools and tests against libfdt shared library
Currently the libfdt based tools (fdtput, fdtget, etc.) and all the
test binaries using libfdt are linked against the static version of libfdt.
That's made it very easy in the past to forget to properly update the
version.lds file which is needed to make functions publicaly accessible
from the shared library.

To avoid problems like that in future, alter the build so that we link and
run the tests against the shared library version of libfdt.

That immediately points out several important symbols that are still
missing from the version.lds, so fix those as well.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-03-29 17:20:16 +11:00
David Gibson 00f9febf9c tests: Rename tests.sh to testutils.sh
tests.sh has a bunch of shell setup that's sourced in a number of other
scripts.  It _doesn't_ actually run a bunch of tests, which is kind of what
the name suggests.  So rename it to be more obvious.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-03-29 16:31:39 +11:00
David Gibson c5d45188f9 Clean up LDLIBS handling
We currently set LDLIBS to include libyaml globally if we're using it.
However only dtc itself actually needs to link with libyaml - the other
tool binaries don't.  Avoid that unnecessary inclusion by making LDLIBS
handling per-target.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-03-29 16:15:08 +11:00
David Gibson 6ef8fcd05b Rebuild libfdt shared object if versioning linker script changes
The usable content of the shared library varies depending on the symbol
versions given in the version.lds linker script, however it's not currently
in the make dependencies.  Correct that, and move the libfdt rules together
for consistency while we're at it.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-03-29 15:43:24 +11:00
David Gibson 26ee65a16c Use Python3 by default
Python2 is deprecated upstream, lets try to move forwards. Along with it
generalize the .gitignore file so we ignore the .pyc files in the new
location that Python3 uses.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-03-29 15:43:24 +11:00
David Gibson cca6546244 libfdt: Make fdt_get_max_phandle() an inline
It's now a trivial wrapper around fdt_find_max_phandle() so we might as
well inline it.  We also remove it from the versioning linker script.
Theoretically, that's a breaking ABI change except that we haven't yet
released a version with it exposed in the shared object, so we can get
away with it.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-03-29 13:59:04 +11:00
Thierry Reding 730875016a libfdt: Add phandle generation helper
The new fdt_generate_phandle() function can be used to generate a new,
unused phandle given a specific device tree blob. The implementation is
somewhat naive in that it simply walks the entire device tree to find
the highest phandle value and then returns a phandle value one higher
than that. A more clever implementation might try to find holes in the
current set of phandle values and fill them. But this implementation is
relatively simple and works reliably.

Also add a test that validates that phandles generated by this new API
are indeed unique.

Signed-off-by: Thierry Reding <treding@nvidia.com>
Message-Id: <20190326153302.17109-3-thierry.reding@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-03-29 13:31:16 +11:00
Thierry Reding 7dfb61ba96 libfdt: Use fdt_find_max_phandle()
Use the fdt_find_max_phandle() function instead of the deprecated
fdt_get_max_phandle() function.

Signed-off-by: Thierry Reding <treding@nvidia.com>
Message-Id: <20190326153302.17109-2-thierry.reding@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-03-29 13:31:16 +11:00
Thierry Reding 2bc5b66d7f libfdt: Add new maximum phandle lookup function
The fdt_get_max_phandle() function has some shortcomings. On one hand
it returns just a uint32_t which means to check for the "negative"
error code a caller has to explicitly check against the error code
(uint32_t)-1. In addition, the -1 is the only error code that can be
returned, so a caller cannot tell the difference between the various
failures.

Fix this by adding a new fdt_find_max_phandle() function that returns an
error code on failure and 0 on success, just like other APIs, and stores
the maximum phandle value in an output argument on success.

This also refactors fdt_get_max_phandle() to use the new function. Add a
note pointing out that the new fdt_find_max_phandle() function should be
preferred over fdt_get_max_phandle().

Signed-off-by: Thierry Reding <treding@nvidia.com>
Message-Id: <20190326153302.17109-1-thierry.reding@gmail.com>
[dwg: Reword for some inaccuracies in the commit message]
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-03-29 13:29:51 +11:00
AKASHI Takahiro 7fcf8208b8 libfdt: add fdt_append_addrrange()
This function will append an address range property using parent node's
"#address-cells" and "#size-cells" properties.

It will be used in implementing kdump with kexec_file_load system call
at linux kernel for arm64 once it is merged into kernel tree.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Message-Id: <20190327061552.17170-2-takahiro.akashi@linaro.org>
[dwg: Correct a SEGV error in the testcase]
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-03-29 12:12:29 +11:00
Chen-Yu Tsai ae795b2db7 checks: Do not omit nodes with labels if symbol generation is requested
Commit 4038fd9005 ("dtc: add ability to make nodes conditional on them
being referenced") added the new /omit-if-no-ref/ directive to mark
nodes as eligible to be discarded if not referenced. The mechanism to
process this happens before the symbol generation phase. This means even
if symbol generation is requested and the node has a label, it will be
discarded if there are no references to it within the same file.

This is probably not what people expect. When using symbol generation to
compile base device trees for applying overlays, nodes with labels could
be referenced by the overlays, and therefore should be preserved.

Check if the node has a label and symbol generation was requested before
dropping the node.

Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Message-Id: <20190327035352.24036-1-wens@csie.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-03-27 17:02:54 +11:00
David Gibson eac2ad495b Update version.lds again
Yet again, we've added several functions to libfdt that were supposed
to be exported, but forgotten to add them to the versio.lds script.
This adds them.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-03-25 14:52:47 +11:00
David Gibson f67b471355 Revert "libfdt: Add phandle generation helper"
This reverts commit 54ea41c224.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-03-25 14:51:27 +11:00
Thierry Reding 54ea41c224 libfdt: Add phandle generation helper
The new fdt_generate_phandle() function can be used to generate a new,
unused phandle given a specific device tree blob. The implementation is
somewhat naive in that it simply walks the entire device tree to find
the highest phandle value and then returns a phandle value one higher
than that. A more clever implementation might try to find holes in the
current set of phandle values and fill them. But this implementation is
relatively simple and works reliably.

Also add a test that validates that phandles generated by this new API
are indeed unique.

Signed-off-by: Thierry Reding <treding@nvidia.com>
Message-Id: <20190320151003.28941-1-thierry.reding@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-03-21 11:37:44 +11:00
Leonard Crestez 4762ad051e checks: Fix spelling in check_graph_endpoint
Should be "endpoint" rather than "endpont"

Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
Message-Id: <6fcb6e160163467b706c312ffe307ee8a5d9255d.1552328099.git.leonard.crestez@nxp.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2019-03-12 19:16:14 +11:00
199 changed files with 5743 additions and 3689 deletions

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
...

33
.editorconfig Normal file
View File

@ -0,0 +1,33 @@
# EditorConfig is a file format and collection of text editor plugins
# for maintaining consistent coding styles between different editors
# and IDEs. Most popular editors support this either natively or via
# plugin.
#
# Check https://editorconfig.org for details.

root = true

[*]
end_of_line = lf
insert_final_newline = true
charset = utf-8
indent_style = space

[Makefile*]
indent_style = tab
indent_size = 8
file_type_emacs = makefile

[*.[ch]]
indent_style = tab
indent_size = 8

[*.py]
indent_size = 4

[meson.build]
indent_style = space
indent_size = 2

[*.lds]
indent_style = tab

113
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,113 @@
---
name: Build test
'on':
push:
branches:
- main
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

12
.gitignore vendored
View File

@ -3,10 +3,13 @@
*.a
*.patch
*.so
*.so.*
*~
*.bak
*.tab.[ch]
lex.yy.c
*.lex.c
.*.swp
/dtc
/fdtdump
/convert-dtsv0
@ -16,3 +19,12 @@ lex.yy.c
/fdtoverlay
/patches
/.pc

# cscope files
cscope.*
ncscope.*

.eggs/
build/
dist/
*.egg-info/

View File

@ -1,33 +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

32
BSD-2-Clause Normal file
View File

@ -0,0 +1,32 @@
Valid-License-Identifier: BSD-2-Clause
SPDX-URL: https://spdx.org/licenses/BSD-2-Clause.html
Usage-Guide:
To use the BSD 2-clause "Simplified" License put the following SPDX
tag/value pair into a comment according to the placement guidelines in
the licensing rules documentation:
SPDX-License-Identifier: BSD-2-Clause
License-Text:

Copyright (c) <year> <owner> . All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

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

@ -37,15 +37,14 @@ The upstream repository is here:
git://git.kernel.org/pub/scm/utils/dtc/dtc.git
https://git.kernel.org/pub/scm/utils/dtc/dtc.git

The gitweb interface for the upstream respository is:
The gitweb interface for the upstream repository is:

https://git.kernel.org/cgit/utils/dtc/dtc.git/

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
@ -234,7 +245,7 @@ For example:
"childnode at address". It in turn has a string property
called "childprop".

childnode@addresss {
childnode@address {
childprop = "hello\n";
};

@ -253,7 +264,7 @@ Labels may be applied to nodes or properties. Labels appear
before a node name, and are referenced using an ampersand: &label.
Absolute node path names are also allowed in node references.

In this exmaple, a node is labled "mpic" and then referenced:
In this example, a node is labeled "mpic" and then referenced:

mpic: interrupt-controller@40000 {
...
@ -264,7 +275,7 @@ In this exmaple, a node is labled "mpic" and then referenced:
...
};

And used in properties, lables may appear before or after any value:
And used in properties, labels may appear before or after any value:

randomnode {
prop: string = data: "mystring\n" data_end: ;
@ -418,7 +429,7 @@ value of r3.
among others, by kexec. If you are on an SMP system, this value
should match the content of the "reg" property of the CPU node in
the device-tree corresponding to the CPU calling the kernel entry
point (see further chapters for more informations on the required
point (see further chapters for more information on the required
device-tree contents)

- size_dt_strings
@ -584,7 +595,7 @@ looks like in practice.

This tree is almost a minimal tree. It pretty much contains the
minimal set of required nodes and properties to boot a linux kernel;
that is, some basic model informations at the root, the CPUs, and the
that is, some basic model information at the root, the CPUs, and the
physical memory layout. It also includes misc information passed
through /chosen, like in this example, the platform type (mandatory)
and the kernel command line arguments (optional).
@ -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)


41
GPL
View File

@ -1,12 +1,12 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991

Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.

Preamble
Preamble

The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
@ -15,7 +15,7 @@ software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.

When we speak of free software, we are referring to freedom, not
@ -55,8 +55,8 @@ patent must be licensed for everyone's free use or not licensed at all.

The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE

GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

0. This License applies to any program or other work which contains
@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions:
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)

These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
@ -168,7 +168,7 @@ access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.

4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
@ -225,7 +225,7 @@ impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
@ -255,7 +255,7 @@ make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.

NO WARRANTY
NO WARRANTY

11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
@ -277,9 +277,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.

END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
END OF TERMS AND CONDITIONS

How to Apply These Terms to Your New Programs

If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
@ -303,17 +303,16 @@ the "copyright" line and a pointer to where the full notice is found.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

Also add information on how to contact you by electronic and paper mail.

If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:

Gnomovision version 69, Copyright (C) year name of author
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
@ -336,5 +335,5 @@ necessary. Here is a sample; alter the names:
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

133
Makefile
View File

@ -1,32 +1,38 @@
# SPDX-License-Identifier: GPL-2.0-or-later
#
# 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 = 5
SUBLEVEL = 0
EXTRAVERSION =
DTC_VERSION = $(shell cat VERSION.txt)
LOCAL_VERSION =
CONFIG_LOCALVERSION =

CPPFLAGS = -I libfdt -I .
WARNINGS = -Wall -Wpointer-arith -Wcast-qual -Wnested-externs \
-Wstrict-prototypes -Wmissing-prototypes -Wredundant-decls -Wshadow
CFLAGS = -g -Os $(SHAREDLIB_CFLAGS) -Werror $(WARNINGS)
# Control the assumptions made (e.g. risking security issues) in the code.
# See libfdt_internal.h for details
ASSUME_MASK ?= 0

CPPFLAGS = -I libfdt -I . -DFDT_ASSUME_MASK=$(ASSUME_MASK)
WARNINGS = -Wall -Wpointer-arith -Wcast-qual -Wnested-externs -Wsign-compare \
-Wstrict-prototypes -Wmissing-prototypes -Wredundant-decls -Wshadow \
-Wsuggest-attribute=format -Wwrite-strings
CFLAGS = -g -Os $(SHAREDLIB_CFLAGS) -Werror $(WARNINGS) $(EXTRA_CFLAGS)

BISON = bison
LEX = flex
SWIG = swig
PKG_CONFIG ?= pkg-config
PYTHON ?= python2

INSTALL = /usr/bin/install
INSTALL = install
INSTALL_PROGRAM = $(INSTALL)
INSTALL_LIB = $(INSTALL)
INSTALL_DATA = $(INSTALL) -m 644
@ -42,16 +48,21 @@ HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \

NO_VALGRIND := $(shell $(PKG_CONFIG) --exists valgrind; echo $$?)
ifeq ($(NO_VALGRIND),1)
CFLAGS += -DNO_VALGRIND
CPPFLAGS += -DNO_VALGRIND
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 += $(shell $(PKG_CONFIG) --libs yaml-0.1)
LDLIBS_dtc += $(shell $(PKG_CONFIG) --libs yaml-0.1)
CFLAGS += $(shell $(PKG_CONFIG) --cflags yaml-0.1)
endif

ifeq ($(HOSTOS),darwin)
@ -90,7 +101,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; \
@ -145,30 +155,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),)
all: maybe_pylibfdt
endif


ifneq ($(DEPTARGETS),)
ifneq ($(MAKECMDGOALS),libfdt)
-include $(DTC_OBJS:%.o=%.d)
-include $(CONVERT_OBJS:%.o=%.d)
-include $(FDTDUMP_OBJS:%.o=%.d)
@ -176,6 +164,7 @@ ifneq ($(DEPTARGETS),)
-include $(FDTPUT_OBJS:%.o=%.d)
-include $(FDTOVERLAY_OBJS:%.o=%.d)
endif
endif



@ -184,17 +173,30 @@ endif
#
LIBFDT_dir = libfdt
LIBFDT_archive = $(LIBFDT_dir)/libfdt.a
LIBFDT_lib = $(LIBFDT_dir)/libfdt-$(DTC_VERSION).$(SHAREDLIB_EXT)
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
libfdt: $(LIBFDT_archive) $(LIBFDT_lib)

$(LIBFDT_archive): $(addprefix $(LIBFDT_dir)/,$(LIBFDT_OBJS))
$(LIBFDT_lib): $(addprefix $(LIBFDT_dir)/,$(LIBFDT_OBJS))

$(LIBFDT_lib): $(addprefix $(LIBFDT_dir)/,$(LIBFDT_OBJS)) $(LIBFDT_version)
@$(VECHO) LD $@
$(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)
@ -211,7 +213,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)
@ -226,14 +228,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),)
install: maybe_install_pylibfdt
endif

$(VERSION_FILE): Makefile FORCE
$(call filechk,version)

@ -246,11 +240,11 @@ convert-dtsv0: $(CONVERT_OBJS)

fdtdump: $(FDTDUMP_OBJS)

fdtget: $(FDTGET_OBJS) $(LIBFDT_archive)
fdtget: $(FDTGET_OBJS) $(LIBFDT_dep)

fdtput: $(FDTPUT_OBJS) $(LIBFDT_archive)
fdtput: $(FDTPUT_OBJS) $(LIBFDT_dep)

fdtoverlay: $(FDTOVERLAY_OBJS) $(LIBFDT_archive)
fdtoverlay: $(FDTOVERLAY_OBJS) $(LIBFDT_dep)

dist:
git archive --format=tar --prefix=dtc-$(dtc_version)/ HEAD \
@ -259,16 +253,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.
@ -302,11 +286,10 @@ TESTS_BIN += fdtput
TESTS_BIN += fdtget
TESTS_BIN += fdtdump
TESTS_BIN += fdtoverlay
ifeq ($(NO_PYTHON),)
TESTS_PYLIBFDT += maybe_pylibfdt
endif

ifneq ($(MAKECMDGOALS),libfdt)
include tests/Makefile.tests
endif

#
# Clean rules
@ -314,7 +297,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)
@ -326,7 +309,7 @@ clean: libfdt_clean pylibfdt_clean tests_clean
#
%: %.o
@$(VECHO) LD $@
$(LINK.c) -o $@ $^ $(LDLIBS)
$(LINK.c) -o $@ $^ $(LDLIBS_$*)

%.o: %.c
@$(VECHO) CC $@
@ -334,11 +317,11 @@ 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 $<
$(CC) $(CPPFLAGS) -MM -MG -MT "$*.o $@" $< > $@
$(CC) $(CPPFLAGS) $(CFLAGS) -MM -MG -MT "$*.o $@" $< > $@

%.d: %.S
@$(VECHO) DEP $<
@ -356,16 +339,16 @@ clean: libfdt_clean pylibfdt_clean tests_clean
@$(VECHO) AR $@
$(AR) $(ARFLAGS) $@ $^

$(LIBFDT_lib):
@$(VECHO) LD $@
$(CC) $(LDFLAGS) $(SHAREDLIB_LDFLAGS)$(LIBFDT_soname) -o $(LIBFDT_lib) $^

%.lex.c: %.l
@$(VECHO) LEX $@
$(LEX) -o$@ $<

%.tab.c %.tab.h %.output: %.y
%.tab.c %.tab.h: %.y
@$(VECHO) BISON $@
$(BISON) -d $<
$(BISON) -b $(basename $(basename $@)) -d $<

FORCE:

ifeq ($(MAKE_RESTARTS),10)
$(error "Make re-executed itself $(MAKE_RESTARTS) times. Infinite recursion?")
endif

View File

@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-or-later
#
# This is not a complete Makefile of itself.
# Instead, it is designed to be easily embeddable

View File

@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Makefile.dtc
#
# This is not a complete Makefile of itself. Instead, it is designed to

View File

@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-or-later
#
# This is not a complete Makefile of itself. Instead, it is designed to
# be easily embeddable into other systems of Makefiles.

93
README
View File

@ -1,93 +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 python-dev

The library provides an Fdt class which you can use like this:

$ PYTHONPATH=../pylibfdt python
>>> import libfdt
>>> fdt = libfdt.Fdt(open('test_tree1.dtb').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=%r' % (prop.name, prop.value)
compatible=bytearray(b'subnode1\x00')
>>> print '%s=%s' % (prop.name, prop.value)
compatible=subnode1
>>> node2 = fdt.path_offset('/')
>>> print fdt.getprop(node2, 'compatible')
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
$ python -c "import libfdt; help(libfdt)"

If you add new features, please check code coverage:

$ sudo apt-get install python-pip python-pytest
$ sudo pip install coverage
$ cd tests
$ coverage run pylibfdt_tests.py
$ coverage html
# Open 'htmlcov/index.html' in your browser


To install the library via the normal setup.py method, use:

./pylibfdt/setup.py [--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

@ -4,11 +4,11 @@ Licensing and contribution policy of dtc and libfdt
This dtc package contains two pieces of software: dtc itself, and
libfdt which comprises the files in the libfdt/ subdirectory. These
two pieces of software, although closely related, are quite distinct.
dtc does not incoporate or rely on libfdt for its operation, nor vice
dtc does not incorporate or rely on libfdt for its operation, nor vice
versa. It is important that these two pieces of software have
different license conditions.

As the copyright banners in each source file attest, dtc is licensed
As SPDX license tags in each source file attest, dtc is licensed
under the GNU GPL. The full text of the GPL can be found in the file
entitled 'GPL' which should be included in this package. dtc code,
therefore, may not be incorporated into works which do not have a GPL
@ -16,10 +16,10 @@ compatible license.

libfdt, however, is GPL/BSD dual-licensed. That is, it may be used
either under the terms of the GPL, or under the terms of the 2-clause
BSD license (aka the ISC license). The full terms of that license are
given in the copyright banners of each of the libfdt source files.
This is, in practice, equivalent to being BSD licensed, since the
terms of the BSD license are strictly more permissive than the GPL.
BSD license (aka the ISC license). The full terms of that license can
be found are in the file entitled 'BSD-2-Clause'. This is, in
practice, equivalent to being BSD licensed, since the terms of the BSD
license are strictly more permissive than the GPL.

I made the decision to license libfdt in this way because I want to
encourage widespread and correct usage of flattened device trees,
@ -28,12 +28,12 @@ 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
rocket science; so the incentive for such impolite behaviour is small,
and the inconvenience caused therby is not dire.
and the inconvenience caused thereby is not dire.

Licenses such as the LGPL which would allow code to be used in non-GPL
software, but also require contributions to be returned were

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

441
checks.c
View File

@ -1,21 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2007.
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/

#include "dtc.h"
@ -46,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;
@ -129,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, ...) \
@ -158,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;
@ -214,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)
@ -233,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);
@ -261,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)
@ -312,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)
@ -345,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)
{
@ -367,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);
@ -378,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,
@ -395,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;
@ -512,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;
@ -571,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);
@ -660,6 +669,8 @@ ERROR(path_references, fixup_path_references, NULL, &duplicate_node_names);
static void fixup_omit_unused_nodes(struct check *c, struct dt_info *dti,
struct node *node)
{
if (generate_symbols && node->labels)
return;
if (node->omit_if_unused && !node->is_referenced)
delete_node(node);
}
@ -670,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");
@ -685,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;
@ -704,6 +713,11 @@ static void check_alias_paths(struct check *c, struct dt_info *dti,
return;

for_each_property(node, prop) {
if (streq(prop->name, "phandle")
|| streq(prop->name, "linux,phandle")) {
continue;
}

if (!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);
@ -761,7 +775,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);
@ -773,13 +787,15 @@ static void check_ranges_format(struct check *c, struct dt_info *dti,
{
struct property *prop;
int c_addr_cells, p_addr_cells, c_size_cells, p_size_cells, entrylen;
const char *ranges = c->data;

prop = get_property(node, "ranges");
prop = get_property(node, ranges);
if (!prop)
return;

if (!node->parent) {
FAIL_PROP(c, dti, node, prop, "Root node has a \"ranges\" property");
FAIL_PROP(c, dti, node, prop, "Root node has a \"%s\" property",
ranges);
return;
}

@ -791,23 +807,24 @@ static void check_ranges_format(struct check *c, struct dt_info *dti,

if (prop->val.len == 0) {
if (p_addr_cells != c_addr_cells)
FAIL_PROP(c, dti, node, prop, "empty \"ranges\" property but its "
FAIL_PROP(c, dti, node, prop, "empty \"%s\" property but its "
"#address-cells (%d) differs from %s (%d)",
c_addr_cells, node->parent->fullpath,
ranges, c_addr_cells, node->parent->fullpath,
p_addr_cells);
if (p_size_cells != c_size_cells)
FAIL_PROP(c, dti, node, prop, "empty \"ranges\" property but its "
FAIL_PROP(c, dti, node, prop, "empty \"%s\" property but its "
"#size-cells (%d) differs from %s (%d)",
c_size_cells, node->parent->fullpath,
ranges, c_size_cells, node->parent->fullpath,
p_size_cells);
} else if ((prop->val.len % entrylen) != 0) {
FAIL_PROP(c, dti, node, prop, "\"ranges\" property has invalid length (%d bytes) "
} 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)", prop->val.len,
"#size-cells == %d)", ranges, prop->val.len,
p_addr_cells, c_addr_cells, c_size_cells);
}
}
WARNING(ranges_format, check_ranges_format, NULL, &addr_size_cells);
WARNING(ranges_format, check_ranges_format, "ranges", &addr_size_cells);
WARNING(dma_ranges_format, check_ranges_format, "dma-ranges", &addr_size_cells);

static const struct bus_type pci_bus = {
.name = "PCI",
@ -876,7 +893,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)",
@ -896,10 +913,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])
@ -1009,7 +1024,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;
@ -1027,6 +1042,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;
@ -1049,6 +1067,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\"",
@ -1056,10 +1076,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);
@ -1084,7 +1110,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;
}
@ -1156,7 +1182,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,
@ -1191,24 +1217,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);

@ -1358,15 +1387,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));
@ -1376,14 +1405,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;
@ -1426,10 +1456,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;
}
}
}
@ -1438,7 +1470,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);
@ -1449,7 +1481,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");
@ -1470,24 +1503,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,
@ -1522,13 +1548,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,
@ -1552,6 +1575,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)
@ -1559,13 +1697,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));

@ -1578,10 +1716,14 @@ static void check_interrupts_property(struct check *c,
prop = get_property(parent, "interrupt-parent");
if (prop) {
phandle = propval_cell(prop);
/* Give up if this is an overlay with external references */
if ((phandle == 0 || phandle == -1) &&
(dti->dtsflags & DTSF_PLUGIN))
if (!phandle_is_valid(phandle)) {
/* Give up if this is an overlay with
* external references */
if (dti->dtsflags & DTSF_PLUGIN)
return;
FAIL_PROP(c, dti, parent, prop, "Invalid phandle");
continue;
}

irq_node = get_node_by_phandle(root, phandle);
if (!irq_node) {
@ -1605,12 +1747,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)));
@ -1636,6 +1778,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 */
@ -1649,31 +1796,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)
{
@ -1711,17 +1833,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;

@ -1731,7 +1857,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);
@ -1749,11 +1875,15 @@ static void check_graph_endpoint(struct check *c, struct dt_info *dti,
if (!node->parent || node->parent->bus != &graph_port_bus)
return;

if (!strprefixeq(node->name, node->basenamelen, "endpoint"))
FAIL(c, dti, node, "graph endpont node name should be 'endpoint'");

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'");

remote_node = get_remote_endpoint(c, dti, node);
if (!remote_node)
return;
@ -1764,10 +1894,35 @@ static void check_graph_endpoint(struct check *c, struct dt_info *dti,
}
WARNING(graph_endpoint, check_graph_endpoint, NULL, &graph_nodes);

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, &graph_port, &graph_endpoint);

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,

@ -1775,7 +1930,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,

@ -1784,7 +1939,7 @@ static struct check *check_table[] = {
&property_name_chars_strict,
&node_name_chars_strict,

&addr_size_cells, &reg_format, &ranges_format,
&addr_size_cells, &reg_format, &ranges_format, &dma_ranges_format,

&unit_address_vs_reg,
&unit_address_format,
@ -1810,25 +1965,43 @@ 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,

@ -1852,7 +2025,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 */
@ -1873,7 +2046,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;

@ -1900,7 +2073,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

@ -1,20 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005, 2008.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/

%option noyywrap nounput noinput never-interactive
@ -108,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);


70
data.c
View File

@ -1,21 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/

#include "dtc.h"
@ -36,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;
@ -99,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;
@ -243,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);
}
@ -269,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

@ -1,21 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/

%option noyywrap nounput noinput never-interactive
@ -38,7 +23,6 @@ LINECOMMENT "//".*\n
#include "srcpos.h"
#include "dtc-parser.tab.h"

YYLTYPE yylloc;
extern bool treesource_error;

/* CAUTION: this will stop working if we ever use yyless() or yyunput() */
@ -73,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 # */
@ -167,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);
@ -216,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

@ -1,22 +1,9 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
%locations

%{
#include <stdio.h>
#include <inttypes.h>
@ -32,8 +19,16 @@ extern void yyerror(char const *s);
treesource_error = true; \
} while (0)

#define YYERROR_CALL(msg) yyerror(msg)

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 {
@ -180,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),
""),
@ -189,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);
@ -204,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);
@ -282,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
{
@ -402,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);
@ -487,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
;

@ -563,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
{

38
dtc.c
View File

@ -1,21 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/

#include <sys/stat.h>
@ -27,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 */
@ -62,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'},
@ -82,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'},
@ -119,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",
@ -137,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;
@ -210,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);
@ -265,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;
@ -295,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)

116
dtc.h
View File

@ -1,24 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#ifndef DTC_H
#define DTC_H

/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/

#include <stdio.h>
@ -50,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 */
@ -66,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))

@ -85,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;
};
@ -109,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);
@ -130,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);
@ -208,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);
@ -231,12 +286,13 @@ void add_child(struct node *parent, struct node *child);
void delete_node_by_name(struct node *parent, char *name);
void delete_node(struct node *node);
void append_to_property(struct node *node,
char *name, const void *data, int len);
char *name, const void *data, int len,
enum markertype type);

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,
@ -283,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 */


3
dtdiff
View File

@ -1,4 +1,5 @@
#! /bin/bash
# SPDX-License-Identifier: GPL-2.0-or-later

# This script uses the bash <(...) extension.
# If you want to change this to work with a generic /bin/sh, make sure
@ -16,7 +17,7 @@ source_and_sort () {
*.dts)
IFORMAT=dts
;;
*.dtb)
*.dtb|*.dtbo)
IFORMAT=dtb
;;
esac

View File

@ -1,3 +1,4 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* fdtdump.c - Contributed by Pantelis Antoniou <pantelis.antoniou AT gmail.com>
*/
@ -17,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)
@ -162,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 ||
@ -216,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) {
@ -234,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

@ -1,3 +1,4 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
*
@ -6,21 +7,6 @@
* Based on code written by:
* Pantelis Antoniou <pantelis.antoniou@gmail.com> and
* Matthew McClintock <msm@freescale.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/

#include <assert.h>
@ -76,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);
}

@ -105,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

@ -1,23 +1,9 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2017 Konsulko Group Inc. All rights reserved.
*
* Author:
* Pantelis Antoniou <pantelis.antoniou@konsulko.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/

#include <assert.h>
@ -32,12 +18,12 @@

#include "util.h"

#define BUF_INCREMENT 65536

/* 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'},
@ -54,65 +40,118 @@ static const char * const usage_opts_help[] = {

int verbose = 0;

static void *apply_one(char *base, const char *overlay, size_t *buf_len,
const char *name)
{
char *tmp = NULL;
char *tmpo;
int ret;
bool has_symbols;

/*
* We take copies first, because a failed apply can trash
* both the base blob and the overlay
*/
tmpo = xmalloc(fdt_totalsize(overlay));

do {
tmp = xrealloc(tmp, *buf_len);
ret = fdt_open_into(base, tmp, *buf_len);
if (ret) {
fprintf(stderr,
"\nFailed to make temporary copy: %s\n",
fdt_strerror(ret));
goto fail;
}
ret = fdt_path_offset(tmp, "/__symbols__");
has_symbols = ret >= 0;

memcpy(tmpo, overlay, fdt_totalsize(overlay));

ret = fdt_overlay_apply(tmp, tmpo);
if (ret == -FDT_ERR_NOSPACE) {
*buf_len += BUF_INCREMENT;
}
} while (ret == -FDT_ERR_NOSPACE);

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;
}

free(base);
free(tmpo);
return tmp;

fail:
free(tmpo);
if (tmp)
free(tmp);

return NULL;
}
static int do_fdtoverlay(const char *input_filename,
const char *output_filename,
int argc, char *argv[])
{
char *blob = NULL;
char **ovblob = NULL;
size_t blob_len, ov_len, total_len;
size_t buf_len;
int i, ret = -1;

blob = utilfdt_read(input_filename, &blob_len);
blob = utilfdt_read(input_filename, &buf_len);
if (!blob) {
fprintf(stderr, "\nFailed to read base blob %s\n",
input_filename);
fprintf(stderr, "\nFailed to read '%s'\n", input_filename);
goto out_err;
}
if (fdt_totalsize(blob) > blob_len) {
if (fdt_totalsize(blob) > buf_len) {
fprintf(stderr,
"\nBase blob is incomplete (%lu / %" PRIu32 " bytes read)\n",
(unsigned long)blob_len, fdt_totalsize(blob));
(unsigned long)buf_len, fdt_totalsize(blob));
goto out_err;
}
ret = 0;

/* allocate blob pointer array */
ovblob = malloc(sizeof(*ovblob) * argc);
ovblob = xmalloc(sizeof(*ovblob) * argc);
memset(ovblob, 0, sizeof(*ovblob) * argc);

/* read and keep track of the overlay blobs */
total_len = 0;
for (i = 0; i < argc; i++) {
size_t ov_len;
ovblob[i] = utilfdt_read(argv[i], &ov_len);
if (!ovblob[i]) {
fprintf(stderr, "\nFailed to read overlay %s\n",
argv[i]);
fprintf(stderr, "\nFailed to read '%s'\n", argv[i]);
goto out_err;
}
if (fdt_totalsize(ovblob[i]) > ov_len) {
fprintf(stderr,
"\nOverlay '%s' is incomplete (%lu / %" PRIu32 " bytes read)\n",
argv[i], (unsigned long)ov_len,
fdt_totalsize(ovblob[i]));
goto out_err;
}
total_len += ov_len;
}

/* grow the blob to worst case */
blob_len = fdt_totalsize(blob) + total_len;
blob = xrealloc(blob, blob_len);
fdt_open_into(blob, blob, blob_len);
buf_len = fdt_totalsize(blob);

/* apply the overlays in sequence */
for (i = 0; i < argc; i++) {
ret = fdt_overlay_apply(blob, ovblob[i]);
if (ret) {
fprintf(stderr, "\nFailed to apply %s (%d)\n",
argv[i], ret);
blob = apply_one(blob, ovblob[i], &buf_len, argv[i]);
if (!blob)
goto out_err;
}
}

fdt_pack(blob);
ret = utilfdt_write(output_filename, blob);
if (ret)
fprintf(stderr, "\nFailed to write output blob %s\n",
output_filename);
fprintf(stderr, "\nFailed to write '%s'\n",
output_filename);

out_err:
if (ovblob) {

View File

@ -1,20 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/

#include <assert.h>
@ -403,8 +389,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",
@ -447,6 +433,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

@ -1,21 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/

#include "dtc.h"
@ -139,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);
}
@ -149,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)
@ -164,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);
}

@ -234,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? */

@ -310,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);
@ -360,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;
@ -453,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;
}
}
@ -461,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";
@ -517,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");
@ -525,7 +511,7 @@ void dt_to_asm(FILE *f, struct dt_info *dti, int version)
fprintf(f, "/* Memory reserve map from source file */\n");

/*
* Use .long on high and low halfs of u64s to avoid .quad
* Use .long on high and low halves of u64s to avoid .quad
* as it appears .quad isn't available in some assemblers.
*/
for (re = dti->reservelist; re; re = re->next) {
@ -618,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)
@ -630,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;

@ -725,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;

@ -739,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,
@ -747,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);
@ -755,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;
@ -799,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

@ -1,21 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/

#include "dtc.h"
@ -45,7 +30,7 @@ static struct node *read_fstree(const char *dirname)

tmpname = join_path(dirname, de->d_name);

if (lstat(tmpname, &st) < 0)
if (stat(tmpname, &st) < 0)
die("stat(%s): %s\n", tmpname, strerror(errno));

if (S_ISREG(st.st_mode)) {
@ -58,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);

1
libfdt/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
libfdt.so.1

View File

@ -1,15 +1,22 @@
# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
# Makefile.libfdt
#
# 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_addresses.c fdt_overlay.c fdt_check.c
LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
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,52 +1,7 @@
// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
*
* libfdt is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
*
* a) This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*
* Alternatively,
*
* b) Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "libfdt_env.h"

@ -60,23 +15,38 @@
* that the given buffer contains what appears to be a flattened
* device tree with sane information in its header.
*/
int fdt_ro_probe_(const void *fdt)
int32_t fdt_ro_probe_(const void *fdt)
{
uint32_t totalsize = fdt_totalsize(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 (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
return -FDT_ERR_BADVERSION;
if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)
return -FDT_ERR_BADVERSION;
if (!can_assume(LATEST)) {
if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
return -FDT_ERR_BADVERSION;
if (fdt_last_comp_version(fdt) >
FDT_LAST_SUPPORTED_VERSION)
return -FDT_ERR_BADVERSION;
}
} else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
/* Unfinished sequential-write blob */
if (fdt_size_dt_struct(fdt) == 0)
if (!can_assume(VALID_INPUT) && fdt_size_dt_struct(fdt) == 0)
return -FDT_ERR_BADSTATE;
} else {
return -FDT_ERR_BADMAGIC;
}

return 0;
if (totalsize < INT32_MAX)
return totalsize;
else
return -FDT_ERR_TRUNCATED;
}

static int check_off_(uint32_t hdrsize, uint32_t totalsize, uint32_t off)
@ -110,58 +80,79 @@ size_t fdt_header_size_(uint32_t version)
return FDT_V17_SIZE;
}

size_t fdt_header_size(const void *fdt)
{
return can_assume(LATEST) ? FDT_V17_SIZE :
fdt_header_size_(fdt_version(fdt));
}

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)) {
if ((fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
|| (fdt_last_comp_version(fdt) >
FDT_LAST_SUPPORTED_VERSION))
return -FDT_ERR_BADVERSION;
if (fdt_version(fdt) < fdt_last_comp_version(fdt))
return -FDT_ERR_BADVERSION;
}
hdrsize = fdt_header_size(fdt);
if ((fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
|| (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION))
return -FDT_ERR_BADVERSION;
if (fdt_version(fdt) < fdt_last_comp_version(fdt))
return -FDT_ERR_BADVERSION;

if ((fdt_totalsize(fdt) < hdrsize)
|| (fdt_totalsize(fdt) > INT_MAX))
return -FDT_ERR_TRUNCATED;

/* Bounds check memrsv block */
if (!check_off_(hdrsize, fdt_totalsize(fdt), fdt_off_mem_rsvmap(fdt)))
return -FDT_ERR_TRUNCATED;

/* Bounds check structure block */
if (fdt_version(fdt) < 17) {
if (!check_off_(hdrsize, fdt_totalsize(fdt),
fdt_off_dt_struct(fdt)))
if (!can_assume(VALID_DTB)) {
if ((fdt_totalsize(fdt) < hdrsize)
|| (fdt_totalsize(fdt) > INT_MAX))
return -FDT_ERR_TRUNCATED;
} else {

/* Bounds check memrsv block */
if (!check_off_(hdrsize, fdt_totalsize(fdt),
fdt_off_mem_rsvmap(fdt)))
return -FDT_ERR_TRUNCATED;

/* Bounds check structure block */
if (!can_assume(LATEST) && fdt_version(fdt) < 17) {
if (!check_off_(hdrsize, fdt_totalsize(fdt),
fdt_off_dt_struct(fdt)))
return -FDT_ERR_TRUNCATED;
} else {
if (!check_block_(hdrsize, fdt_totalsize(fdt),
fdt_off_dt_struct(fdt),
fdt_size_dt_struct(fdt)))
return -FDT_ERR_TRUNCATED;
}

/* Bounds check strings block */
if (!check_block_(hdrsize, fdt_totalsize(fdt),
fdt_off_dt_struct(fdt),
fdt_size_dt_struct(fdt)))
fdt_off_dt_strings(fdt),
fdt_size_dt_strings(fdt)))
return -FDT_ERR_TRUNCATED;
}

/* Bounds check strings block */
if (!check_block_(hdrsize, fdt_totalsize(fdt),
fdt_off_dt_strings(fdt), fdt_size_dt_strings(fdt)))
return -FDT_ERR_TRUNCATED;

return 0;
}

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 ((absoffset < offset)
|| ((absoffset + len) < absoffset)
|| (absoffset + len) > fdt_totalsize(fdt))
if (offset < 0)
return NULL;

if (fdt_version(fdt) >= 0x11)
if (((offset + len) < offset)
if (!can_assume(VALID_INPUT))
if ((absoffset < uoffset)
|| ((absoffset + len) < absoffset)
|| (absoffset + len) > fdt_totalsize(fdt))
return NULL;

if (can_assume(LATEST) || fdt_version(fdt) >= 0x11)
if (((uoffset + len) < uoffset)
|| ((offset + len) > fdt_size_dt_struct(fdt)))
return NULL;

@ -171,13 +162,13 @@ 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;

*nextoffset = -FDT_ERR_TRUNCATED;
tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
if (!tagp)
if (!can_assume(VALID_DTB) && !tagp)
return FDT_END; /* premature end */
tag = fdt32_to_cpu(*tagp);
offset += FDT_TAGSIZE;
@ -189,19 +180,27 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
do {
p = fdt_offset_ptr(fdt, offset++, 1);
} while (p && (*p != '\0'));
if (!p)
if (!can_assume(VALID_DTB) && !p)
return FDT_END; /* premature end */
break;

case FDT_PROP:
lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
if (!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);
if (fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 &&
((offset - fdt32_to_cpu(*lenp)) % 8) != 0)
offset += sizeof(struct fdt_property) - FDT_TAGSIZE + len;

if (!can_assume(LATEST) &&
fdt_version(fdt) < 0x10 && len >= 8 &&
((offset - len) % 8) != 0)
offset += 4;
break;

@ -223,8 +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 ((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;
@ -232,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;
@ -307,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

@ -1,58 +1,13 @@
/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
#ifndef FDT_H
#define FDT_H
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
* Copyright 2012 Kim Phillips, Freescale Semiconductor.
*
* libfdt is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
*
* a) This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*
* Alternatively,
*
* b) Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#ifndef __ASSEMBLY__
#ifndef __ASSEMBLER__

struct fdt_header {
fdt32_t magic; /* magic word FDT_MAGIC */
@ -80,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

@ -1,53 +1,8 @@
// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2014 David Gibson <david@gibson.dropbear.id.au>
* Copyright (C) 2018 embedded brains GmbH
*
* libfdt is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
*
* a) This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*
* Alternatively,
*
* b) Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "libfdt_env.h"

@ -59,7 +14,7 @@
static int fdt_cells(const void *fdt, int nodeoffset, const char *name)
{
const fdt32_t *c;
int val;
uint32_t val;
int len;

c = fdt_getprop(fdt, nodeoffset, name, &len);
@ -70,10 +25,10 @@ static int fdt_cells(const void *fdt, int nodeoffset, const char *name)
return -FDT_ERR_BADNCELLS;

val = fdt32_to_cpu(*c);
if ((val <= 0) || (val > FDT_MAX_NCELLS))
if (val > FDT_MAX_NCELLS)
return -FDT_ERR_BADNCELLS;

return val;
return (int)val;
}

int fdt_address_cells(const void *fdt, int nodeoffset)
@ -81,6 +36,8 @@ int fdt_address_cells(const void *fdt, int nodeoffset)
int val;

val = fdt_cells(fdt, nodeoffset, "#address-cells");
if (val == 0)
return -FDT_ERR_BADNCELLS;
if (val == -FDT_ERR_NOTFOUND)
return 2;
return val;
@ -95,3 +52,50 @@ int fdt_size_cells(const void *fdt, int nodeoffset)
return 1;
return val;
}

/* This function assumes that [address|size]_cells is 1 or 2 */
int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset,
const char *name, uint64_t addr, uint64_t size)
{
int addr_cells, size_cells, ret;
uint8_t data[sizeof(fdt64_t) * 2], *prop;

ret = fdt_address_cells(fdt, parent);
if (ret < 0)
return ret;
addr_cells = ret;

ret = fdt_size_cells(fdt, parent);
if (ret < 0)
return ret;
size_cells = ret;

/* check validity of address */
prop = data;
if (addr_cells == 1) {
if ((addr > UINT32_MAX) || (((uint64_t) UINT32_MAX + 1 - addr) < size))
return -FDT_ERR_BADVALUE;

fdt32_st(prop, (uint32_t)addr);
} else if (addr_cells == 2) {
fdt64_st(prop, addr);
} else {
return -FDT_ERR_BADNCELLS;
}

/* check validity of size */
prop += addr_cells * sizeof(fdt32_t);
if (size_cells == 1) {
if (size > UINT32_MAX)
return -FDT_ERR_BADVALUE;

fdt32_st(prop, (uint32_t)size);
} else if (size_cells == 2) {
fdt64_st(prop, size);
} else {
return -FDT_ERR_BADNCELLS;
}

return fdt_appendprop(fdt, nodeoffset, name, data,
(addr_cells + size_cells) * sizeof(fdt32_t));
}

96
libfdt/fdt_check.c Normal file
View File

@ -0,0 +1,96 @@
// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
*/
#include "libfdt_env.h"

#include <fdt.h>
#include <libfdt.h>

#include "libfdt_internal.h"

int fdt_check_full(const void *fdt, size_t bufsize)
{
int err;
int num_memrsv;
int offset, nextoffset = 0;
uint32_t tag;
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;
if (bufsize < fdt_totalsize(fdt))
return -FDT_ERR_TRUNCATED;

num_memrsv = fdt_num_mem_rsv(fdt);
if (num_memrsv < 0)
return num_memrsv;

while (1) {
offset = nextoffset;
tag = fdt_next_tag(fdt, offset, &nextoffset);

if (nextoffset < 0)
return nextoffset;

/* 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;

case FDT_END:
if (depth != 0)
return -FDT_ERR_BADSTRUCTURE;
return 0;

case FDT_BEGIN_NODE:
depth++;
if (depth > INT_MAX)
return -FDT_ERR_BADSTRUCTURE;

/* 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:
prop = fdt_getprop_by_offset(fdt, offset, &propname,
&err);
if (!prop)
return err;
break;

default:
return -FDT_ERR_INTERNAL;
}
}
}

View File

@ -1,52 +1,7 @@
// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2012 David Gibson, IBM Corporation.
*
* libfdt is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
*
* a) This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*
* Alternatively,
*
* b) Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "libfdt_env.h"


View File

@ -1,53 +1,8 @@
// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2016 Free Electrons
* Copyright (C) 2016 NextThing Co.
*
* libfdt is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
*
* a) This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*
* Alternatively,
*
* b) Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "libfdt_env.h"

@ -85,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 targetting is
* done (through a phandle or a path)
*
* returns:
* the targetted 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
@ -161,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;
}

/**
@ -273,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;
@ -286,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;
@ -295,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);
}
}

@ -388,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
@ -396,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.
@ -409,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;
@ -448,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
@ -475,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);
@ -485,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;
@ -524,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);
@ -579,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
@ -680,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,26 +944,36 @@ static int overlay_symbol_update(void *fdt, void *fdto)
/* keep end marker to avoid strlen() */
e = path + path_len;

/* format: /<fragment-name>/__overlay__/<relative-subnode-path> */

if (*path != '/')
return -FDT_ERR_BADVALUE;

/* get fragment name first */
s = strchr(path + 1, '/');
if (!s)
return -FDT_ERR_BADOVERLAY;
if (!s) {
/* Symbol refers to something that won't end
* up in the target tree */
continue;
}

frag_name = path + 1;
frag_name_len = s - path - 1;

/* verify format; safe since "s" lies in \0 terminated prop */
len = sizeof("/__overlay__/") - 1;
if ((e - s) < len || memcmp(s, "/__overlay__/", len))
return -FDT_ERR_BADOVERLAY;

rel_path = s + len;
rel_path_len = e - rel_path;
if ((e - s) > len && (memcmp(s, "/__overlay__/", len) == 0)) {
/* /<fragment-name>/__overlay__/<relative-subnode-path> */
rel_path = s + len;
rel_path_len = e - rel_path - 1;
} else if ((e - s) == len
&& (memcmp(s, "/__overlay__", len - 1) == 0)) {
/* /<fragment-name>/__overlay__ */
rel_path = "";
rel_path_len = 0;
} else {
/* Symbol refers to something that won't end
* up in the target tree */
continue;
}

/* find the fragment index in which the symbol lies */
ret = fdt_subnode_offset_namelen(fdto, 0, frag_name,
@ -813,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;
@ -835,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;
@ -863,24 +1039,36 @@ static int overlay_symbol_update(void *fdt, void *fdto)

int fdt_overlay_apply(void *fdt, void *fdto)
{
uint32_t delta = fdt_get_max_phandle(fdt);
uint32_t delta;
int ret;

FDT_RO_PROBE(fdt);
FDT_RO_PROBE(fdto);

ret = fdt_find_max_phandle(fdt, &delta);
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

@ -1,52 +1,7 @@
// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
*
* libfdt is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
*
* a) This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*
* Alternatively,
*
* b) Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "libfdt_env.h"

@ -78,35 +33,47 @@ static int fdt_nodename_eq_(const void *fdt, int offset,

const char *fdt_get_string(const void *fdt, int stroffset, int *lenp)
{
uint32_t absoffset = stroffset + fdt_off_dt_strings(fdt);
int32_t totalsize;
uint32_t absoffset;
size_t len;
int err;
const char *s, *n;

err = fdt_ro_probe_(fdt);
if (err != 0)
if (can_assume(VALID_INPUT)) {
s = (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;

if (lenp)
*lenp = strlen(s);
return s;
}
totalsize = fdt_ro_probe_(fdt);
err = totalsize;
if (totalsize < 0)
goto fail;

err = -FDT_ERR_BADOFFSET;
if (absoffset >= fdt_totalsize(fdt))
absoffset = stroffset + fdt_off_dt_strings(fdt);
if (absoffset >= (unsigned)totalsize)
goto fail;
len = fdt_totalsize(fdt) - absoffset;
len = totalsize - absoffset;

if (fdt_magic(fdt) == FDT_MAGIC) {
if (stroffset < 0)
goto fail;
if (fdt_version(fdt) >= 17) {
if (stroffset >= fdt_size_dt_strings(fdt))
if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
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;
@ -144,41 +111,64 @@ static int fdt_string_eq_(const void *fdt, int stroffset,
return p && (slen == len) && (memcmp(p, s, len) == 0);
}

uint32_t fdt_get_max_phandle(const void *fdt)
int fdt_find_max_phandle(const void *fdt, uint32_t *phandle)
{
uint32_t max_phandle = 0;
int offset;
uint32_t max = 0;
int offset = -1;

for (offset = fdt_next_node(fdt, -1, NULL);;
offset = fdt_next_node(fdt, offset, NULL)) {
uint32_t phandle;
while (true) {
uint32_t value;

if (offset == -FDT_ERR_NOTFOUND)
return max_phandle;
offset = fdt_next_node(fdt, offset, NULL);
if (offset < 0) {
if (offset == -FDT_ERR_NOTFOUND)
break;

if (offset < 0)
return (uint32_t)-1;
return offset;
}

phandle = fdt_get_phandle(fdt, offset);
if (phandle == (uint32_t)-1)
continue;
value = fdt_get_phandle(fdt, offset);

if (phandle > max_phandle)
max_phandle = phandle;
if (value > max)
max = value;
}

if (phandle)
*phandle = max;

return 0;
}

int fdt_generate_phandle(const void *fdt, uint32_t *phandle)
{
uint32_t max;
int err;

err = fdt_find_max_phandle(fdt, &max);
if (err < 0)
return err;

if (max == FDT_MAX_PHANDLE)
return -FDT_ERR_NOPHANDLES;

if (phandle)
*phandle = max + 1;

return 0;
}

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 (absoffset < fdt_off_mem_rsvmap(fdt))
return NULL;
if (absoffset > fdt_totalsize(fdt) - sizeof(struct fdt_reserve_entry))
return NULL;
if (!can_assume(VALID_INPUT)) {
if (absoffset < fdt_off_mem_rsvmap(fdt))
return NULL;
if (absoffset > fdt_totalsize(fdt) -
sizeof(struct fdt_reserve_entry))
return NULL;
}
return fdt_mem_rsv_(fdt, n);
}

@ -188,11 +178,11 @@ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)

FDT_RO_PROBE(fdt);
re = fdt_mem_rsv(fdt, n);
if (!re)
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;
}

@ -202,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;
@ -265,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);
@ -313,13 +306,13 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
const char *nameptr;
int err;

if (((err = fdt_ro_probe_(fdt)) != 0)
if (((err = fdt_ro_probe_(fdt)) < 0)
|| ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0))
goto fail;

nameptr = nh->name;

if (fdt_version(fdt) < 0x10) {
if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) {
/*
* For old FDT versions, match the naming conventions of V16:
* give only the leaf name (after all /). The actual tree
@ -370,7 +363,8 @@ static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt,
int err;
const struct fdt_property *prop;

if ((err = fdt_check_prop_offset_(fdt, offset)) < 0) {
if (!can_assume(VALID_INPUT) &&
(err = fdt_check_prop_offset_(fdt, offset)) < 0) {
if (lenp)
*lenp = err;
return NULL;
@ -379,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;
}
@ -391,7 +385,7 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
/* Prior to version 16, properties may need realignment
* and this API does not work. fdt_getprop_*() will, however. */

if (fdt_version(fdt) < 0x10) {
if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) {
if (lenp)
*lenp = -FDT_ERR_BADVERSION;
return NULL;
@ -412,11 +406,12 @@ static const struct fdt_property *fdt_get_property_namelen_(const void *fdt,
(offset = fdt_next_property_offset(fdt, offset))) {
const struct fdt_property *prop;

if (!(prop = fdt_get_property_by_offset_(fdt, offset, lenp))) {
prop = fdt_get_property_by_offset_(fdt, offset, lenp);
if (!can_assume(LIBFDT_FLAWLESS) && !prop) {
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;
@ -437,7 +432,7 @@ const struct fdt_property *fdt_get_property_namelen(const void *fdt,
{
/* Prior to version 16, properties may need realignment
* and this API does not work. fdt_getprop_*() will, however. */
if (fdt_version(fdt) < 0x10) {
if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) {
if (lenp)
*lenp = -FDT_ERR_BADVERSION;
return NULL;
@ -468,8 +463,8 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
return NULL;

/* Handle realignment */
if (fdt_version(fdt) < 0x10 && (poffset + sizeof(*prop)) % 8 &&
fdt32_ld(&prop->len) >= 8)
if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
(poffset + sizeof(*prop)) % 8 && fdt32_ld_(&prop->len) >= 8)
return prop->data + 4;
return prop->data;
}
@ -485,19 +480,24 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
if (namep) {
const char *name;
int namelen;
name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff),
&namelen);
if (!name) {
if (lenp)
*lenp = namelen;
return NULL;

if (!can_assume(VALID_INPUT)) {
name = fdt_get_string(fdt, fdt32_ld_(&prop->nameoff),
&namelen);
*namep = name;
if (!name) {
if (lenp)
*lenp = namelen;
return NULL;
}
} else {
*namep = fdt_string(fdt, fdt32_ld_(&prop->nameoff));
}
*namep = name;
}

/* Handle realignment */
if (fdt_version(fdt) < 0x10 && (offset + sizeof(*prop)) % 8 &&
fdt32_ld(&prop->len) >= 8)
if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
(offset + sizeof(*prop)) % 8 && fdt32_ld_(&prop->len) >= 8)
return prop->data + 4;
return prop->data;
}
@ -522,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)
@ -542,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;
@ -622,10 +648,12 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
}
}

if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
return -FDT_ERR_BADOFFSET;
else if (offset == -FDT_ERR_BADOFFSET)
return -FDT_ERR_BADSTRUCTURE;
if (!can_assume(VALID_INPUT)) {
if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
return -FDT_ERR_BADOFFSET;
else if (offset == -FDT_ERR_BADOFFSET)
return -FDT_ERR_BADSTRUCTURE;
}

return offset; /* error from fdt_next_node() */
}
@ -637,7 +665,8 @@ int fdt_node_depth(const void *fdt, int nodeoffset)

err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth);
if (err)
return (err < 0) ? err : -FDT_ERR_INTERNAL;
return (can_assume(LIBFDT_FLAWLESS) || err < 0) ? err :
-FDT_ERR_INTERNAL;
return nodedepth;
}

@ -682,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);
@ -857,66 +886,3 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,

return offset; /* error from fdt_next_node() */
}

int fdt_check_full(const void *fdt, size_t bufsize)
{
int err;
int num_memrsv;
int offset, nextoffset = 0;
uint32_t tag;
unsigned depth = 0;
const void *prop;
const char *propname;

if (bufsize < FDT_V1_SIZE)
return -FDT_ERR_TRUNCATED;
err = fdt_check_header(fdt);
if (err != 0)
return err;
if (bufsize < fdt_totalsize(fdt))
return -FDT_ERR_TRUNCATED;

num_memrsv = fdt_num_mem_rsv(fdt);
if (num_memrsv < 0)
return num_memrsv;

while (1) {
offset = nextoffset;
tag = fdt_next_tag(fdt, offset, &nextoffset);

if (nextoffset < 0)
return nextoffset;

switch (tag) {
case FDT_NOP:
break;

case FDT_END:
if (depth != 0)
return -FDT_ERR_BADSTRUCTURE;
return 0;

case FDT_BEGIN_NODE:
depth++;
if (depth > INT_MAX)
return -FDT_ERR_BADSTRUCTURE;
break;

case FDT_END_NODE:
if (depth == 0)
return -FDT_ERR_BADSTRUCTURE;
depth--;
break;

case FDT_PROP:
prop = fdt_getprop_by_offset(fdt, offset, &propname,
&err);
if (!prop)
return err;
break;

default:
return -FDT_ERR_INTERNAL;
}
}
}

View File

@ -1,52 +1,7 @@
// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
*
* libfdt is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
*
* a) This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*
* Alternatively,
*
* b) Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "libfdt_env.h"

@ -69,14 +24,16 @@ static int fdt_blocks_misordered_(const void *fdt,

static int fdt_rw_probe_(void *fdt)
{
if (can_assume(VALID_DTB))
return 0;
FDT_RO_PROBE(fdt);

if (fdt_version(fdt) < 17)
if (!can_assume(LATEST) && fdt_version(fdt) < 17)
return -FDT_ERR_BADVERSION;
if (fdt_blocks_misordered_(fdt, sizeof(struct fdt_reserve_entry),
fdt_size_dt_struct(fdt)))
return -FDT_ERR_BADLAYOUT;
if (fdt_version(fdt) > 17)
if (!can_assume(LATEST) && fdt_version(fdt) > 17)
fdt_set_version(fdt, 17);

return 0;
@ -89,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);
}
@ -97,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;
}

@ -136,6 +94,14 @@ static int fdt_splice_struct_(void *fdt, void *p,
return 0;
}

/* Must only be used to roll back in case of error */
static void fdt_del_last_string_(void *fdt, const char *s)
{
int newlen = strlen(s) + 1;

fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) - newlen);
}

static int fdt_splice_string_(void *fdt, int newlen)
{
void *p = (char *)fdt
@ -149,25 +115,42 @@ static int fdt_splice_string_(void *fdt, int newlen)
return 0;
}

static int fdt_find_add_string_(void *fdt, const char *s)
/**
* fdt_find_add_string_() - Find or allocate a string
*
* @fdt: pointer to the device tree to check/adjust
* @s: string to find/add
* @allocated: Set to 0 if the string was found, 1 if not found and so
* 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 slen,
int *allocated)
{
char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);
const char *p;
char *new;
int len = strlen(s) + 1;
int err;

p = fdt_find_string_(strtab, fdt_size_dt_strings(fdt), s);
if (!can_assume(NO_ROLLBACK))
*allocated = 0;

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;

memcpy(new, s, len);
if (!can_assume(NO_ROLLBACK))
*allocated = 1;

memcpy(new, s, slen);
new[slen] = '\0';

return (new - strtab);
}

@ -200,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;

@ -219,17 +204,18 @@ 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;
int namestroff;
int err;
int allocated;

if ((nextoffset = fdt_check_node_offset_(fdt, nodeoffset)) < 0)
return nextoffset;

namestroff = fdt_find_add_string_(fdt, name);
namestroff = fdt_find_add_string_(fdt, name, namelen, &allocated);
if (namestroff < 0)
return namestroff;

@ -237,8 +223,12 @@ static int fdt_add_property_(void *fdt, int nodeoffset, const char *name,
proplen = sizeof(**prop) + FDT_TAGALIGN(len);

err = fdt_splice_struct_(fdt, *prop, 0, proplen);
if (err)
if (err) {
/* Delete the string if we failed to add it */
if (!can_assume(NO_ROLLBACK) && allocated)
fdt_del_last_string_(fdt, name);
return err;
}

(*prop)->tag = cpu_to_fdt32(FDT_PROP);
(*prop)->nameoff = cpu_to_fdt32(namestroff);
@ -269,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;

@ -287,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;

@ -321,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);
@ -363,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);
@ -405,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;

@ -420,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));
}
@ -440,17 +437,20 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
* sizeof(struct fdt_reserve_entry);

if (fdt_version(fdt) >= 17) {
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 (!fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) {
if (can_assume(LIBFDT_ORDER) ||
!fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) {
/* no further work necessary */
err = fdt_move(fdt, buf, bufsize);
if (err)
@ -478,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);
@ -498,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

@ -1,51 +1,7 @@
// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
*
* libfdt is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
*
* a) This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*
* Alternatively,
*
* b) Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "libfdt_env.h"
@ -82,8 +38,10 @@ static struct fdt_errtabent fdt_errtable[] = {
FDT_ERRTABENT(FDT_ERR_BADVALUE),
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)
{
@ -91,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

@ -1,52 +1,7 @@
// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
*
* libfdt is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
*
* a) This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*
* Alternatively,
*
* b) Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "libfdt_env.h"

@ -57,10 +12,13 @@

static int fdt_sw_probe_(void *fdt)
{
if (fdt_magic(fdt) == FDT_MAGIC)
return -FDT_ERR_BADSTATE;
else if (fdt_magic(fdt) != FDT_SW_MAGIC)
return -FDT_ERR_BADMAGIC;
if (!can_assume(VALID_INPUT)) {
if (fdt_magic(fdt) == FDT_MAGIC)
return -FDT_ERR_BADSTATE;
else if (fdt_magic(fdt) != FDT_SW_MAGIC)
return -FDT_ERR_BADMAGIC;
}

return 0;
}

@ -74,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)
@ -83,7 +41,7 @@ static int fdt_sw_probe_memrsv_(void *fdt)
if (err)
return err;

if (fdt_off_dt_strings(fdt) != 0)
if (!can_assume(VALID_INPUT) && fdt_off_dt_strings(fdt) != 0)
return -FDT_ERR_BADSTATE;
return 0;
}
@ -109,7 +67,8 @@ static int fdt_sw_probe_struct_(void *fdt)
if (err)
return err;

if (fdt_off_dt_strings(fdt) != fdt_totalsize(fdt))
if (!can_assume(VALID_INPUT) &&
fdt_off_dt_strings(fdt) != fdt_totalsize(fdt))
return -FDT_ERR_BADSTATE;
return 0;
}
@ -121,6 +80,12 @@ static int fdt_sw_probe_struct_(void *fdt)
return err; \
}

static inline uint32_t sw_flags(void *fdt)
{
/* assert: (fdt_magic(fdt) == FDT_SW_MAGIC) */
return fdt_last_comp_version(fdt);
}

/* 'complete' state: Enter this state after fdt_finish()
*
* Allowed functions: none
@ -128,8 +93,8 @@ static int fdt_sw_probe_struct_(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);
@ -141,20 +106,31 @@ static void *fdt_grab_space_(void *fdt, size_t len)
return fdt_offset_ptr_w_(fdt, offset);
}

int fdt_create(void *buf, int bufsize)
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)
return -FDT_ERR_NOSPACE;

if (flags & ~FDT_CREATE_FLAGS_ALL)
return -FDT_ERR_BADFLAGS;

memset(buf, 0, bufsize);

/*
* magic and last_comp_version keep intermediate state during the fdt
* creation process, which is replaced with the proper FDT format by
* fdt_finish().
*
* flags should be accessed with sw_flags().
*/
fdt_set_magic(fdt, FDT_SW_MAGIC);
fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION);
fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
fdt_set_last_comp_version(fdt, flags);

fdt_set_totalsize(fdt, bufsize);

fdt_set_off_mem_rsvmap(fdt, hdrsize);
@ -164,6 +140,11 @@ int fdt_create(void *buf, int bufsize)
return 0;
}

int fdt_create(void *buf, int bufsize)
{
return fdt_create_with_flags(buf, bufsize, 0);
}

int fdt_resize(void *fdt, void *buf, int bufsize)
{
size_t headsize, tailsize;
@ -171,13 +152,17 @@ 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);

if ((headsize + tailsize) > fdt_totalsize(fdt))
if (!can_assume(VALID_DTB) &&
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;
@ -262,43 +247,73 @@ int fdt_end_node(void *fdt)
return 0;
}

static int fdt_find_add_string_(void *fdt, const char *s)
static int fdt_add_string_(void *fdt, const char *s)
{
char *strtab = (char *)fdt + fdt_totalsize(fdt);
const char *p;
unsigned int strtabsize = fdt_size_dt_strings(fdt);
unsigned int len = strlen(s) + 1;
unsigned int struct_top, offset;

offset = strtabsize + len;
struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
if (fdt_totalsize(fdt) - offset < struct_top)
return 0; /* no more room :( */

memcpy(strtab - offset, s, len);
fdt_set_size_dt_strings(fdt, strtabsize + len);
return -offset;
}

/* Must only be used to roll back in case of error */
static void fdt_del_last_string_(void *fdt, const char *s)
{
int strtabsize = fdt_size_dt_strings(fdt);
int len = strlen(s) + 1;
int struct_top, offset;

fdt_set_size_dt_strings(fdt, strtabsize - len);
}

static int fdt_find_add_string_(void *fdt, const char *s, int *allocated)
{
char *strtab = (char *)fdt + fdt_totalsize(fdt);
int strtabsize = fdt_size_dt_strings(fdt);
const char *p;

*allocated = 0;

p = fdt_find_string_(strtab - strtabsize, strtabsize, s);
if (p)
return p - strtab;

/* Add it */
offset = -strtabsize - len;
struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
if (fdt_totalsize(fdt) + offset < struct_top)
return 0; /* no more room :( */
*allocated = 1;

memcpy(strtab + offset, s, len);
fdt_set_size_dt_strings(fdt, strtabsize + len);
return offset;
return fdt_add_string_(fdt, s);
}

int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp)
{
struct fdt_property *prop;
int nameoff;
int allocated;

FDT_SW_PROBE_STRUCT(fdt);

nameoff = fdt_find_add_string_(fdt, name);
/* String de-duplication can be slow, _NO_NAME_DEDUP skips it */
if (sw_flags(fdt) & FDT_CREATE_FLAG_NO_NAME_DEDUP) {
allocated = 1;
nameoff = fdt_add_string_(fdt, name);
} else {
nameoff = fdt_find_add_string_(fdt, name, &allocated);
}
if (nameoff == 0)
return -FDT_ERR_NOSPACE;

prop = fdt_grab_space_(fdt, sizeof(*prop) + FDT_TAGALIGN(len));
if (! prop)
if (! prop) {
if (allocated)
fdt_del_last_string_(fdt, name);
return -FDT_ERR_NOSPACE;
}

prop->tag = cpu_to_fdt32(FDT_PROP);
prop->nameoff = cpu_to_fdt32(nameoff);
@ -360,6 +375,10 @@ int fdt_finish(void *fdt)

/* Finally, adjust the header */
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_LAST_COMPATIBLE_VERSION);
fdt_set_magic(fdt, FDT_MAGIC);

return 0;
}

View File

@ -1,52 +1,7 @@
// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
*
* libfdt is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
*
* a) This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*
* Alternatively,
*
* b) Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "libfdt_env.h"

@ -68,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);

View File

@ -1,60 +1,20 @@
/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
#ifndef LIBFDT_H
#define LIBFDT_H
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
*
* libfdt is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
*
* a) This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*
* Alternatively,
*
* b) Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <libfdt_env.h>
#include <fdt.h>

#ifdef __cplusplus
extern "C" {
#endif

#define FDT_FIRST_SUPPORTED_VERSION 0x02
#define FDT_LAST_COMPATIBLE_VERSION 0x10
#define FDT_LAST_SUPPORTED_VERSION 0x11

/* Error codes: informative error codes */
@ -138,7 +98,19 @@
/* FDT_ERR_NOPHANDLES: The device tree doesn't have any
* phandle available anymore without causing an overflow */

#define FDT_ERR_MAX 17
#define FDT_ERR_BADFLAGS 18
/* FDT_ERR_BADFLAGS: The function was passed a flags field that
* contains invalid flags or an invalid combination of flags. */

#define FDT_ERR_ALIGNMENT 19
/* FDT_ERR_ALIGNMENT: The device tree base address is not 8-byte
* aligned. */

#define FDT_ERR_MAX 19

/* constants */
#define FDT_MAX_PHANDLE 0xfffffffe
/* Valid values for phandles range from 1 to 2^32-2. */

/**********************************************************************/
/* Low-level functions (you probably don't need these) */
@ -155,11 +127,16 @@ static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)
uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);

/*
* Alignment helpers:
* These helpers access words from a device tree blob. They're
* built to work even with unaligned pointers on platforms (ike
* ARM) that don't like unaligned loads and stores
* External helpers to access words from a device tree blob. They're built
* to work even with unaligned pointers on platforms (such as ARMv5) that don't
* like unaligned loads and stores.
*/
static inline uint16_t fdt16_ld(const fdt16_t *p)
{
const uint8_t *bp = (const uint8_t *)p;

return ((uint16_t)bp[0] << 8) | bp[1];
}

static inline uint32_t fdt32_ld(const fdt32_t *p)
{
@ -171,6 +148,16 @@ static inline uint32_t fdt32_ld(const fdt32_t *p)
| bp[3];
}

static inline void fdt32_st(void *property, uint32_t value)
{
uint8_t *bp = (uint8_t *)property;

bp[0] = value >> 24;
bp[1] = (value >> 16) & 0xff;
bp[2] = (value >> 8) & 0xff;
bp[3] = value & 0xff;
}

static inline uint64_t fdt64_ld(const fdt64_t *p)
{
const uint8_t *bp = (const uint8_t *)p;
@ -185,6 +172,20 @@ static inline uint64_t fdt64_ld(const fdt64_t *p)
| bp[7];
}

static inline void fdt64_st(void *property, uint64_t value)
{
uint8_t *bp = (uint8_t *)property;

bp[0] = value >> 56;
bp[1] = (value >> 48) & 0xff;
bp[2] = (value >> 40) & 0xff;
bp[3] = (value >> 32) & 0xff;
bp[4] = (value >> 24) & 0xff;
bp[5] = (value >> 16) & 0xff;
bp[6] = (value >> 8) & 0xff;
bp[7] = value & 0xff;
}

/**********************************************************************/
/* Traversal functions */
/**********************************************************************/
@ -193,23 +194,23 @@ int fdt_next_node(const void *fdt, int offset, int *depth);

/**
* fdt_first_subnode() - get offset of first direct subnode
*
* @fdt: FDT blob
* @offset: Offset of node to check
* @return offset of first subnode, or -FDT_ERR_NOTFOUND if there is none
*
* Return: offset of first subnode, or -FDT_ERR_NOTFOUND if there is none
*/
int fdt_first_subnode(const void *fdt, int offset);

/**
* fdt_next_subnode() - get offset of next direct subnode
* @fdt: FDT blob
* @offset: Offset of previous subnode
*
* After first calling fdt_first_subnode(), call this function repeatedly to
* get direct subnodes of a parent node.
*
* @fdt: FDT blob
* @offset: Offset of previous subnode
* @return offset of next subnode, or -FDT_ERR_NOTFOUND if there are no more
* subnodes
* Return: offset of next subnode, or -FDT_ERR_NOTFOUND if there are no more
* subnodes
*/
int fdt_next_subnode(const void *fdt, int offset);

@ -234,7 +235,6 @@ int fdt_next_subnode(const void *fdt, int offset);
* Note that this is implemented as a macro and @node is used as
* iterator in the loop. The parent variable be constant or even a
* literal.
*
*/
#define fdt_for_each_subnode(node, fdt, parent) \
for (node = fdt_first_subnode(fdt, parent); \
@ -263,31 +263,36 @@ int fdt_next_subnode(const void *fdt, int offset);
struct fdt_header *fdth = (struct fdt_header *)fdt; \
fdth->name = cpu_to_fdt32(val); \
}
fdt_set_hdr_(magic);
fdt_set_hdr_(totalsize);
fdt_set_hdr_(off_dt_struct);
fdt_set_hdr_(off_dt_strings);
fdt_set_hdr_(off_mem_rsvmap);
fdt_set_hdr_(version);
fdt_set_hdr_(last_comp_version);
fdt_set_hdr_(boot_cpuid_phys);
fdt_set_hdr_(size_dt_strings);
fdt_set_hdr_(size_dt_struct);
fdt_set_hdr_(magic)
fdt_set_hdr_(totalsize)
fdt_set_hdr_(off_dt_struct)
fdt_set_hdr_(off_dt_strings)
fdt_set_hdr_(off_mem_rsvmap)
fdt_set_hdr_(version)
fdt_set_hdr_(last_comp_version)
fdt_set_hdr_(boot_cpuid_phys)
fdt_set_hdr_(size_dt_strings)
fdt_set_hdr_(size_dt_struct)
#undef fdt_set_hdr_

/**
* fdt_header_size - return the size of the tree's header
* @fdt: pointer to a flattened device tree
*
* Return: size of DTB header in bytes
*/
size_t fdt_header_size(const void *fdt);

/**
* fdt_header_size_ - internal function to get header size from a version number
* @version: device tree version number
*
* Return: size of DTB header in bytes
*/
size_t fdt_header_size_(uint32_t version);
static inline size_t fdt_header_size(const void *fdt)
{
return fdt_header_size_(fdt_version(fdt));
}

/**
* fdt_check_header - sanity check a device tree header

* @fdt: pointer to data which might be a flattened device tree
*
* fdt_check_header() checks that the given buffer contains what
@ -361,6 +366,20 @@ const char *fdt_get_string(const void *fdt, int stroffset, int *lenp);
*/
const char *fdt_string(const void *fdt, int stroffset);

/**
* fdt_find_max_phandle - find and return the highest phandle in a tree
* @fdt: pointer to the device tree blob
* @phandle: return location for the highest phandle value found in the tree
*
* fdt_find_max_phandle() finds the highest phandle value in the given device
* tree. The value returned in @phandle is only valid if the function returns
* success.
*
* returns:
* 0 on success or a negative error code on failure
*/
int fdt_find_max_phandle(const void *fdt, uint32_t *phandle);

/**
* fdt_get_max_phandle - retrieves the highest phandle in a tree
* @fdt: pointer to the device tree blob
@ -369,12 +388,38 @@ const char *fdt_string(const void *fdt, int stroffset);
* device tree. This will ignore badly formatted phandles, or phandles
* with a value of 0 or -1.
*
* This function is deprecated in favour of fdt_find_max_phandle().
*
* returns:
* the highest phandle on success
* 0, if no phandle was found in the device tree
* -1, if an error occurred
*/
uint32_t fdt_get_max_phandle(const void *fdt);
static inline uint32_t fdt_get_max_phandle(const void *fdt)
{
uint32_t phandle;
int err;

err = fdt_find_max_phandle(fdt, &phandle);
if (err < 0)
return (uint32_t)-1;

return phandle;
}

/**
* fdt_generate_phandle - return a new, unused phandle for a device tree blob
* @fdt: pointer to the device tree blob
* @phandle: return location for the new phandle
*
* Walks the device tree blob and looks for the highest phandle value. On
* success, the new, unused phandle value (one higher than the previously
* highest phandle value in the device tree blob) will be returned in the
* @phandle parameter.
*
* Return: 0 on success or a negative error-code on failure
*/
int fdt_generate_phandle(const void *fdt, uint32_t *phandle);

/**
* fdt_num_mem_rsv - retrieve the number of memory reserve map entries
@ -392,9 +437,11 @@ int fdt_num_mem_rsv(const void *fdt);
/**
* fdt_get_mem_rsv - retrieve one memory reserve map entry
* @fdt: pointer to the device tree blob
* @address, @size: pointers to 64-bit variables
* @n: index of reserve map entry
* @address: pointer to 64-bit variable to hold the start address
* @size: pointer to 64-bit variable to hold the size of the entry
*
* On success, *address and *size will contain the address and size of
* On success, @address and @size will contain the address and size of
* the n-th reserve map entry from the device tree blob, in
* native-endian format.
*
@ -417,6 +464,8 @@ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size);
* namelen characters of name for matching the subnode name. This is
* useful for finding subnodes based on a portion of a larger string,
* such as a full path.
*
* Return: offset of the subnode or -FDT_ERR_NOTFOUND if name not found.
*/
#ifndef SWIG /* Not available in Python */
int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
@ -456,6 +505,8 @@ int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
*
* Identical to fdt_path_offset(), but only consider the first namelen
* characters of path as the path name.
*
* Return: offset of the node or negative libfdt error value otherwise
*/
#ifndef SWIG /* Not available in Python */
int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen);
@ -473,12 +524,37 @@ int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen);
* level matching the given component, differentiated only by unit
* address).
*
* If the path is not absolute (i.e. does not begin with '/'), the
* first component is treated as an alias. That is, the property by
* that name is looked up in the /aliases node, and the value of that
* property used in place of that first component.
*
* For example, for this small fragment
*
* / {
* aliases {
* i2c2 = &foo; // RHS compiles to "/soc@0/i2c@30a40000/eeprom@52"
* };
* soc@0 {
* foo: i2c@30a40000 {
* bar: eeprom@52 {
* };
* };
* };
* };
*
* these would be equivalent:
*
* /soc@0/i2c@30a40000/eeprom@52
* i2c2/eeprom@52
*
* returns:
* structure block offset of the node with the requested path (>=0), on
* success
* -FDT_ERR_BADPATH, given path does not begin with '/' or is invalid
* -FDT_ERR_BADPATH, given path does not begin with '/' and the first
* component is not a valid alias
* -FDT_ERR_NOTFOUND, if the requested node does not exist
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE,
* -FDT_ERR_BADSTRUCTURE,
@ -523,7 +599,7 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp);
* structure block offset of the property (>=0), on success
* -FDT_ERR_NOTFOUND, if the requested node has no properties
* -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_BEGIN_NODE tag
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE,
* -FDT_ERR_BADSTRUCTURE,
@ -544,7 +620,7 @@ int fdt_first_property_offset(const void *fdt, int nodeoffset);
* structure block offset of the next property (>=0), on success
* -FDT_ERR_NOTFOUND, if the given property is the last in its node
* -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_PROP tag
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE,
* -FDT_ERR_BADSTRUCTURE,
@ -555,9 +631,9 @@ int fdt_next_property_offset(const void *fdt, int offset);
/**
* fdt_for_each_property_offset - iterate over all properties of a node
*
* @property_offset: property offset (int, lvalue)
* @fdt: FDT blob (const void *)
* @node: node offset (int)
* @property: property offset (int, lvalue)
* @fdt: FDT blob (const void *)
* @node: node offset (int)
*
* This is actually a wrapper around a for loop and would be used like so:
*
@ -609,6 +685,13 @@ int fdt_next_property_offset(const void *fdt, int offset);
const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
int offset,
int *lenp);
static inline struct fdt_property *fdt_get_property_by_offset_w(void *fdt,
int offset,
int *lenp)
{
return (struct fdt_property *)(uintptr_t)
fdt_get_property_by_offset(fdt, offset, lenp);
}

/**
* fdt_get_property_namelen - find a property based on substring
@ -620,12 +703,22 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
*
* Identical to fdt_get_property(), but only examine the first namelen
* characters of name for matching the property name.
*
* Return: pointer to the structure representing the property, or NULL
* if not found
*/
#ifndef SWIG /* Not available in Python */
const struct fdt_property *fdt_get_property_namelen(const void *fdt,
int nodeoffset,
const char *name,
int namelen, int *lenp);
static inline struct fdt_property *
fdt_get_property_namelen_w(void *fdt, int nodeoffset, const char *name,
int namelen, int *lenp)
{
return (struct fdt_property *)(uintptr_t)fdt_get_property_namelen(
fdt, nodeoffset, name, namelen, lenp);
}
#endif

/**
@ -678,7 +771,7 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
* to within the device blob itself, not a copy of the value). If
* lenp is non-NULL, the length of the property value is also
* returned, in the integer pointed to by lenp. If namep is non-NULL,
* the property's namne will also be returned in the char * pointed to
* the property's name will also be returned in the char * pointed to
* by namep (this will be a pointer to within the device tree's string
* block, not a new copy of the name).
*
@ -686,7 +779,7 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
* pointer to the property's value
* if lenp is non-NULL, *lenp contains the length of the property
* value (>=0)
* if namep is non-NULL *namep contiains a pointer to the property
* if namep is non-NULL *namep contains a pointer to the property
* name.
* NULL, on error
* if lenp is non-NULL, *lenp contains an error code (<0):
@ -712,6 +805,8 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
*
* Identical to fdt_getprop(), but only examine the first namelen
* characters of name for matching the property name.
*
* Return: pointer to the property's value or NULL on error
*/
#ifndef SWIG /* Not available in Python */
const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
@ -733,10 +828,10 @@ static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset,
* @lenp: pointer to an integer variable (will be overwritten) or NULL
*
* fdt_getprop() retrieves a pointer to the value of the property
* named 'name' of the node at offset nodeoffset (this will be a
* named @name of the node at offset @nodeoffset (this will be a
* pointer to within the device blob itself, not a copy of the value).
* If lenp is non-NULL, the length of the property value is also
* returned, in the integer pointed to by lenp.
* If @lenp is non-NULL, the length of the property value is also
* returned, in the integer pointed to by @lenp.
*
* returns:
* pointer to the property's value
@ -778,11 +873,14 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset);
/**
* fdt_get_alias_namelen - get alias based on substring
* @fdt: pointer to the device tree blob
* @name: name of the alias th look up
* @name: name of the alias to look up
* @namelen: number of characters of name to consider
*
* Identical to fdt_get_alias(), but only examine the first namelen
* characters of name for matching the alias name.
* Identical to fdt_get_alias(), but only examine the first @namelen
* characters of @name for matching the alias name.
*
* Return: a pointer to the expansion of the alias named @name, if it exists,
* NULL otherwise
*/
#ifndef SWIG /* Not available in Python */
const char *fdt_get_alias_namelen(const void *fdt,
@ -792,10 +890,10 @@ const char *fdt_get_alias_namelen(const void *fdt,
/**
* fdt_get_alias - retrieve the path referenced by a given alias
* @fdt: pointer to the device tree blob
* @name: name of the alias th look up
* @name: name of the alias to look up
*
* fdt_get_alias() retrieves the value of a given alias. That is, the
* value of the property named 'name' in the node /aliases.
* value of the property named @name in the node /aliases.
*
* returns:
* a pointer to the expansion of the alias named 'name', if it exists
@ -803,6 +901,42 @@ const char *fdt_get_alias_namelen(const void *fdt,
*/
const char *fdt_get_alias(const void *fdt, const char *name);

/**
* fdt_get_symbol_namelen - get symbol based on substring
* @fdt: pointer to the device tree blob
* @name: name of the symbol to look up
* @namelen: number of characters of name to consider
*
* Identical to fdt_get_symbol(), but only examine the first @namelen
* characters of @name for matching the symbol name.
*
* Return: a pointer to the expansion of the symbol named @name, if it exists,
* NULL otherwise
*/
#ifndef SWIG /* Not available in Python */
const char *fdt_get_symbol_namelen(const void *fdt,
const char *name, int namelen);
#endif

/**
* fdt_get_symbol - retrieve the path referenced by a given symbol
* @fdt: pointer to the device tree blob
* @name: name of the symbol to look up
*
* fdt_get_symbol() retrieves the value of a given symbol. That is,
* the value of the property named @name in the node
* /__symbols__. Such a node exists only for a device tree blob that
* has been compiled with the -@ dtc option. Each property corresponds
* to a label appearing in the device tree source, with the name of
* the property being the label and the value being the full path of
* the node it is attached to.
*
* returns:
* a pointer to the expansion of the symbol named 'name', if it exists
* NULL, if the given symbol or the /__symbols__ node does not exist
*/
const char *fdt_get_symbol(const void *fdt, const char *name);

/**
* fdt_get_path - determine the full path of a node
* @fdt: pointer to the device tree blob
@ -971,14 +1105,13 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle);

/**
* fdt_node_check_compatible: check a node's compatible property
* fdt_node_check_compatible - check a node's compatible property
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of a tree node
* @compatible: string to match against
*
*
* fdt_node_check_compatible() returns 0 if the given node contains a
* 'compatible' property with the given string as one of its elements,
* @compatible property with the given string as one of its elements,
* it returns non-zero otherwise, or on error.
*
* returns:
@ -1042,7 +1175,7 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
* one or more strings, each terminated by \0, as is found in a device tree
* "compatible" property.
*
* @return: 1 if the string is found in the list, 0 not found, or invalid list
* Return: 1 if the string is found in the list, 0 not found, or invalid list
*/
int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);

@ -1051,7 +1184,8 @@ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of a tree node
* @property: name of the property containing the string list
* @return:
*
* Return:
* the number of strings in the given property
* -FDT_ERR_BADVALUE if the property value is not NUL-terminated
* -FDT_ERR_NOTFOUND if the property does not exist
@ -1071,7 +1205,7 @@ int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property);
* small-valued cell properties, such as #address-cells, when searching for
* the empty string.
*
* @return:
* return:
* the index of the string in the list of strings
* -FDT_ERR_BADVALUE if the property value is not NUL-terminated
* -FDT_ERR_NOTFOUND if the property does not exist or does not contain
@ -1095,7 +1229,7 @@ int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,
* If non-NULL, the length of the string (on success) or a negative error-code
* (on failure) will be stored in the integer pointer to by lenp.
*
* @return:
* Return:
* A pointer to the string at the given index in the string list or NULL on
* failure. On success the length of the string will be stored in the memory
* location pointed to by the lenp parameter, if non-NULL. On failure one of
@ -1132,8 +1266,8 @@ const char *fdt_stringlist_get(const void *fdt, int nodeoffset,
*
* returns:
* 0 <= n < FDT_MAX_NCELLS, on success
* 2, if the node has no #address-cells property
* -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid
* 2, if the node has no #address-cells property
* -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid
* #address-cells property
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
@ -1153,8 +1287,8 @@ int fdt_address_cells(const void *fdt, int nodeoffset);
*
* returns:
* 0 <= n < FDT_MAX_NCELLS, on success
* 1, if the node has no #size-cells property
* -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid
* 1, if the node has no #size-cells property
* -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid
* #size-cells property
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
@ -1184,6 +1318,8 @@ int fdt_size_cells(const void *fdt, int nodeoffset);
* starting from the given index, and using only the first characters
* of the name. It is useful when you want to manipulate only one value of
* an array and you have a string that doesn't end with \0.
*
* Return: 0 on success, negative libfdt error value otherwise
*/
#ifndef SWIG /* Not available in Python */
int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
@ -1297,8 +1433,13 @@ static inline int fdt_setprop_inplace_u64(void *fdt, int nodeoffset,

/**
* fdt_setprop_inplace_cell - change the value of a single-cell property
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node containing the property
* @name: name of the property to change the value of
* @val: new value of the 32-bit cell
*
* This is an alternative name for fdt_setprop_inplace_u32()
* Return: 0 on success, negative libfdt error number otherwise.
*/
static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset,
const char *name, uint32_t val)
@ -1360,7 +1501,45 @@ int fdt_nop_node(void *fdt, int nodeoffset);
/* Sequential write functions */
/**********************************************************************/

/* fdt_create_with_flags flags */
#define FDT_CREATE_FLAG_NO_NAME_DEDUP 0x1
/* FDT_CREATE_FLAG_NO_NAME_DEDUP: Do not try to de-duplicate property
* names in the fdt. This can result in faster creation times, but
* a larger fdt. */

#define FDT_CREATE_FLAGS_ALL (FDT_CREATE_FLAG_NO_NAME_DEDUP)

/**
* fdt_create_with_flags - begin creation of a new fdt
* @buf: pointer to memory allocated where fdt will be created
* @bufsize: size of the memory space at fdt
* @flags: a valid combination of FDT_CREATE_FLAG_ flags, or 0.
*
* fdt_create_with_flags() begins the process of creating a new fdt with
* the sequential write interface.
*
* fdt creation process must end with fdt_finish() to produce a valid fdt.
*
* returns:
* 0, on success
* -FDT_ERR_NOSPACE, bufsize is insufficient for a minimal fdt
* -FDT_ERR_BADFLAGS, flags is not valid
*/
int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags);

/**
* fdt_create - begin creation of a new fdt
* @buf: pointer to memory allocated where fdt will be created
* @bufsize: size of the memory space at fdt
*
* fdt_create() is equivalent to fdt_create_with_flags() with flags=0.
*
* returns:
* 0, on success
* -FDT_ERR_NOSPACE, bufsize is insufficient for a minimal fdt
*/
int fdt_create(void *buf, int bufsize);

int fdt_resize(void *fdt, void *buf, int bufsize);
int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size);
int fdt_finish_reservemap(void *fdt);
@ -1390,7 +1569,7 @@ static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
* @fdt: pointer to the device tree blob
* @name: name of property to add
* @len: length of property value in bytes
* @valp: returns a pointer to where where the value should be placed
* @valp: returns a pointer to where the value should be placed
*
* returns:
* 0, on success
@ -1415,7 +1594,8 @@ int fdt_pack(void *fdt);
/**
* fdt_add_mem_rsv - add one memory reserve map entry
* @fdt: pointer to the device tree blob
* @address, @size: 64-bit values (native endian)
* @address: 64-bit start address of the reserve map entry
* @size: 64-bit size of the reserved region
*
* Adds a reserve map entry to the given blob reserving a region at
* address address of length size.
@ -1486,6 +1666,38 @@ int fdt_del_mem_rsv(void *fdt, int n);
*/
int fdt_set_name(void *fdt, int nodeoffset, const char *name);

/**
* fdt_setprop_namelen - create or change a property
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose property to change
* @name: name of the property to change
* @namelen: length of the name
* @val: pointer to data to set the property value to
* @len: length of the property value
*
* fdt_setprop_namelen() sets the value of the named property in the given
* node to the given value and length, creating the property if it
* does not already exist.
*
* This function may insert or delete data from the blob, and will
* therefore change the offsets of some existing nodes.
*
* returns:
* 0, on success
* -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
* contain the new property value
* -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
* -FDT_ERR_BADLAYOUT,
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE,
* -FDT_ERR_BADSTRUCTURE,
* -FDT_ERR_BADLAYOUT,
* -FDT_ERR_TRUNCATED, standard meanings
*/
int fdt_setprop_namelen(void *fdt, int nodeoffset, const char *name,
int namelen, const void *val, int len);

/**
* fdt_setprop - create or change a property
* @fdt: pointer to the device tree blob
@ -1514,18 +1726,23 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name);
* -FDT_ERR_BADLAYOUT,
* -FDT_ERR_TRUNCATED, standard meanings
*/
int fdt_setprop(void *fdt, int nodeoffset, const char *name,
const void *val, int len);
static inline int fdt_setprop(void *fdt, int nodeoffset, const char *name,
const void *val, int len)
{
return fdt_setprop_namelen(fdt, nodeoffset, name, strlen(name), val,
len);
}

/**
* fdt_setprop_placeholder - allocate space for a property
* fdt_setprop_placeholder_namelen - allocate space for a property
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose property to change
* @name: name of the property to change
* @namelen: length of the name
* @len: length of the property value
* @prop_data: return pointer to property data
*
* fdt_setprop_placeholer() allocates the named property in the given node.
* fdt_setprop_placeholder_namelen() allocates the named property in the given node.
* If the property exists it is resized. In either case a pointer to the
* property data is returned.
*
@ -1545,8 +1762,44 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,
* -FDT_ERR_BADLAYOUT,
* -FDT_ERR_TRUNCATED, standard meanings
*/
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);

/**
* fdt_setprop_placeholder - allocate space for a property
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose property to change
* @name: name of the property to change
* @len: length of the property value
* @prop_data: return pointer to property data
*
* fdt_setprop_placeholder() allocates the named property in the given node.
* If the property exists it is resized. In either case a pointer to the
* property data is returned.
*
* This function may insert or delete data from the blob, and will
* therefore change the offsets of some existing nodes.
*
* returns:
* 0, on success
* -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
* contain the new property value
* -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
* -FDT_ERR_BADLAYOUT,
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE,
* -FDT_ERR_BADSTRUCTURE,
* -FDT_ERR_BADLAYOUT,
* -FDT_ERR_TRUNCATED, standard meanings
*/
static inline int fdt_setprop_placeholder(void *fdt, int nodeoffset,
const char *name, int len,
void **prop_data)
{
return fdt_setprop_placeholder_namelen(fdt, nodeoffset, name,
strlen(name), len, prop_data);
}

/**
* fdt_setprop_u32 - set a property to a 32-bit integer
@ -1620,8 +1873,14 @@ static inline int fdt_setprop_u64(void *fdt, int nodeoffset, const char *name,

/**
* fdt_setprop_cell - set a property to a single cell value
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose property to change
* @name: name of the property to change
* @val: 32-bit integer value for the property (native endian)
*
* This is an alternative name for fdt_setprop_u32()
*
* Return: 0 on success, negative libfdt error value otherwise.
*/
static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
uint32_t val)
@ -1660,6 +1919,38 @@ static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
#define fdt_setprop_string(fdt, nodeoffset, name, str) \
fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)

/**
* fdt_setprop_namelen_string - set a property to a string value
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose property to change
* @name: name of the property to change
* @namelen: number of characters of name to consider
* @str: string value for the property
*
* fdt_setprop_namelen_string() sets the value of the named property in the
* given node to the given string value (using the length of the
* string to determine the new length of the property), or creates a
* new property with that value if it does not already exist.
*
* This function may insert or delete data from the blob, and will
* therefore change the offsets of some existing nodes.
*
* returns:
* 0, on success
* -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
* contain the new property value
* -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
* -FDT_ERR_BADLAYOUT,
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE,
* -FDT_ERR_BADSTRUCTURE,
* -FDT_ERR_BADLAYOUT,
* -FDT_ERR_TRUNCATED, standard meanings
*/
#define fdt_setprop_namelen_string(fdt, nodeoffset, name, namelen, str) \
fdt_setprop_namelen((fdt), (nodeoffset), (name), (namelen), (str), \
strlen(str) + 1)

/**
* fdt_setprop_empty - set a property to an empty value
@ -1792,8 +2083,14 @@ static inline int fdt_appendprop_u64(void *fdt, int nodeoffset,

/**
* fdt_appendprop_cell - append a single cell value to a property
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose property to change
* @name: name of the property to change
* @val: 32-bit integer value to append to the property (native endian)
*
* This is an alternative name for fdt_appendprop_u32()
*
* Return: 0 on success, negative libfdt error value otherwise.
*/
static inline int fdt_appendprop_cell(void *fdt, int nodeoffset,
const char *name, uint32_t val)
@ -1831,13 +2128,50 @@ static inline int fdt_appendprop_cell(void *fdt, int nodeoffset,
#define fdt_appendprop_string(fdt, nodeoffset, name, str) \
fdt_appendprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)

/**
* fdt_appendprop_addrrange - append a address range property
* @fdt: pointer to the device tree blob
* @parent: offset of the parent node
* @nodeoffset: offset of the node to add a property at
* @name: name of property
* @addr: start address of a given range
* @size: size of a given range
*
* fdt_appendprop_addrrange() appends an address range value (start
* address and size) to the value of the named property in the given
* node, or creates a new property with that value if it does not
* already exist.
*
* Cell sizes are determined by parent's #address-cells and #size-cells.
*
* This function may insert data into the blob, and will therefore
* change the offsets of some existing nodes.
*
* returns:
* 0, on success
* -FDT_ERR_BADLAYOUT,
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid
* #address-cells property
* -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
* -FDT_ERR_BADSTATE,
* -FDT_ERR_BADSTRUCTURE,
* -FDT_ERR_BADVERSION,
* -FDT_ERR_BADVALUE, addr or size doesn't fit to respective cells size
* -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
* contain a new property
* -FDT_ERR_TRUNCATED, standard meanings
*/
int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset,
const char *name, uint64_t addr, uint64_t size);

/**
* fdt_delprop - delete a property
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose property to nop
* @name: name of the property to nop
*
* fdt_del_property() will delete the given property.
* fdt_delprop() will delete the given property.
*
* This function will delete data from the blob, and will therefore
* change the offsets of some existing nodes.
@ -1859,13 +2193,16 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name);
* fdt_add_subnode_namelen - creates a new node based on substring
* @fdt: pointer to the device tree blob
* @parentoffset: structure block offset of a node
* @name: name of the subnode to locate
* @name: name of the subnode to create
* @namelen: number of characters of name to consider
*
* Identical to fdt_add_subnode(), but use only the first namelen
* characters of name as the name of the new node. This is useful for
* Identical to fdt_add_subnode(), but use only the first @namelen
* characters of @name as the name of the new node. This is useful for
* creating subnodes based on a portion of a larger string, such as a
* full path.
*
* Return: structure block offset of the created subnode (>=0),
* negative libfdt error value otherwise
*/
#ifndef SWIG /* Not available in Python */
int fdt_add_subnode_namelen(void *fdt, int parentoffset,
@ -1884,10 +2221,9 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
*
* This function will insert data into the blob, and will therefore
* change the offsets of some existing nodes.

*
* returns:
* structure block offset of the created nodeequested subnode (>=0), on
* success
* structure block offset of the created subnode (>=0), on success
* -FDT_ERR_NOTFOUND, if the requested subnode does not exist
* -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE
* tag
@ -1897,7 +2233,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
* blob to contain the new node
* -FDT_ERR_NOSPACE
* -FDT_ERR_BADLAYOUT
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE,
* -FDT_ERR_BADSTRUCTURE,
@ -1942,7 +2278,7 @@ int fdt_del_node(void *fdt, int nodeoffset);
* returns:
* 0, on success
* -FDT_ERR_NOSPACE, there's not enough space in the base device tree
* -FDT_ERR_NOTFOUND, the overlay points to some inexistant nodes or
* -FDT_ERR_NOTFOUND, the overlay points to some nonexistent nodes or
* properties in the base DT
* -FDT_ERR_BADPHANDLE,
* -FDT_ERR_BADOVERLAY,
@ -1959,10 +2295,32 @@ int fdt_del_node(void *fdt, int nodeoffset);
*/
int fdt_overlay_apply(void *fdt, void *fdto);

/**
* fdt_overlay_target_offset - retrieves the offset of a fragment's target
* @fdt: Base device tree blob
* @fdto: Device tree overlay blob
* @fragment_offset: node offset of the fragment in the overlay
* @pathp: pointer which receives the path of the target (or NULL)
*
* fdt_overlay_target_offset() 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
*/
int fdt_overlay_target_offset(const void *fdt, const void *fdto,
int fragment_offset, char const **pathp);

/**********************************************************************/
/* Debugging / informational functions */
/**********************************************************************/

const char *fdt_strerror(int errval);

#ifdef __cplusplus
}
#endif

#endif /* LIBFDT_H */

View File

@ -1,57 +1,13 @@
/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
#ifndef LIBFDT_ENV_H
#define LIBFDT_ENV_H
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
* Copyright 2012 Kim Phillips, Freescale Semiconductor.
*
* libfdt is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
*
* a) This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*
* Alternatively,
*
* b) Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>

View File

@ -1,71 +1,35 @@
/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
#ifndef LIBFDT_INTERNAL_H
#define LIBFDT_INTERNAL_H
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
*
* libfdt is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
*
* a) This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*
* Alternatively,
*
* b) Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <fdt.h>
#include <string.h>

#define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
#define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE))

int fdt_ro_probe_(const void *fdt);
#define FDT_RO_PROBE(fdt) \
{ \
int err_; \
if ((err_ = fdt_ro_probe_(fdt)) != 0) \
return err_; \
int32_t fdt_ro_probe_(const void *fdt);
#define FDT_RO_PROBE(fdt) \
{ \
int32_t totalsize_; \
if ((totalsize_ = fdt_ro_probe_(fdt)) < 0) \
return totalsize_; \
}

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)
@ -91,6 +55,147 @@ 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)

/**********************************************************************/
/* Checking controls */
/**********************************************************************/

#ifndef FDT_ASSUME_MASK
#define FDT_ASSUME_MASK 0
#endif

/*
* Defines assumptions which can be enabled. Each of these can be enabled
* individually. For maximum safety, don't enable any assumptions!
*
* For minimal code size and no safety, use ASSUME_PERFECT at your own risk.
* You should have another method of validating the device tree, such as a
* signature or hash check before using libfdt.
*
* For situations where security is not a concern it may be safe to enable
* ASSUME_SANE.
*/
enum {
/*
* This does essentially no checks. Only the latest device-tree
* version is correctly handled. Inconsistencies or errors in the device
* tree may cause undefined behaviour or crashes. Invalid parameters
* passed to libfdt may do the same.
*
* If an error occurs when modifying the tree it may leave the tree in
* an intermediate (but valid) state. As an example, adding a property
* where there is insufficient space may result in the property name
* being added to the string table even though the property itself is
* not added to the struct section.
*
* Only use this if you have a fully validated device tree with
* the latest supported version and wish to minimise code size.
*/
ASSUME_PERFECT = 0xff,

/*
* This assumes that the device tree is sane. i.e. header metadata
* and basic hierarchy are correct.
*
* With this assumption enabled, normal device trees produced by libfdt
* and the compiler should be handled safely. Malicious device trees and
* complete garbage may cause libfdt to behave badly or crash. Truncated
* device trees (e.g. those only partially loaded) can also cause
* problems.
*
* Note: Only checks that relate exclusively to the device tree itself
* (not the parameters passed to libfdt) are disabled by this
* assumption. This includes checking headers, tags and the like.
*/
ASSUME_VALID_DTB = 1 << 0,

/*
* This builds on ASSUME_VALID_DTB and further assumes that libfdt
* functions are called with valid parameters, i.e. not trigger
* FDT_ERR_BADOFFSET or offsets that are out of bounds. It disables any
* extensive checking of parameters and the device tree, making various
* assumptions about correctness.
*
* It doesn't make sense to enable this assumption unless
* ASSUME_VALID_DTB is also enabled.
*/
ASSUME_VALID_INPUT = 1 << 1,

/*
* This disables checks for device-tree version and removes all code
* which handles older versions.
*
* Only enable this if you know you have a device tree with the latest
* version.
*/
ASSUME_LATEST = 1 << 2,

/*
* This assumes that it is OK for a failed addition to the device tree,
* due to lack of space or some other problem, to skip any rollback
* steps (such as dropping the property name from the string table).
* This is safe to enable in most circumstances, even though it may
* leave the tree in a sub-optimal state.
*/
ASSUME_NO_ROLLBACK = 1 << 3,

/*
* This assumes that the device tree components appear in a 'convenient'
* order, i.e. the memory reservation block first, then the structure
* block and finally the string block.
*
* This order is not specified by the device-tree specification,
* but is expected by libfdt. The device-tree compiler always created
* device trees with this order.
*
* This assumption disables a check in fdt_open_into() and removes the
* ability to fix the problem there. This is safe if you know that the
* device tree is correctly ordered. See fdt_blocks_misordered_().
*/
ASSUME_LIBFDT_ORDER = 1 << 4,

/*
* This assumes that libfdt itself does not have any internal bugs. It
* drops certain checks that should never be needed unless libfdt has an
* undiscovered bug.
*
* This can generally be considered safe to enable.
*/
ASSUME_LIBFDT_FLAWLESS = 1 << 5,
};

/**
* can_assume_() - check if a particular assumption is enabled
*
* @mask: Mask to check (ASSUME_...)
* @return true if that assumption is enabled, else false
*/
static inline bool can_assume_(int mask)
{
return FDT_ASSUME_MASK & mask;
}

/** helper macros for checking assumptions */
#define can_assume(_assume) can_assume_(ASSUME_ ## _assume)

#endif /* LIBFDT_INTERNAL_H */

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

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
LIBFDT_1.2 {
global:
fdt_next_node;
@ -19,6 +20,7 @@ LIBFDT_1.2 {
fdt_get_alias_namelen;
fdt_get_alias;
fdt_get_path;
fdt_header_size;
fdt_supernode_atdepth_offset;
fdt_node_depth;
fdt_parent_offset;
@ -41,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;
@ -66,6 +69,19 @@ LIBFDT_1.2 {
fdt_resize;
fdt_overlay_apply;
fdt_get_string;
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

@ -1,21 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/

#include "dtc.h"
@ -51,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;
@ -131,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;
}
@ -189,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;
@ -249,6 +234,7 @@ struct node * add_orphan_node(struct node *dt, struct node *new_node, char *ref)
char *name;

if (ref[0] == '/') {
d = data_add_marker(d, TYPE_STRING, ref);
d = data_append_data(d, ref, strlen(ref) + 1);

p = build_property("target-path", d, NULL);
@ -264,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;
@ -350,17 +337,20 @@ void delete_node(struct node *node)
}

void append_to_property(struct node *node,
char *name, const void *data, int len)
char *name, const void *data, int len,
enum markertype type)
{
struct data d;
struct property *p;

p = get_property(node, name);
if (p) {
d = data_append_data(p->val, data, len);
d = data_add_marker(p->val, type, name);
d = data_append_data(d, data, len);
p->val = d;
} else {
d = data_append_data(empty_data, data, len);
d = data_add_marker(empty_data, type, name);
d = data_append_data(d, data, len);
p = build_property(name, d, NULL);
add_property(node, p);
}
@ -449,9 +439,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));
}

@ -514,7 +504,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;
@ -537,8 +527,7 @@ struct node *get_node_by_path(struct node *tree, const char *path)
p = strchr(path, '/');

for_each_child(tree, child) {
if (p && (strlen(child->name) == p-path) &&
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;
@ -571,7 +560,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;
}
@ -593,20 +582,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))
@ -614,16 +645,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
@ -793,18 +816,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;

@ -858,8 +881,8 @@ static void generate_label_tree_internal(struct dt_info *dti,

/* insert it */
p = build_property(l->label,
data_copy_mem(node->fullpath,
strlen(node->fullpath) + 1),
data_copy_escape_string(node->fullpath,
strlen(node->fullpath)),
NULL);
add_property(an, p);
}
@ -904,13 +927,19 @@ static void add_fixup_entry(struct dt_info *dti, struct node *fn,
/* 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);
append_to_property(fn, m->ref, entry, strlen(entry) + 1, TYPE_STRING);

free(entry);
}
@ -970,7 +999,7 @@ static void add_local_fixup_entry(struct dt_info *dti,
char **compp;
int i, depth;

/* walk back retreiving depth */
/* walk back retrieving depth */
depth = 0;
for (wn = node; wn; wn = wn->parent)
depth++;
@ -985,15 +1014,13 @@ 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));
append_to_property(wn, prop->name, &value_32, sizeof(value_32), TYPE_UINT32);
}

static void generate_local_fixups_tree_internal(struct dt_info *dti,
@ -1019,7 +1046,7 @@ static void generate_local_fixups_tree_internal(struct dt_info *dti,
generate_local_fixups_tree_internal(dti, lfn, c);
}

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;
@ -1027,18 +1054,31 @@ 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)
{
struct node *n = get_subnode(dti->dt, name);

/* Start with an empty __fixups__ node to not get duplicates */
if (n)
n->deleted = true;

if (!any_fixup_tree(dti, dti->dt))
return;
generate_fixups_tree_internal(dti, build_root_node(dti->dt, name),
generate_fixups_tree_internal(dti,
build_and_name_child_node(dti->dt, name),
dti->dt);
}

void generate_local_fixups_tree(struct dt_info *dti, char *name)
void generate_local_fixups_tree(struct dt_info *dti, const char *name)
{
struct node *n = get_subnode(dti->dt, name);

/* Start with an empty __local_fixups__ node to not get duplicates */
if (n)
n->deleted = true;
if (!any_local_fixup_tree(dti, dti->dt))
return;
generate_local_fixups_tree_internal(dti, build_root_node(dti->dt, name),
generate_local_fixups_tree_internal(dti,
build_and_name_child_node(dti->dt, name),
dti->dt);
}

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')

2
pylibfdt/.gitignore vendored
View File

@ -1,3 +1,3 @@
libfdt.py
libfdt.pyc
*.pyc
libfdt_wrap.c

View File

@ -1,29 +0,0 @@
# 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

@ -1,53 +1,8 @@
// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
/*
* pylibfdt - Flat Device Tree manipulation in Python
* Copyright (C) 2017 Google, Inc.
* Written by Simon Glass <sjg@chromium.org>
*
* libfdt is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
*
* a) This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*
* Alternatively,
*
* b) Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

%module libfdt
@ -63,7 +18,7 @@
* a struct called fdt_property. That struct causes swig to create a class in
* libfdt.py called fdt_property(), which confuses things.
*/
static int fdt_property_stub(void *fdt, const char *name, const char *val,
static int fdt_property_stub(void *fdt, const char *name, const void *val,
int len)
{
return fdt_property(fdt, name, val, len);
@ -159,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):
@ -204,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

@ -340,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
@ -438,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=()):
@ -460,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

@ -476,6 +465,41 @@ class FdtRo(object):
"""
return fdt_get_phandle(self._fdt, nodeoffset)

def get_alias(self, name):
"""Get the full path referenced by a given alias

Args:
name: name of the alias to lookup

Returns:
Full path to the node for the alias named 'name', if it exists
None, if the given alias or the /aliases node does not exist
"""
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

@ -615,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

@ -749,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:
@ -757,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
@ -772,8 +844,10 @@ class FdtSw(FdtRo):

# First create the device tree with a node and property:
sw = FdtSw()
with sw.add_node('node'):
sw.property_u32('reg', 2)
sw.finish_reservemap()
with sw.add_node(''):
with sw.add_node('node'):
sw.property_u32('reg', 2)
fdt = sw.as_fdt()

# Now we can use it as a real device tree
@ -961,7 +1035,7 @@ class FdtSw(FdtRo):

Args:
name: Name of property to add
val: Value of property
val: Value of property (bytes)
quiet: Errors to ignore (empty to raise on all errors)

Raises:
@ -1022,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.
@ -1040,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 * */
@ -1051,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() */
@ -1063,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);
}
}

@ -1071,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() */
@ -1102,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 };
@ -1114,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;

@ -1144,6 +1223,6 @@ int fdt_property_cell(void *fdt, const char *name, uint32_t val);
* This function has a stub since the name fdt_property is used for both a
* function and a struct, which confuses SWIG.
*/
int fdt_property_stub(void *fdt, const char *name, const char *val, int len);
int fdt_property_stub(void *fdt, const char *name, const void *val, int len);

%include <libfdt.h>

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,44 +0,0 @@
#!/usr/bin/env python2

"""
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 valgrind which
elif [ "$NAME" = "Alpine Linux" ]
then
apk add build-base bison coreutils flex git yaml yaml-dev python3-dev \
meson py3-setuptools_scm swig valgrind
elif [ "$NAME" = "Fedora Linux" ]
then
dnf install -y bison diffutils flex gcc git libyaml libyaml-devel \
make meson python3-devel python3-setuptools swig valgrind which
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 valgrind
else
echo "ERROR: OS name is not provided."
exit 1
fi

View File

@ -1,4 +1,5 @@
#! /bin/sh
# SPDX-License-Identifier: GPL-2.0-or-later

REMOTE_GIT=/pub/scm/utils/dtc/dtc.git
REMOTE_PATH=/pub/software/utils/dtc

View File

@ -1,4 +1,5 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-or-later
# Print additional version information for non-release trees.

usage() {

View File

@ -1,23 +1,11 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/

#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif

#include <stdio.h>

@ -34,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)
@ -172,8 +160,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;
@ -297,6 +287,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)
{
@ -325,8 +326,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) {
@ -344,9 +345,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;
}
@ -360,7 +361,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

@ -1,20 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/

#ifndef SRCPOS_H
@ -102,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);

4
tests/.gitignore vendored
View File

@ -8,6 +8,7 @@ tmp.*
/addr_size_cells
/addr_size_cells2
/appendprop[12]
/appendprop_addrrange
/asm_tree_dump
/boot-cpuid
/char_literal
@ -53,8 +54,10 @@ tmp.*
/property_iterate
/propname_escapes
/references
/relref_merge
/root_node
/rw_tree1
/rw_oom
/set_name
/setprop
/setprop_inplace
@ -71,3 +74,4 @@ tmp.*
/truncated_memrsv
/utilfdt_test
/value-labels
/get_next_tag_invalid_prop_len

View File

@ -4,20 +4,21 @@ 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 \
addr_size_cells \
addr_size_cells2 \
appendprop_addrrange \
stringlist \
setprop_inplace nop_property nop_node \
sw_tree1 sw_states \
move_and_save mangle-layout nopulate \
open_pack rw_tree1 set_name setprop del_property del_node \
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 \
@ -32,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)
@ -48,7 +54,7 @@ TESTS_DEPFILES = $(TESTS:%=%.d) \
$(addprefix $(TESTS_PREFIX),testutils.d trees.d dumptrees.d)

TESTS_CLEANFILES_L = $(STD_CLEANFILES) \
*.dtb *.test.dts *.test.dt.yaml *.dtsv1 tmp.* \
*.dtb *.test.dts *.test.dt.yaml *.dtsv1 tmp.* *.bak \
dumptrees
TESTS_CLEANFILES = $(TESTS) $(TESTS_CLEANFILES_L:%=$(TESTS_PREFIX)%)
TESTS_CLEANDIRS_L = fs
@ -57,23 +63,23 @@ TESTS_CLEANDIRS = $(TESTS_CLEANDIRS_L:%=$(TESTS_PREFIX)%)
.PHONY: tests
tests: $(TESTS) $(TESTS_TREES)

$(LIB_TESTS): %: $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_archive)
$(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_archive)
$(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_archive)
util.o $(LIBFDT_dep)

$(TESTS_PREFIX)dumptrees: $(TESTS_PREFIX)trees.o

$(TESTS_TREES): $(TESTS_PREFIX)dumptrees
@$(VECHO) DUMPTREES
cd $(TESTS_PREFIX); ./dumptrees >/dev/null
cd $(TESTS_PREFIX); ./dumptrees . >/dev/null

tests_clean:
@$(VECHO) CLEAN "(tests)"
@ -81,18 +87,18 @@ tests_clean:
rm -rf $(TESTS_CLEANDIRS)

check: tests ${TESTS_BIN} $(TESTS_PYLIBFDT)
cd $(TESTS_PREFIX); PYTHON=$(PYTHON) ./run_tests.sh
cd $(TESTS_PREFIX); ./run_tests.sh

ifeq ($(NO_VALGRIND),1)
checkm:
@echo "make checkm requires valgrind, but NO_VALGRIND=1"
else
checkm: tests ${TESTS_BIN} $(TESTS_PYLIBFDT)
cd $(TESTS_PREFIX); PYTHON=$(PYTHON) ./run_tests.sh -m
cd $(TESTS_PREFIX); ./run_tests.sh -m
endif

checkv: tests ${TESTS_BIN} $(TESTS_PYLIBFDT)
cd $(TESTS_PREFIX); PYTHON=$(PYTHON) ./run_tests.sh -v
cd $(TESTS_PREFIX); ./run_tests.sh -v

ifneq ($(DEPTARGETS),)
-include $(TESTS_DEPFILES)

View File

@ -1,21 +1,8 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for fdt_nop_node()
* Copyright (C) 2006 David Gibson, IBM Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include <stdlib.h>

View File

@ -1,21 +1,8 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for #address-cells and #size-cells handling
* Copyright (C) 2014 David Gibson, <david@gibson.dropbear.id.au>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdlib.h>
#include <stdio.h>
@ -60,8 +47,10 @@ int main(int argc, char *argv[])
check_node(fdt, "/", 2, 2);
check_node(fdt, "/identity-bus@0", 2, 1);
check_node(fdt, "/simple-bus@1000000", 2, 1);
check_node(fdt, "/discrete-bus@2000000", 1, 0);
check_node(fdt, "/c0", -FDT_ERR_BADNCELLS, -FDT_ERR_BADNCELLS);
check_node(fdt, "/c1", -FDT_ERR_BADNCELLS, -FDT_ERR_BADNCELLS);
check_node(fdt, "/c2", -FDT_ERR_BADNCELLS, -FDT_ERR_BADNCELLS);
check_node(fdt, "/c3", -FDT_ERR_BADNCELLS, 0);
PASS();
}

View File

@ -1,21 +1,8 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for #address-cells and #size-cells handling
* Copyright (C) 2014 David Gibson, <david@gibson.dropbear.id.au>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdlib.h>
#include <stdio.h>

View File

@ -13,6 +13,11 @@
#size-cells = <1>;
};

discrete-bus@2000000 {
#address-cells = <1>;
#size-cells = <0>;
};

c0@0 {
#address-cells = <1 1>;
#size-cells = <1 1>;
@ -27,4 +32,9 @@
#address-cells = <5>;
#size-cells = <5>;
};

c3@0 {
#address-cells = <0>;
#size-cells = <0>;
};
};

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

@ -1,21 +1,8 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for fdt_appendprop()
* Copyright (C) 2006 David Gibson, IBM Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include <stdlib.h>

View File

@ -1,21 +1,8 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for fdt_appendprop()
* Copyright (C) 2006 David Gibson, IBM Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include <stdlib.h>
@ -49,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

@ -0,0 +1,95 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for fdt_appendprop_addrrange()
* Copyright (C) 2018 AKASHI Takahiro, Linaro Limited
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>

#include <libfdt.h>

#include "tests.h"
#include "testdata.h"

int main(int argc, char *argv[])
{
void *fdt, *buf;
int offset, xac, xsc, num, i, err;
uint64_t addr, size;

if (argc != 5)
CONFIG("Usage: %s <dtb file> <address-cells> <size-cells> <num>\n",
argv[0]);

test_init(argc, argv);
fdt = load_blob(argv[1]);
xac = strtol(argv[2], NULL, 10);
xsc = strtol(argv[3], NULL, 10);
num = strtol(argv[4], NULL, 10);

buf = xmalloc(0x1000);
if (!buf)
FAIL("Couldn't allocate temporary buffer");
err = fdt_open_into(fdt, buf, 0x1000);
if (err)
FAIL("fdt_open_into(): %s", fdt_strerror(err));
free(fdt);
fdt = buf;

/* Set up */
err = fdt_setprop_cell(fdt, 0, "#address-cells", xac);
if (err)
FAIL("fdt_setprop_cell(\"#address-cells\"): %s",
fdt_strerror(err));
err = fdt_setprop_cell(fdt, 0, "#size-cells", xsc);
if (err)
FAIL("fdt_setprop_cell(\"#size-cells\"): %s",
fdt_strerror(err));

offset = fdt_path_offset(fdt, "/node@1");
if (offset < 0)
FAIL("Couldn't find path %s", "/node@1");

addr = TEST_MEMREGION_ADDR;
if (xac > 1)
addr += TEST_MEMREGION_ADDR_HI;
size = TEST_MEMREGION_SIZE;
if (xsc > 1)
size += TEST_MEMREGION_SIZE_HI;

/*
* Do test
*/
/* 1. repeat append's */
for (i = 0; i < num; i++) {
err = fdt_appendprop_addrrange(fdt, 0, offset,
"prop-memregion", addr, size);
if (err)
FAIL("Failed to append[%d] \"prop-memregion\": %s",
i, fdt_strerror(err));

check_getprop_addrrange(fdt, 0, offset, "prop-memregion",
i + 1);

addr += size;
size += TEST_MEMREGION_SIZE_INC;
}

/* 2. default property name */
addr = TEST_MEMREGION_ADDR;
if (xac > 1)
addr += TEST_MEMREGION_ADDR_HI;
size = TEST_MEMREGION_SIZE;
if (xsc > 1)
size += TEST_MEMREGION_SIZE_HI;

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);

PASS();
}

View File

@ -1,21 +1,8 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Tests if an asm tree built into a shared object matches a given dtb
* Copyright (C) 2008 David Gibson, IBM Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include <stdlib.h>

12
tests/bad-dma-ranges.dts Normal file
View File

@ -0,0 +1,12 @@
/dts-v1/;

/ {
#address-cells = <2>;
#size-cells = <2>;
node {
#address-cells = <1>;
#size-cells = <1>;
ranges;
dma-ranges = <0 0 0 0 0>;
};
};

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

@ -1,19 +1,6 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* Copyright (C) 2008 David Gibson, IBM Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include <stdlib.h>

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

@ -1,22 +1,9 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for character literals in dtc
* Copyright (C) 2006 David Gibson, IBM Corporation.
* Copyright (C) 2011 The Chromium Authors. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdlib.h>
#include <stdio.h>

View File

@ -1,21 +1,8 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Tests if two given dtbs are structurally equal (including order)
* Copyright (C) 2007 David Gibson, IBM Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include <stdlib.h>

View File

@ -1,21 +1,8 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for fdt_check_header
* Copyright (C) 2018 David Gibson
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include <stdio.h>

View File

@ -1,21 +1,8 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for node existence
* Copyright (C) 2016 Konsulko Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include <stdio.h>
@ -45,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

@ -1,21 +1,8 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for fdt_nop_node()
* Copyright (C) 2006 David Gibson, IBM Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include <stdlib.h>
@ -31,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

@ -1,21 +1,8 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for fdt_delprop()
* Copyright (C) 2006 David Gibson, IBM Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include <stdlib.h>
@ -31,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);

@ -86,5 +74,6 @@ int main(int argc, char *argv[])
if (newsize >= oldsize)
FAIL("Tree failed to shrink after deletions");

free(fdt);
PASS();
}

View File

@ -1,21 +1,8 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Tests if two given dtbs are structurally equal (including order)
* Copyright (C) 2010 David Gibson, IBM Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include <stdlib.h>

View File

@ -1,21 +1,8 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Tests if two given dtbs are structurally equal (including order)
* Copyright (C) 2007 David Gibson, IBM Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include <stdlib.h>

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