aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Muckle <smuckle@google.com>2020-07-10 03:37:15 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2020-07-10 03:37:15 +0000
commitda1de56263c85d4ef1337c314e15cdab037741bb (patch)
treea9fd8927d7222e9a3a66d60a11509addff78341d
parent2583eaa841c8a9f9dbbe3744d0507f0a0fec0d8f (diff)
parent7139aa3c994340b16cf956cae77e6cc1c711b813 (diff)
downloaddtc-da1de56263c85d4ef1337c314e15cdab037741bb.tar.gz
Update dtc to 1.6.0 am: b734cfd607 am: 7713e835e7 am: a2d66c5f84 am: 7139aa3c99
Original change: https://android-review.googlesource.com/c/platform/external/dtc/+/1358703 Change-Id: I1d3a25b2768331be6ad6cd7a3695d80f6e7bfebb
-rw-r--r--.cirrus.yml23
-rw-r--r--.editorconfig30
-rw-r--r--.gitignore2
-rw-r--r--.travis.yml43
-rw-r--r--Android.bp1
-rw-r--r--BSD-2-Clause32
-rw-r--r--Documentation/manual.txt79
-rw-r--r--GPL41
-rw-r--r--Makefile133
-rw-r--r--Makefile.convert-dtsv01
-rw-r--r--Makefile.dtc5
-rw-r--r--Makefile.utils1
-rw-r--r--README37
-rw-r--r--README.license14
-rw-r--r--checks.c1177
-rw-r--r--convert-dtsv0-lexer.l16
-rw-r--r--data.c21
-rw-r--r--dtc-lexer.l29
-rw-r--r--dtc-parser.y114
-rw-r--r--dtc.c46
-rw-r--r--dtc.h91
-rw-r--r--dtdiff1
-rw-r--r--fdtdump.c43
-rw-r--r--fdtget.c71
-rw-r--r--fdtoverlay.c116
-rw-r--r--fdtput.c24
-rw-r--r--flattree.c29
-rw-r--r--fstree.c24
-rw-r--r--libfdt/.gitignore1
-rw-r--r--libfdt/Android.bp1
-rw-r--r--libfdt/Makefile.libfdt9
-rw-r--r--libfdt/fdt.c197
-rw-r--r--libfdt/fdt.h53
-rw-r--r--libfdt/fdt_addresses.c133
-rw-r--r--libfdt/fdt_check.c74
-rw-r--r--libfdt/fdt_empty_tree.c47
-rw-r--r--libfdt/fdt_overlay.c258
-rw-r--r--libfdt/fdt_ro.c386
-rw-r--r--libfdt/fdt_rw.c229
-rw-r--r--libfdt/fdt_strerror.c47
-rw-r--r--libfdt/fdt_sw.c255
-rw-r--r--libfdt/fdt_wip.c57
-rw-r--r--libfdt/libfdt.h368
-rw-r--r--libfdt/libfdt_env.h82
-rw-r--r--libfdt/libfdt_internal.h206
-rw-r--r--libfdt/version.lds16
-rw-r--r--livetree.c115
-rw-r--r--pylibfdt/.gitignore2
-rw-r--r--pylibfdt/Makefile.pylibfdt36
-rw-r--r--pylibfdt/libfdt.i939
-rwxr-xr-xpylibfdt/setup.py113
-rwxr-xr-xscripts/kup-dtc1
-rwxr-xr-xscripts/setlocalversion1
-rw-r--r--srcpos.c174
-rw-r--r--srcpos.h36
-rw-r--r--tests/.gitignore12
-rw-r--r--tests/Makefile.tests43
-rw-r--r--tests/add_subnode_with_nops.c15
-rw-r--r--tests/addr_size_cells.c22
-rw-r--r--tests/addr_size_cells2.c49
-rw-r--r--tests/addresses.dts25
-rw-r--r--tests/appendprop1.c15
-rw-r--r--tests/appendprop2.c15
-rw-r--r--tests/appendprop_addrrange.c95
-rw-r--r--tests/asm_tree_dump.c15
-rw-r--r--tests/bad-chosen.dts10
-rw-r--r--tests/bad-dma-ranges.dts12
-rw-r--r--tests/bad-gpio.dts13
-rw-r--r--tests/bad-graph.dts24
-rw-r--r--tests/bad-interrupt-cells.dts12
-rw-r--r--tests/bad-interrupt-controller.dts7
-rw-r--r--tests/bad-phandle-cells.dts11
-rw-r--r--tests/bad-string-props.dts7
-rw-r--r--tests/boot-cpuid.c15
-rw-r--r--tests/char_literal.c15
-rw-r--r--tests/check_full.c50
-rw-r--r--tests/check_header.c115
-rw-r--r--tests/check_path.c15
-rw-r--r--tests/del_node.c15
-rw-r--r--tests/del_property.c15
-rw-r--r--tests/dtb_reverse.c15
-rw-r--r--tests/dtbs_equal_ordered.c15
-rw-r--r--tests/dtbs_equal_unordered.c51
-rwxr-xr-xtests/dtc-checkfails.sh7
-rwxr-xr-xtests/dtc-fails.sh3
-rwxr-xr-x[-rw-r--r--]tests/dtc-fatal.sh3
-rw-r--r--tests/dumptrees.c31
-rw-r--r--tests/extra-terminating-null.c15
-rwxr-xr-x[-rw-r--r--]tests/fdtdump-runtest.sh3
-rwxr-xr-xtests/fdtget-runtest.sh3
-rwxr-xr-x[-rw-r--r--]tests/fdtoverlay-runtest.sh5
-rwxr-xr-x[-rw-r--r--]tests/fdtput-runtest.sh5
-rw-r--r--tests/find_property.c15
-rw-r--r--tests/fs_tree1.c155
-rw-r--r--tests/get_alias.c15
-rw-r--r--tests/get_mem_rsv.c15
-rw-r--r--tests/get_name.c15
-rw-r--r--tests/get_path.c18
-rw-r--r--tests/get_phandle.c54
-rw-r--r--tests/get_prop_offset.c43
-rw-r--r--tests/getprop.c15
-rw-r--r--tests/incbin.c22
-rw-r--r--tests/integer-expressions.c17
-rw-r--r--tests/mangle-layout.c23
-rw-r--r--tests/mangle-layout.supp7
-rw-r--r--tests/move_and_save.c15
-rw-r--r--tests/multilabel.dts5
-rw-r--r--tests/multilabel_merge.dts5
-rw-r--r--tests/node_check_compatible.c34
-rw-r--r--tests/node_offset_by_compatible.c15
-rw-r--r--tests/node_offset_by_phandle.c15
-rw-r--r--tests/node_offset_by_prop_value.c15
-rw-r--r--tests/nop_node.c15
-rw-r--r--tests/nop_property.c15
-rw-r--r--tests/nopulate.c15
-rw-r--r--tests/notfound.c15
-rw-r--r--tests/omit-no-ref.dts26
-rw-r--r--tests/open_pack.c15
-rw-r--r--tests/open_pack.supp7
-rw-r--r--tests/overlay.c15
-rw-r--r--tests/overlay_bad_fixup.c15
-rw-r--r--tests/overlay_base.dts4
-rw-r--r--tests/overlay_overlay.dts94
-rw-r--r--tests/overlay_overlay_bypath.dts48
-rw-r--r--tests/overlay_overlay_local_merge.dts29
-rw-r--r--tests/overlay_overlay_long_path.dts32
-rw-r--r--tests/overlay_overlay_manual_fixups.dts34
-rw-r--r--tests/overlay_overlay_nosugar.dts86
-rw-r--r--tests/parent_offset.c15
-rw-r--r--tests/path-references.c15
-rw-r--r--tests/path-references.dts2
-rw-r--r--tests/path_offset.c15
-rw-r--r--tests/path_offset_aliases.c15
-rw-r--r--tests/pci-bridge-bad1.dts16
-rw-r--r--tests/pci-bridge-bad2.dts16
-rw-r--r--tests/pci-bridge-ok.dts25
-rw-r--r--tests/phandle_format.c15
-rw-r--r--tests/property_iterate.c15
-rw-r--r--tests/propname_escapes.c15
-rw-r--r--tests/pylibfdt_tests.py496
-rw-r--r--tests/references.c34
-rw-r--r--tests/references.dts5
-rw-r--r--tests/root_node.c15
-rwxr-xr-xtests/run_tests.sh505
-rw-r--r--tests/rw_oom.c83
-rw-r--r--tests/rw_tree1.c15
-rw-r--r--tests/set_name.c15
-rw-r--r--tests/setprop.c15
-rw-r--r--tests/setprop_inplace.c15
-rw-r--r--tests/sized_cells.c15
-rw-r--r--tests/sourceoutput.dts2
-rw-r--r--tests/stacked_overlay_addlabel.dts15
-rw-r--r--tests/stacked_overlay_bar.dts13
-rw-r--r--tests/stacked_overlay_base.dts6
-rw-r--r--tests/stacked_overlay_base_nolabel.dts6
-rw-r--r--tests/stacked_overlay_baz.dts13
-rw-r--r--tests/string_escapes.c15
-rw-r--r--tests/stringlist.c24
-rw-r--r--tests/subnode_iterate.c15
-rw-r--r--tests/subnode_offset.c15
-rw-r--r--tests/supernode_atdepth_offset.c15
-rw-r--r--tests/sw_states.c127
-rw-r--r--tests/sw_tree1.c93
-rw-r--r--tests/sw_tree1.supp18
-rw-r--r--tests/test_props.dts11
-rw-r--r--tests/testdata.h40
-rw-r--r--tests/tests.h35
-rw-r--r--tests/testutils.c197
-rw-r--r--tests/testutils.sh (renamed from tests/tests.sh)14
-rw-r--r--tests/trees.S85
-rw-r--r--tests/truncated_memrsv.c50
-rw-r--r--tests/truncated_property.c19
-rw-r--r--tests/truncated_string.c68
-rw-r--r--tests/type-preservation.dt.yaml20
-rw-r--r--tests/type-preservation.dts28
-rw-r--r--tests/unit-addr-simple-bus-compatible.dts18
-rw-r--r--tests/unit-addr-simple-bus-reg-mismatch.dts18
-rw-r--r--tests/unit-addr-unique.dts14
-rw-r--r--tests/utilfdt_test.c15
-rw-r--r--tests/value-labels.c15
-rw-r--r--treesource.c281
-rw-r--r--util.c102
-rw-r--r--util.h55
-rw-r--r--version_non_gen.h2
-rw-r--r--yamltree.c233
185 files changed, 7660 insertions, 3275 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
new file mode 100644
index 0000000..c270a09
--- /dev/null
+++ b/.cirrus.yml
@@ -0,0 +1,23 @@
+env:
+ CIRRUS_CLONE_DEPTH: 1
+
+freebsd_12_task:
+ freebsd_instance:
+ image: freebsd-12-1-release-amd64
+ install_script:
+ pkg install -y bison gmake pkgconf
+ build_script:
+ gmake
+ test_script:
+ gmake check
+
+linux_gcc_task:
+ container:
+ image: gcc:latest
+ install_script:
+ - apt-get update
+ - apt-get -y install bison flex
+ build_script:
+ - make
+ test_script:
+ - make check
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..d7e68fb
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,30 @@
+# 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
diff --git a/.gitignore b/.gitignore
index 545b899..1f2a0f2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,6 +4,7 @@
*.patch
*.so
*~
+*.bak
*.tab.[ch]
lex.yy.c
*.lex.c
@@ -13,5 +14,6 @@ lex.yy.c
/version_gen.h
/fdtget
/fdtput
+/fdtoverlay
/patches
/.pc
diff --git a/.travis.yml b/.travis.yml
index a07c989..a5163de 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -13,6 +13,8 @@ matrix:
packages:
- swig
- python-dev
+ - valgrind
+ - libyaml-0-2
coverity_scan:
project:
name: dtc
@@ -20,11 +22,44 @@ matrix:
notification_email: david@gibson.dropbear.id.au
build_command: make
branch_pattern: coverity_scan
+ script:
+ - make
+ - make check && make checkm
- - addons:
- apt:
- packages:
+ # Check it builds properly without optional packages:
+ # python, valgrind, libyaml
+ - script:
+ - make
+ - make check
+
+ - arch: arm64
+ addons:
+ apt_packages:
+ - swig
+ - python-dev
+ - valgrind
+ - libyaml-0-2
+ script:
+ - make
+ - make check checkm
-script:
+ - arch: ppc64le
+ addons:
+ apt_packages:
+ - swig
+ - python-dev
+ - libyaml-0-2
+ script:
- make
- make check
+
+ - arch: s390x
+ addons:
+ apt_packages:
+ - swig
+ - python-dev
+ - valgrind
+ - libyaml-0-2
+ script:
+ - make
+ - make check checkm
diff --git a/Android.bp b/Android.bp
index d52d98c..712bc4d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -7,6 +7,7 @@ cc_defaults {
"-Wno-sign-compare",
"-Wno-missing-field-initializers",
"-Wno-unused-parameter",
+ "-DNO_YAML"
],
static_libs: ["libfdt"],
diff --git a/BSD-2-Clause b/BSD-2-Clause
new file mode 100644
index 0000000..da366e2
--- /dev/null
+++ b/BSD-2-Clause
@@ -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.
diff --git a/Documentation/manual.txt b/Documentation/manual.txt
index 72403ac..adf5ccb 100644
--- a/Documentation/manual.txt
+++ b/Documentation/manual.txt
@@ -37,7 +37,7 @@ 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/
@@ -78,6 +78,9 @@ The currently supported Output Formats are:
then simply be added to your Makefile. Additionally, the
assembly file exports some symbols that can be used.
+ - "yaml": DT encoded in YAML format. This representation is an
+ intermediate format used for validation tools.
+
3) Command Line
@@ -231,7 +234,7 @@ For example:
"childnode at address". It in turn has a string property
called "childprop".
- childnode@addresss {
+ childnode@address {
childprop = "hello\n";
};
@@ -250,7 +253,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 {
...
@@ -261,7 +264,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: ;
@@ -415,7 +418,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
@@ -581,7 +584,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).
@@ -693,3 +696,67 @@ Where options are:
-i, --input Input base DT blob
-o, --output Output DT blob
-v, --verbose Verbose message output
+
+4 ) fdtget -- Read properties from device tree
+
+This command can be used to obtain individual values from the device tree in a
+nicely formatted way. You can specify multiple nodes to display (when using -p)
+or multiple node/property pairs (when not using -p). For the latter, each
+property is displayed on its own line, with a space between each cell within
+the property.
+
+The syntax of the fdtget command is:
+
+ fdtget <options> <dt file> [<node> <property>]...
+ fdtget -p <options> <dt file> [<node> ]...
+
+where options are:
+
+ <type> s=string, i=int, u=unsigned, x=hex
+ Optional modifier prefix:
+ hh or b=byte, h=2 byte, l=4 byte (default)
+
+ Options: -[t:pld:hV]
+ -t, --type <arg> Type of data
+ -p, --properties List properties for each node
+ -l, --list List subnodes for each node
+ -d, --default <arg> Default value to display when the property is missing
+ -h, --help Print this help and exit
+ -V, --version Print version and exit
+
+If -t is not provided, fdtget will try to figure out the type, trying to detect
+strings, string lists and the size of each value in the property. This is
+similar to how fdtdump works, and uses the same heuristics.
+
+
+5 ) fdtput - Write properties to a device tree
+
+The syntax of the fdtput command is:
+
+ fdtput <options> <dt file> <node> <property> [<value>...]
+ fdtput -c <options> <dt file> [<node>...]
+ fdtput -r <options> <dt file> [<node>...]
+ fdtput -d <options> <dt file> <node> [<property>...]
+
+Options are:
+
+ <type> s=string, i=int, u=unsigned, x=hex
+ Optional modifier prefix:
+ hh or b=byte, h=2 byte, l=4 byte (default)
+
+ -c, --create Create nodes if they don't already exist
+ -r, --remove Delete nodes (and any subnodes) if they already exist
+ -d, --delete Delete properties if they already exist
+ -p, --auto-path Automatically create nodes as needed for the node path
+ -t, --type <arg> Type of data
+ -v, --verbose Display each value decoded from command line
+ -h, --help Print this help and exit
+ -V, --version Print version and exit
+
+The option determines which usage is selected and therefore the operation that
+is performed. The first usage adds or updates properties; the rest are used to
+create/delete nodes and delete properties.
+
+For the first usage, the command line arguments are joined together into a
+single value which is written to the property. The -t option is required so
+that fdtput knows how to decode its arguments.
diff --git a/GPL b/GPL
index d60c31a..d159169 100644
--- a/GPL
+++ b/GPL
@@ -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.
diff --git a/Makefile b/Makefile
index fe482b9..cb256e8 100644
--- a/Makefile
+++ b/Makefile
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
#
# Device Tree Compiler
#
@@ -9,23 +10,32 @@
# CONFIG_LOCALVERSION from some future config system.
#
VERSION = 1
-PATCHLEVEL = 4
-SUBLEVEL = 4
+PATCHLEVEL = 6
+SUBLEVEL = 0
EXTRAVERSION =
LOCAL_VERSION =
CONFIG_LOCALVERSION =
-CPPFLAGS = -I libfdt -I .
+# 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 \
-Wstrict-prototypes -Wmissing-prototypes -Wredundant-decls -Wshadow
-CFLAGS = -g -Os $(SHAREDLIB_CFLAGS) -Werror $(WARNINGS)
+CFLAGS = -g -Os $(SHAREDLIB_CFLAGS) -Werror $(WARNINGS) $(EXTRA_CFLAGS)
BISON = bison
LEX = flex
SWIG = swig
PKG_CONFIG ?= pkg-config
+PYTHON ?= python3
INSTALL = /usr/bin/install
+INSTALL_PROGRAM = $(INSTALL)
+INSTALL_LIB = $(INSTALL)
+INSTALL_DATA = $(INSTALL) -m 644
+INSTALL_SCRIPT = $(INSTALL)
DESTDIR =
PREFIX = $(HOME)
BINDIR = $(PREFIX)/bin
@@ -35,6 +45,22 @@ INCLUDEDIR = $(PREFIX)/include
HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \
sed -e 's/\(cygwin\|msys\).*/\1/')
+NO_PYTHON ?= 0
+
+NO_VALGRIND := $(shell $(PKG_CONFIG) --exists valgrind; echo $$?)
+ifeq ($(NO_VALGRIND),1)
+ CPPFLAGS += -DNO_VALGRIND
+else
+ CFLAGS += $(shell $(PKG_CONFIG) --cflags valgrind)
+endif
+
+NO_YAML := $(shell $(PKG_CONFIG) --exists yaml-0.1; echo $$?)
+ifeq ($(NO_YAML),1)
+ CFLAGS += -DNO_YAML
+else
+ LDLIBS_dtc += $(shell $(PKG_CONFIG) --libs yaml-0.1)
+endif
+
ifeq ($(HOSTOS),darwin)
SHAREDLIB_EXT = dylib
SHAREDLIB_CFLAGS = -fPIC
@@ -126,26 +152,31 @@ SCRIPTS = dtdiff
all: $(BIN) libfdt
-# We need both Python and swig to build pylibfdt.
-.PHONY: maybe_pylibfdt
-maybe_pylibfdt: FORCE
- if $(PKG_CONFIG) --cflags python >/dev/null 2>&1; then \
+# 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) pylibfdt; \
+ if [ "$${can_build}" = "yes" ]; then \
+ $(MAKE) $${target}; \
else \
- echo "## Skipping pylibfdt (install python dev and swig to build)"; \
- fi
+ 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),)
+ifeq ($(NO_PYTHON),0)
all: maybe_pylibfdt
endif
ifneq ($(DEPTARGETS),)
+ifneq ($(MAKECMDGOALS),libfdt)
-include $(DTC_OBJS:%.o=%.d)
-include $(CONVERT_OBJS:%.o=%.d)
-include $(FDTDUMP_OBJS:%.o=%.d)
@@ -153,34 +184,34 @@ ifneq ($(DEPTARGETS),)
-include $(FDTPUT_OBJS:%.o=%.d)
-include $(FDTOVERLAY_OBJS:%.o=%.d)
endif
+endif
#
# Rules for libfdt
#
-LIBFDT_objdir = libfdt
-LIBFDT_srcdir = libfdt
-LIBFDT_archive = $(LIBFDT_objdir)/libfdt.a
-LIBFDT_lib = $(LIBFDT_objdir)/libfdt-$(DTC_VERSION).$(SHAREDLIB_EXT)
-LIBFDT_include = $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_INCLUDES))
-LIBFDT_version = $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_VERSION))
+LIBFDT_dir = libfdt
+LIBFDT_archive = $(LIBFDT_dir)/libfdt.a
+LIBFDT_lib = $(LIBFDT_dir)/$(LIBFDT_LIB)
+LIBFDT_include = $(addprefix $(LIBFDT_dir)/,$(LIBFDT_INCLUDES))
+LIBFDT_version = $(addprefix $(LIBFDT_dir)/,$(LIBFDT_VERSION))
-include $(LIBFDT_srcdir)/Makefile.libfdt
+include $(LIBFDT_dir)/Makefile.libfdt
.PHONY: libfdt
libfdt: $(LIBFDT_archive) $(LIBFDT_lib)
-$(LIBFDT_archive): $(addprefix $(LIBFDT_objdir)/,$(LIBFDT_OBJS))
-$(LIBFDT_lib): $(addprefix $(LIBFDT_objdir)/,$(LIBFDT_OBJS))
+$(LIBFDT_archive): $(addprefix $(LIBFDT_dir)/,$(LIBFDT_OBJS))
-libfdt_clean:
- @$(VECHO) CLEAN "(libfdt)"
- rm -f $(addprefix $(LIBFDT_objdir)/,$(STD_CLEANFILES))
- rm -f $(LIBFDT_objdir)/*.so
+$(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)
ifneq ($(DEPTARGETS),)
--include $(LIBFDT_OBJS:%.o=$(LIBFDT_objdir)/%.d)
+-include $(LIBFDT_OBJS:%.o=$(LIBFDT_dir)/%.d)
endif
# This stops make from generating the lex and bison output during
@@ -191,25 +222,30 @@ endif
install-bin: all $(SCRIPTS)
@$(VECHO) INSTALL-BIN
$(INSTALL) -d $(DESTDIR)$(BINDIR)
- $(INSTALL) $(BIN) $(SCRIPTS) $(DESTDIR)$(BINDIR)
+ $(INSTALL_PROGRAM) $(BIN) $(DESTDIR)$(BINDIR)
+ $(INSTALL_SCRIPT) $(SCRIPTS) $(DESTDIR)$(BINDIR)
install-lib: all
@$(VECHO) INSTALL-LIB
$(INSTALL) -d $(DESTDIR)$(LIBDIR)
- $(INSTALL) $(LIBFDT_lib) $(DESTDIR)$(LIBDIR)
+ $(INSTALL_LIB) $(LIBFDT_lib) $(DESTDIR)$(LIBDIR)
ln -sf $(notdir $(LIBFDT_lib)) $(DESTDIR)$(LIBDIR)/$(LIBFDT_soname)
ln -sf $(LIBFDT_soname) $(DESTDIR)$(LIBDIR)/libfdt.$(SHAREDLIB_EXT)
- $(INSTALL) -m 644 $(LIBFDT_archive) $(DESTDIR)$(LIBDIR)
+ $(INSTALL_DATA) $(LIBFDT_archive) $(DESTDIR)$(LIBDIR)
install-includes:
@$(VECHO) INSTALL-INC
$(INSTALL) -d $(DESTDIR)$(INCLUDEDIR)
- $(INSTALL) -m 644 $(LIBFDT_include) $(DESTDIR)$(INCLUDEDIR)
+ $(INSTALL_DATA) $(LIBFDT_include) $(DESTDIR)$(INCLUDEDIR)
install: install-bin install-lib install-includes
-ifeq ($(NO_PYTHON),)
-install: install_pylibfdt
+.PHONY: maybe_install_pylibfdt
+maybe_install_pylibfdt: FORCE
+ target=install_pylibfdt; $(check_python_deps)
+
+ifeq ($(NO_PYTHON),0)
+install: maybe_install_pylibfdt
endif
$(VERSION_FILE): Makefile FORCE
@@ -224,11 +260,11 @@ convert-dtsv0: $(CONVERT_OBJS)
fdtdump: $(FDTDUMP_OBJS)
-fdtget: $(FDTGET_OBJS) $(LIBFDT_archive)
+fdtget: $(FDTGET_OBJS) $(LIBFDT_lib)
-fdtput: $(FDTPUT_OBJS) $(LIBFDT_archive)
+fdtput: $(FDTPUT_OBJS) $(LIBFDT_lib)
-fdtoverlay: $(FDTOVERLAY_OBJS) $(LIBFDT_archive)
+fdtoverlay: $(FDTOVERLAY_OBJS) $(LIBFDT_lib)
dist:
git archive --format=tar --prefix=dtc-$(dtc_version)/ HEAD \
@@ -240,17 +276,12 @@ dist:
#
# Rules for pylibfdt
#
-PYLIBFDT_srcdir = pylibfdt
-PYLIBFDT_objdir = pylibfdt
+PYLIBFDT_dir = pylibfdt
-include $(PYLIBFDT_srcdir)/Makefile.pylibfdt
+include $(PYLIBFDT_dir)/Makefile.pylibfdt
.PHONY: pylibfdt
-pylibfdt: $(PYLIBFDT_objdir)/_libfdt.so
-
-pylibfdt_clean:
- @$(VECHO) CLEAN "(pylibfdt)"
- rm -f $(addprefix $(PYLIBFDT_objdir)/,$(PYLIBFDT_cleanfiles))
+pylibfdt: $(PYLIBFDT_dir)/_libfdt.so
#
# Release signing and uploading
@@ -285,11 +316,13 @@ TESTS_BIN += fdtput
TESTS_BIN += fdtget
TESTS_BIN += fdtdump
TESTS_BIN += fdtoverlay
-ifeq ($(NO_PYTHON),)
+ifeq ($(NO_PYTHON),0)
TESTS_PYLIBFDT += maybe_pylibfdt
endif
+ifneq ($(MAKECMDGOALS),libfdt)
include tests/Makefile.tests
+endif
#
# Clean rules
@@ -309,7 +342,7 @@ clean: libfdt_clean pylibfdt_clean tests_clean
#
%: %.o
@$(VECHO) LD $@
- $(LINK.c) -o $@ $^
+ $(LINK.c) -o $@ $^ $(LDLIBS_$*)
%.o: %.c
@$(VECHO) CC $@
@@ -321,7 +354,7 @@ clean: libfdt_clean pylibfdt_clean tests_clean
%.d: %.c
@$(VECHO) DEP $<
- $(CC) $(CPPFLAGS) -MM -MG -MT "$*.o $@" $< > $@
+ $(CC) $(CPPFLAGS) $(CFLAGS) -MM -MG -MT "$*.o $@" $< > $@
%.d: %.S
@$(VECHO) DEP $<
@@ -339,16 +372,12 @@ 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
@$(VECHO) BISON $@
- $(BISON) -d $<
+ $(BISON) -b $(basename $(basename $@)) -d $<
FORCE:
diff --git a/Makefile.convert-dtsv0 b/Makefile.convert-dtsv0
index 08ea40a..c12ed40 100644
--- a/Makefile.convert-dtsv0
+++ b/Makefile.convert-dtsv0
@@ -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
diff --git a/Makefile.dtc b/Makefile.dtc
index bece49b..9c467b0 100644
--- a/Makefile.dtc
+++ b/Makefile.dtc
@@ -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
@@ -14,5 +15,9 @@ DTC_SRCS = \
treesource.c \
util.c
+ifneq ($(NO_YAML),1)
+DTC_SRCS += yamltree.c
+endif
+
DTC_GEN_SRCS = dtc-lexer.lex.c dtc-parser.tab.c
DTC_OBJS = $(DTC_SRCS:%.c=%.o) $(DTC_GEN_SRCS:%.c=%.o)
diff --git a/Makefile.utils b/Makefile.utils
index e028922..9436b34 100644
--- a/Makefile.utils
+++ b/Makefile.utils
@@ -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.
diff --git a/README b/README
index 17dc845..9465ee5 100644
--- a/README
+++ b/README
@@ -14,45 +14,43 @@ 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
+ sudo apt-get install swig python3-dev
The library provides an Fdt class which you can use like this:
-$ PYTHONPATH=../pylibfdt python
+$ PYTHONPATH=../pylibfdt python3
>>> import libfdt
->>> fdt = libfdt.Fdt(open('test_tree1.dtb').read())
+>>> fdt = libfdt.Fdt(open('test_tree1.dtb', mode='rb').read())
>>> node = fdt.path_offset('/subnode@1')
->>> print node
+>>> 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)
+>>> print('%s=%s' % (prop.name, prop.as_str()))
compatible=subnode1
>>> node2 = fdt.path_offset('/')
->>> print fdt.getprop(node2, 'compatible')
+>>> 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
- $ python -c "import libfdt; help(libfdt)"
+ $ python3 -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
+ $ sudo apt-get install python3-coverage
$ cd tests
- $ coverage run pylibfdt_tests.py
- $ coverage html
+ # It's just 'coverage' on most other distributions
+ $ python3-coverage run pylibfdt_tests.py
+ $ python3-coverage html
# Open 'htmlcov/index.html' in your browser
To install the library via the normal setup.py method, use:
- ./pylibfdt/setup.py [--prefix=/path/to/install_dir]
+ ./pylibfdt/setup.py install [--prefix=/path/to/install_dir]
If --prefix is not provided, the default prefix is used, typically '/usr'
or '/usr/local'. See Python's distutils documentation for details. You can
@@ -73,6 +71,17 @@ 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
diff --git a/README.license b/README.license
index d56c88f..102b004 100644
--- a/README.license
+++ b/README.license
@@ -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,
@@ -33,7 +33,7 @@ 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
diff --git a/checks.c b/checks.c
index afabf64..b7955db 100644
--- a/checks.c
+++ b/checks.c
@@ -1,24 +1,10 @@
+// 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"
+#include "srcpos.h"
#ifdef TRACE_CHECKS
#define TRACE(c, ...) \
@@ -53,49 +39,98 @@ struct check {
struct check **prereq;
};
-#define CHECK_ENTRY(_nm, _fn, _d, _w, _e, ...) \
- static struct check *_nm##_prereqs[] = { __VA_ARGS__ }; \
- static struct check _nm = { \
- .name = #_nm, \
- .fn = (_fn), \
- .data = (_d), \
- .warn = (_w), \
- .error = (_e), \
+#define CHECK_ENTRY(nm_, fn_, d_, w_, e_, ...) \
+ static struct check *nm_##_prereqs[] = { __VA_ARGS__ }; \
+ static struct check nm_ = { \
+ .name = #nm_, \
+ .fn = (fn_), \
+ .data = (d_), \
+ .warn = (w_), \
+ .error = (e_), \
.status = UNCHECKED, \
- .num_prereqs = ARRAY_SIZE(_nm##_prereqs), \
- .prereq = _nm##_prereqs, \
+ .num_prereqs = ARRAY_SIZE(nm_##_prereqs), \
+ .prereq = nm_##_prereqs, \
};
-#define WARNING(_nm, _fn, _d, ...) \
- CHECK_ENTRY(_nm, _fn, _d, true, false, __VA_ARGS__)
-#define ERROR(_nm, _fn, _d, ...) \
- CHECK_ENTRY(_nm, _fn, _d, false, true, __VA_ARGS__)
-#define CHECK(_nm, _fn, _d, ...) \
- CHECK_ENTRY(_nm, _fn, _d, false, false, __VA_ARGS__)
-
-static inline void PRINTF(3, 4) check_msg(struct check *c, struct dt_info *dti,
+#define WARNING(nm_, fn_, d_, ...) \
+ CHECK_ENTRY(nm_, fn_, d_, true, false, __VA_ARGS__)
+#define ERROR(nm_, fn_, d_, ...) \
+ CHECK_ENTRY(nm_, fn_, d_, false, true, __VA_ARGS__)
+#define CHECK(nm_, fn_, d_, ...) \
+ CHECK_ENTRY(nm_, fn_, d_, false, false, __VA_ARGS__)
+
+static inline void PRINTF(5, 6) check_msg(struct check *c, struct dt_info *dti,
+ struct node *node,
+ struct property *prop,
const char *fmt, ...)
{
va_list ap;
- va_start(ap, fmt);
+ char *str = NULL;
+ struct srcpos *pos = NULL;
+ char *file_str;
+
+ if (!(c->warn && (quiet < 1)) && !(c->error && (quiet < 2)))
+ return;
- if ((c->warn && (quiet < 1))
- || (c->error && (quiet < 2))) {
- fprintf(stderr, "%s: %s (%s): ",
- strcmp(dti->outname, "-") ? dti->outname : "<stdout>",
+ if (prop && prop->srcpos)
+ pos = prop->srcpos;
+ else if (node && node->srcpos)
+ pos = node->srcpos;
+
+ if (pos) {
+ file_str = srcpos_string(pos);
+ xasprintf(&str, "%s", file_str);
+ free(file_str);
+ } else if (streq(dti->outname, "-")) {
+ xasprintf(&str, "<stdout>");
+ } else {
+ xasprintf(&str, "%s", dti->outname);
+ }
+
+ xasprintf_append(&str, ": %s (%s): ",
(c->error) ? "ERROR" : "Warning", c->name);
- vfprintf(stderr, fmt, ap);
- fprintf(stderr, "\n");
+
+ if (node) {
+ if (prop)
+ xasprintf_append(&str, "%s:%s: ", node->fullpath, prop->name);
+ else
+ xasprintf_append(&str, "%s: ", node->fullpath);
}
+
+ va_start(ap, fmt);
+ xavsprintf_append(&str, fmt, ap);
va_end(ap);
+
+ xasprintf_append(&str, "\n");
+
+ if (!prop && pos) {
+ pos = node->srcpos;
+ while (pos->next) {
+ pos = pos->next;
+
+ file_str = srcpos_string(pos);
+ xasprintf_append(&str, " also defined at %s\n", file_str);
+ free(file_str);
+ }
+ }
+
+ fputs(str, stderr);
}
-#define FAIL(c, dti, ...) \
+#define FAIL(c, dti, node, ...) \
+ do { \
+ TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \
+ (c)->status = FAILED; \
+ check_msg((c), dti, node, NULL, __VA_ARGS__); \
+ } while (0)
+
+#define FAIL_PROP(c, dti, node, prop, ...) \
do { \
TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \
(c)->status = FAILED; \
- check_msg((c), dti, __VA_ARGS__); \
+ check_msg((c), dti, node, prop, __VA_ARGS__); \
} while (0)
+
static void check_nodes_props(struct check *c, struct dt_info *dti, struct node *node)
{
struct node *child;
@@ -126,7 +161,7 @@ static bool run_check(struct check *c, struct dt_info *dti)
error = error || run_check(prq, dti);
if (prq->status != PASSED) {
c->status = PREREQ;
- check_msg(c, dti, "Failed prerequisite '%s'",
+ check_msg(c, dti, NULL, NULL, "Failed prerequisite '%s'",
c->prereq[i]->name);
}
}
@@ -156,7 +191,7 @@ out:
static inline void check_always_fail(struct check *c, struct dt_info *dti,
struct node *node)
{
- FAIL(c, dti, "always_fail check");
+ FAIL(c, dti, node, "always_fail check");
}
CHECK(always_fail, check_always_fail, NULL);
@@ -171,14 +206,42 @@ static void check_is_string(struct check *c, struct dt_info *dti,
return; /* Not present, assumed ok */
if (!data_is_one_string(prop->val))
- FAIL(c, dti, "\"%s\" property in %s is not a string",
- propname, node->fullpath);
+ FAIL_PROP(c, dti, node, prop, "property is not a string");
}
#define WARNING_IF_NOT_STRING(nm, propname) \
WARNING(nm, check_is_string, (propname))
#define ERROR_IF_NOT_STRING(nm, propname) \
ERROR(nm, check_is_string, (propname))
+static void check_is_string_list(struct check *c, struct dt_info *dti,
+ struct node *node)
+{
+ int rem, l;
+ struct property *prop;
+ char *propname = c->data;
+ char *str;
+
+ prop = get_property(node, propname);
+ if (!prop)
+ return; /* Not present, assumed ok */
+
+ str = prop->val.val;
+ rem = prop->val.len;
+ while (rem > 0) {
+ l = strnlen(str, rem);
+ if (l == rem) {
+ FAIL_PROP(c, dti, node, prop, "property is not a string list");
+ break;
+ }
+ rem -= l + 1;
+ str += l + 1;
+ }
+}
+#define WARNING_IF_NOT_STRING_LIST(nm, propname) \
+ WARNING(nm, check_is_string_list, (propname))
+#define ERROR_IF_NOT_STRING_LIST(nm, propname) \
+ ERROR(nm, check_is_string_list, (propname))
+
static void check_is_cell(struct check *c, struct dt_info *dti,
struct node *node)
{
@@ -190,8 +253,7 @@ static void check_is_cell(struct check *c, struct dt_info *dti,
return; /* Not present, assumed ok */
if (prop->val.len != sizeof(cell_t))
- FAIL(c, dti, "\"%s\" property in %s is not a single cell",
- propname, node->fullpath);
+ FAIL_PROP(c, dti, node, prop, "property is not a single cell");
}
#define WARNING_IF_NOT_CELL(nm, propname) \
WARNING(nm, check_is_cell, (propname))
@@ -212,8 +274,7 @@ static void check_duplicate_node_names(struct check *c, struct dt_info *dti,
child2;
child2 = child2->next_sibling)
if (streq(child->name, child2->name))
- FAIL(c, dti, "Duplicate node name %s",
- child->fullpath);
+ FAIL(c, dti, child2, "Duplicate node name");
}
ERROR(duplicate_node_names, check_duplicate_node_names, NULL);
@@ -227,8 +288,7 @@ static void check_duplicate_property_names(struct check *c, struct dt_info *dti,
if (prop2->deleted)
continue;
if (streq(prop->name, prop2->name))
- FAIL(c, dti, "Duplicate property name %s in %s",
- prop->name, node->fullpath);
+ FAIL_PROP(c, dti, node, prop, "Duplicate property name");
}
}
}
@@ -246,8 +306,8 @@ static void check_node_name_chars(struct check *c, struct dt_info *dti,
int n = strspn(node->name, c->data);
if (n < strlen(node->name))
- FAIL(c, dti, "Bad character '%c' in node %s",
- node->name[n], node->fullpath);
+ FAIL(c, dti, node, "Bad character '%c' in node name",
+ node->name[n]);
}
ERROR(node_name_chars, check_node_name_chars, PROPNODECHARS "@");
@@ -257,8 +317,8 @@ static void check_node_name_chars_strict(struct check *c, struct dt_info *dti,
int n = strspn(node->name, c->data);
if (n < node->basenamelen)
- FAIL(c, dti, "Character '%c' not recommended in node %s",
- node->name[n], node->fullpath);
+ FAIL(c, dti, node, "Character '%c' not recommended in node name",
+ node->name[n]);
}
CHECK(node_name_chars_strict, check_node_name_chars_strict, PROPNODECHARSSTRICT);
@@ -266,8 +326,7 @@ static void check_node_name_format(struct check *c, struct dt_info *dti,
struct node *node)
{
if (strchr(get_unitname(node), '@'))
- FAIL(c, dti, "Node %s has multiple '@' characters in name",
- node->fullpath);
+ FAIL(c, dti, node, "multiple '@' characters in node name");
}
ERROR(node_name_format, check_node_name_format, NULL, &node_name_chars);
@@ -277,6 +336,11 @@ static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti,
const char *unitname = get_unitname(node);
struct property *prop = get_property(node, "reg");
+ if (get_subnode(node, "__overlay__")) {
+ /* HACK: Overlay fragments are a special case */
+ return;
+ }
+
if (!prop) {
prop = get_property(node, "ranges");
if (prop && !prop->val.len)
@@ -285,12 +349,10 @@ static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti,
if (prop) {
if (!unitname[0])
- FAIL(c, dti, "Node %s has a reg or ranges property, but no unit name",
- node->fullpath);
+ FAIL(c, dti, node, "node has a reg or ranges property, but no unit name");
} else {
if (unitname[0])
- FAIL(c, dti, "Node %s has a unit name, but no reg property",
- node->fullpath);
+ 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);
@@ -304,8 +366,8 @@ static void check_property_name_chars(struct check *c, struct dt_info *dti,
int n = strspn(prop->name, c->data);
if (n < strlen(prop->name))
- FAIL(c, dti, "Bad character '%c' in property name \"%s\", node %s",
- prop->name[n], prop->name, node->fullpath);
+ FAIL_PROP(c, dti, node, prop, "Bad character '%c' in property name",
+ prop->name[n]);
}
}
ERROR(property_name_chars, check_property_name_chars, PROPNODECHARS);
@@ -336,8 +398,8 @@ static void check_property_name_chars_strict(struct check *c,
n = strspn(name, c->data);
}
if (n < strlen(name))
- FAIL(c, dti, "Character '%c' not recommended in property name \"%s\", node %s",
- name[n], prop->name, node->fullpath);
+ FAIL_PROP(c, dti, node, prop, "Character '%c' not recommended in property name",
+ name[n]);
}
}
CHECK(property_name_chars_strict, check_property_name_chars_strict, PROPNODECHARSSTRICT);
@@ -370,7 +432,7 @@ static void check_duplicate_label(struct check *c, struct dt_info *dti,
return;
if ((othernode != node) || (otherprop != prop) || (othermark != mark))
- FAIL(c, dti, "Duplicate label '%s' on " DESCLABEL_FMT
+ FAIL(c, dti, node, "Duplicate label '%s' on " DESCLABEL_FMT
" and " DESCLABEL_FMT,
label, DESCLABEL_ARGS(node, prop, mark),
DESCLABEL_ARGS(othernode, otherprop, othermark));
@@ -410,8 +472,8 @@ static cell_t check_phandle_prop(struct check *c, struct dt_info *dti,
return 0;
if (prop->val.len != sizeof(cell_t)) {
- FAIL(c, dti, "%s has bad length (%d) %s property",
- node->fullpath, prop->val.len, prop->name);
+ FAIL_PROP(c, dti, node, prop, "bad length (%d) %s property",
+ prop->val.len, prop->name);
return 0;
}
@@ -422,8 +484,8 @@ static cell_t check_phandle_prop(struct check *c, struct dt_info *dti,
/* "Set this node's phandle equal to some
* other node's phandle". That's nonsensical
* by construction. */ {
- FAIL(c, dti, "%s in %s is a reference to another node",
- prop->name, node->fullpath);
+ FAIL(c, dti, node, "%s is a reference to another node",
+ prop->name);
}
/* But setting this node's phandle equal to its own
* phandle is allowed - that means allocate a unique
@@ -436,8 +498,8 @@ static cell_t check_phandle_prop(struct check *c, struct dt_info *dti,
phandle = propval_cell(prop);
if ((phandle == 0) || (phandle == -1)) {
- FAIL(c, dti, "%s has bad value (0x%x) in %s property",
- node->fullpath, phandle, prop->name);
+ FAIL_PROP(c, dti, node, prop, "bad value (0x%x) in %s property",
+ phandle, prop->name);
return 0;
}
@@ -463,16 +525,16 @@ static void check_explicit_phandles(struct check *c, struct dt_info *dti,
return;
if (linux_phandle && phandle && (phandle != linux_phandle))
- FAIL(c, dti, "%s has mismatching 'phandle' and 'linux,phandle'"
- " properties", node->fullpath);
+ FAIL(c, dti, node, "mismatching 'phandle' and 'linux,phandle'"
+ " properties");
if (linux_phandle && !phandle)
phandle = linux_phandle;
other = get_node_by_phandle(root, phandle);
if (other && (other != node)) {
- FAIL(c, dti, "%s has duplicated phandle 0x%x (seen before at %s)",
- node->fullpath, phandle, other->fullpath);
+ FAIL(c, dti, node, "duplicated phandle 0x%x (seen before at %s)",
+ phandle, other->fullpath);
return;
}
@@ -496,8 +558,8 @@ static void check_name_properties(struct check *c, struct dt_info *dti,
if ((prop->val.len != node->basenamelen+1)
|| (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) {
- FAIL(c, dti, "\"name\" property in %s is incorrect (\"%s\" instead"
- " of base node name)", node->fullpath, prop->val.val);
+ FAIL(c, dti, node, "\"name\" property is incorrect (\"%s\" instead"
+ " of base node name)", prop->val.val);
} else {
/* The name property is correct, and therefore redundant.
* Delete it */
@@ -531,7 +593,7 @@ static void fixup_phandle_references(struct check *c, struct dt_info *dti,
refnode = get_node_by_ref(dt, m->ref);
if (! refnode) {
if (!(dti->dtsflags & DTSF_PLUGIN))
- FAIL(c, dti, "Reference to non-existent node or "
+ FAIL(c, dti, node, "Reference to non-existent node or "
"label \"%s\"\n", m->ref);
else /* mark the entry as unresolved */
*((fdt32_t *)(prop->val.val + m->offset)) =
@@ -541,6 +603,8 @@ static void fixup_phandle_references(struct check *c, struct dt_info *dti,
phandle = get_node_phandle(dt, refnode);
*((fdt32_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle);
+
+ reference_node(refnode);
}
}
}
@@ -563,7 +627,7 @@ static void fixup_path_references(struct check *c, struct dt_info *dti,
refnode = get_node_by_ref(dt, m->ref);
if (!refnode) {
- FAIL(c, dti, "Reference to non-existent node or label \"%s\"\n",
+ FAIL(c, dti, node, "Reference to non-existent node or label \"%s\"\n",
m->ref);
continue;
}
@@ -571,11 +635,23 @@ static void fixup_path_references(struct check *c, struct dt_info *dti,
path = refnode->fullpath;
prop->val = data_insert_at_marker(prop->val, m, path,
strlen(path) + 1);
+
+ reference_node(refnode);
}
}
}
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);
+}
+ERROR(omit_unused_nodes, fixup_omit_unused_nodes, NULL, &phandle_references, &path_references);
+
/*
* Semantic checks
*/
@@ -586,6 +662,50 @@ 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");
WARNING_IF_NOT_STRING(status_is_string, "status");
+WARNING_IF_NOT_STRING(label_is_string, "label");
+
+WARNING_IF_NOT_STRING_LIST(compatible_is_string_list, "compatible");
+
+static void check_names_is_string_list(struct check *c, struct dt_info *dti,
+ struct node *node)
+{
+ struct property *prop;
+
+ for_each_property(node, prop) {
+ const char *s = strrchr(prop->name, '-');
+ if (!s || !streq(s, "-names"))
+ continue;
+
+ c->data = prop->name;
+ check_is_string_list(c, dti, node);
+ }
+}
+WARNING(names_is_string_list, check_names_is_string_list, NULL);
+
+static void check_alias_paths(struct check *c, struct dt_info *dti,
+ struct node *node)
+{
+ struct property *prop;
+
+ if (!streq(node->name, "aliases"))
+ 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);
+ continue;
+ }
+ if (strspn(prop->name, LOWERCASE DIGITS "-") != strlen(prop->name))
+ FAIL(c, dti, node, "aliases property name must include only lowercase and '-'");
+ }
+}
+WARNING(alias_paths, check_alias_paths, NULL);
static void fixup_addr_size_cells(struct check *c, struct dt_info *dti,
struct node *node)
@@ -622,21 +742,21 @@ static void check_reg_format(struct check *c, struct dt_info *dti,
return; /* No "reg", that's fine */
if (!node->parent) {
- FAIL(c, dti, "Root node has a \"reg\" property");
+ FAIL(c, dti, node, "Root node has a \"reg\" property");
return;
}
if (prop->val.len == 0)
- FAIL(c, dti, "\"reg\" property in %s is empty", node->fullpath);
+ FAIL_PROP(c, dti, node, prop, "property is empty");
addr_cells = node_addr_cells(node->parent);
size_cells = node_size_cells(node->parent);
entrylen = (addr_cells + size_cells) * sizeof(cell_t);
if (!entrylen || (prop->val.len % entrylen) != 0)
- FAIL(c, dti, "\"reg\" property in %s has invalid length (%d bytes) "
- "(#address-cells == %d, #size-cells == %d)",
- node->fullpath, prop->val.len, addr_cells, size_cells);
+ 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);
}
WARNING(reg_format, check_reg_format, NULL, &addr_size_cells);
@@ -645,13 +765,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(c, dti, "Root node has a \"ranges\" property");
+ FAIL_PROP(c, dti, node, prop, "Root node has a \"%s\" property",
+ ranges);
return;
}
@@ -663,23 +785,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(c, dti, "%s has empty \"ranges\" property but its "
- "#address-cells (%d) differs from %s (%d)",
- node->fullpath, c_addr_cells, node->parent->fullpath,
- p_addr_cells);
+ FAIL_PROP(c, dti, node, prop, "empty \"%s\" property but its "
+ "#address-cells (%d) differs from %s (%d)",
+ ranges, c_addr_cells, node->parent->fullpath,
+ p_addr_cells);
if (p_size_cells != c_size_cells)
- FAIL(c, dti, "%s has empty \"ranges\" property but its "
- "#size-cells (%d) differs from %s (%d)",
- node->fullpath, c_size_cells, node->parent->fullpath,
- p_size_cells);
+ FAIL_PROP(c, dti, node, prop, "empty \"%s\" property but its "
+ "#size-cells (%d) differs from %s (%d)",
+ ranges, c_size_cells, node->parent->fullpath,
+ p_size_cells);
} else if ((prop->val.len % entrylen) != 0) {
- FAIL(c, dti, "\"ranges\" property in %s has invalid length (%d bytes) "
- "(parent #address-cells == %d, child #address-cells == %d, "
- "#size-cells == %d)", node->fullpath, prop->val.len,
- p_addr_cells, c_addr_cells, c_size_cells);
+ FAIL_PROP(c, dti, node, prop, "\"%s\" property has invalid length (%d bytes) "
+ "(parent #address-cells == %d, child #address-cells == %d, "
+ "#size-cells == %d)", ranges, prop->val.len,
+ 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",
@@ -696,41 +819,32 @@ static void check_pci_bridge(struct check *c, struct dt_info *dti, struct node *
node->bus = &pci_bus;
- if (!strneq(node->name, "pci", node->basenamelen) &&
- !strneq(node->name, "pcie", node->basenamelen))
- FAIL(c, dti, "Node %s node name is not \"pci\" or \"pcie\"",
- node->fullpath);
+ if (!strprefixeq(node->name, node->basenamelen, "pci") &&
+ !strprefixeq(node->name, node->basenamelen, "pcie"))
+ FAIL(c, dti, node, "node name is not \"pci\" or \"pcie\"");
prop = get_property(node, "ranges");
if (!prop)
- FAIL(c, dti, "Node %s missing ranges for PCI bridge (or not a bridge)",
- node->fullpath);
+ FAIL(c, dti, node, "missing ranges for PCI bridge (or not a bridge)");
if (node_addr_cells(node) != 3)
- FAIL(c, dti, "Node %s incorrect #address-cells for PCI bridge",
- node->fullpath);
+ FAIL(c, dti, node, "incorrect #address-cells for PCI bridge");
if (node_size_cells(node) != 2)
- FAIL(c, dti, "Node %s incorrect #size-cells for PCI bridge",
- node->fullpath);
+ FAIL(c, dti, node, "incorrect #size-cells for PCI bridge");
prop = get_property(node, "bus-range");
- if (!prop) {
- FAIL(c, dti, "Node %s missing bus-range for PCI bridge",
- node->fullpath);
+ if (!prop)
return;
- }
+
if (prop->val.len != (sizeof(cell_t) * 2)) {
- FAIL(c, dti, "Node %s bus-range must be 2 cells",
- node->fullpath);
+ FAIL_PROP(c, dti, node, prop, "value must be 2 cells");
return;
}
cells = (cell_t *)prop->val.val;
if (fdt32_to_cpu(cells[0]) > fdt32_to_cpu(cells[1]))
- FAIL(c, dti, "Node %s bus-range 1st cell must be less than or equal to 2nd cell",
- node->fullpath);
+ FAIL_PROP(c, dti, node, prop, "1st cell must be less than or equal to 2nd cell");
if (fdt32_to_cpu(cells[1]) > 0xff)
- FAIL(c, dti, "Node %s bus-range maximum bus number must be less than 256",
- node->fullpath);
+ FAIL_PROP(c, dti, node, prop, "maximum bus number must be less than 256");
}
WARNING(pci_bridge, check_pci_bridge, NULL,
&device_type_is_string, &addr_size_cells);
@@ -760,8 +874,8 @@ static void check_pci_device_bus_num(struct check *c, struct dt_info *dti, struc
max_bus = fdt32_to_cpu(cells[0]);
}
if ((bus_num < min_bus) || (bus_num > max_bus))
- FAIL(c, dti, "Node %s PCI bus number %d out of range, expected (%d - %d)",
- node->fullpath, bus_num, min_bus, max_bus);
+ FAIL_PROP(c, dti, node, prop, "PCI bus number %d out of range, expected (%d - %d)",
+ bus_num, min_bus, max_bus);
}
WARNING(pci_device_bus_num, check_pci_device_bus_num, NULL, &reg_format, &pci_bridge);
@@ -778,25 +892,22 @@ static void check_pci_device_reg(struct check *c, struct dt_info *dti, struct no
prop = get_property(node, "reg");
if (!prop) {
- FAIL(c, dti, "Node %s missing PCI reg property", node->fullpath);
+ FAIL(c, dti, node, "missing PCI reg property");
return;
}
cells = (cell_t *)prop->val.val;
if (cells[1] || cells[2])
- FAIL(c, dti, "Node %s PCI reg config space address cells 2 and 3 must be 0",
- node->fullpath);
+ FAIL_PROP(c, dti, node, prop, "PCI reg config space address cells 2 and 3 must be 0");
reg = fdt32_to_cpu(cells[0]);
dev = (reg & 0xf800) >> 11;
func = (reg & 0x700) >> 8;
if (reg & 0xff000000)
- FAIL(c, dti, "Node %s PCI reg address is not configuration space",
- node->fullpath);
+ FAIL_PROP(c, dti, node, prop, "PCI reg address is not configuration space");
if (reg & 0x000000ff)
- FAIL(c, dti, "Node %s PCI reg config space address register number must be 0",
- node->fullpath);
+ FAIL_PROP(c, dti, node, prop, "PCI reg config space address register number must be 0");
if (func == 0) {
snprintf(unit_addr, sizeof(unit_addr), "%x", dev);
@@ -808,8 +919,8 @@ static void check_pci_device_reg(struct check *c, struct dt_info *dti, struct no
if (streq(unitname, unit_addr))
return;
- FAIL(c, dti, "Node %s PCI unit address format error, expected \"%s\"",
- node->fullpath, unit_addr);
+ FAIL(c, dti, node, "PCI unit address format error, expected \"%s\"",
+ unit_addr);
}
WARNING(pci_device_reg, check_pci_device_reg, NULL, &reg_format, &pci_bridge);
@@ -828,7 +939,7 @@ static bool node_is_compatible(struct node *node, const char *compat)
for (str = prop->val.val, end = str + prop->val.len; str < end;
str += strnlen(str, end - str) + 1) {
- if (strneq(str, compat, end - str))
+ if (streq(str, compat))
return true;
}
return false;
@@ -839,7 +950,8 @@ static void check_simple_bus_bridge(struct check *c, struct dt_info *dti, struct
if (node_is_compatible(node, "simple-bus"))
node->bus = &simple_bus;
}
-WARNING(simple_bus_bridge, check_simple_bus_bridge, NULL, &addr_size_cells);
+WARNING(simple_bus_bridge, check_simple_bus_bridge, NULL,
+ &addr_size_cells, &compatible_is_string_list);
static void check_simple_bus_reg(struct check *c, struct dt_info *dti, struct node *node)
{
@@ -865,7 +977,7 @@ static void check_simple_bus_reg(struct check *c, struct dt_info *dti, struct no
if (!cells) {
if (node->parent->parent && !(node->bus == &simple_bus))
- FAIL(c, dti, "Node %s missing or empty reg/ranges property", node->fullpath);
+ FAIL(c, dti, node, "missing or empty reg/ranges property");
return;
}
@@ -875,11 +987,164 @@ static void check_simple_bus_reg(struct check *c, struct dt_info *dti, struct no
snprintf(unit_addr, sizeof(unit_addr), "%"PRIx64, reg);
if (!streq(unitname, unit_addr))
- FAIL(c, dti, "Node %s simple-bus unit address format error, expected \"%s\"",
- node->fullpath, unit_addr);
+ FAIL(c, dti, node, "simple-bus unit address format error, expected \"%s\"",
+ unit_addr);
}
WARNING(simple_bus_reg, check_simple_bus_reg, NULL, &reg_format, &simple_bus_bridge);
+static const struct bus_type i2c_bus = {
+ .name = "i2c-bus",
+};
+
+static void check_i2c_bus_bridge(struct check *c, struct dt_info *dti, struct node *node)
+{
+ if (strprefixeq(node->name, node->basenamelen, "i2c-bus") ||
+ strprefixeq(node->name, node->basenamelen, "i2c-arb")) {
+ node->bus = &i2c_bus;
+ } else if (strprefixeq(node->name, node->basenamelen, "i2c")) {
+ struct node *child;
+ for_each_child(node, child) {
+ if (strprefixeq(child->name, node->basenamelen, "i2c-bus"))
+ return;
+ }
+ node->bus = &i2c_bus;
+ } else
+ return;
+
+ if (!node->children)
+ return;
+
+ if (node_addr_cells(node) != 1)
+ FAIL(c, dti, node, "incorrect #address-cells for I2C bus");
+ if (node_size_cells(node) != 0)
+ FAIL(c, dti, node, "incorrect #size-cells for I2C bus");
+
+}
+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;
+ const char *unitname = get_unitname(node);
+ char unit_addr[17];
+ uint32_t reg = 0;
+ int len;
+ cell_t *cells = NULL;
+
+ if (!node->parent || (node->parent->bus != &i2c_bus))
+ return;
+
+ prop = get_property(node, "reg");
+ if (prop)
+ cells = (cell_t *)prop->val.val;
+
+ if (!cells) {
+ FAIL(c, dti, node, "missing or empty reg property");
+ return;
+ }
+
+ 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\"",
+ unit_addr);
+
+ for (len = prop->val.len; len > 0; len -= 4) {
+ reg = fdt32_to_cpu(*(cells++));
+ /* Ignore I2C_OWN_SLAVE_ADDRESS */
+ reg &= ~I2C_OWN_SLAVE_ADDRESS;
+
+ if ((reg & I2C_TEN_BIT_ADDRESS) && ((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);
+
+static const struct bus_type spi_bus = {
+ .name = "spi-bus",
+};
+
+static void check_spi_bus_bridge(struct check *c, struct dt_info *dti, struct node *node)
+{
+ int spi_addr_cells = 1;
+
+ if (strprefixeq(node->name, node->basenamelen, "spi")) {
+ node->bus = &spi_bus;
+ } else {
+ /* Try to detect SPI buses which don't have proper node name */
+ struct node *child;
+
+ if (node_addr_cells(node) != 1 || node_size_cells(node) != 0)
+ return;
+
+ for_each_child(node, child) {
+ struct property *prop;
+ for_each_property(child, prop) {
+ if (strprefixeq(prop->name, 4, "spi-")) {
+ node->bus = &spi_bus;
+ break;
+ }
+ }
+ if (node->bus == &spi_bus)
+ break;
+ }
+
+ if (node->bus == &spi_bus && get_property(node, "reg"))
+ FAIL(c, dti, node, "node name for SPI buses should be 'spi'");
+ }
+ if (node->bus != &spi_bus || !node->children)
+ return;
+
+ if (get_property(node, "spi-slave"))
+ spi_addr_cells = 0;
+ if (node_addr_cells(node) != spi_addr_cells)
+ FAIL(c, dti, node, "incorrect #address-cells for SPI bus");
+ if (node_size_cells(node) != 0)
+ FAIL(c, dti, node, "incorrect #size-cells for SPI bus");
+
+}
+WARNING(spi_bus_bridge, check_spi_bus_bridge, NULL, &addr_size_cells);
+
+static void check_spi_bus_reg(struct check *c, struct dt_info *dti, struct node *node)
+{
+ struct property *prop;
+ const char *unitname = get_unitname(node);
+ char unit_addr[9];
+ uint32_t reg = 0;
+ cell_t *cells = NULL;
+
+ if (!node->parent || (node->parent->bus != &spi_bus))
+ return;
+
+ if (get_property(node->parent, "spi-slave"))
+ return;
+
+ prop = get_property(node, "reg");
+ if (prop)
+ cells = (cell_t *)prop->val.val;
+
+ if (!cells) {
+ FAIL(c, dti, node, "missing or empty reg property");
+ return;
+ }
+
+ reg = fdt32_to_cpu(*cells);
+ snprintf(unit_addr, sizeof(unit_addr), "%x", reg);
+ if (!streq(unitname, unit_addr))
+ FAIL(c, dti, node, "SPI bus unit address format error, expected \"%s\"",
+ unit_addr);
+}
+WARNING(spi_bus_reg, check_spi_bus_reg, NULL, &reg_format, &spi_bus_bridge);
+
static void check_unit_address_format(struct check *c, struct dt_info *dti,
struct node *node)
{
@@ -892,14 +1157,12 @@ static void check_unit_address_format(struct check *c, struct dt_info *dti,
return;
if (!strncmp(unitname, "0x", 2)) {
- FAIL(c, dti, "Node %s unit name should not have leading \"0x\"",
- node->fullpath);
+ FAIL(c, dti, node, "unit name should not have leading \"0x\"");
/* skip over 0x for next test */
unitname += 2;
}
if (unitname[0] == '0' && isxdigit(unitname[1]))
- FAIL(c, dti, "Node %s unit name should not have leading 0s",
- node->fullpath);
+ FAIL(c, dti, node, "unit name should not have leading 0s");
}
WARNING(unit_address_format, check_unit_address_format, NULL,
&node_name_format, &pci_bridge, &simple_bus_bridge);
@@ -922,16 +1185,104 @@ static void check_avoid_default_addr_size(struct check *c, struct dt_info *dti,
return;
if (node->parent->addr_cells == -1)
- FAIL(c, dti, "Relying on default #address-cells value for %s",
- node->fullpath);
+ FAIL(c, dti, node, "Relying on default #address-cells value");
if (node->parent->size_cells == -1)
- FAIL(c, dti, "Relying on default #size-cells value for %s",
- node->fullpath);
+ FAIL(c, dti, node, "Relying on default #size-cells value");
}
WARNING(avoid_default_addr_size, check_avoid_default_addr_size, NULL,
&addr_size_cells);
+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)
+ return;
+
+ for_each_child(node, child) {
+ prop = get_property(child, "reg");
+ if (prop)
+ has_reg = true;
+ }
+
+ if (!has_reg)
+ FAIL(c, dti, node, "unnecessary #address-cells/#size-cells without \"ranges\" or child \"reg\" property");
+}
+WARNING(avoid_unnecessary_addr_size, check_avoid_unnecessary_addr_size, NULL, &avoid_default_addr_size);
+
+static bool node_is_disabled(struct node *node)
+{
+ struct property *prop;
+
+ prop = get_property(node, "status");
+ if (prop) {
+ char *str = prop->val.val;
+ if (streq("disabled", str))
+ return true;
+ }
+
+ return false;
+}
+
+static void check_unique_unit_address_common(struct check *c,
+ struct dt_info *dti,
+ struct node *node,
+ bool disable_check)
+{
+ struct node *childa;
+
+ if (node->addr_cells < 0 || node->size_cells < 0)
+ return;
+
+ if (!node->children)
+ return;
+
+ for_each_child(node, childa) {
+ struct node *childb;
+ const char *addr_a = get_unitname(childa);
+
+ if (!strlen(addr_a))
+ continue;
+
+ if (disable_check && node_is_disabled(childa))
+ continue;
+
+ for_each_child(node, childb) {
+ const char *addr_b = get_unitname(childb);
+ if (childa == childb)
+ break;
+
+ if (disable_check && node_is_disabled(childb))
+ continue;
+
+ if (streq(addr_a, addr_b))
+ FAIL(c, dti, childb, "duplicate unit-address (also used in node %s)", childa->fullpath);
+ }
+ }
+}
+
+static void check_unique_unit_address(struct check *c, struct dt_info *dti,
+ struct node *node)
+{
+ check_unique_unit_address_common(c, dti, node, false);
+}
+WARNING(unique_unit_address, check_unique_unit_address, NULL, &avoid_default_addr_size);
+
+static void check_unique_unit_address_if_enabled(struct check *c, struct dt_info *dti,
+ struct node *node)
+{
+ check_unique_unit_address_common(c, dti, node, true);
+}
+CHECK_ENTRY(unique_unit_address_if_enabled, check_unique_unit_address_if_enabled,
+ NULL, false, false, &avoid_default_addr_size);
+
static void check_obsolete_chosen_interrupt_controller(struct check *c,
struct dt_info *dti,
struct node *node)
@@ -950,12 +1301,500 @@ static void check_obsolete_chosen_interrupt_controller(struct check *c,
prop = get_property(chosen, "interrupt-controller");
if (prop)
- FAIL(c, dti, "/chosen has obsolete \"interrupt-controller\" "
- "property");
+ FAIL_PROP(c, dti, node, prop,
+ "/chosen has obsolete \"interrupt-controller\" property");
}
WARNING(obsolete_chosen_interrupt_controller,
check_obsolete_chosen_interrupt_controller, NULL);
+static void check_chosen_node_is_root(struct check *c, struct dt_info *dti,
+ struct node *node)
+{
+ if (!streq(node->name, "chosen"))
+ return;
+
+ if (node->parent != dti->dt)
+ FAIL(c, dti, node, "chosen node must be at root node");
+}
+WARNING(chosen_node_is_root, check_chosen_node_is_root, NULL);
+
+static void check_chosen_node_bootargs(struct check *c, struct dt_info *dti,
+ struct node *node)
+{
+ struct property *prop;
+
+ if (!streq(node->name, "chosen"))
+ return;
+
+ prop = get_property(node, "bootargs");
+ if (!prop)
+ return;
+
+ c->data = prop->name;
+ check_is_string(c, dti, node);
+}
+WARNING(chosen_node_bootargs, check_chosen_node_bootargs, NULL);
+
+static void check_chosen_node_stdout_path(struct check *c, struct dt_info *dti,
+ struct node *node)
+{
+ struct property *prop;
+
+ if (!streq(node->name, "chosen"))
+ return;
+
+ prop = get_property(node, "stdout-path");
+ if (!prop) {
+ prop = get_property(node, "linux,stdout-path");
+ if (!prop)
+ return;
+ FAIL_PROP(c, dti, node, prop, "Use 'stdout-path' instead");
+ }
+
+ c->data = prop->name;
+ check_is_string(c, dti, node);
+}
+WARNING(chosen_node_stdout_path, check_chosen_node_stdout_path, NULL);
+
+struct provider {
+ const char *prop_name;
+ const char *cell_name;
+ bool optional;
+};
+
+static void check_property_phandle_args(struct check *c,
+ struct dt_info *dti,
+ struct node *node,
+ struct property *prop,
+ const struct provider *provider)
+{
+ struct node *root = dti->dt;
+ int cell, cellsize = 0;
+
+ if (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));
+ return;
+ }
+
+ for (cell = 0; cell < prop->val.len / sizeof(cell_t); cell += cellsize + 1) {
+ struct node *provider_node;
+ struct property *cellprop;
+ int phandle;
+
+ 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) {
+ /* Give up if this is an overlay with external references */
+ if (dti->dtsflags & DTSF_PLUGIN)
+ break;
+
+ cellsize = 0;
+ continue;
+ }
+
+ /* If we have markers, verify the current cell is a phandle */
+ if (prop->val.markers) {
+ struct marker *m = prop->val.markers;
+ for_each_marker_of_type(m, REF_PHANDLE) {
+ if (m->offset == (cell * sizeof(cell_t)))
+ break;
+ }
+ if (!m)
+ FAIL_PROP(c, dti, node, prop,
+ "cell %d is not a phandle reference",
+ cell);
+ }
+
+ provider_node = get_node_by_phandle(root, phandle);
+ if (!provider_node) {
+ FAIL_PROP(c, dti, node, prop,
+ "Could not get phandle node for (cell %d)",
+ cell);
+ break;
+ }
+
+ cellprop = get_property(provider_node, provider->cell_name);
+ if (cellprop) {
+ cellsize = propval_cell(cellprop);
+ } else if (provider->optional) {
+ cellsize = 0;
+ } else {
+ FAIL(c, dti, node, "Missing property '%s' in node %s or bad phandle (referred from %s[%d])",
+ provider->cell_name,
+ provider_node->fullpath,
+ prop->name, cell);
+ break;
+ }
+
+ if (prop->val.len < ((cell + cellsize + 1) * sizeof(cell_t))) {
+ FAIL_PROP(c, dti, node, prop,
+ "property size (%d) too small for cell size %d",
+ prop->val.len, cellsize);
+ }
+ }
+}
+
+static void check_provider_cells_property(struct check *c,
+ struct dt_info *dti,
+ struct node *node)
+{
+ struct provider *provider = c->data;
+ struct property *prop;
+
+ prop = get_property(node, provider->prop_name);
+ if (!prop)
+ return;
+
+ check_property_phandle_args(c, dti, node, prop, provider);
+}
+#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_PROPERTY_PHANDLE_CELLS(clocks, "clocks", "#clock-cells");
+WARNING_PROPERTY_PHANDLE_CELLS(cooling_device, "cooling-device", "#cooling-cells");
+WARNING_PROPERTY_PHANDLE_CELLS(dmas, "dmas", "#dma-cells");
+WARNING_PROPERTY_PHANDLE_CELLS(hwlocks, "hwlocks", "#hwlock-cells");
+WARNING_PROPERTY_PHANDLE_CELLS(interrupts_extended, "interrupts-extended", "#interrupt-cells");
+WARNING_PROPERTY_PHANDLE_CELLS(io_channels, "io-channels", "#io-channel-cells");
+WARNING_PROPERTY_PHANDLE_CELLS(iommus, "iommus", "#iommu-cells");
+WARNING_PROPERTY_PHANDLE_CELLS(mboxes, "mboxes", "#mbox-cells");
+WARNING_PROPERTY_PHANDLE_CELLS(msi_parent, "msi-parent", "#msi-cells", true);
+WARNING_PROPERTY_PHANDLE_CELLS(mux_controls, "mux-controls", "#mux-control-cells");
+WARNING_PROPERTY_PHANDLE_CELLS(phys, "phys", "#phy-cells");
+WARNING_PROPERTY_PHANDLE_CELLS(power_domains, "power-domains", "#power-domain-cells");
+WARNING_PROPERTY_PHANDLE_CELLS(pwms, "pwms", "#pwm-cells");
+WARNING_PROPERTY_PHANDLE_CELLS(resets, "resets", "#reset-cells");
+WARNING_PROPERTY_PHANDLE_CELLS(sound_dai, "sound-dai", "#sound-dai-cells");
+WARNING_PROPERTY_PHANDLE_CELLS(thermal_sensors, "thermal-sensors", "#thermal-sensor-cells");
+
+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"))
+ return false;
+
+ str = strrchr(prop->name, '-');
+ if (str)
+ str++;
+ else
+ str = prop->name;
+ if (!(streq(str, "gpios") || streq(str, "gpio")))
+ return false;
+
+ return true;
+}
+
+static void check_gpios_property(struct check *c,
+ struct dt_info *dti,
+ struct node *node)
+{
+ struct property *prop;
+
+ /* Skip GPIO hog nodes which have 'gpios' property */
+ if (get_property(node, "gpio-hog"))
+ return;
+
+ for_each_property(node, prop) {
+ struct provider provider;
+
+ if (!prop_is_gpio(prop))
+ continue;
+
+ provider.prop_name = prop->name;
+ provider.cell_name = "#gpio-cells";
+ provider.optional = false;
+ check_property_phandle_args(c, dti, node, prop, &provider);
+ }
+
+}
+WARNING(gpios_property, check_gpios_property, NULL, &phandle_references);
+
+static void check_deprecated_gpio_property(struct check *c,
+ struct dt_info *dti,
+ struct node *node)
+{
+ 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"))
+ continue;
+
+ FAIL_PROP(c, dti, node, prop,
+ "'[*-]gpio' is deprecated, use '[*-]gpios' instead");
+ }
+
+}
+CHECK(deprecated_gpio_property, check_deprecated_gpio_property, NULL);
+
+static bool node_is_interrupt_provider(struct node *node)
+{
+ struct property *prop;
+
+ prop = get_property(node, "interrupt-controller");
+ if (prop)
+ return true;
+
+ prop = get_property(node, "interrupt-map");
+ if (prop)
+ return true;
+
+ return false;
+}
+
+static void check_interrupt_provider(struct check *c,
+ struct dt_info *dti,
+ struct node *node)
+{
+ struct property *prop;
+
+ if (!node_is_interrupt_provider(node))
+ return;
+
+ prop = get_property(node, "#interrupt-cells");
+ if (!prop)
+ FAIL(c, dti, node,
+ "Missing #interrupt-cells in interrupt provider");
+
+ prop = get_property(node, "#address-cells");
+ if (!prop)
+ FAIL(c, dti, node,
+ "Missing #address-cells in interrupt provider");
+}
+WARNING(interrupt_provider, check_interrupt_provider, NULL);
+
+static void check_interrupts_property(struct check *c,
+ struct dt_info *dti,
+ struct node *node)
+{
+ struct node *root = dti->dt;
+ struct node *irq_node = NULL, *parent = node;
+ struct property *irq_prop, *prop = NULL;
+ int irq_cells, phandle;
+
+ irq_prop = get_property(node, "interrupts");
+ if (!irq_prop)
+ return;
+
+ if (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));
+
+ while (parent && !prop) {
+ if (parent != node && node_is_interrupt_provider(parent)) {
+ irq_node = parent;
+ break;
+ }
+
+ prop = get_property(parent, "interrupt-parent");
+ if (prop) {
+ phandle = propval_cell(prop);
+ if ((phandle == 0) || (phandle == -1)) {
+ /* 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) {
+ FAIL_PROP(c, dti, parent, prop, "Bad phandle");
+ return;
+ }
+ if (!node_is_interrupt_provider(irq_node))
+ FAIL(c, dti, irq_node,
+ "Missing interrupt-controller or interrupt-map property");
+
+ break;
+ }
+
+ parent = parent->parent;
+ }
+
+ if (!irq_node) {
+ FAIL(c, dti, node, "Missing interrupt-parent");
+ return;
+ }
+
+ prop = get_property(irq_node, "#interrupt-cells");
+ if (!prop) {
+ /* We warn about that already in another test. */
+ return;
+ }
+
+ irq_cells = propval_cell(prop);
+ if (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)));
+ }
+}
+WARNING(interrupts_property, check_interrupts_property, &phandle_references);
+
+static const struct bus_type graph_port_bus = {
+ .name = "graph-port",
+};
+
+static const struct bus_type graph_ports_bus = {
+ .name = "graph-ports",
+};
+
+static void check_graph_nodes(struct check *c, struct dt_info *dti,
+ struct node *node)
+{
+ struct node *child;
+
+ for_each_child(node, child) {
+ if (!(strprefixeq(child->name, child->basenamelen, "endpoint") ||
+ get_property(child, "remote-endpoint")))
+ continue;
+
+ node->bus = &graph_port_bus;
+
+ /* The parent of 'port' nodes can be either 'ports' or a device */
+ if (!node->parent->bus &&
+ (streq(node->parent->name, "ports") || get_property(node, "reg")))
+ node->parent->bus = &graph_ports_bus;
+
+ break;
+ }
+
+}
+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)
+{
+ char unit_addr[9];
+ const char *unitname = get_unitname(node);
+ struct property *prop;
+
+ prop = get_property(node, "reg");
+ if (!prop || !unitname)
+ return;
+
+ if (!(prop->val.val && prop->val.len == sizeof(cell_t))) {
+ FAIL(c, dti, node, "graph node malformed 'reg' property");
+ return;
+ }
+
+ snprintf(unit_addr, sizeof(unit_addr), "%x", propval_cell(prop));
+ if (!streq(unitname, unit_addr))
+ FAIL(c, dti, node, "graph node unit address error, expected \"%s\"",
+ unit_addr);
+
+ if (node->parent->addr_cells != 1)
+ FAIL_PROP(c, dti, node, get_property(node, "#address-cells"),
+ "graph node '#address-cells' is %d, must be 1",
+ node->parent->addr_cells);
+ if (node->parent->size_cells != 0)
+ FAIL_PROP(c, dti, node, get_property(node, "#size-cells"),
+ "graph node '#size-cells' is %d, must be 0",
+ node->parent->size_cells);
+}
+
+static void check_graph_port(struct check *c, struct dt_info *dti,
+ struct node *node)
+{
+ if (node->bus != &graph_port_bus)
+ 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;
+ struct node *node;
+ struct property *prop;
+
+ prop = get_property(endpoint, "remote-endpoint");
+ if (!prop)
+ return NULL;
+
+ phandle = propval_cell(prop);
+ /* Give up if this is an overlay with external references */
+ if (phandle == 0 || phandle == -1)
+ return NULL;
+
+ node = get_node_by_phandle(dti->dt, phandle);
+ if (!node)
+ FAIL_PROP(c, dti, endpoint, prop, "graph phandle is not valid");
+
+ return node;
+}
+
+static void check_graph_endpoint(struct check *c, struct dt_info *dti,
+ struct node *node)
+{
+ struct node *remote_node;
+
+ if (!node->parent || node->parent->bus != &graph_port_bus)
+ return;
+
+ if (!strprefixeq(node->name, node->basenamelen, "endpoint"))
+ FAIL(c, dti, node, "graph endpoint node name should be 'endpoint'");
+
+ check_graph_reg(c, dti, node);
+
+ remote_node = get_remote_endpoint(c, dti, node);
+ if (!remote_node)
+ return;
+
+ if (get_remote_endpoint(c, dti, remote_node) != node)
+ FAIL(c, dti, node, "graph connection to node '%s' is not bidirectional",
+ remote_node->fullpath);
+}
+WARNING(graph_endpoint, check_graph_endpoint, NULL, &graph_nodes);
+
static struct check *check_table[] = {
&duplicate_node_names, &duplicate_property_names,
&node_name_chars, &node_name_format, &property_name_chars,
@@ -965,14 +1804,18 @@ static struct check *check_table[] = {
&explicit_phandles,
&phandle_references, &path_references,
+ &omit_unused_nodes,
&address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell,
&device_type_is_string, &model_is_string, &status_is_string,
+ &label_is_string,
+
+ &compatible_is_string_list, &names_is_string_list,
&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,
@@ -984,8 +1827,44 @@ static struct check *check_table[] = {
&simple_bus_bridge,
&simple_bus_reg,
+ &i2c_bus_bridge,
+ &i2c_bus_reg,
+
+ &spi_bus_bridge,
+ &spi_bus_reg,
+
&avoid_default_addr_size,
+ &avoid_unnecessary_addr_size,
+ &unique_unit_address,
+ &unique_unit_address_if_enabled,
&obsolete_chosen_interrupt_controller,
+ &chosen_node_is_root, &chosen_node_bootargs, &chosen_node_stdout_path,
+
+ &clocks_property,
+ &cooling_device_property,
+ &dmas_property,
+ &hwlocks_property,
+ &interrupts_extended_property,
+ &io_channels_property,
+ &iommus_property,
+ &mboxes_property,
+ &msi_parent_property,
+ &mux_controls_property,
+ &phys_property,
+ &power_domains_property,
+ &pwms_property,
+ &resets_property,
+ &sound_dai_property,
+ &thermal_sensors_property,
+
+ &deprecated_gpio_property,
+ &gpios_property,
+ &interrupts_property,
+ &interrupt_provider,
+
+ &alias_paths,
+
+ &graph_nodes, &graph_child_address, &graph_port, &graph_endpoint,
&always_fail,
};
diff --git a/convert-dtsv0-lexer.l b/convert-dtsv0-lexer.l
index d6d68cd..f52e8a1 100644
--- a/convert-dtsv0-lexer.l
+++ b/convert-dtsv0-lexer.l
@@ -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
diff --git a/data.c b/data.c
index aa37a16..0a43b6d 100644
--- a/data.c
+++ b/data.c
@@ -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"
@@ -74,7 +59,8 @@ struct data data_copy_escape_string(const char *s, int len)
struct data d;
char *q;
- d = data_grow_for(empty_data, len + 1);
+ d = data_add_marker(empty_data, TYPE_STRING, NULL);
+ d = data_grow_for(d, len + 1);
q = d.val;
while (i < len) {
@@ -94,6 +80,7 @@ struct data data_copy_file(FILE *f, size_t maxlen)
{
struct data d = empty_data;
+ d = data_add_marker(d, TYPE_NONE, NULL);
while (!feof(f) && (d.len < maxlen)) {
size_t chunksize, ret;
diff --git a/dtc-lexer.l b/dtc-lexer.l
index 13f4b06..f0faa28 100644
--- a/dtc-lexer.l
+++ b/dtc-lexer.l
@@ -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.h"
-YYLTYPE yylloc;
extern bool treesource_error;
/* CAUTION: this will stop working if we ever use yyless() or yyunput() */
@@ -153,6 +137,13 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
return DT_DEL_NODE;
}
+<*>"/omit-if-no-ref/" {
+ DPRINT("Keyword: /omit-if-no-ref/\n");
+ DPRINT("<PROPNODENAME>\n");
+ BEGIN(PROPNODENAME);
+ return DT_OMIT_NO_REF;
+ }
+
<*>{LABEL}: {
DPRINT("Label: %s\n", yytext);
yylval.labelref = xstrdup(yytext);
@@ -206,14 +197,14 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
<*>\&{LABEL} { /* label reference */
DPRINT("Ref: %s\n", yytext+1);
yylval.labelref = xstrdup(yytext+1);
- return DT_REF;
+ return DT_LABEL_REF;
}
<*>"&{/"{PATHCHAR}*\} { /* new-style path reference */
yytext[yyleng-1] = '\0';
DPRINT("Ref: %s\n", yytext+2);
yylval.labelref = xstrdup(yytext+2);
- return DT_REF;
+ return DT_PATH_REF;
}
<BYTESTRING>[0-9a-fA-F]{2} {
diff --git a/dtc-parser.y b/dtc-parser.y
index affc81a..cf0e361 100644
--- a/dtc-parser.y
+++ b/dtc-parser.y
@@ -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,6 +19,8 @@ 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;
%}
@@ -63,13 +52,15 @@ extern bool treesource_error;
%token DT_BITS
%token DT_DEL_PROP
%token DT_DEL_NODE
+%token DT_OMIT_NO_REF
%token <propnodename> DT_PROPNODENAME
%token <integer> DT_LITERAL
%token <integer> DT_CHAR_LITERAL
%token <byte> DT_BYTE
%token <data> DT_STRING
%token <labelref> DT_LABEL
-%token <labelref> DT_REF
+%token <labelref> DT_LABEL_REF
+%token <labelref> DT_PATH_REF
%token DT_INCBIN
%type <data> propdata
@@ -82,6 +73,7 @@ extern bool treesource_error;
%type <data> bytestring
%type <prop> propdef
%type <proplist> proplist
+%type <labelref> dt_ref
%type <node> devicetree
%type <node> nodedef
@@ -157,6 +149,8 @@ memreserve:
}
;
+dt_ref: DT_LABEL_REF | DT_PATH_REF;
+
devicetree:
'/' nodedef
{
@@ -166,8 +160,21 @@ devicetree:
{
$$ = merge_nodes($1, $3);
}
-
- | devicetree DT_LABEL DT_REF nodedef
+ | dt_ref nodedef
+ {
+ /*
+ * We rely on the rule being always:
+ * versioninfo plugindecl memreserves devicetree
+ * so $-1 is what we want (plugindecl)
+ */
+ if (!($<flags>-1 & DTSF_PLUGIN))
+ ERROR(&@2, "Label or path %s not found", $1);
+ $$ = add_orphan_node(
+ name_node(build_node(NULL, NULL, NULL),
+ ""),
+ $2, $1);
+ }
+ | devicetree DT_LABEL dt_ref nodedef
{
struct node *target = get_node_by_ref($1, $3);
@@ -178,7 +185,26 @@ devicetree:
ERROR(&@3, "Label or path %s not found", $3);
$$ = $1;
}
- | devicetree DT_REF nodedef
+ | devicetree DT_PATH_REF nodedef
+ {
+ /*
+ * We rely on the rule being always:
+ * versioninfo plugindecl memreserves devicetree
+ * so $-1 is what we want (plugindecl)
+ */
+ if ($<flags>-1 & DTSF_PLUGIN) {
+ add_orphan_node($1, $3, $2);
+ } else {
+ struct node *target = get_node_by_ref($1, $2);
+
+ if (target)
+ merge_nodes(target, $3);
+ else
+ ERROR(&@2, "Label or path %s not found", $2);
+ }
+ $$ = $1;
+ }
+ | devicetree DT_LABEL_REF nodedef
{
struct node *target = get_node_by_ref($1, $2);
@@ -197,7 +223,7 @@ devicetree:
}
$$ = $1;
}
- | devicetree DT_DEL_NODE DT_REF ';'
+ | devicetree DT_DEL_NODE dt_ref ';'
{
struct node *target = get_node_by_ref($1, $3);
@@ -209,17 +235,29 @@ devicetree:
$$ = $1;
}
+ | devicetree DT_OMIT_NO_REF dt_ref ';'
+ {
+ struct node *target = get_node_by_ref($1, $3);
+
+ if (target)
+ omit_node_if_unused(target);
+ else
+ ERROR(&@3, "Label or path %s not found", $3);
+
+
+ $$ = $1;
+ }
| /* empty */
{
/* build empty node */
- $$ = name_node(build_node(NULL, NULL), "");
+ $$ = name_node(build_node(NULL, NULL, NULL), "");
}
;
nodedef:
'{' proplist subnodes '}' ';'
{
- $$ = build_node($2, $3);
+ $$ = build_node($2, $3, &@$);
}
;
@@ -237,11 +275,11 @@ proplist:
propdef:
DT_PROPNODENAME '=' propdata ';'
{
- $$ = build_property($1, $3);
+ $$ = build_property($1, $3, &@$);
}
| DT_PROPNODENAME ';'
{
- $$ = build_property($1, empty_data);
+ $$ = build_property($1, empty_data, &@$);
}
| DT_DEL_PROP DT_PROPNODENAME ';'
{
@@ -267,8 +305,9 @@ propdata:
{
$$ = data_merge($1, $3);
}
- | propdataprefix DT_REF
+ | propdataprefix dt_ref
{
+ $1 = data_add_marker($1, TYPE_STRING, $2);
$$ = data_add_marker($1, REF_PATH, $2);
}
| propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')'
@@ -322,22 +361,27 @@ arrayprefix:
DT_BITS DT_LITERAL '<'
{
unsigned long long bits;
+ enum markertype type = TYPE_UINT32;
bits = $2;
- if ((bits != 8) && (bits != 16) &&
- (bits != 32) && (bits != 64)) {
+ switch (bits) {
+ case 8: type = TYPE_UINT8; break;
+ case 16: type = TYPE_UINT16; break;
+ case 32: type = TYPE_UINT32; break;
+ case 64: type = TYPE_UINT64; break;
+ default:
ERROR(&@2, "Array elements must be"
" 8, 16, 32 or 64-bits");
bits = 32;
}
- $$.data = empty_data;
+ $$.data = data_add_marker(empty_data, type, NULL);
$$.bits = bits;
}
| '<'
{
- $$.data = empty_data;
+ $$.data = data_add_marker(empty_data, TYPE_UINT32, NULL);
$$.bits = 32;
}
| arrayprefix integer_prim
@@ -359,7 +403,7 @@ arrayprefix:
$$.data = data_append_integer($1.data, $2, $1.bits);
}
- | arrayprefix DT_REF
+ | arrayprefix dt_ref
{
uint64_t val = ~0ULL >> (64 - $1.bits);
@@ -481,7 +525,7 @@ integer_unary:
bytestring:
/* empty */
{
- $$ = empty_data;
+ $$ = data_add_marker(empty_data, TYPE_UINT8, NULL);
}
| bytestring DT_BYTE
{
@@ -516,7 +560,11 @@ subnode:
}
| DT_DEL_NODE DT_PROPNODENAME ';'
{
- $$ = name_node(build_node_delete(), $2);
+ $$ = name_node(build_node_delete(&@$), $2);
+ }
+ | DT_OMIT_NO_REF subnode
+ {
+ $$ = omit_node_if_unused($2);
}
| DT_LABEL subnode
{
diff --git a/dtc.c b/dtc.c
index 5ed873c..bdb3f59 100644
--- a/dtc.c
+++ b/dtc.c
@@ -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>
@@ -35,6 +20,8 @@ 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 */
int auto_label_aliases; /* auto generate labels -> aliases */
+int annotate; /* Level of annotation: 1 for input source location
+ >1 for full input source location. */
static int is_power_of_2(int x)
{
@@ -59,10 +46,8 @@ static void fill_fullpaths(struct node *tree, const char *prefix)
}
/* Usage related data. */
-#define FDT_VERSION(version) _FDT_VERSION(version)
-#define _FDT_VERSION(version) #version
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:@Ahv";
+static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@AThv";
static struct option const usage_long_opts[] = {
{"quiet", no_argument, NULL, 'q'},
{"in-format", a_argument, NULL, 'I'},
@@ -83,6 +68,7 @@ static struct option const usage_long_opts[] = {
{"error", a_argument, NULL, 'E'},
{"symbols", no_argument, NULL, '@'},
{"auto-alias", no_argument, NULL, 'A'},
+ {"annotate", no_argument, NULL, 'T'},
{"help", no_argument, NULL, 'h'},
{"version", no_argument, NULL, 'v'},
{NULL, no_argument, NULL, 0x0},
@@ -97,8 +83,11 @@ static const char * const usage_opts_help[] = {
"\n\tOutput formats are:\n"
"\t\tdts - device tree source text\n"
"\t\tdtb - device tree blob\n"
+#ifndef NO_YAML
+ "\t\tyaml - device tree encoded as YAML\n"
+#endif
"\t\tasm - assembler source",
- "\n\tBlob version to produce, defaults to "FDT_VERSION(DEFAULT_FDT_VERSION)" (for dtb and asm output)",
+ "\n\tBlob version to produce, defaults to "stringify(DEFAULT_FDT_VERSION)" (for dtb and asm output)",
"\n\tOutput dependency file",
"\n\tMake space for <number> reserve map entries (for dtb and asm output)",
"\n\tMake the blob at least <bytes> long (extra space)",
@@ -116,6 +105,7 @@ static const char * const usage_opts_help[] = {
"\n\tEnable/disable errors (prefix with \"no-\")",
"\n\tEnable generation of symbols",
"\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",
"\n\tPrint version and exit",
NULL,
@@ -130,6 +120,8 @@ static const char *guess_type_by_name(const char *fname, const char *fallback)
return fallback;
if (!strcasecmp(s, ".dts"))
return "dts";
+ if (!strcasecmp(s, ".yaml"))
+ return "yaml";
if (!strcasecmp(s, ".dtb"))
return "dtb";
return fallback;
@@ -261,6 +253,9 @@ int main(int argc, char *argv[])
case 'A':
auto_label_aliases = 1;
break;
+ case 'T':
+ annotate++;
+ break;
case 'h':
usage(NULL);
@@ -299,6 +294,8 @@ int main(int argc, char *argv[])
outform = "dts";
}
}
+ if (annotate && (!streq(inform, "dts") || !streq(outform, "dts")))
+ die("--annotate requires -I dts -O dts\n");
if (streq(inform, "dts"))
dti = dt_from_source(arg);
else if (streq(inform, "fs"))
@@ -319,13 +316,14 @@ int main(int argc, char *argv[])
dti->boot_cpuid_phys = cmdline_boot_cpuid;
fill_fullpaths(dti->dt, "");
- process_checks(force, dti);
/* on a plugin, generate by default */
if (dti->dtsflags & DTSF_PLUGIN) {
generate_fixups = 1;
}
+ process_checks(force, dti);
+
if (auto_label_aliases)
generate_label_tree(dti, "aliases", false);
@@ -351,6 +349,12 @@ int main(int argc, char *argv[])
if (streq(outform, "dts")) {
dt_to_source(outf, dti);
+#ifndef NO_YAML
+ } else if (streq(outform, "yaml")) {
+ if (!streq(inform, "dts"))
+ die("YAML output format requires dts input format\n");
+ dt_to_yaml(outf, dti);
+#endif
} else if (streq(outform, "dtb")) {
dt_to_blob(outf, dti, outversion);
} else if (streq(outform, "asm")) {
diff --git a/dtc.h b/dtc.h
index 07e3ddb..a08f415 100644
--- a/dtc.h
+++ b/dtc.h
@@ -1,24 +1,9 @@
-#ifndef _DTC_H
-#define _DTC_H
+/* 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>
@@ -58,6 +43,7 @@ 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 */
extern int auto_label_aliases; /* auto generate labels -> aliases */
+extern int annotate; /* annotate .dts with input source location */
#define PHANDLE_LEGACY 0x1
#define PHANDLE_EPAPR 0x2
@@ -65,18 +51,57 @@ extern int auto_label_aliases; /* auto generate labels -> aliases */
typedef uint32_t cell_t;
+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 strneq(a, b, n) (strncmp((a), (b), (n)) == 0)
+#define strstarts(s, prefix) (strncmp((s), (prefix), strlen(prefix)) == 0)
+#define strprefixeq(a, n, b) (strlen(b) == (n) && (memcmp(a, b, n) == 0))
#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
/* Data blobs */
enum markertype {
+ TYPE_NONE,
REF_PHANDLE,
REF_PATH,
LABEL,
+ TYPE_UINT8,
+ TYPE_UINT16,
+ TYPE_UINT32,
+ TYPE_UINT64,
+ TYPE_STRING,
};
+extern const char *markername(enum markertype markertype);
struct marker {
enum markertype type;
@@ -100,6 +125,8 @@ struct data {
for_each_marker(m) \
if ((m)->type == (t))
+size_t type_marker_length(struct marker *m);
+
void data_free(struct data d);
struct data data_grow_for(struct data d, int xlen);
@@ -148,6 +175,7 @@ struct property {
struct property *next;
struct label *labels;
+ struct srcpos *srcpos;
};
struct node {
@@ -167,6 +195,9 @@ struct node {
struct label *labels;
const struct bus_type *bus;
+ struct srcpos *srcpos;
+
+ bool omit_if_unused, is_referenced;
};
#define for_each_label_withdel(l0, l) \
@@ -193,17 +224,21 @@ 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(char *name, struct data val,
+ struct srcpos *srcpos);
struct property *build_property_delete(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 node *build_node_delete(void);
+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 *omit_node_if_unused(struct node *node);
+struct node *reference_node(struct node *node);
struct node *chain_node(struct node *first, struct node *list);
struct node *merge_nodes(struct node *old_node, struct node *new_node);
-void add_orphan_node(struct node *old_node, struct node *new_node, char *ref);
+struct node *add_orphan_node(struct node *old_node, struct node *new_node, char *ref);
void add_property(struct node *node, struct property *prop);
void delete_property_by_name(struct node *node, char *name);
@@ -212,11 +247,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);
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,
@@ -284,8 +321,12 @@ struct dt_info *dt_from_blob(const char *fname);
void dt_to_source(FILE *f, struct dt_info *dti);
struct dt_info *dt_from_source(const char *f);
+/* YAML source */
+
+void dt_to_yaml(FILE *f, struct dt_info *dti);
+
/* FS trees */
struct dt_info *dt_from_fs(const char *dirname);
-#endif /* _DTC_H */
+#endif /* DTC_H */
diff --git a/dtdiff b/dtdiff
index 5fa772b..cdbf079 100644
--- a/dtdiff
+++ b/dtdiff
@@ -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
diff --git a/fdtdump.c b/fdtdump.c
index fa3b561..9613bef 100644
--- a/fdtdump.c
+++ b/fdtdump.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* fdtdump.c - Contributed by Pantelis Antoniou <pantelis.antoniou AT gmail.com>
*/
@@ -8,6 +9,7 @@
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
+#include <inttypes.h>
#include <libfdt.h>
#include <libfdt_env.h>
@@ -65,23 +67,24 @@ static void dump_blob(void *blob, bool debug)
shift = 4;
printf("/dts-v1/;\n");
- printf("// magic:\t\t0x%x\n", fdt32_to_cpu(bph->magic));
- printf("// totalsize:\t\t0x%x (%d)\n", totalsize, totalsize);
- printf("// off_dt_struct:\t0x%x\n", off_dt);
- printf("// off_dt_strings:\t0x%x\n", off_str);
- printf("// off_mem_rsvmap:\t0x%x\n", off_mem_rsvmap);
- printf("// version:\t\t%d\n", version);
- printf("// last_comp_version:\t%d\n",
+ printf("// magic:\t\t0x%"PRIx32"\n", fdt32_to_cpu(bph->magic));
+ printf("// totalsize:\t\t0x%"PRIx32" (%"PRIu32")\n",
+ totalsize, totalsize);
+ printf("// off_dt_struct:\t0x%"PRIx32"\n", off_dt);
+ printf("// off_dt_strings:\t0x%"PRIx32"\n", off_str);
+ printf("// off_mem_rsvmap:\t0x%"PRIx32"\n", off_mem_rsvmap);
+ printf("// version:\t\t%"PRIu32"\n", version);
+ printf("// last_comp_version:\t%"PRIu32"\n",
fdt32_to_cpu(bph->last_comp_version));
if (version >= 2)
- printf("// boot_cpuid_phys:\t0x%x\n",
+ printf("// boot_cpuid_phys:\t0x%"PRIx32"\n",
fdt32_to_cpu(bph->boot_cpuid_phys));
if (version >= 3)
- printf("// size_dt_strings:\t0x%x\n",
+ printf("// size_dt_strings:\t0x%"PRIx32"\n",
fdt32_to_cpu(bph->size_dt_strings));
if (version >= 17)
- printf("// size_dt_struct:\t0x%x\n",
+ printf("// size_dt_struct:\t0x%"PRIx32"\n",
fdt32_to_cpu(bph->size_dt_struct));
printf("\n");
@@ -91,14 +94,14 @@ static void dump_blob(void *blob, bool debug)
if (addr == 0 && size == 0)
break;
- printf("/memreserve/ %#llx %#llx;\n",
- (unsigned long long)addr, (unsigned long long)size);
+ printf("/memreserve/ %#"PRIx64" %#"PRIx64";\n",
+ addr, size);
}
p = p_struct;
while ((tag = fdt32_to_cpu(GET_CELL(p))) != FDT_END) {
- dumpf("%04zx: tag: 0x%08x (%s)\n",
+ dumpf("%04"PRIxPTR": tag: 0x%08"PRIx32" (%s)\n",
(uintptr_t)p - blob_off - 4, tag, tagname(tag));
if (tag == FDT_BEGIN_NODE) {
@@ -127,7 +130,7 @@ static void dump_blob(void *blob, bool debug)
}
if (tag != FDT_PROP) {
- fprintf(stderr, "%*s ** Unknown tag 0x%08x\n", depth * shift, "", tag);
+ fprintf(stderr, "%*s ** Unknown tag 0x%08"PRIx32"\n", depth * shift, "", tag);
break;
}
sz = fdt32_to_cpu(GET_CELL(p));
@@ -138,8 +141,8 @@ static void dump_blob(void *blob, bool debug)
p = PALIGN(p + sz, 4);
- dumpf("%04zx: string: %s\n", (uintptr_t)s - blob_off, s);
- dumpf("%04zx: value\n", (uintptr_t)t - blob_off);
+ dumpf("%04"PRIxPTR": string: %s\n", (uintptr_t)s - blob_off, s);
+ dumpf("%04"PRIxPTR": value\n", (uintptr_t)t - blob_off);
printf("%*s%s", depth * shift, "", s);
utilfdt_print_data(t, sz);
printf(";\n");
@@ -181,7 +184,7 @@ int main(int argc, char *argv[])
char *buf;
bool debug = false;
bool scan = false;
- off_t len;
+ size_t len;
fprintf(stderr, "\n"
"**** fdtdump is a low-level debugging tool, not meant for general use.\n"
@@ -204,7 +207,7 @@ int main(int argc, char *argv[])
usage("missing input filename");
file = argv[optind];
- buf = utilfdt_read_len(file, &len);
+ buf = utilfdt_read(file, &len);
if (!buf)
die("could not read: %s\n", file);
@@ -227,14 +230,14 @@ int main(int argc, char *argv[])
if (valid_header(p, this_len))
break;
if (debug)
- printf("%s: skipping fdt magic at offset %#zx\n",
+ printf("%s: skipping fdt magic at offset %#tx\n",
file, p - buf);
}
++p;
}
if (!p || endp - p < sizeof(struct fdt_header))
die("%s: could not locate fdt magic\n", file);
- printf("%s: found fdt at offset %#zx\n", file, p - buf);
+ printf("%s: found fdt at offset %#tx\n", file, p - buf);
buf = p;
} else if (!valid_header(buf, len))
die("%s: header is not valid\n", file);
diff --git a/fdtget.c b/fdtget.c
index 39f1742..777582e 100644
--- a/fdtget.c
+++ b/fdtget.c
@@ -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>
@@ -54,6 +40,37 @@ static void report_error(const char *where, int err)
}
/**
+ * Shows a list of cells in the requested format
+ *
+ * @param disp Display information / options
+ * @param data Data to display
+ * @param len Maximum length of buffer
+ * @param size Data size to use for display (e.g. 4 for 32-bit)
+ * @return 0 if ok, -1 on error
+ */
+static int show_cell_list(struct display_info *disp, const char *data, int len,
+ int size)
+{
+ const uint8_t *p = (const uint8_t *)data;
+ char fmt[3];
+ int value;
+ int i;
+
+ fmt[0] = '%';
+ fmt[1] = disp->type ? disp->type : 'd';
+ fmt[2] = '\0';
+ 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;
+ printf(fmt, value);
+ }
+
+ return 0;
+}
+
+/**
* Displays data of a given length according to selected options
*
* If a specific data type is provided in disp, then this is used. Otherwise
@@ -66,12 +83,9 @@ static void report_error(const char *where, int err)
*/
static int show_data(struct display_info *disp, const char *data, int len)
{
- int i, size;
- const uint8_t *p = (const uint8_t *)data;
+ int size;
const char *s;
- int value;
int is_string;
- char fmt[3];
/* no data, don't print */
if (len == 0)
@@ -99,17 +113,8 @@ static int show_data(struct display_info *disp, const char *data, int len)
"selected data size\n");
return -1;
}
- fmt[0] = '%';
- fmt[1] = disp->type ? disp->type : 'd';
- fmt[2] = '\0';
- for (i = 0; i < len; i += size, p += size) {
- if (i)
- printf(" ");
- value = size == 4 ? fdt32_to_cpu(*(const fdt32_t *)p) :
- size == 2 ? (*p << 8) | p[1] : *p;
- printf(fmt, value);
- }
- return 0;
+
+ return show_cell_list(disp, data, len, size);
}
/**
@@ -121,7 +126,6 @@ static int show_data(struct display_info *disp, const char *data, int len)
*/
static int list_properties(const void *blob, int node)
{
- const struct fdt_property *data;
const char *name;
int prop;
@@ -130,8 +134,7 @@ static int list_properties(const void *blob, int node)
/* Stop silently when there are no more properties */
if (prop < 0)
return prop == -FDT_ERR_NOTFOUND ? 0 : prop;
- data = fdt_get_property_by_offset(blob, prop, NULL);
- name = fdt_string(blob, fdt32_to_cpu(data->nameoff));
+ fdt_getprop_by_offset(blob, prop, &name, NULL);
if (name)
puts(name);
prop = fdt_next_property_offset(blob, prop);
@@ -254,7 +257,7 @@ static int do_fdtget(struct display_info *disp, const char *filename,
const char *prop;
int i, node;
- blob = utilfdt_read(filename);
+ blob = utilfdt_read(filename, NULL);
if (!blob)
return -1;
diff --git a/fdtoverlay.c b/fdtoverlay.c
index 9c5618c..5350af6 100644
--- a/fdtoverlay.c
+++ b/fdtoverlay.c
@@ -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>
@@ -26,12 +12,14 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <alloca.h>
+#include <inttypes.h>
#include <libfdt.h>
#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"
@@ -54,59 +42,110 @@ 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;
+
+ /*
+ * We take a copies first, because a 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;
+ }
+
+ 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));
+ 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;
- off_t blob_len, ov_len, total_len;
+ size_t buf_len;
int i, ret = -1;
- blob = utilfdt_read_len(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) > buf_len) {
+ fprintf(stderr,
+ "\nBase blob is incomplete (%lu / %" PRIu32 " bytes read)\n",
+ (unsigned long)buf_len, fdt_totalsize(blob));
goto out_err;
}
- ret = 0;
/* allocate blob pointer array */
- ovblob = alloca(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++) {
- ovblob[i] = utilfdt_read_len(argv[i], &ov_len);
+ 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) {
@@ -114,6 +153,7 @@ out_err:
if (ovblob[i])
free(ovblob[i]);
}
+ free(ovblob);
}
free(blob);
diff --git a/fdtput.c b/fdtput.c
index 8d8e934..428745a 100644
--- a/fdtput.c
+++ b/fdtput.c
@@ -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>
@@ -130,7 +116,7 @@ static int encode_value(struct display_info *disp, char **arg, int arg_count,
#define ALIGN(x) (((x) + (FDT_TAGSIZE) - 1) & ~((FDT_TAGSIZE) - 1))
-static char *_realloc_fdt(char *fdt, int delta)
+static char *realloc_fdt(char *fdt, int delta)
{
int new_sz = fdt_totalsize(fdt) + delta;
fdt = xrealloc(fdt, new_sz);
@@ -144,7 +130,7 @@ static char *realloc_node(char *fdt, const char *name)
/* FDT_BEGIN_NODE, node name in off_struct and FDT_END_NODE */
delta = sizeof(struct fdt_node_header) + ALIGN(strlen(name) + 1)
+ FDT_TAGSIZE;
- return _realloc_fdt(fdt, delta);
+ return realloc_fdt(fdt, delta);
}
static char *realloc_property(char *fdt, int nodeoffset,
@@ -161,7 +147,7 @@ static char *realloc_property(char *fdt, int nodeoffset,
/* actual value in off_struct */
delta += ALIGN(newlen) - ALIGN(oldlen);
- return _realloc_fdt(fdt, delta);
+ return realloc_fdt(fdt, delta);
}
static int store_key_value(char **blob, const char *node_name,
@@ -333,7 +319,7 @@ static int do_fdtput(struct display_info *disp, const char *filename,
char *node;
int len, ret = 0;
- blob = utilfdt_read(filename);
+ blob = utilfdt_read(filename, NULL);
if (!blob)
return -1;
diff --git a/flattree.c b/flattree.c
index fcf7154..07f10d2 100644
--- a/flattree.c
+++ b/flattree.c
@@ -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"
@@ -171,7 +156,7 @@ static void asm_emit_data(void *e, struct data d)
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);
}
@@ -393,7 +378,7 @@ void dt_to_blob(FILE *f, struct dt_info *dti, int version)
padlen = 0;
if (quiet < 1)
fprintf(stderr,
- "Warning: blob size %d >= minimum size %d\n",
+ "Warning: blob size %"PRIu32" >= minimum size %d\n",
fdt32_to_cpu(fdt.totalsize), minsize);
}
}
@@ -525,7 +510,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) {
@@ -692,7 +677,7 @@ static struct property *flat_read_property(struct inbuf *dtbuf,
val = flat_read_data(dtbuf, proplen);
- return build_property(name, val);
+ return build_property(name, val, NULL);
}
@@ -731,7 +716,7 @@ static char *nodename_from_path(const char *ppath, const char *cpath)
plen = strlen(ppath);
- if (!strneq(ppath, cpath, plen))
+ if (!strstarts(cpath, ppath))
die("Path \"%s\" is not valid as a child of \"%s\"\n",
cpath, ppath);
@@ -750,7 +735,7 @@ static struct node *unflatten_tree(struct inbuf *dtbuf,
char *flatname;
uint32_t val;
- node = build_node(NULL, NULL);
+ node = build_node(NULL, NULL, NULL);
flatname = flat_read_string(dtbuf);
diff --git a/fstree.c b/fstree.c
index ae7d06c..5e59594 100644
--- a/fstree.c
+++ b/fstree.c
@@ -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"
@@ -34,7 +19,7 @@ static struct node *read_fstree(const char *dirname)
if (!d)
die("Couldn't opendir() \"%s\": %s\n", dirname, strerror(errno));
- tree = build_node(NULL, NULL);
+ tree = build_node(NULL, NULL, NULL);
while ((de = readdir(d)) != NULL) {
char *tmpname;
@@ -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)) {
@@ -60,7 +45,8 @@ static struct node *read_fstree(const char *dirname)
} else {
prop = build_property(xstrdup(de->d_name),
data_copy_file(pfile,
- st.st_size));
+ st.st_size),
+ NULL);
add_property(tree, prop);
fclose(pfile);
}
diff --git a/libfdt/.gitignore b/libfdt/.gitignore
new file mode 100644
index 0000000..fed4603
--- /dev/null
+++ b/libfdt/.gitignore
@@ -0,0 +1 @@
+libfdt.so.1
diff --git a/libfdt/Android.bp b/libfdt/Android.bp
index 320d4fc..16c6cf4 100644
--- a/libfdt/Android.bp
+++ b/libfdt/Android.bp
@@ -9,6 +9,7 @@ cc_library_static {
],
srcs: [
"fdt.c",
+ "fdt_check.c",
"fdt_ro.c",
"fdt_wip.c",
"fdt_sw.c",
diff --git a/libfdt/Makefile.libfdt b/libfdt/Makefile.libfdt
index efe1537..3e70abf 100644
--- a/libfdt/Makefile.libfdt
+++ b/libfdt/Makefile.libfdt
@@ -1,3 +1,4 @@
+# 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
@@ -7,5 +8,11 @@ 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 acpi.c
+ fdt_addresses.c fdt_overlay.c fdt_check.c acpi.c
LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
+LIBFDT_LIB = libfdt-$(DTC_VERSION).$(SHAREDLIB_EXT)
+
+libfdt_clean:
+ @$(VECHO) CLEAN "(libfdt)"
+ rm -f $(STD_CLEANFILES:%=$(LIBFDT_dir)/%)
+ rm -f $(LIBFDT_dir)/$(LIBFDT_soname)
diff --git a/libfdt/fdt.c b/libfdt/fdt.c
index 22286a1..c28fcc1 100644
--- a/libfdt/fdt.c
+++ b/libfdt/fdt.c
@@ -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"
@@ -55,22 +10,125 @@
#include "libfdt_internal.h"
-int fdt_check_header(const void *fdt)
+/*
+ * Minimal sanity check for a read-only tree. fdt_ro_probe_() checks
+ * that the given buffer contains what appears to be a flattened
+ * device tree with sane information in its header.
+ */
+int32_t fdt_ro_probe_(const void *fdt)
{
+ uint32_t totalsize = fdt_totalsize(fdt);
+
+ if (can_assume(VALID_DTB))
+ return totalsize;
+
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;
}
+ if (totalsize < INT32_MAX)
+ return totalsize;
+ else
+ return -FDT_ERR_TRUNCATED;
+}
+
+static int check_off_(uint32_t hdrsize, uint32_t totalsize, uint32_t off)
+{
+ return (off >= hdrsize) && (off <= totalsize);
+}
+
+static int check_block_(uint32_t hdrsize, uint32_t totalsize,
+ uint32_t base, uint32_t size)
+{
+ if (!check_off_(hdrsize, totalsize, base))
+ return 0; /* block start out of bounds */
+ if ((base + size) < base)
+ return 0; /* overflow */
+ if (!check_off_(hdrsize, totalsize, base + size))
+ return 0; /* block end out of bounds */
+ return 1;
+}
+
+size_t fdt_header_size_(uint32_t version)
+{
+ if (version <= 1)
+ return FDT_V1_SIZE;
+ else if (version <= 2)
+ return FDT_V2_SIZE;
+ else if (version <= 3)
+ return FDT_V3_SIZE;
+ else if (version <= 16)
+ return FDT_V16_SIZE;
+ else
+ 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;
+
+ 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 (!can_assume(VALID_DTB)) {
+
+ 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;
+ }
+
+ if (!can_assume(VALID_DTB)) {
+ /* 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_strings(fdt),
+ fdt_size_dt_strings(fdt)))
+ return -FDT_ERR_TRUNCATED;
+ }
+
return 0;
}
@@ -78,17 +136,18 @@ const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
{
unsigned absoffset = offset + fdt_off_dt_struct(fdt);
- if ((absoffset < offset)
- || ((absoffset + len) < absoffset)
- || (absoffset + len) > fdt_totalsize(fdt))
- return NULL;
+ if (!can_assume(VALID_INPUT))
+ if ((absoffset < offset)
+ || ((absoffset + len) < absoffset)
+ || (absoffset + len) > fdt_totalsize(fdt))
+ return NULL;
- if (fdt_version(fdt) >= 0x11)
+ if (can_assume(LATEST) || fdt_version(fdt) >= 0x11)
if (((offset + len) < offset)
|| ((offset + len) > fdt_size_dt_struct(fdt)))
return NULL;
- return _fdt_offset_ptr(fdt, offset);
+ return fdt_offset_ptr_(fdt, offset);
}
uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
@@ -100,7 +159,7 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
*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;
@@ -112,17 +171,21 @@ 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 */
/* skip-name offset, length and value */
offset += sizeof(struct fdt_property) - FDT_TAGSIZE
+ fdt32_to_cpu(*lenp);
+ if (!can_assume(LATEST) &&
+ fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 &&
+ ((offset - fdt32_to_cpu(*lenp)) % 8) != 0)
+ offset += 4;
break;
case FDT_END:
@@ -141,8 +204,10 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
return tag;
}
-int _fdt_check_node_offset(const void *fdt, int offset)
+int fdt_check_node_offset_(const void *fdt, int offset)
{
+ if (can_assume(VALID_INPUT))
+ return offset;
if ((offset < 0) || (offset % FDT_TAGSIZE)
|| (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE))
return -FDT_ERR_BADOFFSET;
@@ -150,7 +215,7 @@ int _fdt_check_node_offset(const void *fdt, int offset)
return offset;
}
-int _fdt_check_prop_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))
@@ -165,7 +230,7 @@ int fdt_next_node(const void *fdt, int offset, int *depth)
uint32_t tag;
if (offset >= 0)
- if ((nextoffset = _fdt_check_node_offset(fdt, offset)) < 0)
+ if ((nextoffset = fdt_check_node_offset_(fdt, offset)) < 0)
return nextoffset;
do {
@@ -227,7 +292,7 @@ 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_(const char *strtab, int tabsize, const char *s)
{
int len = strlen(s) + 1;
const char *last = strtab + tabsize - len;
@@ -241,7 +306,7 @@ const char *_fdt_find_string(const char *strtab, int tabsize, const char *s)
int fdt_move(const void *fdt, void *buf, int bufsize)
{
- FDT_CHECK_HEADER(fdt);
+ FDT_RO_PROBE(fdt);
if (fdt_totalsize(fdt) > bufsize)
return -FDT_ERR_NOSPACE;
diff --git a/libfdt/fdt.h b/libfdt/fdt.h
index 526aedb..f2e6880 100644
--- a/libfdt/fdt.h
+++ b/libfdt/fdt.h
@@ -1,55 +1,10 @@
-#ifndef _FDT_H
-#define _FDT_H
+/* 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__
@@ -108,4 +63,4 @@ struct fdt_property {
#define FDT_V16_SIZE FDT_V3_SIZE
#define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(fdt32_t))
-#endif /* _FDT_H */
+#endif /* FDT_H */
diff --git a/libfdt/fdt_addresses.c b/libfdt/fdt_addresses.c
index eff4dbc..9a82cd0 100644
--- a/libfdt/fdt_addresses.c
+++ b/libfdt/fdt_addresses.c
@@ -1,52 +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>
- *
- * 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.
+ * Copyright (C) 2018 embedded brains GmbH
*/
#include "libfdt_env.h"
@@ -55,42 +11,91 @@
#include "libfdt_internal.h"
-int fdt_address_cells(const void *fdt, int nodeoffset)
+static int fdt_cells(const void *fdt, int nodeoffset, const char *name)
{
- const fdt32_t *ac;
- int val;
+ const fdt32_t *c;
+ uint32_t val;
int len;
- ac = fdt_getprop(fdt, nodeoffset, "#address-cells", &len);
- if (!ac)
- return 2;
+ c = fdt_getprop(fdt, nodeoffset, name, &len);
+ if (!c)
+ return len;
- if (len != sizeof(*ac))
+ if (len != sizeof(*c))
return -FDT_ERR_BADNCELLS;
- val = fdt32_to_cpu(*ac);
- if ((val <= 0) || (val > FDT_MAX_NCELLS))
+ val = fdt32_to_cpu(*c);
+ if (val > FDT_MAX_NCELLS)
return -FDT_ERR_BADNCELLS;
+ return (int)val;
+}
+
+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;
}
int fdt_size_cells(const void *fdt, int nodeoffset)
{
- const fdt32_t *sc;
int val;
- int len;
- sc = fdt_getprop(fdt, nodeoffset, "#size-cells", &len);
- if (!sc)
- return 2;
+ val = fdt_cells(fdt, nodeoffset, "#size-cells");
+ if (val == -FDT_ERR_NOTFOUND)
+ 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;
- if (len != sizeof(*sc))
+ 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) || ((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;
+ }
- val = fdt32_to_cpu(*sc);
- if ((val < 0) || (val > FDT_MAX_NCELLS))
+ /* 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 val;
+ return fdt_appendprop(fdt, nodeoffset, name, data,
+ (addr_cells + size_cells) * sizeof(fdt32_t));
}
diff --git a/libfdt/fdt_check.c b/libfdt/fdt_check.c
new file mode 100644
index 0000000..7f6a96c
--- /dev/null
+++ b/libfdt/fdt_check.c
@@ -0,0 +1,74 @@
+// 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;
+
+ 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;
+ }
+ }
+}
diff --git a/libfdt/fdt_empty_tree.c b/libfdt/fdt_empty_tree.c
index f2ae9b7..49d54d4 100644
--- a/libfdt/fdt_empty_tree.c
+++ b/libfdt/fdt_empty_tree.c
@@ -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"
diff --git a/libfdt/fdt_overlay.c b/libfdt/fdt_overlay.c
index ceb9687..b310e49 100644
--- a/libfdt/fdt_overlay.c
+++ b/libfdt/fdt_overlay.c
@@ -1,3 +1,9 @@
+// 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.
+ */
#include "libfdt_env.h"
#include <fdt.h>
@@ -39,47 +45,58 @@ static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
* @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
+ * device tree of a fragment, no matter how the actual targeting is
* done (through a phandle or a path)
*
* returns:
- * the targetted node offset in the base device tree
+ * the targeted node offset in the base device tree
* Negative error code on error
*/
static int overlay_get_target(const void *fdt, const void *fdto,
- int fragment)
+ int fragment, char const **pathp)
{
uint32_t phandle;
- const char *path;
- int path_len;
+ const char *path = NULL;
+ int path_len = 0, ret;
/* Try first to do a phandle based lookup */
phandle = overlay_get_target_phandle(fdto, fragment);
if (phandle == (uint32_t)-1)
return -FDT_ERR_BADPHANDLE;
- if (phandle)
- return fdt_node_offset_by_phandle(fdt, phandle);
+ /* no phandle, try path */
+ if (!phandle) {
+ /* And then a path based lookup */
+ path = fdt_getprop(fdto, fragment, "target-path", &path_len);
+ if (path)
+ ret = fdt_path_offset(fdt, path);
+ else
+ ret = path_len;
+ } else
+ ret = fdt_node_offset_by_phandle(fdt, phandle);
- /* And then a path based lookup */
- path = fdt_getprop(fdto, fragment, "target-path", &path_len);
- if (!path) {
- /*
- * If we haven't found either a target or a
- * target-path property in a node that contains a
- * __overlay__ subnode (we wouldn't be called
- * otherwise), consider it a improperly written
- * overlay
- */
- if (path_len == -FDT_ERR_NOTFOUND)
- return -FDT_ERR_BADOVERLAY;
+ /*
+ * If we haven't found either a target or a
+ * target-path property in a node that contains a
+ * __overlay__ subnode (we wouldn't be called
+ * otherwise), consider it a improperly written
+ * overlay
+ */
+ if (ret < 0 && path_len == -FDT_ERR_NOTFOUND)
+ ret = -FDT_ERR_BADOVERLAY;
+
+ /* return on error */
+ if (ret < 0)
+ return ret;
- return path_len;
- }
+ /* return pointer to path (if available) */
+ if (pathp)
+ *pathp = path ? path : NULL;
- return fdt_path_offset(fdt, path);
+ return ret;
}
/**
@@ -590,7 +607,7 @@ static int overlay_apply_node(void *fdt, int target,
*
* overlay_merge() merges an overlay into its base device tree.
*
- * This is the final step in the device tree overlay application
+ * This is the next to last step in the device tree overlay application
* process, when all the phandles have been adjusted and resolved and
* you just have to merge overlay into the base device tree.
*
@@ -618,7 +635,7 @@ static int overlay_merge(void *fdt, void *fdto)
if (overlay < 0)
return overlay;
- target = overlay_get_target(fdt, fdto, fragment);
+ target = overlay_get_target(fdt, fdto, fragment, NULL);
if (target < 0)
return target;
@@ -630,13 +647,196 @@ static int overlay_merge(void *fdt, void *fdto)
return 0;
}
+static int get_path_len(const void *fdt, int nodeoffset)
+{
+ int len = 0, namelen;
+ const char *name;
+
+ FDT_RO_PROBE(fdt);
+
+ for (;;) {
+ name = fdt_get_name(fdt, nodeoffset, &namelen);
+ if (!name)
+ return namelen;
+
+ /* root? we're done */
+ if (namelen == 0)
+ break;
+
+ nodeoffset = fdt_parent_offset(fdt, nodeoffset);
+ if (nodeoffset < 0)
+ return nodeoffset;
+ len += namelen + 1;
+ }
+
+ /* in case of root pretend it's "/" */
+ if (len == 0)
+ len++;
+ return len;
+}
+
+/**
+ * overlay_symbol_update - Update the symbols of base tree after a merge
+ * @fdt: Base Device Tree blob
+ * @fdto: Device tree overlay blob
+ *
+ * overlay_symbol_update() updates the symbols of the base tree with the
+ * symbols of the applied overlay
+ *
+ * This is the last step in the device tree overlay application
+ * process, allowing the reference of overlay symbols by subsequent
+ * overlay operations.
+ *
+ * returns:
+ * 0 on success
+ * Negative error code on failure
+ */
+static int overlay_symbol_update(void *fdt, void *fdto)
+{
+ int root_sym, ov_sym, prop, path_len, fragment, target;
+ int len, frag_name_len, ret, rel_path_len;
+ const char *s, *e;
+ const char *path;
+ const char *name;
+ const char *frag_name;
+ const char *rel_path;
+ const char *target_path;
+ char *buf;
+ void *p;
+
+ ov_sym = fdt_subnode_offset(fdto, 0, "__symbols__");
+
+ /* if no overlay symbols exist no problem */
+ if (ov_sym < 0)
+ return 0;
+
+ root_sym = fdt_subnode_offset(fdt, 0, "__symbols__");
+
+ /* it no root symbols exist we should create them */
+ if (root_sym == -FDT_ERR_NOTFOUND)
+ root_sym = fdt_add_subnode(fdt, 0, "__symbols__");
+
+ /* any error is fatal now */
+ if (root_sym < 0)
+ return root_sym;
+
+ /* iterate over each overlay symbol */
+ fdt_for_each_property_offset(prop, fdto, ov_sym) {
+ path = fdt_getprop_by_offset(fdto, prop, &name, &path_len);
+ if (!path)
+ return path_len;
+
+ /* verify it's a string property (terminated by a single \0) */
+ if (path_len < 1 || memchr(path, '\0', path_len) != &path[path_len - 1])
+ return -FDT_ERR_BADVALUE;
+
+ /* keep end marker to avoid strlen() */
+ e = path + path_len;
+
+ if (*path != '/')
+ return -FDT_ERR_BADVALUE;
+
+ /* get fragment name first */
+ s = strchr(path + 1, '/');
+ 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) == 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,
+ frag_name_len);
+ /* not found? */
+ if (ret < 0)
+ return -FDT_ERR_BADOVERLAY;
+ fragment = ret;
+
+ /* an __overlay__ subnode must exist */
+ ret = fdt_subnode_offset(fdto, fragment, "__overlay__");
+ if (ret < 0)
+ return -FDT_ERR_BADOVERLAY;
+
+ /* get the target of the fragment */
+ ret = overlay_get_target(fdt, fdto, fragment, &target_path);
+ if (ret < 0)
+ return ret;
+ target = ret;
+
+ /* if we have a target path use */
+ if (!target_path) {
+ ret = get_path_len(fdt, target);
+ if (ret < 0)
+ return ret;
+ len = ret;
+ } else {
+ len = strlen(target_path);
+ }
+
+ ret = fdt_setprop_placeholder(fdt, root_sym, name,
+ len + (len > 1) + rel_path_len + 1, &p);
+ if (ret < 0)
+ return ret;
+
+ if (!target_path) {
+ /* again in case setprop_placeholder changed it */
+ ret = overlay_get_target(fdt, fdto, fragment, &target_path);
+ if (ret < 0)
+ return ret;
+ target = ret;
+ }
+
+ buf = p;
+ if (len > 1) { /* target is not root */
+ if (!target_path) {
+ ret = fdt_get_path(fdt, target, buf, len + 1);
+ if (ret < 0)
+ return ret;
+ } else
+ memcpy(buf, target_path, len + 1);
+
+ } else
+ len--;
+
+ buf[len] = '/';
+ memcpy(buf + len + 1, rel_path, rel_path_len);
+ buf[len + 1 + rel_path_len] = '\0';
+ }
+
+ return 0;
+}
+
int fdt_overlay_apply(void *fdt, void *fdto)
{
- uint32_t delta = fdt_get_max_phandle(fdt);
+ uint32_t delta;
int ret;
- FDT_CHECK_HEADER(fdt);
- FDT_CHECK_HEADER(fdto);
+ FDT_RO_PROBE(fdt);
+ FDT_RO_PROBE(fdto);
+
+ ret = fdt_find_max_phandle(fdt, &delta);
+ if (ret)
+ goto err;
ret = overlay_adjust_local_phandles(fdto, delta);
if (ret)
@@ -654,6 +854,10 @@ int fdt_overlay_apply(void *fdt, void *fdto)
if (ret)
goto err;
+ ret = overlay_symbol_update(fdt, fdto);
+ if (ret)
+ goto err;
+
/*
* The overlay has been damaged, erase its magic.
*/
diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c
index 08de2cc..e03570a 100644
--- a/libfdt/fdt_ro.c
+++ b/libfdt/fdt_ro.c
@@ -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"
@@ -55,12 +10,13 @@
#include "libfdt_internal.h"
-static int _fdt_nodename_eq(const void *fdt, int offset,
+static int fdt_nodename_eq_(const void *fdt, int offset,
const char *s, int len)
{
- const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1);
+ int olen;
+ const char *p = fdt_get_name(fdt, offset, &olen);
- if (!p)
+ if (!p || olen < len)
/* short match */
return 0;
@@ -75,63 +31,172 @@ static int _fdt_nodename_eq(const void *fdt, int offset,
return 0;
}
+const char *fdt_get_string(const void *fdt, int stroffset, int *lenp)
+{
+ int32_t totalsize;
+ uint32_t absoffset;
+ size_t len;
+ int err;
+ const char *s, *n;
+
+ 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;
+ absoffset = stroffset + fdt_off_dt_strings(fdt);
+ if (absoffset >= totalsize)
+ goto fail;
+ len = totalsize - absoffset;
+
+ if (fdt_magic(fdt) == FDT_MAGIC) {
+ if (stroffset < 0)
+ goto fail;
+ if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
+ if (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)))
+ goto fail;
+ if ((-stroffset) < len)
+ len = -stroffset;
+ } else {
+ err = -FDT_ERR_INTERNAL;
+ goto fail;
+ }
+
+ s = (const char *)fdt + absoffset;
+ n = memchr(s, '\0', len);
+ if (!n) {
+ /* missing terminating NULL */
+ err = -FDT_ERR_TRUNCATED;
+ goto fail;
+ }
+
+ if (lenp)
+ *lenp = n - s;
+ return s;
+
+fail:
+ if (lenp)
+ *lenp = err;
+ return NULL;
+}
+
const char *fdt_string(const void *fdt, int stroffset)
{
- return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
+ return fdt_get_string(fdt, stroffset, NULL);
}
-static int _fdt_string_eq(const void *fdt, int stroffset,
+static int fdt_string_eq_(const void *fdt, int stroffset,
const char *s, int len)
{
- const char *p = fdt_string(fdt, stroffset);
+ int slen;
+ const char *p = fdt_get_string(fdt, stroffset, &slen);
- return (strlen(p) == len) && (memcmp(p, s, len) == 0);
+ 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;
+
+ 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);
+}
+
int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
{
- FDT_CHECK_HEADER(fdt);
- *address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address);
- *size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size);
+ const struct fdt_reserve_entry *re;
+
+ FDT_RO_PROBE(fdt);
+ re = fdt_mem_rsv(fdt, n);
+ if (!can_assume(VALID_INPUT) && !re)
+ return -FDT_ERR_BADOFFSET;
+
+ *address = fdt64_ld(&re->address);
+ *size = fdt64_ld(&re->size);
return 0;
}
int fdt_num_mem_rsv(const void *fdt)
{
- int i = 0;
+ int i;
+ const struct fdt_reserve_entry *re;
- while (fdt64_to_cpu(_fdt_mem_rsv(fdt, i)->size) != 0)
- i++;
- return i;
+ for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) {
+ if (fdt64_ld(&re->size) == 0)
+ return i;
+ }
+ return -FDT_ERR_TRUNCATED;
}
-static int _nextprop(const void *fdt, int offset)
+static int nextprop_(const void *fdt, int offset)
{
uint32_t tag;
int nextoffset;
@@ -160,13 +225,13 @@ int fdt_subnode_offset_namelen(const void *fdt, int offset,
{
int depth;
- FDT_CHECK_HEADER(fdt);
+ FDT_RO_PROBE(fdt);
for (depth = 0;
(offset >= 0) && (depth >= 0);
offset = fdt_next_node(fdt, offset, &depth))
if ((depth == 1)
- && _fdt_nodename_eq(fdt, offset, name, namelen))
+ && fdt_nodename_eq_(fdt, offset, name, namelen))
return offset;
if (depth < 0)
@@ -186,7 +251,7 @@ int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen)
const char *p = path;
int offset = 0;
- FDT_CHECK_HEADER(fdt);
+ FDT_RO_PROBE(fdt);
/* see if we have an alias */
if (*path != '/') {
@@ -232,17 +297,35 @@ int fdt_path_offset(const void *fdt, const char *path)
const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
{
- const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset);
+ const struct fdt_node_header *nh = fdt_offset_ptr_(fdt, nodeoffset);
+ const char *nameptr;
int err;
- if (((err = fdt_check_header(fdt)) != 0)
- || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0))
+ if (((err = fdt_ro_probe_(fdt)) < 0)
+ || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0))
goto fail;
+ nameptr = nh->name;
+
+ 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
+ * contents are loosely checked.
+ */
+ const char *leaf;
+ leaf = strrchr(nameptr, '/');
+ if (leaf == NULL) {
+ err = -FDT_ERR_BADSTRUCTURE;
+ goto fail;
+ }
+ nameptr = leaf+1;
+ }
+
if (len)
- *len = strlen(nh->name);
+ *len = strlen(nameptr);
- return nh->name;
+ return nameptr;
fail:
if (len)
@@ -254,58 +337,81 @@ int fdt_first_property_offset(const void *fdt, int nodeoffset)
{
int offset;
- if ((offset = _fdt_check_node_offset(fdt, nodeoffset)) < 0)
+ if ((offset = fdt_check_node_offset_(fdt, nodeoffset)) < 0)
return offset;
- return _nextprop(fdt, offset);
+ return nextprop_(fdt, offset);
}
int fdt_next_property_offset(const void *fdt, int offset)
{
- if ((offset = _fdt_check_prop_offset(fdt, offset)) < 0)
+ if ((offset = fdt_check_prop_offset_(fdt, offset)) < 0)
return offset;
- return _nextprop(fdt, offset);
+ return nextprop_(fdt, offset);
}
-const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
- int offset,
- int *lenp)
+static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt,
+ int offset,
+ int *lenp)
{
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;
}
- prop = _fdt_offset_ptr(fdt, offset);
+ prop = fdt_offset_ptr_(fdt, offset);
if (lenp)
- *lenp = fdt32_to_cpu(prop->len);
+ *lenp = fdt32_ld(&prop->len);
return prop;
}
-const struct fdt_property *fdt_get_property_namelen(const void *fdt,
- int offset,
- const char *name,
- int namelen, int *lenp)
+const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
+ int offset,
+ int *lenp)
+{
+ /* Prior to version 16, properties may need realignment
+ * and this API does not work. fdt_getprop_*() will, however. */
+
+ if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) {
+ if (lenp)
+ *lenp = -FDT_ERR_BADVERSION;
+ return NULL;
+ }
+
+ return fdt_get_property_by_offset_(fdt, offset, lenp);
+}
+
+static const struct fdt_property *fdt_get_property_namelen_(const void *fdt,
+ int offset,
+ const char *name,
+ int namelen,
+ int *lenp,
+ int *poffset)
{
for (offset = fdt_first_property_offset(fdt, offset);
(offset >= 0);
(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_to_cpu(prop->nameoff),
- name, namelen))
+ if (fdt_string_eq_(fdt, fdt32_ld(&prop->nameoff),
+ name, namelen)) {
+ if (poffset)
+ *poffset = offset;
return prop;
+ }
}
if (lenp)
@@ -313,6 +419,25 @@ const struct fdt_property *fdt_get_property_namelen(const void *fdt,
return NULL;
}
+
+const struct fdt_property *fdt_get_property_namelen(const void *fdt,
+ int offset,
+ const char *name,
+ int namelen, int *lenp)
+{
+ /* Prior to version 16, properties may need realignment
+ * and this API does not work. fdt_getprop_*() will, however. */
+ if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) {
+ if (lenp)
+ *lenp = -FDT_ERR_BADVERSION;
+ return NULL;
+ }
+
+ return fdt_get_property_namelen_(fdt, offset, name, namelen, lenp,
+ NULL);
+}
+
+
const struct fdt_property *fdt_get_property(const void *fdt,
int nodeoffset,
const char *name, int *lenp)
@@ -324,12 +449,18 @@ const struct fdt_property *fdt_get_property(const void *fdt,
const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
const char *name, int namelen, int *lenp)
{
+ int poffset;
const struct fdt_property *prop;
- prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp);
+ prop = fdt_get_property_namelen_(fdt, nodeoffset, name, namelen, lenp,
+ &poffset);
if (!prop)
return NULL;
+ /* Handle realignment */
+ if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
+ (poffset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
+ return prop->data + 4;
return prop->data;
}
@@ -338,11 +469,31 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
{
const struct fdt_property *prop;
- prop = fdt_get_property_by_offset(fdt, offset, lenp);
+ prop = fdt_get_property_by_offset_(fdt, offset, lenp);
if (!prop)
return NULL;
- if (namep)
- *namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
+ if (namep) {
+ const char *name;
+ int namelen;
+
+ if (!can_assume(VALID_INPUT)) {
+ name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff),
+ &namelen);
+ if (!name) {
+ if (lenp)
+ *lenp = namelen;
+ return NULL;
+ }
+ *namep = name;
+ } else {
+ *namep = fdt_string(fdt, fdt32_ld(&prop->nameoff));
+ }
+ }
+
+ /* Handle realignment */
+ if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
+ (offset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
+ return prop->data + 4;
return prop->data;
}
@@ -366,7 +517,7 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
return 0;
}
- return fdt32_to_cpu(*php);
+ return fdt32_ld(php);
}
const char *fdt_get_alias_namelen(const void *fdt,
@@ -392,7 +543,7 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
int offset, depth, namelen;
const char *name;
- FDT_CHECK_HEADER(fdt);
+ FDT_RO_PROBE(fdt);
if (buflen < 2)
return -FDT_ERR_NOSPACE;
@@ -444,7 +595,7 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
int offset, depth;
int supernodeoffset = -FDT_ERR_INTERNAL;
- FDT_CHECK_HEADER(fdt);
+ FDT_RO_PROBE(fdt);
if (supernodedepth < 0)
return -FDT_ERR_NOTFOUND;
@@ -466,10 +617,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() */
}
@@ -481,7 +634,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;
}
@@ -503,7 +657,7 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
const void *val;
int len;
- FDT_CHECK_HEADER(fdt);
+ FDT_RO_PROBE(fdt);
/* FIXME: The algorithm here is pretty horrible: we scan each
* property of a node in fdt_getprop(), then if that didn't
@@ -529,7 +683,7 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
if ((phandle == 0) || (phandle == -1))
return -FDT_ERR_BADPHANDLE;
- FDT_CHECK_HEADER(fdt);
+ FDT_RO_PROBE(fdt);
/* FIXME: The algorithm here is pretty horrible: we
* potentially scan each property of a node in
@@ -682,7 +836,7 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
{
int offset, err;
- FDT_CHECK_HEADER(fdt);
+ FDT_RO_PROBE(fdt);
/* FIXME: The algorithm here is pretty horrible: we scan each
* property of a node in fdt_node_check_compatible(), then if
diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c
index 8b487f6..93e4a2b 100644
--- a/libfdt/fdt_rw.c
+++ b/libfdt/fdt_rw.c
@@ -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"
@@ -55,8 +10,8 @@
#include "libfdt_internal.h"
-static int _fdt_blocks_misordered(const void *fdt,
- int mem_rsv_size, int struct_size)
+static int fdt_blocks_misordered_(const void *fdt,
+ int mem_rsv_size, int struct_size)
{
return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8))
|| (fdt_off_dt_struct(fdt) <
@@ -67,54 +22,57 @@ static int _fdt_blocks_misordered(const void *fdt,
(fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt)));
}
-static int _fdt_rw_check_header(void *fdt)
+static int fdt_rw_probe_(void *fdt)
{
- FDT_CHECK_HEADER(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),
+ 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;
}
-#define FDT_RW_CHECK_HEADER(fdt) \
+#define FDT_RW_PROBE(fdt) \
{ \
- int __err; \
- if ((__err = _fdt_rw_check_header(fdt)) != 0) \
- return __err; \
+ int err_; \
+ if ((err_ = fdt_rw_probe_(fdt)) != 0) \
+ 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);
}
-static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen)
+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 < 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;
}
-static int _fdt_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p,
+static int fdt_splice_mem_rsv_(void *fdt, struct fdt_reserve_entry *p,
int oldn, int newn)
{
int delta = (newn - oldn) * sizeof(*p);
int err;
- err = _fdt_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p));
+ err = fdt_splice_(fdt, p, oldn * sizeof(*p), newn * sizeof(*p));
if (err)
return err;
fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta);
@@ -122,13 +80,13 @@ static int _fdt_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p,
return 0;
}
-static int _fdt_splice_struct(void *fdt, void *p,
+static int fdt_splice_struct_(void *fdt, void *p,
int oldlen, int newlen)
{
int delta = newlen - oldlen;
int err;
- if ((err = _fdt_splice(fdt, p, oldlen, newlen)))
+ if ((err = fdt_splice_(fdt, p, oldlen, newlen)))
return err;
fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta);
@@ -136,20 +94,37 @@ static int _fdt_splice_struct(void *fdt, void *p,
return 0;
}
-static int _fdt_splice_string(void *fdt, int newlen)
+/* 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
+ fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
int err;
- if ((err = _fdt_splice(fdt, p, 0, newlen)))
+ if ((err = fdt_splice_(fdt, p, 0, newlen)))
return err;
fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + 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 *allocated)
{
char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);
const char *p;
@@ -157,16 +132,22 @@ static int _fdt_find_add_string(void *fdt, const char *s)
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_(strtab, fdt_size_dt_strings(fdt), s);
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, len);
if (err)
return err;
+ if (!can_assume(NO_ROLLBACK))
+ *allocated = 1;
+
memcpy(new, s, len);
return (new - strtab);
}
@@ -176,10 +157,10 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size)
struct fdt_reserve_entry *re;
int err;
- FDT_RW_CHECK_HEADER(fdt);
+ FDT_RW_PROBE(fdt);
- re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt));
- err = _fdt_splice_mem_rsv(fdt, re, 0, 1);
+ re = fdt_mem_rsv_w_(fdt, fdt_num_mem_rsv(fdt));
+ err = fdt_splice_mem_rsv_(fdt, re, 0, 1);
if (err)
return err;
@@ -190,17 +171,17 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size)
int fdt_del_mem_rsv(void *fdt, int n)
{
- struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n);
+ struct fdt_reserve_entry *re = fdt_mem_rsv_w_(fdt, n);
- FDT_RW_CHECK_HEADER(fdt);
+ FDT_RW_PROBE(fdt);
if (n >= fdt_num_mem_rsv(fdt))
return -FDT_ERR_NOTFOUND;
- return _fdt_splice_mem_rsv(fdt, re, 1, 0);
+ 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 len, struct fdt_property **prop)
{
int oldlen;
@@ -210,7 +191,7 @@ static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name,
if (!*prop)
return oldlen;
- if ((err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen),
+ if ((err = fdt_splice_struct_(fdt, (*prop)->data, FDT_TAGALIGN(oldlen),
FDT_TAGALIGN(len))))
return err;
@@ -218,27 +199,32 @@ static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name,
return 0;
}
-static int _fdt_add_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 proplen;
int nextoffset;
int namestroff;
int err;
+ int allocated;
- if ((nextoffset = _fdt_check_node_offset(fdt, nodeoffset)) < 0)
+ 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, &allocated);
if (namestroff < 0)
return namestroff;
- *prop = _fdt_offset_ptr_w(fdt, nextoffset);
+ *prop = fdt_offset_ptr_w_(fdt, nextoffset);
proplen = sizeof(**prop) + FDT_TAGALIGN(len);
- err = _fdt_splice_struct(fdt, *prop, 0, proplen);
- if (err)
+ err = fdt_splice_struct_(fdt, *prop, 0, proplen);
+ 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);
@@ -252,7 +238,7 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name)
int oldlen, newlen;
int err;
- FDT_RW_CHECK_HEADER(fdt);
+ FDT_RW_PROBE(fdt);
namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen);
if (!namep)
@@ -260,7 +246,7 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name)
newlen = strlen(name);
- err = _fdt_splice_struct(fdt, namep, FDT_TAGALIGN(oldlen+1),
+ err = fdt_splice_struct_(fdt, namep, FDT_TAGALIGN(oldlen+1),
FDT_TAGALIGN(newlen+1));
if (err)
return err;
@@ -269,22 +255,36 @@ int fdt_set_name(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_placeholder(void *fdt, int nodeoffset, const char *name,
+ int len, void **prop_data)
{
struct fdt_property *prop;
int err;
- FDT_RW_CHECK_HEADER(fdt);
+ FDT_RW_PROBE(fdt);
- err = _fdt_resize_property(fdt, nodeoffset, name, len, &prop);
+ err = fdt_resize_property_(fdt, nodeoffset, name, len, &prop);
if (err == -FDT_ERR_NOTFOUND)
- err = _fdt_add_property(fdt, nodeoffset, name, len, &prop);
+ err = fdt_add_property_(fdt, nodeoffset, name, len, &prop);
+ if (err)
+ return err;
+
+ *prop_data = prop->data;
+ return 0;
+}
+
+int fdt_setprop(void *fdt, int nodeoffset, const char *name,
+ const void *val, int len)
+{
+ void *prop_data;
+ int err;
+
+ err = fdt_setprop_placeholder(fdt, nodeoffset, name, len, &prop_data);
if (err)
return err;
if (len)
- memcpy(prop->data, val, len);
+ memcpy(prop_data, val, len);
return 0;
}
@@ -294,12 +294,12 @@ int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
struct fdt_property *prop;
int err, oldlen, newlen;
- FDT_RW_CHECK_HEADER(fdt);
+ FDT_RW_PROBE(fdt);
prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
if (prop) {
newlen = len + oldlen;
- err = _fdt_splice_struct(fdt, prop->data,
+ err = fdt_splice_struct_(fdt, prop->data,
FDT_TAGALIGN(oldlen),
FDT_TAGALIGN(newlen));
if (err)
@@ -307,7 +307,7 @@ 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, len, &prop);
if (err)
return err;
memcpy(prop->data, val, len);
@@ -320,14 +320,14 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name)
struct fdt_property *prop;
int len, proplen;
- FDT_RW_CHECK_HEADER(fdt);
+ FDT_RW_PROBE(fdt);
prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
if (!prop)
return len;
proplen = sizeof(*prop) + FDT_TAGALIGN(len);
- return _fdt_splice_struct(fdt, prop, proplen, 0);
+ return fdt_splice_struct_(fdt, prop, proplen, 0);
}
int fdt_add_subnode_namelen(void *fdt, int parentoffset,
@@ -340,7 +340,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
uint32_t tag;
fdt32_t *endtag;
- FDT_RW_CHECK_HEADER(fdt);
+ FDT_RW_PROBE(fdt);
offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen);
if (offset >= 0)
@@ -355,10 +355,10 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
tag = fdt_next_tag(fdt, offset, &nextoffset);
} while ((tag == FDT_PROP) || (tag == FDT_NOP));
- nh = _fdt_offset_ptr_w(fdt, offset);
+ nh = fdt_offset_ptr_w_(fdt, offset);
nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE;
- err = _fdt_splice_struct(fdt, nh, 0, nodelen);
+ err = fdt_splice_struct_(fdt, nh, 0, nodelen);
if (err)
return err;
@@ -380,17 +380,17 @@ int fdt_del_node(void *fdt, int nodeoffset)
{
int endoffset;
- FDT_RW_CHECK_HEADER(fdt);
+ FDT_RW_PROBE(fdt);
- endoffset = _fdt_node_end_offset(fdt, nodeoffset);
+ endoffset = fdt_node_end_offset_(fdt, nodeoffset);
if (endoffset < 0)
return endoffset;
- return _fdt_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset),
+ return fdt_splice_struct_(fdt, fdt_offset_ptr_w_(fdt, nodeoffset),
endoffset - nodeoffset, 0);
}
-static void _fdt_packblocks(const char *old, char *new,
+static void fdt_packblocks_(const char *old, char *new,
int mem_rsv_size, int struct_size)
{
int mem_rsv_off, struct_off, strings_off;
@@ -421,12 +421,12 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
const char *fdtend = fdtstart + fdt_totalsize(fdt);
char *tmp;
- FDT_CHECK_HEADER(fdt);
+ FDT_RO_PROBE(fdt);
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 {
struct_size = 0;
@@ -436,7 +436,8 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
return struct_size;
}
- 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)
@@ -464,7 +465,7 @@ 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);
memmove(buf, tmp, newsize);
fdt_set_magic(buf, FDT_MAGIC);
@@ -480,12 +481,12 @@ int fdt_pack(void *fdt)
{
int mem_rsv_size;
- FDT_RW_CHECK_HEADER(fdt);
+ FDT_RW_PROBE(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_set_totalsize(fdt, _fdt_data_size(fdt));
+ fdt_packblocks_(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt));
+ fdt_set_totalsize(fdt, fdt_data_size_(fdt));
return 0;
}
diff --git a/libfdt/fdt_strerror.c b/libfdt/fdt_strerror.c
index 9677a18..768db66 100644
--- a/libfdt/fdt_strerror.c
+++ b/libfdt/fdt_strerror.c
@@ -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,6 +38,7 @@ 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),
};
#define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0]))
diff --git a/libfdt/fdt_sw.c b/libfdt/fdt_sw.c
index 2bd15e7..94ce4bb 100644
--- a/libfdt/fdt_sw.c
+++ b/libfdt/fdt_sw.c
@@ -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"
@@ -55,22 +10,88 @@
#include "libfdt_internal.h"
-static int _fdt_sw_check_header(void *fdt)
+static int fdt_sw_probe_(void *fdt)
+{
+ 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;
+}
+
+#define FDT_SW_PROBE(fdt) \
+ { \
+ int err; \
+ if ((err = fdt_sw_probe_(fdt)) != 0) \
+ return err; \
+ }
+
+/* 'memrsv' state: Initial state after fdt_create()
+ *
+ * Allowed functions:
+ * fdt_add_reservemap_entry()
+ * fdt_finish_reservemap() [moves to 'struct' state]
+ */
+static int fdt_sw_probe_memrsv_(void *fdt)
+{
+ int err = fdt_sw_probe_(fdt);
+ if (err)
+ return err;
+
+ if (!can_assume(VALID_INPUT) && fdt_off_dt_strings(fdt) != 0)
+ return -FDT_ERR_BADSTATE;
+ return 0;
+}
+
+#define FDT_SW_PROBE_MEMRSV(fdt) \
+ { \
+ int err; \
+ if ((err = fdt_sw_probe_memrsv_(fdt)) != 0) \
+ return err; \
+ }
+
+/* 'struct' state: Enter this state after fdt_finish_reservemap()
+ *
+ * Allowed functions:
+ * fdt_begin_node()
+ * fdt_end_node()
+ * fdt_property*()
+ * fdt_finish() [moves to 'complete' state]
+ */
+static int fdt_sw_probe_struct_(void *fdt)
{
- if (fdt_magic(fdt) != FDT_SW_MAGIC)
- return -FDT_ERR_BADMAGIC;
- /* FIXME: should check more details about the header state */
+ int err = fdt_sw_probe_(fdt);
+ if (err)
+ return err;
+
+ if (!can_assume(VALID_INPUT) &&
+ fdt_off_dt_strings(fdt) != fdt_totalsize(fdt))
+ return -FDT_ERR_BADSTATE;
return 0;
}
-#define FDT_SW_CHECK_HEADER(fdt) \
+#define FDT_SW_PROBE_STRUCT(fdt) \
{ \
int err; \
- if ((err = _fdt_sw_check_header(fdt)) != 0) \
+ if ((err = fdt_sw_probe_struct_(fdt)) != 0) \
return err; \
}
-static void *_fdt_grab_space(void *fdt, size_t len)
+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
+ */
+
+static void *fdt_grab_space_(void *fdt, size_t len)
{
int offset = fdt_size_dt_struct(fdt);
int spaceleft;
@@ -82,41 +103,62 @@ static void *_fdt_grab_space(void *fdt, size_t len)
return NULL;
fdt_set_size_dt_struct(fdt, offset + len);
- return _fdt_offset_ptr_w(fdt, offset);
+ 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));
void *fdt = buf;
- if (bufsize < sizeof(struct fdt_header))
+ 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, FDT_ALIGN(sizeof(struct fdt_header),
- sizeof(struct fdt_reserve_entry)));
+ fdt_set_off_mem_rsvmap(fdt, hdrsize);
fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt));
- fdt_set_off_dt_strings(fdt, bufsize);
+ fdt_set_off_dt_strings(fdt, 0);
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;
char *oldtail, *newtail;
- FDT_SW_CHECK_HEADER(fdt);
+ FDT_SW_PROBE(fdt);
- headsize = fdt_off_dt_struct(fdt);
+ headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
tailsize = fdt_size_dt_strings(fdt);
+ if (!can_assume(VALID_DTB) &&
+ headsize + tailsize > fdt_totalsize(fdt))
+ return -FDT_ERR_INTERNAL;
+
if ((headsize + tailsize) > bufsize)
return -FDT_ERR_NOSPACE;
@@ -133,8 +175,9 @@ int fdt_resize(void *fdt, void *buf, int bufsize)
memmove(buf, fdt, headsize);
}
- fdt_set_off_dt_strings(buf, bufsize);
fdt_set_totalsize(buf, bufsize);
+ if (fdt_off_dt_strings(buf))
+ fdt_set_off_dt_strings(buf, bufsize);
return 0;
}
@@ -144,10 +187,7 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)
struct fdt_reserve_entry *re;
int offset;
- FDT_SW_CHECK_HEADER(fdt);
-
- if (fdt_size_dt_struct(fdt))
- return -FDT_ERR_BADSTATE;
+ FDT_SW_PROBE_MEMRSV(fdt);
offset = fdt_off_dt_struct(fdt);
if ((offset + sizeof(*re)) > fdt_totalsize(fdt))
@@ -164,17 +204,24 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)
int fdt_finish_reservemap(void *fdt)
{
- return fdt_add_reservemap_entry(fdt, 0, 0);
+ int err = fdt_add_reservemap_entry(fdt, 0, 0);
+
+ if (err)
+ return err;
+
+ fdt_set_off_dt_strings(fdt, fdt_totalsize(fdt));
+ return 0;
}
int fdt_begin_node(void *fdt, const char *name)
{
struct fdt_node_header *nh;
- int namelen = strlen(name) + 1;
+ int namelen;
- FDT_SW_CHECK_HEADER(fdt);
+ FDT_SW_PROBE_STRUCT(fdt);
- nh = _fdt_grab_space(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen));
+ namelen = strlen(name) + 1;
+ nh = fdt_grab_space_(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen));
if (! nh)
return -FDT_ERR_NOSPACE;
@@ -187,9 +234,9 @@ int fdt_end_node(void *fdt)
{
fdt32_t *en;
- FDT_SW_CHECK_HEADER(fdt);
+ FDT_SW_PROBE_STRUCT(fdt);
- en = _fdt_grab_space(fdt, FDT_TAGSIZE);
+ en = fdt_grab_space_(fdt, FDT_TAGSIZE);
if (! en)
return -FDT_ERR_NOSPACE;
@@ -197,19 +244,13 @@ 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;
int strtabsize = fdt_size_dt_strings(fdt);
int len = strlen(s) + 1;
int struct_top, offset;
- 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)
@@ -220,20 +261,56 @@ static int _fdt_find_add_string(void *fdt, const char *s)
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;
+
+ 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;
+
+ *allocated = 1;
+
+ 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_CHECK_HEADER(fdt);
+ 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)
+ prop = fdt_grab_space_(fdt, sizeof(*prop) + FDT_TAGALIGN(len));
+ 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);
@@ -262,10 +339,10 @@ int fdt_finish(void *fdt)
uint32_t tag;
int offset, nextoffset;
- FDT_SW_CHECK_HEADER(fdt);
+ FDT_SW_PROBE_STRUCT(fdt);
/* Add terminator */
- end = _fdt_grab_space(fdt, sizeof(*end));
+ end = fdt_grab_space_(fdt, sizeof(*end));
if (! end)
return -FDT_ERR_NOSPACE;
*end = cpu_to_fdt32(FDT_END);
@@ -281,7 +358,7 @@ int fdt_finish(void *fdt)
while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) {
if (tag == FDT_PROP) {
struct fdt_property *prop =
- _fdt_offset_ptr_w(fdt, offset);
+ fdt_offset_ptr_w_(fdt, offset);
int nameoff;
nameoff = fdt32_to_cpu(prop->nameoff);
@@ -295,6 +372,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_FIRST_SUPPORTED_VERSION);
fdt_set_magic(fdt, FDT_MAGIC);
+
return 0;
}
diff --git a/libfdt/fdt_wip.c b/libfdt/fdt_wip.c
index 5e85919..f64139e 100644
--- a/libfdt/fdt_wip.c
+++ b/libfdt/fdt_wip.c
@@ -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"
@@ -93,7 +48,7 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
val, len);
}
-static void _fdt_nop_region(void *start, int len)
+static void fdt_nop_region_(void *start, int len)
{
fdt32_t *p;
@@ -110,12 +65,12 @@ int fdt_nop_property(void *fdt, int nodeoffset, const char *name)
if (!prop)
return len;
- _fdt_nop_region(prop, len + sizeof(*prop));
+ fdt_nop_region_(prop, len + sizeof(*prop));
return 0;
}
-int _fdt_node_end_offset(void *fdt, int offset)
+int fdt_node_end_offset_(void *fdt, int offset)
{
int depth = 0;
@@ -129,11 +84,11 @@ int fdt_nop_node(void *fdt, int nodeoffset)
{
int endoffset;
- endoffset = _fdt_node_end_offset(fdt, nodeoffset);
+ endoffset = fdt_node_end_offset_(fdt, nodeoffset);
if (endoffset < 0)
return endoffset;
- _fdt_nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0),
+ fdt_nop_region_(fdt_offset_ptr_w(fdt, nodeoffset, 0),
endoffset - nodeoffset);
return 0;
}
diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h
index a248b1b..544d3ef 100644
--- a/libfdt/libfdt.h
+++ b/libfdt/libfdt.h
@@ -1,60 +1,19 @@
-#ifndef _LIBFDT_H
-#define _LIBFDT_H
+/* 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>
-#define FDT_FIRST_SUPPORTED_VERSION 0x10
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define FDT_FIRST_SUPPORTED_VERSION 0x02
#define FDT_LAST_SUPPORTED_VERSION 0x11
/* Error codes: informative error codes */
@@ -90,8 +49,9 @@
/* Error codes: codes for bad device tree blobs */
#define FDT_ERR_TRUNCATED 8
- /* FDT_ERR_TRUNCATED: Structure block of the given device tree
- * ends without an FDT_END tag. */
+ /* FDT_ERR_TRUNCATED: FDT or a sub-block is improperly
+ * terminated (overflows, goes outside allowed bounds, or
+ * isn't properly terminated). */
#define FDT_ERR_BADMAGIC 9
/* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a
* device tree at all - it is missing the flattened device
@@ -137,7 +97,15 @@
/* 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_MAX 18
+
+/* 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) */
@@ -153,6 +121,61 @@ 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
+ */
+
+static inline uint32_t fdt32_ld(const fdt32_t *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 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;
+
+ 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];
+}
+
+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 */
/**********************************************************************/
@@ -195,7 +218,7 @@ int fdt_next_subnode(const void *fdt, int offset);
* ...
* }
*
- * if ((node < 0) && (node != -FDT_ERR_NOT_FOUND)) {
+ * if ((node < 0) && (node != -FDT_ERR_NOTFOUND)) {
* Error handling
* }
*
@@ -213,7 +236,7 @@ int fdt_next_subnode(const void *fdt, int offset);
/* General functions */
/**********************************************************************/
#define fdt_get_header(fdt, field) \
- (fdt32_to_cpu(((const struct fdt_header *)(fdt))->field))
+ (fdt32_ld(&((const struct fdt_header *)(fdt))->field))
#define fdt_magic(fdt) (fdt_get_header(fdt, magic))
#define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize))
#define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct))
@@ -225,37 +248,51 @@ int fdt_next_subnode(const void *fdt, int offset);
#define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings))
#define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct))
-#define __fdt_set_hdr(name) \
+#define fdt_set_hdr_(name) \
static inline void fdt_set_##name(void *fdt, uint32_t val) \
{ \
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);
-#undef __fdt_set_hdr
-
-/**
- * fdt_check_header - sanity check a device tree or possible device tree
+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
+ */
+size_t fdt_header_size(const void *fdt);
+
+/**
+ * fdt_header_size_ - internal function which takes a version number
+ */
+size_t fdt_header_size_(uint32_t version);
+
+/**
+ * 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
- * appears to be a flattened device tree with sane information in its
- * header.
+ * appears to be a flattened device tree, and that the header contains
+ * valid information (to the extent that can be determined from the
+ * header alone).
*
* returns:
* 0, if the buffer appears to contain a valid device tree
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
- * -FDT_ERR_BADSTATE, standard meanings, as above
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_TRUNCATED, standard meanings, as above
*/
int fdt_check_header(const void *fdt);
@@ -284,6 +321,24 @@ int fdt_move(const void *fdt, void *buf, int bufsize);
/* Read-only functions */
/**********************************************************************/
+int fdt_check_full(const void *fdt, size_t bufsize);
+
+/**
+ * fdt_get_string - retrieve a string from the strings block of a device tree
+ * @fdt: pointer to the device tree blob
+ * @stroffset: offset of the string within the strings block (native endian)
+ * @lenp: optional pointer to return the string's length
+ *
+ * fdt_get_string() retrieves a pointer to a single string from the
+ * strings block of the device tree blob at fdt, and optionally also
+ * returns the string's length in *lenp.
+ *
+ * returns:
+ * a pointer to the string, on success
+ * NULL, if stroffset is out of bounds, or doesn't point to a valid string
+ */
+const char *fdt_get_string(const void *fdt, int stroffset, int *lenp);
+
/**
* fdt_string - retrieve a string from the strings block of a device tree
* @fdt: pointer to the device tree blob
@@ -294,11 +349,25 @@ int fdt_move(const void *fdt, void *buf, int bufsize);
*
* returns:
* a pointer to the string, on success
- * NULL, if stroffset is out of bounds
+ * NULL, if stroffset is out of bounds, or doesn't point to a valid string
*/
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
*
@@ -306,12 +375,39 @@ 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.
+ *
+ * Returns:
+ * 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
@@ -503,7 +599,7 @@ int fdt_next_property_offset(const void *fdt, int offset);
* ...
* }
*
- * if ((property < 0) && (property != -FDT_ERR_NOT_FOUND)) {
+ * if ((property < 0) && (property != -FDT_ERR_NOTFOUND)) {
* Error handling
* }
*
@@ -527,6 +623,9 @@ int fdt_next_property_offset(const void *fdt, int offset);
* offset. If lenp is non-NULL, the length of the property value is
* also returned, in the integer pointed to by lenp.
*
+ * Note that this code only works on device tree versions >= 16. fdt_getprop()
+ * works on all versions.
+ *
* returns:
* pointer to the structure representing the property
* if lenp is non-NULL, *lenp contains the length of the property
@@ -603,7 +702,7 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
/**
* fdt_getprop_by_offset - retrieve the value of a property at a given offset
* @fdt: pointer to the device tree blob
- * @ffset: offset of the property to read
+ * @offset: offset of the property to read
* @namep: pointer to a string variable (will be overwritten) or NULL
* @lenp: pointer to an integer variable (will be overwritten) or NULL
*
@@ -1087,7 +1186,7 @@ int fdt_address_cells(const void *fdt, int nodeoffset);
*
* returns:
* 0 <= n < FDT_MAX_NCELLS, on success
- * 2, if the node has no #address-cells property
+ * 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,
@@ -1294,7 +1393,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
+ * @fdt: 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_finished() 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
+ * @fdt: 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);
@@ -1310,10 +1447,13 @@ static inline int fdt_property_u64(void *fdt, const char *name, uint64_t val)
fdt64_t tmp = cpu_to_fdt64(val);
return fdt_property(fdt, name, &tmp, sizeof(tmp));
}
+
+#ifndef SWIG /* Not available in Python */
static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
{
return fdt_property_u32(fdt, name, val);
}
+#endif
/**
* fdt_property_placeholder - add a new property and return a ptr to its value
@@ -1449,6 +1589,37 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,
const void *val, int len);
/**
+ * 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_placeholer() 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
+ */
+int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name,
+ int len, void **prop_data);
+
+/**
* fdt_setprop_u32 - set a property to a 32-bit integer
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose property to change
@@ -1732,6 +1903,43 @@ static inline int fdt_appendprop_cell(void *fdt, int nodeoffset,
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.
+ * If "name" is not specified, a default "reg" is used.
+ * 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
@@ -1865,4 +2073,8 @@ int fdt_overlay_apply(void *fdt, void *fdto);
const char *fdt_strerror(int errval);
-#endif /* _LIBFDT_H */
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LIBFDT_H */
diff --git a/libfdt/libfdt_env.h b/libfdt/libfdt_env.h
index 952056c..73b6d40 100644
--- a/libfdt/libfdt_env.h
+++ b/libfdt/libfdt_env.h
@@ -1,61 +1,18 @@
-#ifndef _LIBFDT_ENV_H
-#define _LIBFDT_ENV_H
+/* 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>
#include <string.h>
+#include <limits.h>
#ifdef __CHECKER__
#define FDT_FORCE __attribute__((force))
@@ -109,4 +66,31 @@ static inline fdt64_t cpu_to_fdt64(uint64_t x)
#undef CPU_TO_FDT16
#undef EXTRACT_BYTE
-#endif /* _LIBFDT_ENV_H */
+#ifdef __APPLE__
+#include <AvailabilityMacros.h>
+
+/* strnlen() is not available on Mac OS < 10.7 */
+# if !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED < \
+ MAC_OS_X_VERSION_10_7)
+
+#define strnlen fdt_strnlen
+
+/*
+ * fdt_strnlen: returns the length of a string or max_count - which ever is
+ * smallest.
+ * Input 1 string: the string whose size is to be determined
+ * Input 2 max_count: the maximum value returned by this function
+ * Output: length of the string or max_count (the smallest of the two)
+ */
+static inline size_t fdt_strnlen(const char *string, size_t max_count)
+{
+ const char *p = memchr(string, 0, max_count);
+ return p ? p - string : max_count;
+}
+
+#endif /* !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED <
+ MAC_OS_X_VERSION_10_7) */
+
+#endif /* __APPLE__ */
+
+#endif /* LIBFDT_ENV_H */
diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h
index 02cfa6f..d4e0bd4 100644
--- a/libfdt/libfdt_internal.h
+++ b/libfdt/libfdt_internal.h
@@ -1,83 +1,39 @@
-#ifndef _LIBFDT_INTERNAL_H
-#define _LIBFDT_INTERNAL_H
+/* 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>
#define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
#define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE))
-#define FDT_CHECK_HEADER(fdt) \
- { \
- int __err; \
- if ((__err = fdt_check_header(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);
-int _fdt_node_end_offset(void *fdt, int nodeoffset);
+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);
+int fdt_node_end_offset_(void *fdt, int nodeoffset);
-static inline const void *_fdt_offset_ptr(const void *fdt, int offset)
+static inline const void *fdt_offset_ptr_(const void *fdt, int offset)
{
return (const char *)fdt + fdt_off_dt_struct(fdt) + offset;
}
-static inline void *_fdt_offset_ptr_w(void *fdt, int offset)
+static inline void *fdt_offset_ptr_w_(void *fdt, int offset)
{
- return (void *)(uintptr_t)_fdt_offset_ptr(fdt, offset);
+ return (void *)(uintptr_t)fdt_offset_ptr_(fdt, offset);
}
-static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int n)
+static inline const struct fdt_reserve_entry *fdt_mem_rsv_(const void *fdt, int n)
{
const struct fdt_reserve_entry *rsv_table =
(const struct fdt_reserve_entry *)
@@ -85,11 +41,133 @@ static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int
return rsv_table + n;
}
-static inline struct fdt_reserve_entry *_fdt_mem_rsv_w(void *fdt, int n)
+static inline struct fdt_reserve_entry *fdt_mem_rsv_w_(void *fdt, int n)
{
- return (void *)(uintptr_t)_fdt_mem_rsv(fdt, n);
+ return (void *)(uintptr_t)fdt_mem_rsv_(fdt, n);
}
#define FDT_SW_MAGIC (~FDT_MAGIC)
-#endif /* _LIBFDT_INTERNAL_H */
+/**********************************************************************/
+/* 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 */
diff --git a/libfdt/version.lds b/libfdt/version.lds
index cff0358..7ab85f1 100644
--- a/libfdt/version.lds
+++ b/libfdt/version.lds
@@ -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;
@@ -60,9 +62,21 @@ LIBFDT_1.2 {
fdt_address_cells;
fdt_size_cells;
fdt_stringlist_contains;
+ fdt_stringlist_count;
+ fdt_stringlist_search;
+ fdt_stringlist_get;
fdt_resize;
fdt_overlay_apply;
-
+ fdt_get_string;
+ fdt_find_max_phandle;
+ fdt_generate_phandle;
+ fdt_check_full;
+ fdt_setprop_placeholder;
+ fdt_property_placeholder;
+ fdt_header_size_;
+ fdt_appendprop_addrrange;
+ fdt_setprop_inplace_namelen_partial;
+ fdt_create_with_flags;
local:
*;
};
diff --git a/livetree.c b/livetree.c
index a5d5676..032df58 100644
--- a/livetree.c
+++ b/livetree.c
@@ -1,24 +1,10 @@
+// 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"
+#include "srcpos.h"
/*
* Tree building functions
@@ -50,7 +36,8 @@ void delete_labels(struct label **labels)
label->deleted = 1;
}
-struct property *build_property(char *name, struct data val)
+struct property *build_property(char *name, struct data val,
+ struct srcpos *srcpos)
{
struct property *new = xmalloc(sizeof(*new));
@@ -58,6 +45,7 @@ struct property *build_property(char *name, struct data val)
new->name = name;
new->val = val;
+ new->srcpos = srcpos_copy(srcpos);
return new;
}
@@ -97,7 +85,8 @@ struct property *reverse_properties(struct property *first)
return head;
}
-struct node *build_node(struct property *proplist, struct node *children)
+struct node *build_node(struct property *proplist, struct node *children,
+ struct srcpos *srcpos)
{
struct node *new = xmalloc(sizeof(*new));
struct node *child;
@@ -106,6 +95,7 @@ struct node *build_node(struct property *proplist, struct node *children)
new->proplist = reverse_properties(proplist);
new->children = children;
+ new->srcpos = srcpos_copy(srcpos);
for_each_child(new, child) {
child->parent = new;
@@ -114,13 +104,14 @@ struct node *build_node(struct property *proplist, struct node *children)
return new;
}
-struct node *build_node_delete(void)
+struct node *build_node_delete(struct srcpos *srcpos)
{
struct node *new = xmalloc(sizeof(*new));
memset(new, 0, sizeof(*new));
new->deleted = 1;
+ new->srcpos = srcpos_copy(srcpos);
return new;
}
@@ -134,6 +125,20 @@ struct node *name_node(struct node *node, char *name)
return node;
}
+struct node *omit_node_if_unused(struct node *node)
+{
+ node->omit_if_unused = 1;
+
+ return node;
+}
+
+struct node *reference_node(struct node *node)
+{
+ node->is_referenced = 1;
+
+ return node;
+}
+
struct node *merge_nodes(struct node *old_node, struct node *new_node)
{
struct property *new_prop, *old_prop;
@@ -169,6 +174,8 @@ 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);
+ old_prop->srcpos = new_prop->srcpos;
free(new_prop);
new_prop = NULL;
break;
@@ -209,6 +216,8 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
add_child(old_node, new_child);
}
+ old_node->srcpos = srcpos_extend(old_node->srcpos, new_node->srcpos);
+
/* The new node contents are now merged into the old node. Free
* the new node. */
free(new_node);
@@ -216,7 +225,7 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
return old_node;
}
-void add_orphan_node(struct node *dt, struct node *new_node, char *ref)
+struct node * add_orphan_node(struct node *dt, struct node *new_node, char *ref)
{
static unsigned int next_orphan_fragment = 0;
struct node *node;
@@ -224,18 +233,26 @@ void add_orphan_node(struct node *dt, struct node *new_node, char *ref)
struct data d = empty_data;
char *name;
- d = data_add_marker(d, REF_PHANDLE, ref);
- d = data_append_integer(d, 0xffffffff, 32);
+ if (ref[0] == '/') {
+ d = data_add_marker(d, TYPE_STRING, ref);
+ d = data_append_data(d, ref, strlen(ref) + 1);
- p = build_property("target", d);
+ p = build_property("target-path", d, NULL);
+ } else {
+ d = data_add_marker(d, REF_PHANDLE, ref);
+ d = data_append_integer(d, 0xffffffff, 32);
+
+ p = build_property("target", d, NULL);
+ }
xasprintf(&name, "fragment@%u",
next_orphan_fragment++);
name_node(new_node, "__overlay__");
- node = build_node(p, new_node);
+ node = build_node(p, new_node, NULL);
name_node(node, name);
add_child(dt, node);
+ return dt;
}
struct node *chain_node(struct node *first, struct node *list)
@@ -319,18 +336,21 @@ 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);
- p = build_property(name, d);
+ 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);
}
}
@@ -418,6 +438,12 @@ 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)
+{
+ assert(prop->val.len / sizeof(cell_t) >= n);
+ return fdt32_to_cpu(*((fdt32_t *)prop->val.val + n));
+}
+
struct property *get_property_by_label(struct node *tree, const char *label,
struct node **node)
{
@@ -500,8 +526,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) &&
- strneq(path, child->name, p-path))
+ if (p && strprefixeq(path, p - path, child->name))
return get_node_by_path(child, p+1);
else if (!p && streq(path, child->name))
return child;
@@ -534,7 +559,10 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
{
struct node *child, *node;
- assert((phandle != 0) && (phandle != -1));
+ if ((phandle == 0) || (phandle == -1)) {
+ assert(generate_fixups);
+ return NULL;
+ }
if (tree->phandle == phandle) {
if (tree->deleted)
@@ -564,6 +592,7 @@ struct node *get_node_by_ref(struct node *tree, const char *ref)
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))
return node->phandle;
@@ -573,17 +602,16 @@ 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",
- data_append_cell(empty_data, phandle)));
+ add_property(node, build_property("linux,phandle", d, NULL));
if (!get_property(node, "phandle")
&& (phandle_format & PHANDLE_EPAPR))
- add_property(node,
- build_property("phandle",
- data_append_cell(empty_data, phandle)));
+ add_property(node, build_property("phandle", d, NULL));
/* If the node *does* have a phandle property, we must
* be dealing with a self-referencing phandle, which will be
@@ -757,7 +785,7 @@ static struct node *build_and_name_child_node(struct node *parent, char *name)
{
struct node *node;
- node = build_node(NULL, NULL);
+ node = build_node(NULL, NULL, NULL);
name_node(node, xstrdup(name));
add_child(parent, node);
@@ -818,8 +846,9 @@ 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);
}
@@ -869,7 +898,7 @@ static void add_fixup_entry(struct dt_info *dti, struct node *fn,
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);
}
@@ -929,7 +958,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++;
@@ -952,7 +981,7 @@ static void add_local_fixup_entry(struct dt_info *dti,
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,
diff --git a/pylibfdt/.gitignore b/pylibfdt/.gitignore
index 5e8c5e3..f63a8f1 100644
--- a/pylibfdt/.gitignore
+++ b/pylibfdt/.gitignore
@@ -1,3 +1,3 @@
libfdt.py
-libfdt.pyc
+*.pyc
libfdt_wrap.c
diff --git a/pylibfdt/Makefile.pylibfdt b/pylibfdt/Makefile.pylibfdt
index 9507d3d..6866a0b 100644
--- a/pylibfdt/Makefile.pylibfdt
+++ b/pylibfdt/Makefile.pylibfdt
@@ -1,24 +1,30 @@
+# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
# Makefile.pylibfdt
#
-PYLIBFDT_srcs = $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_SRCS)) \
- $(PYLIBFDT_srcdir)/libfdt.i
-PYMODULE = $(PYLIBFDT_objdir)/_libfdt.so
+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)/%)
-define run_setup
- SOURCES="$(1)" CPPFLAGS="$(CPPFLAGS)" OBJDIR="$(PYLIBFDT_objdir)"
- VERSION="$(dtc_version)"
- $(PYLIBFDT_objdir)/setup.py --quiet $(2)
-endef
+SETUP = $(PYLIBFDT_dir)/setup.py
+SETUPFLAGS =
-$(PYMODULE): $(PYLIBFDT_srcs)
+ifndef V
+SETUPFLAGS += --quiet
+endif
+
+$(PYMODULE): $(PYLIBFDT_srcs) $(LIBFDT_archive) $(SETUP) $(VERSION_FILE)
@$(VECHO) PYMOD $@
- $(call run_setup, $^, build_ext --inplace)
- mv _libfdt.so $@
+ $(PYTHON) $(SETUP) $(SETUPFLAGS) build_ext --build-lib=../$(PYLIBFDT_dir)
install_pylibfdt: $(PYMODULE)
- $(VECHO) INSTALL-PYLIB; \
- $(call run_setup, $(PYLIBFDT_srcs), \
- install $(if $(SETUP_PREFIX),--prefix=$(SETUP_PREFIX)))
+ @$(VECHO) INSTALL-PYLIB
+ $(PYTHON) $(SETUP) $(SETUPFLAGS) install --prefix=$(PREFIX)
-PYLIBFDT_cleanfiles = libfdt_wrap.c libfdt.py libfdt.pyc _libfdt.so
+pylibfdt_clean:
+ @$(VECHO) CLEAN "(pylibfdt)"
+ rm -f $(PYLIBFDT_CLEANFILES)
+ rm -rf $(PYLIBFDT_CLEANDIRS)
diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i
index cd1c6a9..3e09d3a 100644
--- a/pylibfdt/libfdt.i
+++ b/pylibfdt/libfdt.i
@@ -1,60 +1,29 @@
+// 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
+%include <stdint.i>
+
%{
#define SWIG_FILE_WITH_INIT
#include "libfdt.h"
+
+/*
+ * We rename this function here to avoid problems with swig, since we also have
+ * 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 void *val,
+ int len)
+{
+ return fdt_property(fdt, name, val, len);
+}
+
%}
%pythoncode %{
@@ -86,6 +55,7 @@ import struct
# Pass this as the 'quiet' parameter to return -ENOTFOUND on NOTFOUND errors,
# instead of raising an exception.
QUIET_NOTFOUND = (NOTFOUND,)
+QUIET_NOSPACE = (NOSPACE,)
class FdtException(Exception):
@@ -122,7 +92,7 @@ def check_err(val, quiet=()):
Raises
FdtException if val < 0
"""
- if val < 0:
+ if isinstance(val, int) and val < 0:
if -val not in quiet:
raise FdtException(val)
return val
@@ -151,27 +121,199 @@ def check_err_null(val, quiet=()):
raise FdtException(val)
return val
-class Fdt:
- """Device tree class, supporting all operations
-
- The Fdt object is created is created from a device tree binary file,
- e.g. with something like:
+class FdtRo(object):
+ """Class for a read-only device-tree
- fdt = Fdt(open("filename.dtb").read())
+ This is a base class used by FdtRw (read-write access) and FdtSw
+ (sequential-write access). It implements read-only access to the
+ device tree.
- Operations can then be performed using the methods in this class. Each
- method xxx(args...) corresponds to a libfdt function fdt_xxx(fdt, args...).
+ Here are the three classes and when you should use them:
- All methods raise an FdtException if an error occurs. To avoid this
- behaviour a 'quiet' parameter is provided for some functions. This
- defaults to empty, but you can pass a list of errors that you expect.
- If one of these errors occurs, the function will return an error number
- (e.g. -NOTFOUND).
+ FdtRo - read-only access to an existing FDT
+ FdtRw - read-write access to an existing FDT (most common case)
+ FdtSw - for creating a new FDT, as well as allowing read-only access
"""
def __init__(self, data):
self._fdt = bytearray(data)
check_err(fdt_check_header(self._fdt));
+ def as_bytearray(self):
+ """Get the device tree contents as a bytearray
+
+ This can be passed directly to libfdt functions that access a
+ const void * for the device tree.
+
+ Returns:
+ bytearray containing the device tree
+ """
+ return bytearray(self._fdt)
+
+ def next_node(self, nodeoffset, depth, quiet=()):
+ """Find the next subnode
+
+ Args:
+ nodeoffset: Node offset of previous node
+ depth: The depth of the node at nodeoffset. This is used to
+ calculate the depth of the returned node
+ quiet: Errors to ignore (empty to raise on all errors)
+
+ Returns:
+ Typle:
+ Offset of the next node, if any, else a -ve error
+ Depth of the returned node, if any, else undefined
+
+ Raises:
+ FdtException if no more nodes found or other error occurs
+ """
+ return check_err(fdt_next_node(self._fdt, nodeoffset, depth), quiet)
+
+ def first_subnode(self, nodeoffset, quiet=()):
+ """Find the first subnode of a parent node
+
+ Args:
+ nodeoffset: Node offset of parent node
+ quiet: Errors to ignore (empty to raise on all errors)
+
+ Returns:
+ The offset of the first subnode, if any
+
+ Raises:
+ FdtException if no subnodes found or other error occurs
+ """
+ return check_err(fdt_first_subnode(self._fdt, nodeoffset), quiet)
+
+ def next_subnode(self, nodeoffset, quiet=()):
+ """Find the next subnode
+
+ Args:
+ nodeoffset: Node offset of previous subnode
+ quiet: Errors to ignore (empty to raise on all errors)
+
+ Returns:
+ The offset of the next subnode, if any
+
+ Raises:
+ FdtException if no more subnodes found or other error occurs
+ """
+ return check_err(fdt_next_subnode(self._fdt, nodeoffset), quiet)
+
+ def magic(self):
+ """Return the magic word from the header
+
+ Returns:
+ Magic word
+ """
+ return fdt_magic(self._fdt)
+
+ def totalsize(self):
+ """Return the total size of the device tree
+
+ Returns:
+ Total tree size in bytes
+ """
+ return fdt_totalsize(self._fdt)
+
+ def off_dt_struct(self):
+ """Return the start of the device-tree struct area
+
+ Returns:
+ Start offset of struct area
+ """
+ return fdt_off_dt_struct(self._fdt)
+
+ def off_dt_strings(self):
+ """Return the start of the device-tree string area
+
+ Returns:
+ Start offset of string area
+ """
+ return fdt_off_dt_strings(self._fdt)
+
+ def off_mem_rsvmap(self):
+ """Return the start of the memory reserve map
+
+ Returns:
+ Start offset of memory reserve map
+ """
+ return fdt_off_mem_rsvmap(self._fdt)
+
+ def version(self):
+ """Return the version of the device tree
+
+ Returns:
+ Version number of the device tree
+ """
+ return fdt_version(self._fdt)
+
+ def last_comp_version(self):
+ """Return the last compatible version of the device tree
+
+ Returns:
+ Last compatible version number of the device tree
+ """
+ return fdt_last_comp_version(self._fdt)
+
+ def boot_cpuid_phys(self):
+ """Return the physical boot CPU ID
+
+ Returns:
+ Physical boot CPU ID
+ """
+ return fdt_boot_cpuid_phys(self._fdt)
+
+ def size_dt_strings(self):
+ """Return the start of the device-tree string area
+
+ Returns:
+ Start offset of string area
+ """
+ return fdt_size_dt_strings(self._fdt)
+
+ def size_dt_struct(self):
+ """Return the start of the device-tree struct area
+
+ Returns:
+ Start offset of struct area
+ """
+ return fdt_size_dt_struct(self._fdt)
+
+ def num_mem_rsv(self, quiet=()):
+ """Return the number of memory reserve-map records
+
+ Returns:
+ Number of memory reserve-map records
+ """
+ return check_err(fdt_num_mem_rsv(self._fdt), quiet)
+
+ def get_mem_rsv(self, index, quiet=()):
+ """Return the indexed memory reserve-map record
+
+ Args:
+ index: Record to return (0=first)
+
+ Returns:
+ Number of memory reserve-map records
+ """
+ return check_err(fdt_get_mem_rsv(self._fdt, index), quiet)
+
+ def subnode_offset(self, parentoffset, name, quiet=()):
+ """Get the offset of a named subnode
+
+ Args:
+ parentoffset: Offset of the parent node to check
+ name: Name of the required subnode, e.g. 'subnode@1'
+ quiet: Errors to ignore (empty to raise on all errors)
+
+ Returns:
+ The node offset of the found node, if any
+
+ Raises
+ FdtException if there is no node with that name, or other error
+ """
+ return check_err(fdt_subnode_offset(self._fdt, parentoffset, name),
+ quiet)
+
def path_offset(self, path, quiet=()):
"""Get the offset for a given path
@@ -187,6 +329,20 @@ class Fdt:
"""
return check_err(fdt_path_offset(self._fdt, path), quiet)
+ def get_name(self, nodeoffset):
+ """Get the name of a node
+
+ Args:
+ nodeoffset: Offset of node to check
+
+ Returns:
+ Node name
+
+ Raises:
+ FdtException on error (e.g. nodeoffset is invalid)
+ """
+ return check_err_null(fdt_get_name(self._fdt, nodeoffset))[0]
+
def first_property_offset(self, nodeoffset, quiet=()):
"""Get the offset of the first property in a node offset
@@ -221,20 +377,6 @@ class Fdt:
return check_err(fdt_next_property_offset(self._fdt, prop_offset),
quiet)
- def get_name(self, nodeoffset):
- """Get the name of a node
-
- Args:
- nodeoffset: Offset of node to check
-
- Returns:
- Node name
-
- Raises:
- FdtException on error (e.g. nodeoffset is invalid)
- """
- return check_err_null(fdt_get_name(self._fdt, nodeoffset))[0]
-
def get_property_by_offset(self, prop_offset, quiet=()):
"""Obtains a property that can be examined
@@ -255,51 +397,135 @@ class Fdt:
return pdata
return Property(pdata[0], pdata[1])
- def first_subnode(self, nodeoffset, quiet=()):
- """Find the first subnode of a parent node
+ def getprop(self, nodeoffset, prop_name, quiet=()):
+ """Get a property from a node
Args:
- nodeoffset: Node offset of parent node
+ nodeoffset: Node offset containing property to get
+ prop_name: Name of property to get
quiet: Errors to ignore (empty to raise on all errors)
Returns:
- The offset of the first subnode, if any
+ Value of property as a Property object (which can be used as a
+ bytearray/string), or -ve error number. On failure, returns an
+ integer error
Raises:
- FdtException if no subnode found or other error occurs
+ FdtError if any error occurs (e.g. the property is not found)
"""
- return check_err(fdt_first_subnode(self._fdt, nodeoffset), quiet)
+ pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name),
+ quiet)
+ if isinstance(pdata, (int)):
+ return pdata
+ return Property(prop_name, bytearray(pdata[0]))
- def next_subnode(self, nodeoffset, quiet=()):
- """Find the next subnode
+ def get_phandle(self, nodeoffset):
+ """Get the phandle of a node
Args:
- nodeoffset: Node offset of previous subnode
+ nodeoffset: Node offset to check
+
+ Returns:
+ phandle of node, or 0 if the node has no phandle or another error
+ occurs
+ """
+ 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 parent_offset(self, nodeoffset, quiet=()):
+ """Get the offset of a node's parent
+
+ Args:
+ nodeoffset: Node offset to check
quiet: Errors to ignore (empty to raise on all errors)
Returns:
- The offset of the next subnode, if any
+ The offset of the parent node, if any
Raises:
- FdtException if no more subnode found or other error occurs
+ FdtException if no parent found or other error occurs
"""
- return check_err(fdt_next_subnode(self._fdt, nodeoffset), quiet)
+ return check_err(fdt_parent_offset(self._fdt, nodeoffset), quiet)
- def totalsize(self):
- """Return the total size of the device tree
+ def node_offset_by_phandle(self, phandle, quiet=()):
+ """Get the offset of a node with the given phandle
+
+ Args:
+ phandle: Phandle to search for
+ quiet: Errors to ignore (empty to raise on all errors)
Returns:
- Total tree size in bytes
+ The offset of node with that phandle, if any
+
+ Raises:
+ FdtException if no node found or other error occurs
"""
- return check_err(fdt_totalsize(self._fdt))
+ return check_err(fdt_node_offset_by_phandle(self._fdt, phandle), quiet)
- def off_dt_struct(self):
- """Return the start of the device tree struct area
+
+class Fdt(FdtRo):
+ """Device tree class, supporting all operations
+
+ The Fdt object is created is created from a device tree binary file,
+ e.g. with something like:
+
+ fdt = Fdt(open("filename.dtb").read())
+
+ Operations can then be performed using the methods in this class. Each
+ method xxx(args...) corresponds to a libfdt function fdt_xxx(fdt, args...).
+
+ All methods raise an FdtException if an error occurs. To avoid this
+ behaviour a 'quiet' parameter is provided for some functions. This
+ defaults to empty, but you can pass a list of errors that you expect.
+ If one of these errors occurs, the function will return an error number
+ (e.g. -NOTFOUND).
+ """
+ def __init__(self, data):
+ FdtRo.__init__(self, data)
+
+ @staticmethod
+ def create_empty_tree(size, quiet=()):
+ """Create an empty device tree ready for use
+
+ Args:
+ size: Size of device tree in bytes
Returns:
- Start offset of struct area
+ Fdt object containing the device tree
+ """
+ data = bytearray(size)
+ err = check_err(fdt_create_empty_tree(data, size), quiet)
+ if err:
+ return err
+ return Fdt(data)
+
+ def resize(self, size, quiet=()):
+ """Move the device tree into a larger or smaller space
+
+ This creates a new device tree of size @size and moves the existing
+ device tree contents over to that. It can be used to create more space
+ in a device tree. Note that the Fdt object remains the same, but it
+ now has a new bytearray holding the contents.
+
+ Args:
+ size: Required new size of device tree in bytes
"""
- return check_err(fdt_off_dt_struct(self._fdt))
+ fdt = bytearray(size)
+ err = check_err(fdt_open_into(self._fdt, fdt, size), quiet)
+ if err:
+ return err
+ self._fdt = fdt
def pack(self, quiet=()):
"""Pack the device tree to remove unused space
@@ -309,45 +535,158 @@ class Fdt:
Args:
quiet: Errors to ignore (empty to raise on all errors)
+ Returns:
+ Error code, or 0 if OK
+
Raises:
FdtException if any error occurs
"""
- return check_err(fdt_pack(self._fdt), quiet)
+ err = check_err(fdt_pack(self._fdt), quiet)
+ if err:
+ return err
+ del self._fdt[self.totalsize():]
+ return err
+
+ def set_name(self, nodeoffset, name, quiet=()):
+ """Set the name of a node
+
+ Args:
+ nodeoffset: Node offset of node to update
+ name: New node name (string without \0)
+
+ Returns:
+ Error code, or 0 if OK
+
+ Raises:
+ FdtException if no parent found or other error occurs
+ """
+ if chr(0) in name:
+ raise ValueError('Property contains embedded nul characters')
+ return check_err(fdt_set_name(self._fdt, nodeoffset, name), quiet)
+
+ def setprop(self, nodeoffset, prop_name, val, quiet=()):
+ """Set the value of a property
+
+ Args:
+ nodeoffset: Node offset containing the property to create/update
+ prop_name: Name of property
+ val: Value to write (string or bytearray)
+ 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
+ """
+ return check_err(fdt_setprop(self._fdt, nodeoffset, prop_name, val,
+ len(val)), quiet)
+
+ def setprop_u32(self, nodeoffset, prop_name, val, quiet=()):
+ """Set the value of a property
+
+ Args:
+ nodeoffset: Node offset containing the property to create/update
+ prop_name: Name of property
+ val: Value to write (integer)
+ 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
+ """
+ return check_err(fdt_setprop_u32(self._fdt, nodeoffset, prop_name, val),
+ quiet)
+
+ def setprop_u64(self, nodeoffset, prop_name, val, quiet=()):
+ """Set the value of a property
+
+ Args:
+ nodeoffset: Node offset containing the property to create/update
+ prop_name: Name of property
+ val: Value to write (integer)
+ 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
+ """
+ return check_err(fdt_setprop_u64(self._fdt, nodeoffset, prop_name, val),
+ quiet)
+
+ def setprop_str(self, nodeoffset, prop_name, val, quiet=()):
+ """Set the string value of a property
+
+ The property is set to the string, with a nul terminator added
+
+ Args:
+ nodeoffset: Node offset containing the property to create/update
+ prop_name: Name of property
+ val: Value to write (string without nul terminator). Unicode is
+ supposed by encoding to UTF-8
+ 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
+ """
+ val = val.encode('utf-8') + b'\0'
+ return check_err(fdt_setprop(self._fdt, nodeoffset, prop_name,
+ val, len(val)), quiet)
- def delprop(self, nodeoffset, prop_name):
+ def delprop(self, nodeoffset, prop_name, quiet=()):
"""Delete a property from a node
Args:
nodeoffset: Node offset containing property to delete
prop_name: Name of property to delete
+ quiet: Errors to ignore (empty to raise on all errors)
+
+ Returns:
+ Error code, or 0 if OK
Raises:
FdtError if the property does not exist, or another error occurs
"""
- return check_err(fdt_delprop(self._fdt, nodeoffset, prop_name))
+ return check_err(fdt_delprop(self._fdt, nodeoffset, prop_name), quiet)
- def getprop(self, nodeoffset, prop_name, quiet=()):
- """Get a property from a node
+ def add_subnode(self, parentoffset, name, quiet=()):
+ """Add a new subnode to a node
Args:
- nodeoffset: Node offset containing property to get
- prop_name: Name of property to get
- quiet: Errors to ignore (empty to raise on all errors)
+ parentoffset: Parent offset to add the subnode to
+ name: Name of node to add
Returns:
- Value of property as a bytearray, or -ve error number
+ offset of the node created, or negative error code on failure
Raises:
- FdtError if any error occurs (e.g. the property is not found)
+ FdtError if there is not enough space, or another error occurs
"""
- pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name),
- quiet)
- if isinstance(pdata, (int)):
- return pdata
- return bytearray(pdata[0])
+ return check_err(fdt_add_subnode(self._fdt, parentoffset, name), quiet)
+
+ def del_node(self, nodeoffset, quiet=()):
+ """Delete a node
+
+ Args:
+ nodeoffset: Offset of node to delete
+
+ Returns:
+ Error code, or 0 if OK
+
+ Raises:
+ FdtError if an error occurs
+ """
+ return check_err(fdt_del_node(self._fdt, nodeoffset), quiet)
-class Property:
+class Property(bytearray):
"""Holds a device tree property name and value.
This holds a copy of a property taken from the device tree. It does not
@@ -356,18 +695,309 @@ class Property:
Properties:
name: Property name
- value: Proper value as a bytearray
+ value: Property value as a bytearray
"""
def __init__(self, name, value):
+ bytearray.__init__(self, value)
self.name = name
- self.value = value
+
+ def as_cell(self, fmt):
+ return struct.unpack('>' + fmt, self)[0]
+
+ def as_uint32(self):
+ return self.as_cell('L')
+
+ def as_int32(self):
+ return self.as_cell('l')
+
+ def as_uint64(self):
+ return self.as_cell('Q')
+
+ def as_int64(self):
+ return self.as_cell('q')
+
+ def as_str(self):
+ """Unicode is supported by decoding from UTF-8"""
+ if self[-1] != 0:
+ raise ValueError('Property lacks nul termination')
+ if 0 in self[:-1]:
+ raise ValueError('Property contains embedded nul characters')
+ return self[:-1].decode('utf-8')
+
+
+class FdtSw(FdtRo):
+ """Software interface to create a device tree from scratch
+
+ The methods in this class work by adding to an existing 'partial' device
+ tree buffer of a fixed size created by instantiating this class. When the
+ tree is complete, call as_fdt() to obtain a device tree ready to be used.
+
+ Similarly with nodes, a new node is started with begin_node() and finished
+ with end_node().
+
+ The context manager functions can be used to make this a bit easier:
+
+ # First create the device tree with a node and property:
+ sw = FdtSw()
+ 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
+ fdt.setprop_u32(0, 'reg', 3)
+
+ The size hint provides a starting size for the space to be used by the
+ device tree. This will be increased automatically as needed as new items
+ are added to the tree.
+ """
+ INC_SIZE = 1024 # Expand size by this much when out of space
+
+ def __init__(self, size_hint=None):
+ """Create a new FdtSw object
+
+ Args:
+ size_hint: A hint as to the initial size to use
+
+ Raises:
+ ValueError if size_hint is negative
+
+ Returns:
+ FdtSw object on success, else integer error code (if not raising)
+ """
+ if not size_hint:
+ size_hint = self.INC_SIZE
+ fdtsw = bytearray(size_hint)
+ err = check_err(fdt_create(fdtsw, size_hint))
+ if err:
+ return err
+ self._fdt = fdtsw
+
+ def as_fdt(self):
+ """Convert a FdtSw into an Fdt so it can be accessed as normal
+
+ Creates a new Fdt object from the work-in-progress device tree. This
+ does not call fdt_finish() on the current object, so it is possible to
+ add more nodes/properties and call as_fdt() again to get an updated
+ tree.
+
+ Returns:
+ Fdt object allowing access to the newly created device tree
+ """
+ fdtsw = bytearray(self._fdt)
+ check_err(fdt_finish(fdtsw))
+ return Fdt(fdtsw)
+
+ def check_space(self, val):
+ """Check if we need to add more space to the FDT
+
+ This should be called with the error code from an operation. If this is
+ -NOSPACE then the FDT will be expanded to have more space, and True will
+ be returned, indicating that the operation needs to be tried again.
+
+ Args:
+ val: Return value from the operation that was attempted
+
+ Returns:
+ True if the operation must be retried, else False
+ """
+ if check_err(val, QUIET_NOSPACE) < 0:
+ self.resize(len(self._fdt) + self.INC_SIZE)
+ return True
+ return False
+
+ def resize(self, size):
+ """Resize the buffer to accommodate a larger tree
+
+ Args:
+ size: New size of tree
+
+ Raises:
+ FdtException on any error
+ """
+ fdt = bytearray(size)
+ err = check_err(fdt_resize(self._fdt, fdt, size))
+ self._fdt = fdt
+
+ def add_reservemap_entry(self, addr, size):
+ """Add a new memory reserve map entry
+
+ Once finished adding, you must call finish_reservemap().
+
+ Args:
+ addr: 64-bit start address
+ size: 64-bit size
+
+ Raises:
+ FdtException on any error
+ """
+ while self.check_space(fdt_add_reservemap_entry(self._fdt, addr,
+ size)):
+ pass
+
+ def finish_reservemap(self):
+ """Indicate that there are no more reserve map entries to add
+
+ Raises:
+ FdtException on any error
+ """
+ while self.check_space(fdt_finish_reservemap(self._fdt)):
+ pass
+
+ def begin_node(self, name):
+ """Begin a new node
+
+ Use this before adding properties to the node. Then call end_node() to
+ finish it. You can also use the context manager as shown in the FdtSw
+ class comment.
+
+ Args:
+ name: Name of node to begin
+
+ Raises:
+ FdtException on any error
+ """
+ while self.check_space(fdt_begin_node(self._fdt, name)):
+ pass
+
+ def property_string(self, name, string):
+ """Add a property with a string value
+
+ The string will be nul-terminated when written to the device tree
+
+ Args:
+ name: Name of property to add
+ string: String value of property
+
+ Raises:
+ FdtException on any error
+ """
+ while self.check_space(fdt_property_string(self._fdt, name, string)):
+ pass
+
+ def property_u32(self, name, val):
+ """Add a property with a 32-bit value
+
+ Write a single-cell value to the device tree
+
+ Args:
+ name: Name of property to add
+ val: Value of property
+
+ Raises:
+ FdtException on any error
+ """
+ while self.check_space(fdt_property_u32(self._fdt, name, val)):
+ pass
+
+ def property_u64(self, name, val):
+ """Add a property with a 64-bit value
+
+ Write a double-cell value to the device tree in big-endian format
+
+ Args:
+ name: Name of property to add
+ val: Value of property
+
+ Raises:
+ FdtException on any error
+ """
+ while self.check_space(fdt_property_u64(self._fdt, name, val)):
+ pass
+
+ def property_cell(self, name, val):
+ """Add a property with a single-cell value
+
+ Write a single-cell value to the device tree
+
+ Args:
+ name: Name of property to add
+ val: Value of property
+ quiet: Errors to ignore (empty to raise on all errors)
+
+ Raises:
+ FdtException on any error
+ """
+ while self.check_space(fdt_property_cell(self._fdt, name, val)):
+ pass
+
+ def property(self, name, val):
+ """Add a property
+
+ Write a new property with the given value to the device tree. The value
+ is taken as is and is not nul-terminated
+
+ Args:
+ name: Name of property to add
+ val: Value of property (bytes)
+ quiet: Errors to ignore (empty to raise on all errors)
+
+ Raises:
+ FdtException on any error
+ """
+ while self.check_space(fdt_property_stub(self._fdt, name, val,
+ len(val))):
+ pass
+
+ def end_node(self):
+ """End a node
+
+ Use this after adding properties to a node to close it off. You can also
+ use the context manager as shown in the FdtSw class comment.
+
+ Args:
+ quiet: Errors to ignore (empty to raise on all errors)
+
+ Raises:
+ FdtException on any error
+ """
+ while self.check_space(fdt_end_node(self._fdt)):
+ pass
+
+ def add_node(self, name):
+ """Create a new context for adding a node
+
+ When used in a 'with' clause this starts a new node and finishes it
+ afterward.
+
+ Args:
+ name: Name of node to add
+ """
+ return NodeAdder(self, name)
+
+
+class NodeAdder():
+ """Class to provide a node context
+
+ This allows you to add nodes in a more natural way:
+
+ with fdtsw.add_node('name'):
+ fdtsw.property_string('test', 'value')
+
+ The node is automatically completed with a call to end_node() when the
+ context exits.
+ """
+ def __init__(self, fdtsw, name):
+ self._fdt = fdtsw
+ self._name = name
+
+ def __enter__(self):
+ self._fdt.begin_node(self._name)
+
+ def __exit__(self, type, value, traceback):
+ self._fdt.end_node()
%}
%rename(fdt_property) fdt_property_func;
-typedef int fdt32_t;
+/*
+ * fdt32_t is a big-endian 32-bit value defined to uint32_t in libfdt_env.h
+ * so use the same type here.
+ */
+typedef uint32_t fdt32_t;
-%include "libfdt/fdt.h"
+%include "fdt.h"
%include "typemaps.i"
@@ -393,6 +1023,7 @@ typedef int fdt32_t;
fdt = fdt; /* avoid unused variable warning */
}
+/* typemap used for fdt_get_property_by_offset() */
%typemap(out) (struct fdt_property *) {
PyObject *buff;
@@ -412,22 +1043,76 @@ typedef int fdt32_t;
if (!$1)
$result = Py_None;
else
- $result = Py_BuildValue("s#", $1, *arg4);
+ %#if PY_VERSION_HEX >= 0x03000000
+ $result = Py_BuildValue("y#", $1, *arg4);
+ %#else
+ $result = Py_BuildValue("s#", $1, *arg4);
+ %#endif
+}
+
+/* typemap used for fdt_setprop() */
+%typemap(in) (const void *val) {
+ %#if PY_VERSION_HEX >= 0x03000000
+ if (!PyBytes_Check($input)) {
+ SWIG_exception_fail(SWIG_TypeError, "bytes expected in method '" "$symname"
+ "', argument " "$argnum"" of type '" "$type""'");
+ }
+ $1 = PyBytes_AsString($input);
+ %#else
+ $1 = PyString_AsString($input); /* char *str */
+ %#endif
+}
+
+/* typemaps used for fdt_next_node() */
+%typemap(in, numinputs=1) int *depth (int depth) {
+ depth = (int) PyInt_AsLong($input);
+ $1 = &depth;
+}
+
+%typemap(argout) int *depth {
+ PyObject *val = Py_BuildValue("i", *arg$argnum);
+ resultobj = SWIG_Python_AppendOutput(resultobj, val);
+}
+
+%apply int *depth { int *depth };
+
+/* typemaps for fdt_get_mem_rsv */
+%typemap(in, numinputs=0) uint64_t * (uint64_t temp) {
+ $1 = &temp;
+}
+
+%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);
+ }
}
/* We have both struct fdt_property and a function fdt_property() */
%warnfilter(302) fdt_property;
/* These are macros in the header so have to be redefined here */
-int fdt_magic(const void *fdt);
-int fdt_totalsize(const void *fdt);
-int fdt_off_dt_struct(const void *fdt);
-int fdt_off_dt_strings(const void *fdt);
-int fdt_off_mem_rsvmap(const void *fdt);
-int fdt_version(const void *fdt);
-int fdt_last_comp_version(const void *fdt);
-int fdt_boot_cpuid_phys(const void *fdt);
-int fdt_size_dt_strings(const void *fdt);
-int fdt_size_dt_struct(const void *fdt);
-
-%include <../libfdt/libfdt.h>
+uint32_t fdt_magic(const void *fdt);
+uint32_t fdt_totalsize(const void *fdt);
+uint32_t fdt_off_dt_struct(const void *fdt);
+uint32_t fdt_off_dt_strings(const void *fdt);
+uint32_t fdt_off_mem_rsvmap(const void *fdt);
+uint32_t fdt_version(const void *fdt);
+uint32_t fdt_last_comp_version(const void *fdt);
+uint32_t fdt_boot_cpuid_phys(const void *fdt);
+uint32_t fdt_size_dt_strings(const void *fdt);
+uint32_t fdt_size_dt_struct(const void *fdt);
+
+int fdt_property_string(void *fdt, const char *name, const char *val);
+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 void *val, int len);
+
+%include <libfdt.h>
diff --git a/pylibfdt/setup.py b/pylibfdt/setup.py
index 90e80f3..53f2bef 100755
--- a/pylibfdt/setup.py
+++ b/pylibfdt/setup.py
@@ -1,19 +1,13 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
+# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
+
+# While Python 3 is the default, it's also possible to invoke
+# this setup.py script with Python 2.
"""
setup.py file for SWIG libfdt
Copyright (C) 2017 Google, Inc.
Written by Simon Glass <sjg@chromium.org>
-
-Files to be built into the extension are provided in SOURCES
-C flags to use are provided in CPPFLAGS
-Object file directory is provided in OBJDIR
-Version is provided in VERSION
-
-If these variables are not given they are parsed from the Makefiles. This
-allows this script to be run stand-alone, e.g.:
-
- ./pylibfdt/setup.py install [--prefix=...]
"""
from distutils.core import setup, Extension
@@ -21,101 +15,34 @@ import os
import re
import sys
-# Decodes a Makefile assignment line into key and value (and plus for +=)
-RE_KEY_VALUE = re.compile('(?P<key>\w+) *(?P<plus>[+])?= *(?P<value>.*)$')
-
-
-def ParseMakefile(fname):
- """Parse a Makefile to obtain its variables.
-
- This collects variable assigments of the form:
-
- VAR = value
- VAR += more
-
- It does not pick out := assignments, as these are not needed here. It does
- handle line continuation.
-
- Returns a dict:
- key: Variable name (e.g. 'VAR')
- value: Variable value (e.g. 'value more')
- """
- makevars = {}
- with open(fname) as fd:
- prev_text = '' # Continuation text from previous line(s)
- for line in fd.read().splitlines():
- if line and line[-1] == '\\': # Deal with line continuation
- prev_text += line[:-1]
- continue
- elif prev_text:
- line = prev_text + line
- prev_text = '' # Continuation is now used up
- m = RE_KEY_VALUE.match(line)
- if m:
- value = m.group('value') or ''
- key = m.group('key')
-
- # Appending to a variable inserts a space beforehand
- if 'plus' in m.groupdict() and key in makevars:
- makevars[key] += ' ' + value
- else:
- makevars[key] = value
- return makevars
-
-def GetEnvFromMakefiles():
- """Scan the Makefiles to obtain the settings we need.
- This assumes that this script is being run from the top-level directory,
- not the pylibfdt directory.
+VERSION_PATTERN = '^#define DTC_VERSION "DTC ([^"]*)"$'
- Returns:
- Tuple with:
- List of swig options
- Version string
- List of files to build
- List of extra C preprocessor flags needed
- Object directory to use (always '')
- """
- basedir = os.path.dirname(os.path.dirname(os.path.abspath(sys.argv[0])))
- swig_opts = ['-I%s' % basedir]
- makevars = ParseMakefile(os.path.join(basedir, 'Makefile'))
- version = '%s.%s.%s' % (makevars['VERSION'], makevars['PATCHLEVEL'],
- makevars['SUBLEVEL'])
- makevars = ParseMakefile(os.path.join(basedir, 'libfdt', 'Makefile.libfdt'))
- files = makevars['LIBFDT_SRCS'].split()
- files = [os.path.join(basedir, 'libfdt', fname) for fname in files]
- files.append('pylibfdt/libfdt.i')
- cflags = ['-I%s' % basedir, '-I%s/libfdt' % basedir]
- objdir = ''
- return swig_opts, version, files, cflags, objdir
+def get_version():
+ version_file = "../version_gen.h"
+ f = open(version_file, 'rt')
+ m = re.match(VERSION_PATTERN, f.readline())
+ return m.group(1)
-progname = sys.argv[0]
-files = os.environ.get('SOURCES', '').split()
-cflags = os.environ.get('CPPFLAGS', '').split()
-objdir = os.environ.get('OBJDIR')
-version = os.environ.get('VERSION')
-swig_opts = []
-# If we were called directly rather than through our Makefile (which is often
-# the case with Python module installation), read the settings from the
-# Makefile.
-if not all((version, files, cflags, objdir)):
- swig_opts, version, files, cflags, objdir = GetEnvFromMakefiles()
+setupdir = os.path.dirname(os.path.abspath(sys.argv[0]))
+os.chdir(setupdir)
libfdt_module = Extension(
'_libfdt',
- sources = files,
- extra_compile_args = cflags,
- swig_opts = swig_opts,
+ sources=['libfdt.i'],
+ include_dirs=['../libfdt'],
+ libraries=['fdt'],
+ library_dirs=['../libfdt'],
+ swig_opts=['-I../libfdt'],
)
setup(
name='libfdt',
- version= version,
+ version=get_version(),
author='Simon Glass <sjg@chromium.org>',
description='Python binding for libfdt',
ext_modules=[libfdt_module],
- package_dir={'': objdir},
- py_modules=['pylibfdt/libfdt'],
+ py_modules=['libfdt'],
)
diff --git a/scripts/kup-dtc b/scripts/kup-dtc
index e18abbb..3c3376c 100755
--- a/scripts/kup-dtc
+++ b/scripts/kup-dtc
@@ -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
diff --git a/scripts/setlocalversion b/scripts/setlocalversion
index 82e4993..ea333e7 100755
--- a/scripts/setlocalversion
+++ b/scripts/setlocalversion
@@ -1,4 +1,5 @@
#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0-or-later
# Print additional version information for non-release trees.
usage() {
diff --git a/srcpos.c b/srcpos.c
index 9d38459..f5205fb 100644
--- a/srcpos.c
+++ b/srcpos.c
@@ -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
*/
#define _GNU_SOURCE
@@ -33,6 +19,9 @@ struct search_path {
/* This is the list of directories that we search for source files */
static struct search_path *search_path_head, **search_path_tail;
+/* Detect infinite include recursion. */
+#define MAX_SRCFILE_DEPTH (100)
+static int srcfile_depth; /* = 0 */
static char *get_dirname(const char *path)
{
@@ -51,11 +40,51 @@ static char *get_dirname(const char *path)
FILE *depfile; /* = NULL */
struct srcfile_state *current_srcfile; /* = NULL */
+static char *initial_path; /* = NULL */
+static int initial_pathlen; /* = 0 */
+static bool initial_cpp = true;
-/* Detect infinite include recursion. */
-#define MAX_SRCFILE_DEPTH (100)
-static int srcfile_depth; /* = 0 */
+static void set_initial_path(char *fname)
+{
+ int i, len = strlen(fname);
+ xasprintf(&initial_path, "%s", fname);
+ initial_pathlen = 0;
+ for (i = 0; i != len; i++)
+ if (initial_path[i] == '/')
+ initial_pathlen++;
+}
+
+static char *shorten_to_initial_path(char *fname)
+{
+ char *p1, *p2, *prevslash1 = NULL;
+ int slashes = 0;
+
+ for (p1 = fname, p2 = initial_path; *p1 && *p2; p1++, p2++) {
+ if (*p1 != *p2)
+ break;
+ if (*p1 == '/') {
+ prevslash1 = p1;
+ slashes++;
+ }
+ }
+ p1 = prevslash1 + 1;
+ if (prevslash1) {
+ int diff = initial_pathlen - slashes, i, j;
+ int restlen = strlen(fname) - (p1 - fname);
+ char *res;
+
+ res = xmalloc((3 * diff) + restlen + 1);
+ for (i = 0, j = 0; i != diff; i++) {
+ res[j++] = '.';
+ res[j++] = '.';
+ res[j++] = '/';
+ }
+ strcpy(res + j, p1);
+ return res;
+ }
+ return NULL;
+}
/**
* Try to open a file in a given directory.
@@ -157,6 +186,9 @@ void srcfile_push(const char *fname)
srcfile->colno = 1;
current_srcfile = srcfile;
+
+ if (srcfile_depth == 1)
+ set_initial_path(srcfile->name);
}
bool srcfile_pop(void)
@@ -197,20 +229,6 @@ void srcfile_add_search_path(const char *dirname)
search_path_tail = &node->next;
}
-/*
- * The empty source position.
- */
-
-struct srcpos srcpos_empty = {
- .first_line = 0,
- .first_column = 0,
- .last_line = 0,
- .last_column = 0,
- .file = NULL,
-};
-
-#define TAB_SIZE 8
-
void srcpos_update(struct srcpos *pos, const char *text, int len)
{
int i;
@@ -224,9 +242,6 @@ void srcpos_update(struct srcpos *pos, const char *text, int len)
if (text[i] == '\n') {
current_srcfile->lineno++;
current_srcfile->colno = 1;
- } else if (text[i] == '\t') {
- current_srcfile->colno =
- ALIGN(current_srcfile->colno, TAB_SIZE);
} else {
current_srcfile->colno++;
}
@@ -239,13 +254,35 @@ struct srcpos *
srcpos_copy(struct srcpos *pos)
{
struct srcpos *pos_new;
+ struct srcfile_state *srcfile_state;
+
+ if (!pos)
+ return NULL;
pos_new = xmalloc(sizeof(struct srcpos));
+ assert(pos->next == NULL);
memcpy(pos_new, pos, sizeof(struct srcpos));
+ /* allocate without free */
+ srcfile_state = xmalloc(sizeof(struct srcfile_state));
+ memcpy(srcfile_state, pos->file, sizeof(struct srcfile_state));
+ pos_new->file = srcfile_state;
+
return pos_new;
}
+struct srcpos *srcpos_extend(struct srcpos *pos, struct srcpos *newtail)
+{
+ struct srcpos *p;
+
+ if (!pos)
+ return newtail;
+
+ for (p = pos; p->next != NULL; p = p->next);
+ p->next = newtail;
+ return pos;
+}
+
char *
srcpos_string(struct srcpos *pos)
{
@@ -271,6 +308,68 @@ srcpos_string(struct srcpos *pos)
return pos_str;
}
+static char *
+srcpos_string_comment(struct srcpos *pos, bool first_line, int level)
+{
+ char *pos_str, *fname, *first, *rest;
+ bool fresh_fname = false;
+
+ if (!pos) {
+ if (level > 1) {
+ xasprintf(&pos_str, "<no-file>:<no-line>");
+ return pos_str;
+ } else {
+ return NULL;
+ }
+ }
+
+ if (!pos->file)
+ fname = "<no-file>";
+ else if (!pos->file->name)
+ fname = "<no-filename>";
+ else if (level > 1)
+ fname = pos->file->name;
+ else {
+ fname = shorten_to_initial_path(pos->file->name);
+ if (fname)
+ fresh_fname = true;
+ else
+ fname = pos->file->name;
+ }
+
+ if (level > 1)
+ xasprintf(&first, "%s:%d:%d-%d:%d", fname,
+ pos->first_line, pos->first_column,
+ pos->last_line, pos->last_column);
+ else
+ xasprintf(&first, "%s:%d", fname,
+ first_line ? pos->first_line : pos->last_line);
+
+ if (fresh_fname)
+ free(fname);
+
+ if (pos->next != NULL) {
+ rest = srcpos_string_comment(pos->next, first_line, level);
+ xasprintf(&pos_str, "%s, %s", first, rest);
+ free(first);
+ free(rest);
+ } else {
+ pos_str = first;
+ }
+
+ return pos_str;
+}
+
+char *srcpos_string_first(struct srcpos *pos, int level)
+{
+ return srcpos_string_comment(pos, true, level);
+}
+
+char *srcpos_string_last(struct srcpos *pos, int level)
+{
+ return srcpos_string_comment(pos, false, level);
+}
+
void srcpos_verror(struct srcpos *pos, const char *prefix,
const char *fmt, va_list va)
{
@@ -299,4 +398,9 @@ void srcpos_set_line(char *f, int l)
{
current_srcfile->name = f;
current_srcfile->lineno = l;
+
+ if (initial_cpp) {
+ initial_cpp = false;
+ set_initial_path(f);
+ }
}
diff --git a/srcpos.h b/srcpos.h
index 7caca82..4318d7a 100644
--- a/srcpos.h
+++ b/srcpos.h
@@ -1,24 +1,10 @@
+/* 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_
-#define _SRCPOS_H_
+#ifndef SRCPOS_H
+#define SRCPOS_H
#include <stdio.h>
#include <stdbool.h>
@@ -74,6 +60,7 @@ struct srcpos {
int last_line;
int last_column;
struct srcfile_state *file;
+ struct srcpos *next;
};
#define YYLTYPE struct srcpos
@@ -93,19 +80,18 @@ struct srcpos {
YYRHSLOC(Rhs, 0).last_column; \
(Current).file = YYRHSLOC (Rhs, 0).file; \
} \
+ (Current).next = NULL; \
} while (0)
-/*
- * Fictional source position used for IR nodes that are
- * created without otherwise knowing a true source position.
- * For example,constant definitions from the command line.
- */
-extern struct srcpos srcpos_empty;
-
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 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);
+
extern void PRINTF(3, 0) srcpos_verror(struct srcpos *pos, const char *prefix,
const char *fmt, va_list va);
@@ -114,4 +100,4 @@ extern void PRINTF(3, 4) srcpos_error(struct srcpos *pos, const char *prefix,
extern void srcpos_set_line(char *f, int l);
-#endif /* _SRCPOS_H_ */
+#endif /* SRCPOS_H */
diff --git a/tests/.gitignore b/tests/.gitignore
index 9e209d5..d3f1434 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -1,13 +1,19 @@
*.dtb
*.dts.test.s
*.test.dts
+*.test.dt.yaml
tmp.*
+/fs/
/add_subnode_with_nops
/addr_size_cells
+/addr_size_cells2
/appendprop[12]
+/appendprop_addrrange
/asm_tree_dump
/boot-cpuid
/char_literal
+/check_full
+/check_header
/check_path
/del_node
/del_property
@@ -23,8 +29,10 @@ tmp.*
/get_path
/get_phandle
/getprop
+/get_prop_offset
/incbin
/integer-expressions
+/fs_tree1
/mangle-layout
/move_and_save
/node_check_compatible
@@ -48,6 +56,7 @@ tmp.*
/references
/root_node
/rw_tree1
+/rw_oom
/set_name
/setprop
/setprop_inplace
@@ -58,6 +67,9 @@ tmp.*
/subnode_offset
/supernode_atdepth_offset
/sw_tree1
+/sw_states
/truncated_property
+/truncated_string
+/truncated_memrsv
/utilfdt_test
/value-labels
diff --git a/tests/Makefile.tests b/tests/Makefile.tests
index 2258135..cb66c9f 100644
--- a/tests/Makefile.tests
+++ b/tests/Makefile.tests
@@ -1,6 +1,6 @@
LIB_TESTS_L = get_mem_rsv \
root_node find_property subnode_offset path_offset \
- get_name getprop get_phandle \
+ get_name getprop get_prop_offset get_phandle \
get_path supernode_atdepth_offset parent_offset \
node_offset_by_prop_value node_offset_by_phandle \
node_check_compatible node_offset_by_compatible \
@@ -9,11 +9,13 @@ LIB_TESTS_L = get_mem_rsv \
sized_cells \
notfound \
addr_size_cells \
+ addr_size_cells2 \
+ appendprop_addrrange \
stringlist \
setprop_inplace nop_property nop_node \
- sw_tree1 \
+ 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 \
@@ -26,10 +28,11 @@ LIB_TESTS_L = get_mem_rsv \
property_iterate \
subnode_iterate \
overlay overlay_bad_fixup \
- check_path
+ check_path check_header check_full \
+ fs_tree1
LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%)
-LIBTREE_TESTS_L = truncated_property
+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
@@ -45,38 +48,49 @@ TESTS_TARGETS = $(TESTS) $(TESTS_TREES)
TESTS_DEPFILES = $(TESTS:%=%.d) \
$(addprefix $(TESTS_PREFIX),testutils.d trees.d dumptrees.d)
-TESTS_CLEANFILES_L = *.output vglog.* vgcore.* *.dtb *.test.dts *.dtsv1 tmp.*
-TESTS_CLEANFILES_L += dumptrees
+TESTS_CLEANFILES_L = $(STD_CLEANFILES) \
+ *.dtb *.test.dts *.test.dt.yaml *.dtsv1 tmp.* *.bak \
+ dumptrees
TESTS_CLEANFILES = $(TESTS) $(TESTS_CLEANFILES_L:%=$(TESTS_PREFIX)%)
+TESTS_CLEANDIRS_L = fs
+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_lib)
-$(DL_LIB_TESTS): %: %.o $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_archive)
+# Not necessary on all platforms; allow -ldl to be excluded instead of forcing
+# other platforms to patch it out.
+LIBDL = -ldl
+$(DL_LIB_TESTS): %: %.o $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_lib)
@$(VECHO) LD [libdl] $@
- $(LINK.c) -o $@ $^ -ldl
+ $(LINK.c) -o $@ $^ $(LIBDL)
$(LIBTREE_TESTS): %: $(TESTS_PREFIX)testutils.o $(TESTS_PREFIX)trees.o \
- util.o $(LIBFDT_archive)
+ util.o $(LIBFDT_lib)
$(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)"
- rm -f $(STD_CLEANFILES:%=$(TESTS_PREFIX)%)
rm -f $(TESTS_CLEANFILES)
+ rm -rf $(TESTS_CLEANDIRS)
check: tests ${TESTS_BIN} $(TESTS_PYLIBFDT)
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); ./run_tests.sh -m 2>&1 | tee vglog.$$$$
+ cd $(TESTS_PREFIX); ./run_tests.sh -m
+endif
checkv: tests ${TESTS_BIN} $(TESTS_PYLIBFDT)
cd $(TESTS_PREFIX); ./run_tests.sh -v
@@ -84,4 +98,3 @@ checkv: tests ${TESTS_BIN} $(TESTS_PYLIBFDT)
ifneq ($(DEPTARGETS),)
-include $(TESTS_DEPFILES)
endif
-
diff --git a/tests/add_subnode_with_nops.c b/tests/add_subnode_with_nops.c
index 95ddf6a..29bd34b 100644
--- a/tests/add_subnode_with_nops.c
+++ b/tests/add_subnode_with_nops.c
@@ -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>
diff --git a/tests/addr_size_cells.c b/tests/addr_size_cells.c
index 6090d93..783574d 100644
--- a/tests/addr_size_cells.c
+++ b/tests/addr_size_cells.c
@@ -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>
@@ -58,7 +45,12 @@ int main(int argc, char *argv[])
fdt = load_blob(argv[1]);
check_node(fdt, "/", 2, 2);
- check_node(fdt, "/identity-bus@0", 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();
}
diff --git a/tests/addr_size_cells2.c b/tests/addr_size_cells2.c
new file mode 100644
index 0000000..d97541b
--- /dev/null
+++ b/tests/addr_size_cells2.c
@@ -0,0 +1,49 @@
+// 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>
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+static void check_node(const void *fdt, const char *path, int ac, int sc)
+{
+ int offset;
+ int xac, xsc;
+
+ offset = fdt_path_offset(fdt, path);
+ if (offset < 0)
+ FAIL("Couldn't find path %s", path);
+
+ xac = fdt_address_cells(fdt, offset);
+ xsc = fdt_size_cells(fdt, offset);
+
+ if (xac != ac)
+ FAIL("Address cells for %s is %d instead of %d\n",
+ path, xac, ac);
+ if (xsc != sc)
+ FAIL("Size cells for %s is %d instead of %d\n",
+ path, xsc, sc);
+}
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+
+ if (argc != 2)
+ CONFIG("Usage: %s <dtb file>\n", argv[0]);
+
+ test_init(argc, argv);
+ fdt = load_blob(argv[1]);
+
+ check_node(fdt, "/", 2, 1);
+ PASS();
+}
diff --git a/tests/addresses.dts b/tests/addresses.dts
index a2faaf5..1b307ab 100644
--- a/tests/addresses.dts
+++ b/tests/addresses.dts
@@ -12,4 +12,29 @@
#address-cells = <2>;
#size-cells = <1>;
};
+
+ discrete-bus@2000000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ c0@0 {
+ #address-cells = <1 1>;
+ #size-cells = <1 1>;
+ };
+
+ c1@0 {
+ #address-cells = <0x80000000>;
+ #size-cells = <0x80000000>;
+ };
+
+ c2@0 {
+ #address-cells = <5>;
+ #size-cells = <5>;
+ };
+
+ c3@0 {
+ #address-cells = <0>;
+ #size-cells = <0>;
+ };
};
diff --git a/tests/appendprop1.c b/tests/appendprop1.c
index 9d6b3ad..a7b502a 100644
--- a/tests/appendprop1.c
+++ b/tests/appendprop1.c
@@ -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>
diff --git a/tests/appendprop2.c b/tests/appendprop2.c
index ca1446c..a0c1f6f 100644
--- a/tests/appendprop2.c
+++ b/tests/appendprop2.c
@@ -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>
diff --git a/tests/appendprop_addrrange.c b/tests/appendprop_addrrange.c
new file mode 100644
index 0000000..538afcf
--- /dev/null
+++ b/tests/appendprop_addrrange.c
@@ -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));
+
+ 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();
+}
diff --git a/tests/asm_tree_dump.c b/tests/asm_tree_dump.c
index bd12eda..8236172 100644
--- a/tests/asm_tree_dump.c
+++ b/tests/asm_tree_dump.c
@@ -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>
diff --git a/tests/bad-chosen.dts b/tests/bad-chosen.dts
new file mode 100644
index 0000000..d6f53c6
--- /dev/null
+++ b/tests/bad-chosen.dts
@@ -0,0 +1,10 @@
+/dts-v1/;
+
+/ {
+ node2 {
+ chosen {
+ bootargs = <0xdeadbeef>;
+ stdout-path = <1>;
+ };
+ };
+};
diff --git a/tests/bad-dma-ranges.dts b/tests/bad-dma-ranges.dts
new file mode 100644
index 0000000..fbe7ab8
--- /dev/null
+++ b/tests/bad-dma-ranges.dts
@@ -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>;
+ };
+};
diff --git a/tests/bad-gpio.dts b/tests/bad-gpio.dts
new file mode 100644
index 0000000..6b77be4
--- /dev/null
+++ b/tests/bad-gpio.dts
@@ -0,0 +1,13 @@
+/dts-v1/;
+
+/ {
+ gpio: gpio-controller {
+ #gpio-cells = <3>;
+ };
+
+ node {
+ nr-gpios = <1>;
+ foo-gpios = <&gpio>;
+ bar-gpio = <&gpio 1 2 3>;
+ };
+};
diff --git a/tests/bad-graph.dts b/tests/bad-graph.dts
new file mode 100644
index 0000000..522da0e
--- /dev/null
+++ b/tests/bad-graph.dts
@@ -0,0 +1,24 @@
+/dts-v1/;
+
+/ {
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ bad_endpoint: port-a@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ endpoint@d0 {
+ reg = <0>;
+ remote-endpoint = <0xdeadbeef>;
+ };
+
+ };
+
+ port@1 {
+ reg = <0>;
+ };
+ };
+};
diff --git a/tests/bad-interrupt-cells.dts b/tests/bad-interrupt-cells.dts
new file mode 100644
index 0000000..39fc78f
--- /dev/null
+++ b/tests/bad-interrupt-cells.dts
@@ -0,0 +1,12 @@
+/dts-v1/;
+
+/ {
+ interrupt-parent = <&intc>;
+ intc: interrupt-controller {
+ #interrupt-cells = <3>;
+ };
+
+ node {
+ interrupts = <1>;
+ };
+};
diff --git a/tests/bad-interrupt-controller.dts b/tests/bad-interrupt-controller.dts
new file mode 100644
index 0000000..62fa118
--- /dev/null
+++ b/tests/bad-interrupt-controller.dts
@@ -0,0 +1,7 @@
+/dts-v1/;
+
+/ {
+ intc: interrupt-controller {
+ interrupt-controller;
+ };
+};
diff --git a/tests/bad-phandle-cells.dts b/tests/bad-phandle-cells.dts
new file mode 100644
index 0000000..7f7c6a2
--- /dev/null
+++ b/tests/bad-phandle-cells.dts
@@ -0,0 +1,11 @@
+/dts-v1/;
+
+/ {
+ intc: interrupt-controller {
+ #interrupt-cells = <3>;
+ };
+
+ node {
+ interrupts-extended = <&intc>;
+ };
+};
diff --git a/tests/bad-string-props.dts b/tests/bad-string-props.dts
index 396f820..6694704 100644
--- a/tests/bad-string-props.dts
+++ b/tests/bad-string-props.dts
@@ -4,4 +4,11 @@
device_type = <0xdeadbeef>;
model = <0xdeadbeef>;
status = <0xdeadbeef>;
+ label = <0xdeadbeef>;
+
+ foobar-names = "foo", <1>;
+
+ node {
+ compatible = "good", <0xdeadbeef>;
+ };
};
diff --git a/tests/boot-cpuid.c b/tests/boot-cpuid.c
index ca39f4b..5ed4f9a 100644
--- a/tests/boot-cpuid.c
+++ b/tests/boot-cpuid.c
@@ -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>
diff --git a/tests/char_literal.c b/tests/char_literal.c
index da1f964..3a69e28 100644
--- a/tests/char_literal.c
+++ b/tests/char_literal.c
@@ -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>
diff --git a/tests/check_full.c b/tests/check_full.c
new file mode 100644
index 0000000..b6d5fc3
--- /dev/null
+++ b/tests/check_full.c
@@ -0,0 +1,50 @@
+// 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.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+static int expect_bad; /* = 0 */
+
+int main(int argc, char *argv[])
+{
+ const char *filename;
+ char *fdt;
+ size_t len;
+ int err;
+
+ test_init(argc, argv);
+ if ((argc != 2)
+ && ((argc != 3) || !streq(argv[1], "-n")))
+ CONFIG("Usage: %s [-n] <dtb file>", argv[0]);
+ if (argc == 3)
+ expect_bad = 1;
+
+ filename = argv[argc-1];
+ err = utilfdt_read_err(filename, &fdt, &len);
+ if (err)
+ CONFIG("Couldn't open blob from \"%s\": %s",
+ filename, strerror(err));
+
+ vg_prepare_blob(fdt, len);
+
+ err = fdt_check_full(fdt, len);
+
+ if (expect_bad && (err == 0))
+ FAIL("fdt_check_full() succeeded unexpectedly");
+ else if (!expect_bad && (err != 0))
+ FAIL("fdt_check_full() failed: %s", fdt_strerror(err));
+
+ PASS();
+}
diff --git a/tests/check_header.c b/tests/check_header.c
new file mode 100644
index 0000000..ca26ec1
--- /dev/null
+++ b/tests/check_header.c
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for fdt_check_header
+ * Copyright (C) 2018 David Gibson
+ */
+
+#include <stdio.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+
+static void *dtdup(void *dt)
+{
+ size_t bufsize = fdt_totalsize(dt);
+ void *buf = xmalloc(bufsize);
+ fdt_move(dt, buf, bufsize);
+ return buf;
+}
+
+#define CHECK_MANGLE(exerr, code) \
+ do { \
+ void *fdt = dtdup(template); \
+ { code } \
+ err = fdt_check_header(fdt); \
+ verbose_printf("\"%s\" => %s\n", #code, fdt_strerror(err)); \
+ if (err != (exerr)) \
+ FAIL("fdt_check_header() didn't catch mangle %s", \
+ #code); \
+ free(fdt); \
+ } while (0)
+
+int main(int argc, char *argv[])
+{
+ void *template;
+ int err;
+
+ test_init(argc, argv);
+ template = load_blob(argv[1]);
+
+ /* Check that the base dt is valid before mangling it */
+ err = fdt_check_header(template);
+ if (err != 0)
+ FAIL("Base tree fails: %s", fdt_strerror(err));
+
+ /* Check a no-op mangle doesn't break things */
+ CHECK_MANGLE(0, ; );
+
+ /* Mess up the magic number */
+ CHECK_MANGLE(-FDT_ERR_BADMAGIC,
+ fdt_set_magic(fdt, fdt_magic(fdt) ^ 0x1);
+ );
+ CHECK_MANGLE(-FDT_ERR_BADMAGIC,
+ fdt_set_magic(fdt, fdt_magic(fdt) ^ 0x80000000);
+ );
+
+ /* Mess up the version */
+ CHECK_MANGLE(-FDT_ERR_BADVERSION,
+ fdt_set_version(fdt, FDT_FIRST_SUPPORTED_VERSION - 1);
+ fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION - 1);
+ );
+ CHECK_MANGLE(-FDT_ERR_BADVERSION,
+ fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION + 1);
+ fdt_set_last_comp_version(fdt, FDT_LAST_SUPPORTED_VERSION + 1);
+ );
+ CHECK_MANGLE(-FDT_ERR_BADVERSION,
+ fdt_set_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
+ fdt_set_last_comp_version(fdt, FDT_LAST_SUPPORTED_VERSION);
+ );
+
+ /* Out of bounds sizes */
+ CHECK_MANGLE(-FDT_ERR_TRUNCATED,
+ fdt_set_totalsize(fdt, FDT_V1_SIZE - 1);
+ );
+ CHECK_MANGLE(-FDT_ERR_TRUNCATED,
+ fdt_set_totalsize(fdt, (uint32_t)INT_MAX + 1);
+ );
+
+ /* Truncate within various blocks */
+ CHECK_MANGLE(-FDT_ERR_TRUNCATED,
+ fdt_set_totalsize(fdt, fdt_off_dt_struct(fdt) - 1);
+ );
+ CHECK_MANGLE(-FDT_ERR_TRUNCATED,
+ fdt_set_totalsize(fdt, fdt_off_dt_strings(fdt) - 1);
+ );
+ CHECK_MANGLE(-FDT_ERR_TRUNCATED,
+ fdt_set_totalsize(fdt, fdt_off_mem_rsvmap(fdt) - 1);
+ );
+ CHECK_MANGLE(-FDT_ERR_TRUNCATED,
+ fdt_set_totalsize(fdt, fdt_off_dt_struct(fdt) + 1);
+ );
+ CHECK_MANGLE(-FDT_ERR_TRUNCATED,
+ fdt_set_totalsize(fdt, fdt_off_dt_strings(fdt) + 1);
+ );
+ CHECK_MANGLE(-FDT_ERR_TRUNCATED,
+ fdt_set_totalsize(fdt, fdt_off_mem_rsvmap(fdt) + 1);
+ );
+
+ /* Negative block sizes */
+ CHECK_MANGLE(-FDT_ERR_TRUNCATED,
+ fdt_set_size_dt_struct(fdt, (uint32_t)-1);
+ );
+ CHECK_MANGLE(-FDT_ERR_TRUNCATED,
+ fdt_set_size_dt_strings(fdt, (uint32_t)-1);
+ );
+ CHECK_MANGLE(-FDT_ERR_TRUNCATED,
+ fdt_set_size_dt_struct(fdt, (uint32_t)INT_MIN);
+ );
+ CHECK_MANGLE(-FDT_ERR_TRUNCATED,
+ fdt_set_size_dt_strings(fdt, (uint32_t)INT_MIN);
+ );
+
+ PASS();
+}
diff --git a/tests/check_path.c b/tests/check_path.c
index f12f950..cc9757a 100644
--- a/tests/check_path.c
+++ b/tests/check_path.c
@@ -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>
diff --git a/tests/del_node.c b/tests/del_node.c
index 45cb060..10846df 100644
--- a/tests/del_node.c
+++ b/tests/del_node.c
@@ -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>
diff --git a/tests/del_property.c b/tests/del_property.c
index 42fd7cb..37e8303 100644
--- a/tests/del_property.c
+++ b/tests/del_property.c
@@ -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>
diff --git a/tests/dtb_reverse.c b/tests/dtb_reverse.c
index 527fd71..95b6c1c 100644
--- a/tests/dtb_reverse.c
+++ b/tests/dtb_reverse.c
@@ -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>
diff --git a/tests/dtbs_equal_ordered.c b/tests/dtbs_equal_ordered.c
index 98bf0e7..90c7344 100644
--- a/tests/dtbs_equal_ordered.c
+++ b/tests/dtbs_equal_ordered.c
@@ -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>
diff --git a/tests/dtbs_equal_unordered.c b/tests/dtbs_equal_unordered.c
index baf2ae7..e5ff9e8 100644
--- a/tests/dtbs_equal_unordered.c
+++ b/tests/dtbs_equal_unordered.c
@@ -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>
@@ -30,6 +17,7 @@
#include "testdata.h"
static int notequal; /* = 0 */
+static int ignore_memrsv; /* = 0 */
#define MISMATCH(fmt, ...) \
do { \
@@ -195,22 +183,41 @@ static void compare_node(const void *fdt1, int offset1,
compare_subnodes(fdt2, offset2, fdt1, offset1, 0);
}
+static void badargs(char **argv)
+{
+ CONFIG("Usage: %s [-n] [-m] <dtb file> <dtb file>", argv[0]);
+}
+
int main(int argc, char *argv[])
{
void *fdt1, *fdt2;
uint32_t cpuid1, cpuid2;
+ char **args;
+ int argsleft;
test_init(argc, argv);
- if ((argc != 3)
- && ((argc != 4) || !streq(argv[1], "-n")))
- CONFIG("Usage: %s [-n] <dtb file> <dtb file>", argv[0]);
- if (argc == 4)
- notequal = 1;
- fdt1 = load_blob(argv[argc-2]);
- fdt2 = load_blob(argv[argc-1]);
+ args = &argv[1];
+ argsleft = argc - 1;
+
+ while (argsleft > 2) {
+ if (streq(args[0], "-n"))
+ notequal = 1;
+ else if (streq(args[0], "-m"))
+ ignore_memrsv = 1;
+ else
+ badargs(argv);
+ args++;
+ argsleft--;
+ }
+ if (argsleft != 2)
+ badargs(argv);
+
+ fdt1 = load_blob(args[0]);
+ fdt2 = load_blob(args[1]);
- compare_mem_rsv(fdt1, fdt2);
+ if (!ignore_memrsv)
+ compare_mem_rsv(fdt1, fdt2);
compare_node(fdt1, 0, fdt2, 0);
cpuid1 = fdt_boot_cpuid_phys(fdt1);
diff --git a/tests/dtc-checkfails.sh b/tests/dtc-checkfails.sh
index 76ded15..4fd9691 100755
--- a/tests/dtc-checkfails.sh
+++ b/tests/dtc-checkfails.sh
@@ -1,6 +1,7 @@
#! /bin/sh
-. ./tests.sh
+SRCDIR=`dirname "$0"`
+. "$SRCDIR/testutils.sh"
for x; do
shift
@@ -30,13 +31,13 @@ ret="$?"
FAIL_IF_SIGNAL $ret
for c in $YESCHECKS; do
- if ! grep -E "^(ERROR)|(Warning) \($c\):" $LOG > /dev/null; then
+ if ! grep -E "(ERROR|Warning) \($c\):" $LOG > /dev/null; then
FAIL "Failed to trigger check \"$c\""
fi
done
for c in $NOCHECKS; do
- if grep -E "^(ERROR)|(Warning) \($c\):" $LOG > /dev/null; then
+ if grep -E "(ERROR|Warning) \($c\):" $LOG > /dev/null; then
FAIL "Incorrectly triggered check \"$c\""
fi
done
diff --git a/tests/dtc-fails.sh b/tests/dtc-fails.sh
index 4ddcb27..855b623 100755
--- a/tests/dtc-fails.sh
+++ b/tests/dtc-fails.sh
@@ -1,6 +1,7 @@
#! /bin/sh
-. ./tests.sh
+SRCDIR=`dirname "$0"`
+. "$SRCDIR/testutils.sh"
if [ "$1" = "-n" ]; then
NEG="$1"
diff --git a/tests/dtc-fatal.sh b/tests/dtc-fatal.sh
index 6781ced..08a4d29 100644..100755
--- a/tests/dtc-fatal.sh
+++ b/tests/dtc-fatal.sh
@@ -1,6 +1,7 @@
#! /bin/sh
-. ./tests.sh
+SRCDIR=`dirname "$0"`
+. "$SRCDIR/testutils.sh"
verbose_run $VALGRIND "$DTC" -o/dev/null "$@"
ret="$?"
diff --git a/tests/dumptrees.c b/tests/dumptrees.c
index 0728811..aecb326 100644
--- a/tests/dumptrees.c
+++ b/tests/dumptrees.c
@@ -1,23 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* dumptrees - utility for libfdt testing
*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2006.
- *
- *
- * 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>
#include <stdlib.h>
@@ -33,10 +18,12 @@ static struct {
void *blob;
const char *filename;
} trees[] = {
-#define TREE(name) { &_##name, #name ".dtb" }
+#define TREE(name) { &name, #name ".dtb" }
TREE(test_tree1),
TREE(bad_node_char), TREE(bad_node_format), TREE(bad_prop_char),
TREE(ovf_size_strings),
+ TREE(truncated_property), TREE(truncated_string),
+ TREE(truncated_memrsv),
};
#define NUM_TREES (sizeof(trees) / sizeof(trees[0]))
@@ -45,6 +32,16 @@ int main(int argc, char *argv[])
{
int i;
+ if (argc != 2) {
+ fprintf(stderr, "Missing output directory argument\n");
+ return 1;
+ }
+
+ if (chdir(argv[1]) != 0) {
+ perror("chdir()");
+ return 1;
+ }
+
for (i = 0; i < NUM_TREES; i++) {
void *blob = trees[i].blob;
const char *filename = trees[i].filename;
diff --git a/tests/extra-terminating-null.c b/tests/extra-terminating-null.c
index dc1fe89..0fa2ca8 100644
--- a/tests/extra-terminating-null.c
+++ b/tests/extra-terminating-null.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for properties with more than one terminating null
* Copyright (C) 2009 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>
#include <stdio.h>
diff --git a/tests/fdtdump-runtest.sh b/tests/fdtdump-runtest.sh
index 77593cf..71ac861 100644..100755
--- a/tests/fdtdump-runtest.sh
+++ b/tests/fdtdump-runtest.sh
@@ -4,7 +4,8 @@
# $1 - source file to compile and compare with fdtdump output of the
# compiled file.
-. ./tests.sh
+SRCDIR=`dirname "$0"`
+. "$SRCDIR/testutils.sh"
dts="$1"
dtb="${dts}.dtb"
diff --git a/tests/fdtget-runtest.sh b/tests/fdtget-runtest.sh
index 8d8b058..18b7404 100755
--- a/tests/fdtget-runtest.sh
+++ b/tests/fdtget-runtest.sh
@@ -1,6 +1,7 @@
#! /bin/sh
-. ./tests.sh
+SRCDIR=`dirname "$0"`
+. "$SRCDIR/testutils.sh"
LOG=tmp.log.$$
EXPECT=tmp.expect.$$
diff --git a/tests/fdtoverlay-runtest.sh b/tests/fdtoverlay-runtest.sh
index 06c1169..0c648f4 100644..100755
--- a/tests/fdtoverlay-runtest.sh
+++ b/tests/fdtoverlay-runtest.sh
@@ -1,12 +1,13 @@
#! /bin/sh
# Run script for fdtoverlay tests
-# We run fdtoverlay to generate a target device tree, thn fdtget to check it
+# We run fdtoverlay to generate a target device tree, then fdtget to check it
# Usage
# fdtoverlay-runtest.sh name expected_output dtb_file node property flags value
-. ./tests.sh
+SRCDIR=`dirname "$0"`
+. "$SRCDIR/testutils.sh"
LOG=tmp.log.$$
EXPECT=tmp.expect.$$
diff --git a/tests/fdtput-runtest.sh b/tests/fdtput-runtest.sh
index 527a968..1210eab 100644..100755
--- a/tests/fdtput-runtest.sh
+++ b/tests/fdtput-runtest.sh
@@ -1,12 +1,13 @@
#! /bin/sh
# Run script for fdtput tests
-# We run fdtput to update the device tree, thn fdtget to check it
+# We run fdtput to update the device tree, then fdtget to check it
# Usage
# fdtput-runtest.sh name expected_output dtb_file node property flags value
-. ./tests.sh
+SRCDIR=`dirname "$0"`
+. "$SRCDIR/testutils.sh"
LOG=tmp.log.$$
EXPECT=tmp.expect.$$
diff --git a/tests/find_property.c b/tests/find_property.c
index 4dc3030..0404ea0 100644
--- a/tests/find_property.c
+++ b/tests/find_property.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for fdt_property_offset()
* 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>
#include <stdio.h>
diff --git a/tests/fs_tree1.c b/tests/fs_tree1.c
new file mode 100644
index 0000000..dff3880
--- /dev/null
+++ b/tests/fs_tree1.c
@@ -0,0 +1,155 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase/tool constructing an fs tree for further test
+ * Copyright (C) 2018 David Gibson, Red Hat Inc.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <stdint.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+static void start_dir(const char *name)
+{
+ int rc;
+
+ rc = mkdir(name, 0777);
+ if (rc != 0)
+ FAIL("mkdir(\"%s\"): %s", name, strerror(errno));
+
+ rc = chdir(name);
+ if (rc != 0)
+ FAIL("chdir(\"%s\"): %s", name, strerror(errno));
+}
+
+static void end_dir(void)
+{
+ int rc;
+
+ rc = chdir("..");
+ if (rc != 0)
+ FAIL("chdir(..): %s", strerror(errno));
+}
+
+static void mkfile(const char *name, void *data, size_t len)
+{
+ int fd;
+ int rc;
+
+ fd = open(name, O_WRONLY|O_CREAT, 0666);
+ if (fd < 0)
+ FAIL("open(\"%s\"): %s", name, strerror(errno));
+
+ rc = write(fd, data, len);
+ if (rc < 0)
+ FAIL("write(\"%s\"): %s", name, strerror(errno));
+ if (rc != len)
+ FAIL("write(\"%s\"): short write", name);
+
+ rc = close(fd);
+ if (rc != 0)
+ FAIL("close(\"%s\"): %s", name, strerror(errno));
+}
+
+#define mkfile_str(name, s) \
+ do { \
+ char str[] = s; \
+ mkfile((name), str, sizeof(str)); \
+ } while (0)
+
+static void mkfile_u32(const char *name, uint32_t val)
+{
+ val = cpu_to_fdt32(val);
+ mkfile(name, &val, sizeof(val));
+}
+
+static void mkfile_u64(const char *name, uint64_t val)
+{
+ val = cpu_to_fdt64(val);
+ mkfile(name, &val, sizeof(val));
+}
+
+int main(int argc, char *argv[])
+{
+ const char *base;
+
+ test_init(argc, argv);
+ if (argc != 2)
+ CONFIG("Usage: %s <path>", argv[0]);
+
+ base = argv[1];
+
+ start_dir(base);
+ mkfile_str("compatible", "test_tree1");
+ mkfile_u32("prop-int", TEST_VALUE_1);
+ mkfile_u64("prop-int64", 0xdeadbeef01abcdefULL);
+ mkfile_str("prop-str", "hello world");
+ mkfile_u32("#address-cells", 1);
+ mkfile_u32("#size-cells", 0);
+
+ {
+ start_dir("subnode@1");
+
+ mkfile_str("compatible", "subnode1");
+ mkfile_u32("reg", 1);
+ mkfile_u32("prop-int", TEST_VALUE_1);
+
+ {
+ start_dir("subsubnode");
+
+ mkfile_str("compatible", "subsubnode1\0subsubnode");
+ mkfile_str("placeholder", "this is a placeholder string\0string2");
+ mkfile_u32("prop-int", TEST_VALUE_1);
+
+ end_dir();
+ }
+
+ {
+ start_dir("ss1");
+ end_dir();
+ }
+
+ end_dir();
+ }
+
+ {
+ start_dir("subnode@2");
+
+ mkfile_u32("reg", 2);
+ mkfile_u32("linux,phandle", 0x2000);
+ mkfile_u32("prop-int", TEST_VALUE_2);
+ mkfile_u32("#address-cells", 1);
+ mkfile_u32("#size-cells", 0);
+
+ {
+ start_dir("subsubnode@0");
+
+ mkfile_u32("reg", 0);
+ mkfile_u32("phandle", 0x2001);
+ mkfile_str("compatible", "subsubnode2\0subsubnode");
+ mkfile_u32("prop-int", TEST_VALUE_2);
+
+ end_dir();
+ }
+
+ {
+ start_dir("ss2");
+ end_dir();
+ }
+
+ end_dir();
+ }
+
+ PASS();
+}
diff --git a/tests/get_alias.c b/tests/get_alias.c
index 5060795..fb2c38c 100644
--- a/tests/get_alias.c
+++ b/tests/get_alias.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for fdt_get_alias()
* 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>
diff --git a/tests/get_mem_rsv.c b/tests/get_mem_rsv.c
index 1812639..f977d19 100644
--- a/tests/get_mem_rsv.c
+++ b/tests/get_mem_rsv.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for fdt_get_mem_rsv() and fdt_num_mem_rsv()
* 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>
diff --git a/tests/get_name.c b/tests/get_name.c
index c6ca9f9..5a35103 100644
--- a/tests/get_name.c
+++ b/tests/get_name.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for fdt_get_name()
* 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>
#include <stdio.h>
diff --git a/tests/get_path.c b/tests/get_path.c
index 7352976..7349898 100644
--- a/tests/get_path.c
+++ b/tests/get_path.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for fdt_get_path()
* 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>
#include <stdio.h>
@@ -42,7 +29,8 @@ static void check_path_buf(void *fdt, const char *path, int pathlen, int buflen)
memset(buf, POISON, sizeof(buf)); /* poison the buffer */
len = fdt_get_path(fdt, offset, buf, buflen);
- verbose_printf("get_path() %s -> %d -> %s\n", path, offset, buf);
+ verbose_printf("get_path() %s -> %d -> %s\n", path, offset,
+ len >= 0 ? buf : "<error>");
if (buflen <= pathlen) {
if (len != -FDT_ERR_NOSPACE)
diff --git a/tests/get_phandle.c b/tests/get_phandle.c
index 22bd7b8..157b522 100644
--- a/tests/get_phandle.c
+++ b/tests/get_phandle.c
@@ -1,22 +1,10 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for fdt_get_phandle()
* 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 <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -42,10 +30,32 @@ static void check_phandle(void *fdt, const char *path, uint32_t checkhandle)
path, phandle, checkhandle);
}
+static void check_phandle_unique(const void *fdt, uint32_t checkhandle)
+{
+ uint32_t phandle;
+ int offset = -1;
+
+ while (true) {
+ offset = fdt_next_node(fdt, offset, NULL);
+ if (offset < 0) {
+ if (offset == -FDT_ERR_NOTFOUND)
+ break;
+
+ FAIL("error looking for phandle %#x", checkhandle);
+ }
+
+ phandle = fdt_get_phandle(fdt, offset);
+
+ if (phandle == checkhandle)
+ FAIL("generated phandle already exists");
+ }
+}
+
int main(int argc, char *argv[])
{
- uint32_t max;
+ uint32_t max, phandle;
void *fdt;
+ int err;
test_init(argc, argv);
fdt = load_blob_arg(argc, argv);
@@ -54,10 +64,24 @@ int main(int argc, char *argv[])
check_phandle(fdt, "/subnode@2", PHANDLE_1);
check_phandle(fdt, "/subnode@2/subsubnode@0", PHANDLE_2);
+ err = fdt_find_max_phandle(fdt, &max);
+ if (err < 0)
+ FAIL("fdt_find_max_phandle returned %d instead of 0\n", err);
+
+ if (max != PHANDLE_2)
+ FAIL("fdt_find_max_phandle found 0x%x instead of 0x%x", max,
+ PHANDLE_2);
+
max = fdt_get_max_phandle(fdt);
if (max != PHANDLE_2)
FAIL("fdt_get_max_phandle returned 0x%x instead of 0x%x\n",
max, PHANDLE_2);
+ err = fdt_generate_phandle(fdt, &phandle);
+ if (err < 0)
+ FAIL("failed to generate phandle: %d", err);
+
+ check_phandle_unique(fdt, phandle);
+
PASS();
}
diff --git a/tests/get_prop_offset.c b/tests/get_prop_offset.c
new file mode 100644
index 0000000..cff3c18
--- /dev/null
+++ b/tests/get_prop_offset.c
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for fdt_getprop_by_offset()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+
+#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[])
+{
+ bool found_prop_int = false;
+ bool found_prop_str = false;
+ int poffset;
+ void *fdt;
+
+ test_init(argc, argv);
+ fdt = load_blob_arg(argc, argv);
+
+ fdt_for_each_property_offset(poffset, fdt, 0) {
+ if (check_get_prop_offset_cell(fdt, poffset, "prop-int",
+ TEST_VALUE_1))
+ found_prop_int = true;
+ if (check_get_prop_offset(fdt, poffset, "prop-str",
+ strlen(TEST_STRING_1) + 1,
+ TEST_STRING_1))
+ found_prop_str = true;
+ }
+ if (!found_prop_int)
+ FAIL("Property 'prop-int' not found");
+ if (!found_prop_str)
+ FAIL("Property 'prop-str' not found");
+
+ PASS();
+}
diff --git a/tests/getprop.c b/tests/getprop.c
index 6255bad..cccc8e2 100644
--- a/tests/getprop.c
+++ b/tests/getprop.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for fdt_getprop()
* 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>
diff --git a/tests/incbin.c b/tests/incbin.c
index 4100ba0..36ff669 100644
--- a/tests/incbin.c
+++ b/tests/incbin.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for string escapes in dtc
* 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>
#include <stdio.h>
@@ -65,8 +52,11 @@ int main(int argc, char *argv[])
test_init(argc, argv);
- incbin = load_file("incbin.bin", &len);
- fdt = load_blob_arg(argc, argv);
+ if (argc != 3)
+ CONFIG("Usage: %s <incbin file> <dtb file>", argv[0]);
+
+ incbin = load_file(argv[1], &len);
+ fdt = load_blob(argv[2]);
check_getprop(fdt, 0, "incbin", len, incbin);
check_getprop(fdt, 0, "incbin-partial", 17, incbin + 13);
diff --git a/tests/integer-expressions.c b/tests/integer-expressions.c
index ed1f967..6f33d81 100644
--- a/tests/integer-expressions.c
+++ b/tests/integer-expressions.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* Testcase for dtc expression support
*
* 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>
@@ -97,7 +84,7 @@ int main(int argc, char *argv[])
res = fdt_getprop(fdt, 0, "expressions", &reslen);
if (!res)
- FAIL("Error retreiving expression results: %s\n",
+ FAIL("Error retrieving expression results: %s\n",
fdt_strerror(reslen));
if (reslen != (ARRAY_SIZE(expr_table) * sizeof(uint32_t)))
diff --git a/tests/mangle-layout.c b/tests/mangle-layout.c
index a76e51e..59b1604 100644
--- a/tests/mangle-layout.c
+++ b/tests/mangle-layout.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase/tool for rearranging blocks of a dtb
* 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>
@@ -44,13 +31,9 @@ static void expand_buf(struct bufstate *buf, int newsize)
static void new_header(struct bufstate *buf, int version, const void *fdt)
{
- int hdrsize;
+ int hdrsize = fdt_header_size_(version);
- if (version == 16)
- hdrsize = FDT_V16_SIZE;
- else if (version == 17)
- hdrsize = FDT_V17_SIZE;
- else
+ if ((version != 16) && (version != 17))
CONFIG("Bad version %d", version);
expand_buf(buf, hdrsize);
diff --git a/tests/mangle-layout.supp b/tests/mangle-layout.supp
deleted file mode 100644
index 2890420..0000000
--- a/tests/mangle-layout.supp
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- uninitialized alignment gaps can be dumped to output
- Memcheck:Param
- write(buf)
- obj:/lib/ld-*.so
- fun:main
-}
diff --git a/tests/move_and_save.c b/tests/move_and_save.c
index 393b60a..a89f8de 100644
--- a/tests/move_and_save.c
+++ b/tests/move_and_save.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Basic testcase for read-only access
* 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>
diff --git a/tests/multilabel.dts b/tests/multilabel.dts
index 77da06c..d80ebe1 100644
--- a/tests/multilabel.dts
+++ b/tests/multilabel.dts
@@ -41,4 +41,9 @@ m1: mq: /memreserve/ 0 0x1000;
n2 = &n2;
n3 = &n3;
};
+
+ node6 {
+ linux,phandle = <0xfffffffe>;
+ phandle = <0xfffffffe>;
+ };
};
diff --git a/tests/multilabel_merge.dts b/tests/multilabel_merge.dts
index 3e80298..a27d856 100644
--- a/tests/multilabel_merge.dts
+++ b/tests/multilabel_merge.dts
@@ -39,6 +39,11 @@ m1: mq: /memreserve/ 0 0x1000;
n2 = &n2;
n3 = &n3;
};
+
+ node6 {
+ linux,phandle = <0xfffffffe>;
+ phandle = <0xfffffffe>;
+ };
};
/ {
diff --git a/tests/node_check_compatible.c b/tests/node_check_compatible.c
index 4bdf091..81efe62 100644
--- a/tests/node_check_compatible.c
+++ b/tests/node_check_compatible.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for fdt_node_check_compatible()
* 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>
@@ -45,6 +32,23 @@ static void check_compatible(const void *fdt, const char *path,
FAIL("%s is not compatible with \"%s\"", path, compat);
}
+static void check_not_compatible(const void *fdt, const char *path,
+ const char *compat)
+{
+ int offset, err;
+
+ offset = fdt_path_offset(fdt, path);
+ if (offset < 0)
+ FAIL("fdt_path_offset(%s): %s", path, fdt_strerror(offset));
+
+ err = fdt_node_check_compatible(fdt, offset, compat);
+ if (err < 0)
+ FAIL("fdt_node_check_compatible(%s): %s", path,
+ fdt_strerror(err));
+ if (err == 0)
+ FAIL("%s is incorrectly compatible with \"%s\"", path, compat);
+}
+
int main(int argc, char *argv[])
{
void *fdt;
@@ -55,8 +59,10 @@ int main(int argc, char *argv[])
check_compatible(fdt, "/", "test_tree1");
check_compatible(fdt, "/subnode@1/subsubnode", "subsubnode1");
check_compatible(fdt, "/subnode@1/subsubnode", "subsubnode");
+ check_not_compatible(fdt, "/subnode@1/subsubnode", "subsubnode2");
check_compatible(fdt, "/subnode@2/subsubnode", "subsubnode2");
check_compatible(fdt, "/subnode@2/subsubnode", "subsubnode");
+ check_not_compatible(fdt, "/subnode@2/subsubnode", "subsubnode1");
PASS();
}
diff --git a/tests/node_offset_by_compatible.c b/tests/node_offset_by_compatible.c
index f62b591..a9e6783 100644
--- a/tests/node_offset_by_compatible.c
+++ b/tests/node_offset_by_compatible.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for fdt_node_offset_by_compatible()
* 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>
#include <stdio.h>
diff --git a/tests/node_offset_by_phandle.c b/tests/node_offset_by_phandle.c
index becff0f..60af78a 100644
--- a/tests/node_offset_by_phandle.c
+++ b/tests/node_offset_by_phandle.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for fdt_node_offset_by_phandle()
* 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>
#include <stdio.h>
diff --git a/tests/node_offset_by_prop_value.c b/tests/node_offset_by_prop_value.c
index 286f1e7..48ab1d9 100644
--- a/tests/node_offset_by_prop_value.c
+++ b/tests/node_offset_by_prop_value.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for fdt_path_offset()
* 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>
#include <stdio.h>
diff --git a/tests/nop_node.c b/tests/nop_node.c
index c316444..ee972d2 100644
--- a/tests/nop_node.c
+++ b/tests/nop_node.c
@@ -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>
diff --git a/tests/nop_property.c b/tests/nop_property.c
index 644b0a6..6593828 100644
--- a/tests/nop_property.c
+++ b/tests/nop_property.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for fdt_nop_property()
* 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>
diff --git a/tests/nopulate.c b/tests/nopulate.c
index 94ce8ad..2ae1753 100644
--- a/tests/nopulate.c
+++ b/tests/nopulate.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase/tool for rearranging blocks of a dtb
* 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>
diff --git a/tests/notfound.c b/tests/notfound.c
index dc623d6..70acbcd 100644
--- a/tests/notfound.c
+++ b/tests/notfound.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for behaviour on searching for a non-existent 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>
#include <stdio.h>
diff --git a/tests/omit-no-ref.dts b/tests/omit-no-ref.dts
new file mode 100644
index 0000000..8ace232
--- /dev/null
+++ b/tests/omit-no-ref.dts
@@ -0,0 +1,26 @@
+/dts-v1/;
+
+/ {
+ test-phandle = <&node3>;
+ test-path = &node4;
+
+ /omit-if-no-ref/ node1: node1 {
+ bar = <0xdeadbeef>;
+ };
+
+ node2: node2 {
+ foo = <0x42>;
+ };
+
+ node3: node3 {
+ test = "test";
+ };
+
+ node4: node4 {
+ test;
+ };
+};
+
+/omit-if-no-ref/ &node2;
+/omit-if-no-ref/ &node3;
+/omit-if-no-ref/ &node4;
diff --git a/tests/open_pack.c b/tests/open_pack.c
index 407ef6c..6ed4df7 100644
--- a/tests/open_pack.c
+++ b/tests/open_pack.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Basic testcase for read-only access
* 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>
diff --git a/tests/open_pack.supp b/tests/open_pack.supp
deleted file mode 100644
index c954fe7..0000000
--- a/tests/open_pack.supp
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- opened blob dumps uninitialized data
- Memcheck:Param
- write(buf)
- obj:/lib/ld-*.so
- fun:main
-}
diff --git a/tests/overlay.c b/tests/overlay.c
index 3093eec..91afa72 100644
--- a/tests/overlay.c
+++ b/tests/overlay.c
@@ -1,22 +1,9 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for DT overlays()
* Copyright (C) 2016 Free Electrons
* Copyright (C) 2016 NextThing Co.
- *
- * 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>
diff --git a/tests/overlay_bad_fixup.c b/tests/overlay_bad_fixup.c
index 5014f5e..029bc79 100644
--- a/tests/overlay_bad_fixup.c
+++ b/tests/overlay_bad_fixup.c
@@ -1,22 +1,9 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for DT overlays()
* Copyright (C) 2016 Free Electrons
* Copyright (C) 2016 NextThing Co.
- *
- * 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>
diff --git a/tests/overlay_base.dts b/tests/overlay_base.dts
index 2603adb..a5e55b2 100644
--- a/tests/overlay_base.dts
+++ b/tests/overlay_base.dts
@@ -14,6 +14,10 @@
subtest: sub-test-node {
sub-test-property;
+
+ subtest_with_long_path: sub-test-node-with-very-long-target-path {
+ long-test-path-property;
+ };
};
};
};
diff --git a/tests/overlay_overlay.dts b/tests/overlay_overlay.dts
index b6d841b..c4ef1d4 100644
--- a/tests/overlay_overlay.dts
+++ b/tests/overlay_overlay.dts
@@ -9,78 +9,44 @@
/dts-v1/;
/plugin/;
-/ {
- /* Test that we can change an int by another */
- fragment@0 {
- target = <&test>;
-
- __overlay__ {
- test-int-property = <43>;
- };
- };
-
- /* Test that we can replace a string by a longer one */
- fragment@1 {
- target = <&test>;
-
- __overlay__ {
- test-str-property = "foobar";
- };
- };
-
- /* Test that we add a new property */
- fragment@2 {
- target = <&test>;
-
- __overlay__ {
- test-str-property-2 = "foobar2";
- };
- };
-
- /* Test that we add a new node (by phandle) */
- fragment@3 {
- target = <&test>;
+/* Test that we can change an int by another */
+&test {
+ test-int-property = <43>;
+};
- __overlay__ {
- new-node {
- new-property;
- };
- };
- };
+/* Test that we can replace a string by a longer one */
+&test {
+ test-str-property = "foobar";
+};
- fragment@5 {
- target = <&test>;
+/* Test that we add a new property */
+&test {
+ test-str-property-2 = "foobar2";
+};
- __overlay__ {
- local: new-local-node {
- new-property;
- };
- };
+/* Test that we add a new node (by phandle) */
+&test {
+ new-node {
+ new-property;
};
+};
- fragment@6 {
- target = <&test>;
-
- __overlay__ {
- test-phandle = <&test>, <&local>;
- };
+&test {
+ local: new-local-node {
+ new-property;
};
+};
- fragment@7 {
- target = <&test>;
-
- __overlay__ {
- test-several-phandle = <&local>, <&local>;
- };
- };
+&test {
+ test-phandle = <&test>, <&local>;
+};
- fragment@8 {
- target = <&test>;
+&test {
+ test-several-phandle = <&local>, <&local>;
+};
- __overlay__ {
- sub-test-node {
- new-sub-test-property;
- };
- };
+&test {
+ sub-test-node {
+ new-sub-test-property;
};
};
diff --git a/tests/overlay_overlay_bypath.dts b/tests/overlay_overlay_bypath.dts
new file mode 100644
index 0000000..f23e7b6
--- /dev/null
+++ b/tests/overlay_overlay_bypath.dts
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2016 NextThing Co
+ * Copyright (c) 2016 Free Electrons
+ * Copyright (c) 2016 Konsulko Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/dts-v1/;
+/plugin/;
+
+/* Test that we can change an int by another */
+&{/test-node} {
+ test-int-property = <43>;
+};
+
+/* Test that we can replace a string by a longer one */
+&{/test-node} {
+ test-str-property = "foobar";
+};
+
+/* Test that we add a new property */
+&{/test-node} {
+ test-str-property-2 = "foobar2";
+};
+
+/* Test that we add a new node (by phandle) */
+&{/test-node} {
+ new-node {
+ new-property;
+ };
+};
+
+&{/} {
+ local: new-local-node {
+ new-property;
+ };
+};
+
+&{/} {
+ test-several-phandle = <&local>, <&local>;
+};
+
+&{/test-node} {
+ sub-test-node {
+ new-sub-test-property;
+ };
+};
diff --git a/tests/overlay_overlay_local_merge.dts b/tests/overlay_overlay_local_merge.dts
new file mode 100644
index 0000000..3ee622d
--- /dev/null
+++ b/tests/overlay_overlay_local_merge.dts
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2016 NextThing Co
+ * Copyright (c) 2016 Free Electrons
+ * Copyright (c) 2016 Konsulko Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/dts-v1/;
+/plugin/;
+
+&test {
+ parent: new-node {
+ parent-property;
+ };
+};
+
+&parent {
+ new-merged-property;
+ new-merged-node {
+ new-property;
+ };
+};
+
+&{/} {
+ new-root-node {
+ new-root-node-property;
+ };
+};
diff --git a/tests/overlay_overlay_long_path.dts b/tests/overlay_overlay_long_path.dts
new file mode 100644
index 0000000..4f0d40b
--- /dev/null
+++ b/tests/overlay_overlay_long_path.dts
@@ -0,0 +1,32 @@
+/dts-v1/;
+/plugin/;
+
+&subtest_with_long_path {
+ lpath_0: test-0 {
+ prop = "lpath";
+ };
+
+ lpath_1: test-1 {
+ prop = "lpath";
+ };
+
+ lpath_2: test-2 {
+ prop = "lpath";
+ };
+
+ lpath_3: test-3 {
+ prop = "lpath";
+ };
+
+ lpath_4: test-4 {
+ prop = "lpath";
+ };
+
+ lpath_5: test-5 {
+ prop = "lpath";
+ };
+
+ lpath_6: test-6 {
+ prop = "lpath";
+ };
+};
diff --git a/tests/overlay_overlay_manual_fixups.dts b/tests/overlay_overlay_manual_fixups.dts
index e34c4fc..a5715b6 100644
--- a/tests/overlay_overlay_manual_fixups.dts
+++ b/tests/overlay_overlay_manual_fixups.dts
@@ -50,7 +50,7 @@
};
};
- fragment@5 {
+ fragment@4 {
target = <0xffffffff /*&test*/>;
__overlay__ {
@@ -60,7 +60,7 @@
};
};
- fragment@6 {
+ fragment@5 {
target = <0xffffffff /*&test*/>;
__overlay__ {
@@ -68,7 +68,7 @@
};
};
- fragment@7 {
+ fragment@6 {
target = <0xffffffff /*&test*/>;
__overlay__ {
@@ -76,7 +76,7 @@
};
};
- fragment@8 {
+ fragment@7 {
target = <0xffffffff /*&test*/>;
__overlay__ {
@@ -86,27 +86,27 @@
};
};
+ __fixups__ {
+ test = "/fragment@0:target:0",
+ "/fragment@1:target:0",
+ "/fragment@2:target:0",
+ "/fragment@3:target:0",
+ "/fragment@4:target:0",
+ "/fragment@5:target:0",
+ "/fragment@5/__overlay__:test-phandle:0",
+ "/fragment@6:target:0",
+ "/fragment@7:target:0";
+ };
__local_fixups__ {
- fragment@6 {
+ fragment@5 {
__overlay__ {
test-phandle = <4>;
};
};
- fragment@7 {
+ fragment@6 {
__overlay__ {
test-several-phandle = <0 4>;
};
};
};
- __fixups__ {
- test = "/fragment@0:target:0",
- "/fragment@1:target:0",
- "/fragment@2:target:0",
- "/fragment@3:target:0",
- "/fragment@5:target:0",
- "/fragment@6:target:0",
- "/fragment@6/__overlay__:test-phandle:0",
- "/fragment@7:target:0",
- "/fragment@8:target:0";
- };
};
diff --git a/tests/overlay_overlay_nosugar.dts b/tests/overlay_overlay_nosugar.dts
new file mode 100644
index 0000000..b6d841b
--- /dev/null
+++ b/tests/overlay_overlay_nosugar.dts
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2016 NextThing Co
+ * Copyright (c) 2016 Free Electrons
+ * Copyright (c) 2016 Konsulko Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/dts-v1/;
+/plugin/;
+
+/ {
+ /* Test that we can change an int by another */
+ fragment@0 {
+ target = <&test>;
+
+ __overlay__ {
+ test-int-property = <43>;
+ };
+ };
+
+ /* Test that we can replace a string by a longer one */
+ fragment@1 {
+ target = <&test>;
+
+ __overlay__ {
+ test-str-property = "foobar";
+ };
+ };
+
+ /* Test that we add a new property */
+ fragment@2 {
+ target = <&test>;
+
+ __overlay__ {
+ test-str-property-2 = "foobar2";
+ };
+ };
+
+ /* Test that we add a new node (by phandle) */
+ fragment@3 {
+ target = <&test>;
+
+ __overlay__ {
+ new-node {
+ new-property;
+ };
+ };
+ };
+
+ fragment@5 {
+ target = <&test>;
+
+ __overlay__ {
+ local: new-local-node {
+ new-property;
+ };
+ };
+ };
+
+ fragment@6 {
+ target = <&test>;
+
+ __overlay__ {
+ test-phandle = <&test>, <&local>;
+ };
+ };
+
+ fragment@7 {
+ target = <&test>;
+
+ __overlay__ {
+ test-several-phandle = <&local>, <&local>;
+ };
+ };
+
+ fragment@8 {
+ target = <&test>;
+
+ __overlay__ {
+ sub-test-node {
+ new-sub-test-property;
+ };
+ };
+ };
+};
diff --git a/tests/parent_offset.c b/tests/parent_offset.c
index d4ab3cf..a935a53 100644
--- a/tests/parent_offset.c
+++ b/tests/parent_offset.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for fdt_parent_offset()
* 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>
#include <stdio.h>
diff --git a/tests/path-references.c b/tests/path-references.c
index 5e332e8..4db61a5 100644
--- a/tests/path-references.c
+++ b/tests/path-references.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for string references in dtc
* 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>
#include <stdio.h>
diff --git a/tests/path-references.dts b/tests/path-references.dts
index 8c66d80..1fb7d70 100644
--- a/tests/path-references.dts
+++ b/tests/path-references.dts
@@ -16,7 +16,7 @@
foobar {
n3: baz {
ref = &{/foo/baz};
- lref = &n4;
+ lref = start: &n4 end:;
};
};
foo {
diff --git a/tests/path_offset.c b/tests/path_offset.c
index bfebe9f..82527d4 100644
--- a/tests/path_offset.c
+++ b/tests/path_offset.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for fdt_path_offset()
* 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>
#include <stdio.h>
diff --git a/tests/path_offset_aliases.c b/tests/path_offset_aliases.c
index 78d5a46..0112e72 100644
--- a/tests/path_offset_aliases.c
+++ b/tests/path_offset_aliases.c
@@ -1,22 +1,9 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for fdt_path_offset()
* Copyright (C) 2006 David Gibson, IBM Corporation.
* Copyright 2008 Kumar Gala, Freescale Semiconductor, 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 <stdlib.h>
#include <stdio.h>
diff --git a/tests/pci-bridge-bad1.dts b/tests/pci-bridge-bad1.dts
new file mode 100644
index 0000000..17aac04
--- /dev/null
+++ b/tests/pci-bridge-bad1.dts
@@ -0,0 +1,16 @@
+/dts-v1/;
+
+/ {
+ compatible = "example,pci-bridge-ok";
+ #address-cells = < 2 >;
+ #size-cells = < 2 >;
+ abadname@0 {
+ device_type = "pci";
+ compatible = "example,pci-bridge";
+ #address-cells = < 3 >;
+ #size-cells = < 2 >;
+ reg = <0 0 0 0x1000>;
+ bus-range = <0 0xff>;
+ ranges = <0 0 0 0 0 0 0x10000>;
+ };
+};
diff --git a/tests/pci-bridge-bad2.dts b/tests/pci-bridge-bad2.dts
new file mode 100644
index 0000000..a7e5c05
--- /dev/null
+++ b/tests/pci-bridge-bad2.dts
@@ -0,0 +1,16 @@
+/dts-v1/;
+
+/ {
+ compatible = "example,pci-bridge-ok";
+ #address-cells = < 2 >;
+ #size-cells = < 2 >;
+ p@0 {
+ device_type = "pci";
+ compatible = "example,pci-bridge";
+ #address-cells = < 3 >;
+ #size-cells = < 2 >;
+ reg = <0 0 0 0x1000>;
+ bus-range = <0 0xff>;
+ ranges = <0 0 0 0 0 0 0x10000>;
+ };
+};
diff --git a/tests/pci-bridge-ok.dts b/tests/pci-bridge-ok.dts
new file mode 100644
index 0000000..02e32e0
--- /dev/null
+++ b/tests/pci-bridge-ok.dts
@@ -0,0 +1,25 @@
+/dts-v1/;
+
+/ {
+ compatible = "example,pci-bridge-ok";
+ #address-cells = < 2 >;
+ #size-cells = < 2 >;
+ pci@0 {
+ device_type = "pci";
+ compatible = "example,pci-bridge";
+ #address-cells = < 3 >;
+ #size-cells = < 2 >;
+ reg = <0 0 0 0x1000>;
+ bus-range = <0 0xff>;
+ ranges = <0 0 0 0 0 0 0x10000>;
+ };
+ pcie@10000000000 {
+ device_type = "pci";
+ compatible = "example,pcie-bridge";
+ #address-cells = < 3 >;
+ #size-cells = < 2 >;
+ reg = <0x10 0x00000000 0 0x1000>;
+ bus-range = <0 0xff>;
+ ranges = <0 0 0 0 0 0 0x10000>;
+ };
+};
diff --git a/tests/phandle_format.c b/tests/phandle_format.c
index 5874ae7..d00618f 100644
--- a/tests/phandle_format.c
+++ b/tests/phandle_format.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for phandle format options
* Copyright (C) 2009 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>
#include <stdio.h>
diff --git a/tests/property_iterate.c b/tests/property_iterate.c
index b5cedbe..9a67f49 100644
--- a/tests/property_iterate.c
+++ b/tests/property_iterate.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Tests that fdt_next_subnode() works as expected
@@ -5,20 +6,6 @@
* Copyright (C) 2013 Google, Inc
*
* 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>
diff --git a/tests/propname_escapes.c b/tests/propname_escapes.c
index e91bd99..3e41e63 100644
--- a/tests/propname_escapes.c
+++ b/tests/propname_escapes.c
@@ -1,22 +1,9 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for fdt_getprop()
* Copyright (C) 2006 David Gibson, IBM Corporation.
* Copyright (C) 2012 NVIDIA CORPORATION. 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>
diff --git a/tests/pylibfdt_tests.py b/tests/pylibfdt_tests.py
index ae392bb..64b5bd1 100644
--- a/tests/pylibfdt_tests.py
+++ b/tests/pylibfdt_tests.py
@@ -1,61 +1,48 @@
+# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
# pylibfdt - Tests for 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.
-#
+import struct
import sys
import types
import unittest
-sys.path.append('../pylibfdt')
+sys.path.insert(0, '../pylibfdt')
import libfdt
-from libfdt import FdtException, QUIET_NOTFOUND, QUIET_ALL
+from libfdt import Fdt, FdtSw, FdtException, QUIET_NOTFOUND, QUIET_ALL
+
+TEST_ADDR_1H = 0xdeadbeef
+TEST_ADDR_1L = 0x00000000
+TEST_ADDR_1 = (TEST_ADDR_1H << 32) | TEST_ADDR_1L
+TEST_ADDR_1 = 0x8000000000000000
+TEST_SIZE_1H = 0x00000000
+TEST_SIZE_1L = 0x00100000
+TEST_SIZE_1 = (TEST_SIZE_1H << 32) | TEST_SIZE_1L
+TEST_ADDR_2H = 0
+TEST_ADDR_2L = 123456789
+TEST_ADDR_2 = (TEST_ADDR_2H << 32) | TEST_ADDR_2L
+TEST_SIZE_2H = 0
+TEST_SIZE_2L = 0o10000
+TEST_SIZE_2 = (TEST_SIZE_2H << 32) | TEST_SIZE_2L
+
+TEST_VALUE_1 = 0xdeadbeef
+TEST_VALUE_2 = 123456789
+
+TEST_VALUE64_1H = 0xdeadbeef
+TEST_VALUE64_1L = 0x01abcdef
+TEST_VALUE64_1 = (TEST_VALUE64_1H << 32) | TEST_VALUE64_1L
+
+PHANDLE_1 = 0x2000
+PHANDLE_2 = 0x2001
+
+TEST_BYTES_1 = b'hello world'
+
+TEST_STRING_1 = 'hello world'
+TEST_STRING_2 = 'hi world'
+TEST_STRING_3 = u'unicode \u01d3'
+
def get_err(err_code):
"""Convert an error code into an error message
@@ -66,7 +53,7 @@ def get_err(err_code):
Returns:
String error code
"""
- return 'pylibfdt error %d: %s' % (-err_code, libfdt.fdt_strerror(-err_code))
+ return 'pylibfdt error %d: %s' % (-err_code, libfdt.strerror(-err_code))
def _ReadFdt(fname):
"""Read a device tree file into an Fdt object, ready for use
@@ -77,10 +64,11 @@ def _ReadFdt(fname):
Returns:
Fdt bytearray suitable for passing to libfdt functions
"""
- return libfdt.Fdt(open(fname).read())
+ with open(fname, mode='rb') as f:
+ return libfdt.Fdt(f.read())
-class PyLibfdtTests(unittest.TestCase):
- """Test class for pylibfdt
+class PyLibfdtBasicTests(unittest.TestCase):
+ """Test class for basic pylibfdt access functions
Properties:
fdt: Device tree file used for testing
@@ -89,6 +77,8 @@ class PyLibfdtTests(unittest.TestCase):
def setUp(self):
"""Read in the device tree we use for testing"""
self.fdt = _ReadFdt('test_tree1.dtb')
+ self.fdt2 = _ReadFdt('test_props.dtb')
+ self.fdt3 = _ReadFdt('aliases.dtb')
def GetPropList(self, node_path):
"""Read a list of properties from a node
@@ -108,24 +98,54 @@ class PyLibfdtTests(unittest.TestCase):
poffset = self.fdt.next_property_offset(poffset, QUIET_NOTFOUND)
return prop_list
+ def GetSubnodes(self, node_path):
+ """Read a list of subnodes from a node
+
+ Args:
+ node_path: Full path to node, e.g. '/subnode@1/subsubnode'
+
+ Returns:
+ List of subnode names for that node, e.g. ['subsubnode', 'ss1']
+ """
+ subnode_list = []
+ node = self.fdt.path_offset(node_path)
+ offset = self.fdt.first_subnode(node, QUIET_NOTFOUND)
+ while offset > 0:
+ name = self.fdt.get_name(offset)
+ subnode_list.append(name)
+ offset = self.fdt.next_subnode(offset, QUIET_NOTFOUND)
+ return subnode_list
+
def testImport(self):
"""Check that we can import the library correctly"""
- self.assertEquals(type(libfdt), types.ModuleType)
+ self.assertEqual(type(libfdt), types.ModuleType)
def testBadFdt(self):
"""Check that a filename provided accidentally is not accepted"""
with self.assertRaises(FdtException) as e:
- fdt = libfdt.Fdt('a string')
- self.assertEquals(e.exception.err, -libfdt.BADMAGIC)
+ fdt = libfdt.Fdt(b'a string')
+ self.assertEqual(e.exception.err, -libfdt.BADMAGIC)
+
+ def testSubnodeOffset(self):
+ """check that we can locate a subnode by name"""
+ node1 = self.fdt.path_offset('/subnode@1')
+ self.assertEqual(self.fdt.subnode_offset(0, 'subnode@1'), node1)
+
+ with self.assertRaises(FdtException) as e:
+ self.fdt.subnode_offset(0, 'missing')
+ self.assertEqual(e.exception.err, -libfdt.NOTFOUND)
+
+ node2 = self.fdt.path_offset('/subnode@1/subsubnode')
+ self.assertEqual(self.fdt.subnode_offset(node1, 'subsubnode'), node2)
def testPathOffset(self):
"""Check that we can find the offset of a node"""
- self.assertEquals(self.fdt.path_offset('/'), 0)
+ self.assertEqual(self.fdt.path_offset('/'), 0)
self.assertTrue(self.fdt.path_offset('/subnode@1') > 0)
with self.assertRaises(FdtException) as e:
self.fdt.path_offset('/wibble')
- self.assertEquals(e.exception.err, -libfdt.NOTFOUND)
- self.assertEquals(self.fdt.path_offset('/wibble', QUIET_NOTFOUND),
+ self.assertEqual(e.exception.err, -libfdt.NOTFOUND)
+ self.assertEqual(self.fdt.path_offset('/wibble', QUIET_NOTFOUND),
-libfdt.NOTFOUND)
def testPropertyOffset(self):
@@ -136,54 +156,54 @@ class PyLibfdtTests(unittest.TestCase):
next_offset = self.fdt.next_property_offset(offset)
self.assertTrue(next_offset > offset)
offset = next_offset
- self.assertEquals(self.fdt.next_property_offset(offset, QUIET_NOTFOUND),
+ self.assertEqual(self.fdt.next_property_offset(offset, QUIET_NOTFOUND),
-libfdt.NOTFOUND)
def testPropertyOffsetExceptions(self):
"""Check that exceptions are raised as expected"""
with self.assertRaises(FdtException) as e:
self.fdt.first_property_offset(107)
- self.assertEquals(e.exception.err, -libfdt.BADOFFSET)
+ self.assertEqual(e.exception.err, -libfdt.BADOFFSET)
# Quieten the NOTFOUND exception and check that a BADOFFSET
# exception is still raised.
with self.assertRaises(FdtException) as e:
self.fdt.first_property_offset(107, QUIET_NOTFOUND)
- self.assertEquals(e.exception.err, -libfdt.BADOFFSET)
+ self.assertEqual(e.exception.err, -libfdt.BADOFFSET)
with self.assertRaises(FdtException) as e:
self.fdt.next_property_offset(107, QUIET_NOTFOUND)
- self.assertEquals(e.exception.err, -libfdt.BADOFFSET)
+ self.assertEqual(e.exception.err, -libfdt.BADOFFSET)
# Check that NOTFOUND can be quietened.
node = self.fdt.path_offset('/subnode@1/ss1')
- self.assertEquals(self.fdt.first_property_offset(node, QUIET_NOTFOUND),
+ self.assertEqual(self.fdt.first_property_offset(node, QUIET_NOTFOUND),
-libfdt.NOTFOUND)
with self.assertRaises(FdtException) as e:
self.fdt.first_property_offset(node)
- self.assertEquals(e.exception.err, -libfdt.NOTFOUND)
+ self.assertEqual(e.exception.err, -libfdt.NOTFOUND)
def testGetName(self):
"""Check that we can get the name of a node"""
- self.assertEquals(self.fdt.get_name(0), '')
+ self.assertEqual(self.fdt.get_name(0), '')
node = self.fdt.path_offset('/subnode@1/subsubnode')
- self.assertEquals(self.fdt.get_name(node), 'subsubnode')
+ self.assertEqual(self.fdt.get_name(node), 'subsubnode')
with self.assertRaises(FdtException) as e:
self.fdt.get_name(-2)
- self.assertEquals(e.exception.err, -libfdt.BADOFFSET)
+ self.assertEqual(e.exception.err, -libfdt.BADOFFSET)
def testGetPropertyByOffset(self):
"""Check that we can read the name and contents of a property"""
root = 0
poffset = self.fdt.first_property_offset(root)
prop = self.fdt.get_property_by_offset(poffset)
- self.assertEquals(prop.name, 'compatible')
- self.assertEquals(prop.value, 'test_tree1\0')
+ self.assertEqual(prop.name, 'compatible')
+ self.assertEqual(prop, b'test_tree1\0')
with self.assertRaises(FdtException) as e:
self.fdt.get_property_by_offset(-2)
- self.assertEquals(e.exception.err, -libfdt.BADOFFSET)
- self.assertEquals(
+ self.assertEqual(e.exception.err, -libfdt.BADOFFSET)
+ self.assertEqual(
-libfdt.BADOFFSET,
self.fdt.get_property_by_offset(-2, [libfdt.BADOFFSET]))
@@ -191,23 +211,41 @@ class PyLibfdtTests(unittest.TestCase):
"""Check that we can read the contents of a property by name"""
root = self.fdt.path_offset('/')
value = self.fdt.getprop(root, "compatible")
- self.assertEquals(value, 'test_tree1\0')
- self.assertEquals(-libfdt.NOTFOUND, self.fdt.getprop(root, 'missing',
+ self.assertEqual(value, b'test_tree1\0')
+ self.assertEqual(-libfdt.NOTFOUND, self.fdt.getprop(root, 'missing',
QUIET_NOTFOUND))
with self.assertRaises(FdtException) as e:
self.fdt.getprop(root, 'missing')
- self.assertEquals(e.exception.err, -libfdt.NOTFOUND)
+ self.assertEqual(e.exception.err, -libfdt.NOTFOUND)
node = self.fdt.path_offset('/subnode@1/subsubnode')
value = self.fdt.getprop(node, "compatible")
- self.assertEquals(value, 'subsubnode1\0subsubnode\0')
+ self.assertEqual(value, b'subsubnode1\0subsubnode\0')
def testStrError(self):
"""Check that we can get an error string"""
- self.assertEquals(libfdt.strerror(-libfdt.NOTFOUND),
+ self.assertEqual(libfdt.strerror(-libfdt.NOTFOUND),
'FDT_ERR_NOTFOUND')
+ def testNextNodeOffset(self):
+ """Check that we can walk through nodes"""
+ node_list = []
+ node = 0
+ depth = 0
+ while depth >= 0:
+ node_list.append([depth, self.fdt.get_name(node)])
+ node, depth = self.fdt.next_node(node, depth, (libfdt.BADOFFSET,))
+ self.assertEqual(node_list, [
+ [0, ''],
+ [1, 'subnode@1'],
+ [2, 'subsubnode'],
+ [2, 'ss1'],
+ [1, 'subnode@2'],
+ [2, 'subsubnode@0'],
+ [2, 'ss2'],
+ ])
+
def testFirstNextSubnodeOffset(self):
"""Check that we can walk through subnodes"""
node_list = []
@@ -215,74 +253,340 @@ class PyLibfdtTests(unittest.TestCase):
while node >= 0:
node_list.append(self.fdt.get_name(node))
node = self.fdt.next_subnode(node, QUIET_NOTFOUND)
- self.assertEquals(node_list, ['subnode@1', 'subnode@2'])
+ self.assertEqual(node_list, ['subnode@1', 'subnode@2'])
def testFirstNextSubnodeOffsetExceptions(self):
"""Check except handling for first/next subnode functions"""
node = self.fdt.path_offset('/subnode@1/subsubnode', QUIET_NOTFOUND)
- self.assertEquals(self.fdt.first_subnode(node, QUIET_NOTFOUND),
+ self.assertEqual(self.fdt.first_subnode(node, QUIET_NOTFOUND),
-libfdt.NOTFOUND)
with self.assertRaises(FdtException) as e:
self.fdt.first_subnode(node)
- self.assertEquals(e.exception.err, -libfdt.NOTFOUND)
+ self.assertEqual(e.exception.err, -libfdt.NOTFOUND)
node = self.fdt.path_offset('/subnode@1/ss1', QUIET_NOTFOUND)
- self.assertEquals(self.fdt.next_subnode(node, QUIET_NOTFOUND),
+ self.assertEqual(self.fdt.next_subnode(node, QUIET_NOTFOUND),
-libfdt.NOTFOUND)
with self.assertRaises(FdtException) as e:
self.fdt.next_subnode(node)
- self.assertEquals(e.exception.err, -libfdt.NOTFOUND)
+ self.assertEqual(e.exception.err, -libfdt.NOTFOUND)
def testDeleteProperty(self):
"""Test that we can delete a property"""
node_name = '/subnode@1'
- self.assertEquals(self.GetPropList(node_name),
+ self.assertEqual(self.GetPropList(node_name),
['compatible', 'reg', 'prop-int'])
node = self.fdt.path_offset('/%s' % node_name)
- self.assertEquals(self.fdt.delprop(node, 'reg'), 0)
- self.assertEquals(self.GetPropList(node_name),
+ self.assertEqual(self.fdt.delprop(node, 'reg'), 0)
+ self.assertEqual(self.GetPropList(node_name),
['compatible', 'prop-int'])
def testHeader(self):
"""Test that we can access the header values"""
- self.assertEquals(self.fdt.totalsize(), len(self.fdt._fdt))
- self.assertEquals(self.fdt.off_dt_struct(), 88)
+ self.assertEqual(self.fdt.magic(), 0xd00dfeed)
+ self.assertEqual(self.fdt.totalsize(), len(self.fdt._fdt))
+ self.assertEqual(self.fdt.off_dt_struct(), 88)
+ self.assertEqual(self.fdt.off_dt_strings(), 652)
+ self.assertEqual(self.fdt.off_mem_rsvmap(), 40)
+ self.assertEqual(self.fdt.version(), 17)
+ self.assertEqual(self.fdt.last_comp_version(), 16)
+ self.assertEqual(self.fdt.boot_cpuid_phys(), 0)
+ self.assertEqual(self.fdt.size_dt_strings(), 105)
+ self.assertEqual(self.fdt.size_dt_struct(), 564)
def testPack(self):
"""Test that we can pack the tree after deleting something"""
orig_size = self.fdt.totalsize()
node = self.fdt.path_offset('/subnode@2', QUIET_NOTFOUND)
- self.assertEquals(self.fdt.delprop(node, 'prop-int'), 0)
- self.assertEquals(orig_size, self.fdt.totalsize())
- self.assertEquals(self.fdt.pack(), 0)
+ self.assertEqual(self.fdt.delprop(node, 'prop-int'), 0)
+ self.assertEqual(orig_size, self.fdt.totalsize())
+ self.assertEqual(self.fdt.pack(), 0)
self.assertTrue(self.fdt.totalsize() < orig_size)
+ self.assertEqual(self.fdt.totalsize(), len(self.fdt.as_bytearray()))
def testBadPropertyOffset(self):
"""Test that bad property offsets are detected"""
with self.assertRaises(FdtException) as e:
self.fdt.get_property_by_offset(13)
- self.assertEquals(e.exception.err, -libfdt.BADOFFSET)
+ self.assertEqual(e.exception.err, -libfdt.BADOFFSET)
with self.assertRaises(FdtException) as e:
self.fdt.first_property_offset(3)
- self.assertEquals(e.exception.err, -libfdt.BADOFFSET)
+ self.assertEqual(e.exception.err, -libfdt.BADOFFSET)
with self.assertRaises(FdtException) as e:
self.fdt.next_property_offset(3)
- self.assertEquals(e.exception.err, -libfdt.BADOFFSET)
+ self.assertEqual(e.exception.err, -libfdt.BADOFFSET)
def testBadPathOffset(self):
"""Test that bad path names are detected"""
- with self.assertRaisesRegexp(FdtException, get_err(libfdt.BADPATH)):
+ with self.assertRaisesRegex(FdtException, get_err(libfdt.BADPATH)):
self.fdt.path_offset('not-present')
def testQuietAll(self):
"""Check that exceptions can be masked by QUIET_ALL"""
- self.assertEquals(-libfdt.NOTFOUND,
+ self.assertEqual(-libfdt.NOTFOUND,
self.fdt.path_offset('/missing', QUIET_ALL))
- self.assertEquals(-libfdt.BADOFFSET,
+ self.assertEqual(-libfdt.BADOFFSET,
self.fdt.get_property_by_offset(13, QUIET_ALL))
- self.assertEquals(-libfdt.BADPATH,
+ self.assertEqual(-libfdt.BADPATH,
self.fdt.path_offset('missing', QUIET_ALL))
+ def testIntegers(self):
+ """Check that integers can be passed and returned"""
+ self.assertEqual(0, libfdt.fdt_get_phandle(self.fdt._fdt, 0))
+ node2 = self.fdt.path_offset('/subnode@2')
+ self.assertEqual(0x2000, libfdt.fdt_get_phandle(self.fdt._fdt, node2))
+
+ def testGetPhandle(self):
+ """Test for the get_phandle() method"""
+ self.assertEqual(0, self.fdt.get_phandle(0))
+ node2 = self.fdt.path_offset('/subnode@2')
+ self.assertEqual(0x2000, self.fdt.get_phandle(node2))
+
+ def testGetAlias(self):
+ """Test for the get_alias() method"""
+ self.assertEqual("/subnode@1", self.fdt3.get_alias('s1'))
+ self.assertEqual("/subnode@1/subsubnode", self.fdt3.get_alias('ss1'))
+ self.assertEqual("/subnode@1/subsubnode/subsubsubnode", self.fdt3.get_alias('sss1'))
+
+ def testParentOffset(self):
+ """Test for the parent_offset() method"""
+ self.assertEqual(-libfdt.NOTFOUND,
+ self.fdt.parent_offset(0, QUIET_NOTFOUND))
+ with self.assertRaises(FdtException) as e:
+ self.fdt.parent_offset(0)
+ self.assertEqual(e.exception.err, -libfdt.NOTFOUND)
+
+ node1 = self.fdt.path_offset('/subnode@2')
+ self.assertEqual(0, self.fdt.parent_offset(node1))
+ node2 = self.fdt.path_offset('/subnode@2/subsubnode@0')
+ self.assertEqual(node1, self.fdt.parent_offset(node2))
+
+ def testNodeOffsetByPhandle(self):
+ """Test for the node_offset_by_phandle() method"""
+ self.assertEqual(-libfdt.NOTFOUND,
+ self.fdt.node_offset_by_phandle(1, QUIET_NOTFOUND))
+ node1 = self.fdt.path_offset('/subnode@2')
+ self.assertEqual(node1, self.fdt.node_offset_by_phandle(0x2000))
+ node2 = self.fdt.path_offset('/subnode@2/subsubnode@0')
+ self.assertEqual(node2, self.fdt.node_offset_by_phandle(0x2001))
+
+ def get_prop(self, name):
+ return self.fdt2.getprop(0, name)
+
+ def testGetIntProperties(self):
+ """Test that we can access properties as integers"""
+ self.assertEqual(0xdeadbeef, self.get_prop("prop-hex32").as_uint32())
+ self.assertEqual(123, self.get_prop("prop-uint32").as_uint32())
+ self.assertEqual(-2, self.get_prop("prop-int32").as_int32())
+ self.assertEqual(9223372036854775807,
+ self.get_prop("prop-uint64").as_uint64())
+ self.assertEqual(-2, self.get_prop("prop-int64").as_int64())
+
+ def testReserveMap(self):
+ """Test that we can access the memory reserve map"""
+ self.assertEqual(2, self.fdt.num_mem_rsv())
+ self.assertEqual([ 0xdeadbeef00000000, 0x100000],
+ self.fdt.get_mem_rsv(0))
+ self.assertEqual([123456789, 0o10000], self.fdt.get_mem_rsv(1))
+
+ def testEmpty(self):
+ """Test that we can create an empty tree"""
+ self.assertEqual(-libfdt.NOSPACE,
+ Fdt.create_empty_tree(1, (libfdt.NOSPACE,)))
+ fdt = Fdt.create_empty_tree(128)
+ self.assertEqual(128, fdt.totalsize())
+
+ def testOpenInto(self):
+ """Test that we can resize a tree"""
+ fdt = Fdt.create_empty_tree(128)
+ self.assertEqual(128, fdt.totalsize())
+ fdt.resize(256)
+ self.assertEqual(256, fdt.totalsize())
+ fdt.pack()
+ self.assertTrue(fdt.totalsize() < 128)
+
+ def testSetProp(self):
+ """Test that we can update and create properties"""
+ node = self.fdt.path_offset('/subnode@1')
+ self.fdt.setprop(node, 'compatible', TEST_BYTES_1)
+ self.assertEqual(TEST_BYTES_1, self.fdt.getprop(node, 'compatible'))
+
+ # Check that this property is missing, and that we don't have space to
+ # add it
+ self.assertEqual(-libfdt.NOTFOUND,
+ self.fdt.getprop(node, 'missing', QUIET_NOTFOUND))
+ self.assertEqual(-libfdt.NOSPACE,
+ self.fdt.setprop(node, 'missing', TEST_BYTES_1,
+ quiet=(libfdt.NOSPACE,)))
+
+ # Expand the device tree so we now have room
+ self.fdt.resize(self.fdt.totalsize() + 50)
+ self.fdt.setprop(node, 'missing', TEST_BYTES_1)
+ self.assertEqual(TEST_BYTES_1, self.fdt.getprop(node, 'missing'))
+
+ def testSetPropU32(self):
+ """Test that we can update and create integer properties"""
+ node = 0
+ prop = 'prop-int'
+ self.fdt.setprop_u32(node, prop, TEST_VALUE_1)
+ self.assertEqual(struct.pack('>I', TEST_VALUE_1),
+ self.fdt.getprop(node, prop))
+
+ def testSetPropU64(self):
+ """Test that we can update and create integer properties"""
+ node = 0
+ prop = 'prop-int64'
+ self.fdt.setprop_u64(node, prop, TEST_VALUE64_1)
+ self.assertEqual(struct.pack('>Q', TEST_VALUE64_1),
+ self.fdt.getprop(node, prop))
+
+ def testSetPropStr(self):
+ """Test that we can set a property to a particular string"""
+ node = 0
+ prop = 'prop-str'
+ self.assertEqual(TEST_STRING_1, self.fdt.getprop(node, prop).as_str())
+ self.fdt.setprop_str(node, prop, TEST_STRING_2)
+ self.assertEqual(TEST_STRING_2, self.fdt.getprop(node, prop).as_str())
+ with self.assertRaises(ValueError) as e:
+ self.fdt.getprop(node, 'prop-int').as_str()
+ self.assertIn('lacks nul termination', str(e.exception))
+
+ node2 = self.fdt.path_offset('/subnode@1/subsubnode')
+ with self.assertRaises(ValueError) as e:
+ self.fdt.getprop(node2, 'compatible').as_str()
+ self.assertIn('embedded nul', str(e.exception))
+
+ # Expand the device tree so we now have room
+ self.fdt.resize(self.fdt.totalsize() + 50)
+ prop = 'prop-unicode'
+ self.fdt.setprop_str(node, prop, TEST_STRING_3)
+ self.assertEqual(TEST_STRING_3,
+ self.fdt.getprop(node, prop).as_str())
+
+ def testSetName(self):
+ """Test that we can update a node name"""
+ node = self.fdt.path_offset('/subnode@1')
+ old_val = self.fdt.get_name(node)
+ self.fdt.set_name(node, 'test')
+ self.assertEqual('test', self.fdt.get_name(node))
+
+ with self.assertRaises(ValueError) as e:
+ self.fdt.set_name(node, 'some\0name')
+ self.assertIn('embedded nul', str(e.exception))
+
+ with self.assertRaises(ValueError) as e:
+ self.fdt.set_name(node, 'name\0')
+ self.assertIn('embedded nul', str(e.exception))
+
+ def testAddDeleteNodes(self):
+ """Test that we can add and delete nodes"""
+ node_name = '/subnode@1'
+ self.assertEqual(self.GetSubnodes(node_name), ['subsubnode', 'ss1'])
+ node = self.fdt.path_offset('%s/subsubnode' % node_name)
+ self.assertEqual(self.fdt.del_node(node, 'subsubnode'), 0)
+ self.assertEqual(self.GetSubnodes(node_name), ['ss1'])
+
+ node = self.fdt.path_offset(node_name)
+ offset = self.fdt.add_subnode(node, 'more')
+ self.assertTrue(offset > 0)
+ self.assertEqual(self.GetSubnodes(node_name), ['more', 'ss1'])
+
+
+class PyLibfdtSwTests(unittest.TestCase):
+ """Test class for pylibfdt sequential-write DT creation
+ """
+ def assertOk(self, err_code):
+ self.assertEqual(0, err_code)
+
+ def testCreate(self):
+ # First check the minimum size and also the FdtSw() constructor
+ with self.assertRaisesRegex(FdtException, get_err(libfdt.NOSPACE)):
+ self.assertEqual(-libfdt.NOSPACE, FdtSw(3))
+
+ sw = FdtSw()
+ sw.add_reservemap_entry(TEST_ADDR_1, TEST_SIZE_1)
+ sw.add_reservemap_entry(TEST_ADDR_2, TEST_SIZE_2)
+ sw.finish_reservemap()
+
+ sw.begin_node('')
+ sw.property_string('compatible', 'test_tree1')
+ sw.property_u32('prop-int', TEST_VALUE_1)
+
+ sw.property_u32('prop-int', TEST_VALUE_1)
+ sw.property_u64('prop-int64', TEST_VALUE64_1)
+ sw.property_string('prop-str', TEST_STRING_1)
+ sw.property_u32('#address-cells', 1)
+ sw.property_u32('#size-cells', 0)
+
+ sw.begin_node('subnode@1')
+ sw.property_string('compatible', 'subnode1')
+ sw.property_u32('reg', 1)
+ sw.property_cell('prop-int', TEST_VALUE_1)
+ sw.property('data', b'\x00data\x01')
+ sw.begin_node('subsubnode')
+ sw.property('compatible', b'subsubnode1\0subsubnode')
+ sw.property_cell('prop-int', TEST_VALUE_1)
+ sw.end_node()
+ sw.begin_node('ss1')
+ sw.end_node()
+ sw.end_node()
+
+ for i in range(2, 11):
+ with sw.add_node('subnode@%d' % i):
+ sw.property_u32('reg', 2)
+ sw.property_cell('linux,phandle', PHANDLE_1)
+ sw.property_cell('prop-int', TEST_VALUE_2)
+ sw.property_u32('#address-cells', 1)
+ sw.property_u32('#size-cells', 0)
+ with sw.add_node('subsubnode@0'):
+ sw.property_u32('reg', 0)
+ sw.property_cell('phandle', PHANDLE_2)
+ sw.property('compatible', b'subsubnode2\0subsubnode')
+ sw.property_cell('prop-int', TEST_VALUE_2)
+ with sw.add_node('ss2'):
+ pass
+ sw.end_node()
+
+ fdt = sw.as_fdt()
+ self.assertEqual(2, fdt.num_mem_rsv())
+ self.assertEqual([TEST_ADDR_1, TEST_SIZE_1], fdt.get_mem_rsv(0))
+
+ # Make sure we can add a few more things
+ with sw.add_node('another'):
+ sw.property_u32('reg', 3)
+
+ # Make sure we can read from the tree too
+ node = sw.path_offset('/subnode@1')
+ self.assertEqual(b'subnode1\0', sw.getprop(node, 'compatible'))
+
+ # Make sure we did at least two resizes
+ self.assertTrue(len(fdt.as_bytearray()) > FdtSw.INC_SIZE * 2)
+
+
+class PyLibfdtRoTests(unittest.TestCase):
+ """Test class for read-only pylibfdt access functions
+
+ This just tests a few simple cases. Most of the tests are in
+ PyLibfdtBasicTests.
+
+ Properties:
+ fdt: Device tree file used for testing
+ """
+
+ def setUp(self):
+ """Read in the device tree we use for testing"""
+ with open('test_tree1.dtb', mode='rb') as f:
+ self.fdt = libfdt.FdtRo(f.read())
+
+ def testAccess(self):
+ """Basic sanity check for the FdtRo class"""
+ node = self.fdt.path_offset('/subnode@1')
+ self.assertEqual(b'subnode1\0',
+ self.fdt.getprop(node, 'compatible'))
+ node = self.fdt.first_subnode(node)
+ self.assertEqual(b'this is a placeholder string\0string2\0',
+ self.fdt.getprop(node, 'placeholder'))
+
if __name__ == "__main__":
unittest.main()
diff --git a/tests/references.c b/tests/references.c
index cab70f6..d18e722 100644
--- a/tests/references.c
+++ b/tests/references.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for phandle references in dtc
* 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>
#include <stdio.h>
@@ -76,8 +63,8 @@ static void check_rref(const void *fdt)
int main(int argc, char *argv[])
{
void *fdt;
- int n1, n2, n3, n4, n5;
- uint32_t h1, h2, h4, h5;
+ int n1, n2, n3, n4, n5, n6, err;
+ uint32_t h1, h2, h4, h5, h6, hn;
test_init(argc, argv);
fdt = load_blob_arg(argc, argv);
@@ -97,11 +84,15 @@ int main(int argc, char *argv[])
n5 = fdt_path_offset(fdt, "/node5");
if (n5 < 0)
FAIL("fdt_path_offset(/node5): %s", fdt_strerror(n5));
+ n6 = fdt_path_offset(fdt, "/node6");
+ if (n6 < 0)
+ FAIL("fdt_path_offset(/node6): %s", fdt_strerror(n6));
h1 = fdt_get_phandle(fdt, n1);
h2 = fdt_get_phandle(fdt, n2);
h4 = fdt_get_phandle(fdt, n4);
h5 = fdt_get_phandle(fdt, n5);
+ h6 = fdt_get_phandle(fdt, n6);
if (h1 != 0x2000)
FAIL("/node1 has wrong phandle, 0x%x instead of 0x%x",
@@ -109,6 +100,9 @@ int main(int argc, char *argv[])
if (h2 != 0x1)
FAIL("/node2 has wrong phandle, 0x%x instead of 0x%x",
h2, 0x1);
+ if (h6 != FDT_MAX_PHANDLE)
+ FAIL("/node6 has wrong phandle, 0x%x instead of 0x%x",
+ h6, FDT_MAX_PHANDLE);
if ((h4 == 0x2000) || (h4 == 0x1) || (h4 == 0))
FAIL("/node4 has bad phandle, 0x%x", h4);
@@ -117,6 +111,14 @@ int main(int argc, char *argv[])
if ((h5 == h4) || (h5 == h2) || (h5 == h1))
FAIL("/node5 has duplicate phandle, 0x%x", h5);
+ /*
+ * /node6 has phandle FDT_MAX_PHANDLE, so fdt_generate_phandle() is
+ * expected to fail.
+ */
+ err = fdt_generate_phandle(fdt, &hn);
+ if (err != -FDT_ERR_NOPHANDLES)
+ FAIL("generated invalid phandle 0x%x\n", hn);
+
check_ref(fdt, n1, h2);
check_ref(fdt, n2, h1);
check_ref(fdt, n3, h4);
diff --git a/tests/references.dts b/tests/references.dts
index f783e8b..b390639 100644
--- a/tests/references.dts
+++ b/tests/references.dts
@@ -33,4 +33,9 @@
linux,phandle = <&n5>;
phandle = <&n5>;
};
+
+ node6 {
+ linux,phandle = <0xfffffffe>;
+ phandle = <0xfffffffe>;
+ };
};
diff --git a/tests/root_node.c b/tests/root_node.c
index 58aebf6..37e6f05 100644
--- a/tests/root_node.c
+++ b/tests/root_node.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Basic testcase for read-only access
* 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>
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index b8a2825..294585b 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -1,11 +1,62 @@
#! /bin/sh
-. ./tests.sh
+SRCDIR=`dirname "$0"`
+. "$SRCDIR/testutils.sh"
if [ -z "$CC" ]; then
- CC=gcc
+ CC=cc
fi
+if [ -z "$PYTHON" ]; then
+ PYTHON=python3
+fi
+
+if [ -n "$NO_PYTHON" ]; then
+ if [ "$NO_PYTHON" != "0" ]; then
+ no_python=true
+ else
+ no_python=false
+ fi
+else
+ if [ -f ../pylibfdt/_libfdt.so ] || [ -f ../pylibfdt/_libfdt.cpython-3*.so ]; then
+ no_python=false
+ else
+ no_python=true
+ fi
+fi
+
+if [ -n "$NO_YAML" ]; then
+ if [ "$NO_YAML" != "0" ]; then
+ no_yaml=true
+ else
+ no_yaml=false
+ fi
+else
+ if pkg-config --exists yaml-0.1; then
+ no_yaml=false
+ else
+ no_yaml=true
+ fi
+fi
+
+# stat differs between platforms
+if [ -z "$STATSZ" ]; then
+ stat --version 2>/dev/null | grep -q 'GNU'
+ GNUSTAT=$?
+ if [ "$GNUSTAT" -ne 0 ]; then
+ # Assume BSD stat if we can't detect as GNU stat
+ STATSZ="stat -f %Uz"
+ else
+ STATSZ="stat -c %s"
+ fi
+fi
+
+# Help things find the libfdt shared object
+if [ -z "$TEST_LIBDIR" ]; then
+ TEST_LIBDIR=../libfdt
+fi
+export LD_LIBRARY_PATH="$TEST_LIBDIR"
+
export QUIET_TEST=1
STOP_ON_FAIL=0
@@ -76,6 +127,9 @@ wrap_test () {
if [ "$ret" -gt 127 ]; then
signame=$(kill -l $((ret - 128)))
FAIL "Killed by SIG$signame"
+ elif [ "$ret" -eq $VGCODE ]; then
+ echo "VALGRIND ERROR"
+ exit $VGCODE
else
FAIL "Returned error code $ret"
fi
@@ -114,7 +168,7 @@ run_wrap_error_test () {
# $2: align base
check_align () {
shorten_echo "check_align $@: "
- local size=$(stat -c %s "$1")
+ local size=$($STATSZ "$1")
local align="$2"
(
if [ $(($size % $align)) -eq 0 ] ;then
@@ -131,7 +185,7 @@ run_dtc_test () {
}
asm_to_so () {
- $CC -shared -o $1.test.so data.S $1.test.s
+ $CC -shared -o $1.test.so "$SRCDIR/data.S" $1.test.s
}
asm_to_so_test () {
@@ -142,7 +196,7 @@ run_fdtget_test () {
expect="$1"
shift
printf "fdtget-runtest.sh %s $*: " "$(echo $expect)"
- base_run_test sh fdtget-runtest.sh "$expect" "$@"
+ base_run_test sh "$SRCDIR/fdtget-runtest.sh" "$expect" "$@"
}
run_fdtput_test () {
@@ -150,14 +204,14 @@ run_fdtput_test () {
shift
shorten_echo fdtput-runtest.sh "$expect" "$@"
printf ": "
- base_run_test sh fdtput-runtest.sh "$expect" "$@"
+ base_run_test sh "$SRCDIR/fdtput-runtest.sh" "$expect" "$@"
}
run_fdtdump_test() {
file="$1"
shorten_echo fdtdump-runtest.sh "$file"
printf ": "
- base_run_test sh fdtdump-runtest.sh "$file" 2>/dev/null
+ base_run_test sh "$SRCDIR/fdtdump-runtest.sh" "$file" 2>/dev/null
}
run_fdtoverlay_test() {
@@ -165,7 +219,7 @@ run_fdtoverlay_test() {
shift
shorten_echo fdtoverlay-runtest.sh "$expect" "$@"
printf ": "
- base_run_test sh fdtoverlay-runtest.sh "$expect" "$@"
+ base_run_test sh "$SRCDIR/fdtoverlay-runtest.sh" "$expect" "$@"
}
BAD_FIXUP_TREES="bad_index \
@@ -180,12 +234,12 @@ BAD_FIXUP_TREES="bad_index \
# Test to exercise libfdt overlay application without dtc's overlay support
libfdt_overlay_tests () {
# First test a doctored overlay which requires only local fixups
- run_dtc_test -I dts -O dtb -o overlay_base_no_symbols.test.dtb overlay_base.dts
+ run_dtc_test -I dts -O dtb -o overlay_base_no_symbols.test.dtb "$SRCDIR/overlay_base.dts"
run_test check_path overlay_base_no_symbols.test.dtb not-exists "/__symbols__"
run_test check_path overlay_base_no_symbols.test.dtb not-exists "/__fixups__"
run_test check_path overlay_base_no_symbols.test.dtb not-exists "/__local_fixups__"
- run_dtc_test -I dts -O dtb -o overlay_overlay_no_fixups.test.dtb overlay_overlay_no_fixups.dts
+ run_dtc_test -I dts -O dtb -o overlay_overlay_no_fixups.test.dtb "$SRCDIR/overlay_overlay_no_fixups.dts"
run_test check_path overlay_overlay_no_fixups.test.dtb not-exists "/__symbols__"
run_test check_path overlay_overlay_no_fixups.test.dtb not-exists "/__fixups__"
run_test check_path overlay_overlay_no_fixups.test.dtb exists "/__local_fixups__"
@@ -193,22 +247,28 @@ libfdt_overlay_tests () {
run_test overlay overlay_base_no_symbols.test.dtb overlay_overlay_no_fixups.test.dtb
# Then test with manually constructed fixups
- run_dtc_test -I dts -O dtb -o overlay_base_manual_symbols.test.dtb overlay_base_manual_symbols.dts
+ run_dtc_test -I dts -O dtb -o overlay_base_manual_symbols.test.dtb "$SRCDIR/overlay_base_manual_symbols.dts"
run_test check_path overlay_base_manual_symbols.test.dtb exists "/__symbols__"
run_test check_path overlay_base_manual_symbols.test.dtb not-exists "/__fixups__"
run_test check_path overlay_base_manual_symbols.test.dtb not-exists "/__local_fixups__"
- run_dtc_test -I dts -O dtb -o overlay_overlay_manual_fixups.test.dtb overlay_overlay_manual_fixups.dts
+ run_dtc_test -I dts -O dtb -o overlay_overlay_manual_fixups.test.dtb "$SRCDIR/overlay_overlay_manual_fixups.dts"
run_test check_path overlay_overlay_manual_fixups.test.dtb not-exists "/__symbols__"
run_test check_path overlay_overlay_manual_fixups.test.dtb exists "/__fixups__"
run_test check_path overlay_overlay_manual_fixups.test.dtb exists "/__local_fixups__"
run_test overlay overlay_base_manual_symbols.test.dtb overlay_overlay_manual_fixups.test.dtb
+ # test simplified plugin syntax
+ run_dtc_test -@ -I dts -O dtb -o overlay_overlay_simple.dtb "$SRCDIR/overlay_overlay_simple.dts"
+
+ # verify non-generation of local fixups
+ run_test check_path overlay_overlay_simple.dtb not-exists "/__local_fixups__"
+
# Bad fixup tests
for test in $BAD_FIXUP_TREES; do
tree="overlay_bad_fixup_$test"
- run_dtc_test -I dts -O dtb -o $tree.test.dtb $tree.dts
+ run_dtc_test -I dts -O dtb -o $tree.test.dtb "$SRCDIR/$tree.dts"
run_test overlay_bad_fixup overlay_base_no_symbols.test.dtb $tree.test.dtb
done
}
@@ -216,25 +276,55 @@ libfdt_overlay_tests () {
# Tests to exercise dtc's overlay generation support
dtc_overlay_tests () {
# Overlay tests for dtc
- run_dtc_test -@ -I dts -O dtb -o overlay_base.test.dtb overlay_base.dts
+ run_dtc_test -@ -I dts -O dtb -o overlay_base.test.dtb "$SRCDIR/overlay_base.dts"
run_test check_path overlay_base.test.dtb exists "/__symbols__"
run_test check_path overlay_base.test.dtb not-exists "/__fixups__"
run_test check_path overlay_base.test.dtb not-exists "/__local_fixups__"
- run_dtc_test -I dts -O dtb -o overlay_overlay.test.dtb overlay_overlay.dts
+ # With syntactic sugar
+ run_dtc_test -I dts -O dtb -o overlay_overlay.test.dtb "$SRCDIR/overlay_overlay.dts"
run_test check_path overlay_overlay.test.dtb not-exists "/__symbols__"
run_test check_path overlay_overlay.test.dtb exists "/__fixups__"
run_test check_path overlay_overlay.test.dtb exists "/__local_fixups__"
+ # Without syntactic sugar
+ run_dtc_test -I dts -O dtb -o overlay_overlay_nosugar.test.dtb "$SRCDIR/overlay_overlay.dts"
+ run_test check_path overlay_overlay_nosugar.test.dtb not-exists "/__symbols__"
+ run_test check_path overlay_overlay_nosugar.test.dtb exists "/__fixups__"
+ run_test check_path overlay_overlay_nosugar.test.dtb exists "/__local_fixups__"
+
+ # Using target-path
+ run_dtc_test -I dts -O dtb -o overlay_overlay_bypath.test.dtb "$SRCDIR/overlay_overlay_bypath.dts"
+ run_test check_path overlay_overlay_bypath.test.dtb not-exists "/__symbols__"
+ run_test check_path overlay_overlay_bypath.test.dtb not-exists "/__fixups__"
+ run_test check_path overlay_overlay_bypath.test.dtb exists "/__local_fixups__"
+
+ # Make sure local target references are resolved and nodes are merged and that path references are not
+ run_dtc_test -I dts -O dtb -o overlay_overlay_local_merge.test.dtb "$SRCDIR/overlay_overlay_local_merge.dts"
+ run_test check_path overlay_overlay_local_merge.test.dtb exists "/fragment@0/__overlay__/new-node/new-merged-node"
+ run_test check_path overlay_overlay_local_merge.test.dtb exists "/fragment@1/__overlay__/new-root-node"
+
+ # Check building works the same as manual constructions
+ run_test dtbs_equal_ordered overlay_overlay.test.dtb overlay_overlay_nosugar.test.dtb
+
+ run_dtc_test -I dts -O dtb -o overlay_overlay_manual_fixups.test.dtb "$SRCDIR/overlay_overlay_manual_fixups.dts"
+ run_test dtbs_equal_ordered overlay_overlay.test.dtb overlay_overlay_manual_fixups.test.dtb
+
+ run_dtc_test -I dts -O dtb -o overlay_overlay_no_fixups.test.dtb "$SRCDIR/overlay_overlay_no_fixups.dts"
+ run_test dtbs_equal_ordered overlay_overlay_bypath.test.dtb overlay_overlay_no_fixups.test.dtb
+
+ # Check we can actually apply the result
+ run_dtc_test -I dts -O dtb -o overlay_base_no_symbols.test.dtb "$SRCDIR/overlay_base.dts"
run_test overlay overlay_base.test.dtb overlay_overlay.test.dtb
+ run_test overlay overlay_base_no_symbols.test.dtb overlay_overlay_bypath.test.dtb
# test plugin source to dtb and back
run_dtc_test -I dtb -O dts -o overlay_overlay_decompile.test.dts overlay_overlay.test.dtb
run_dtc_test -I dts -O dtb -o overlay_overlay_decompile.test.dtb overlay_overlay_decompile.test.dts
run_test dtbs_equal_ordered overlay_overlay.test.dtb overlay_overlay_decompile.test.dtb
- # Test generation of aliases insted of symbols
- run_dtc_test -A -I dts -O dtb -o overlay_base_with_aliases.dtb overlay_base.dts
+ # Test generation of aliases instead of symbols
+ run_dtc_test -A -I dts -O dtb -o overlay_base_with_aliases.dtb "$SRCDIR/overlay_base.dts"
run_test check_path overlay_base_with_aliases.dtb exists "/aliases"
run_test check_path overlay_base_with_aliases.dtb not-exists "/__symbols__"
run_test check_path overlay_base_with_aliases.dtb not-exists "/__fixups__"
@@ -252,6 +342,7 @@ tree1_tests () {
run_test path_offset $TREE
run_test get_name $TREE
run_test getprop $TREE
+ run_test get_prop_offset $TREE
run_test get_phandle $TREE
run_test get_path $TREE
run_test supernode_atdepth_offset $TREE
@@ -281,9 +372,9 @@ tree1_tests_rw () {
check_tests () {
tree="$1"
shift
- run_sh_test dtc-checkfails.sh "$@" -- -I dts -O dtb $tree
+ run_sh_test "$SRCDIR/dtc-checkfails.sh" "$@" -- -I dts -O dtb $tree
run_dtc_test -I dts -O dtb -o $tree.test.dtb -f $tree
- run_sh_test dtc-checkfails.sh "$@" -- -I dtb -O dtb $tree.test.dtb
+ run_sh_test "$SRCDIR/dtc-checkfails.sh" "$@" -- -I dtb -O dtb $tree.test.dtb
}
ALL_LAYOUTS="mts mst tms tsm smt stm"
@@ -291,24 +382,29 @@ ALL_LAYOUTS="mts mst tms tsm smt stm"
libfdt_tests () {
tree1_tests test_tree1.dtb
- run_dtc_test -I dts -O dtb -o addresses.test.dtb addresses.dts
+ run_dtc_test -I dts -O dtb -o addresses.test.dtb "$SRCDIR/addresses.dts"
run_test addr_size_cells addresses.test.dtb
+ run_dtc_test -I dts -O dtb -o addresses2.test.dtb "$SRCDIR/empty.dts"
+ run_test addr_size_cells2 addresses2.test.dtb
- run_dtc_test -I dts -O dtb -o stringlist.test.dtb stringlist.dts
+ run_dtc_test -I dts -O dtb -o stringlist.test.dtb "$SRCDIR/stringlist.dts"
run_test stringlist stringlist.test.dtb
- # Sequential write tests
- run_test sw_tree1
- tree1_tests sw_tree1.test.dtb
- tree1_tests unfinished_tree1.test.dtb
- run_test dtbs_equal_ordered test_tree1.dtb sw_tree1.test.dtb
-
- # Resizing tests
- for mode in resize realloc; do
- run_test sw_tree1 $mode
- tree1_tests sw_tree1.test.dtb
- tree1_tests unfinished_tree1.test.dtb
- run_test dtbs_equal_ordered test_tree1.dtb sw_tree1.test.dtb
+ for flags in default no_name_dedup; do
+ # Sequential write tests
+ run_test sw_tree1 fixed $flags
+ tree1_tests sw_tree1.test.dtb
+ tree1_tests unfinished_tree1.test.dtb
+ run_test dtbs_equal_ordered test_tree1.dtb sw_tree1.test.dtb
+ run_test sw_states
+
+ # Resizing tests
+ for mode in resize realloc newalloc; do
+ run_test sw_tree1 $mode $flags
+ tree1_tests sw_tree1.test.dtb
+ tree1_tests unfinished_tree1.test.dtb
+ run_test dtbs_equal_ordered test_tree1.dtb sw_tree1.test.dtb
+ done
done
# fdt_move tests
@@ -352,7 +448,7 @@ libfdt_tests () {
tree1_tests_rw rw_tree1.test.dtb
run_test appendprop1
run_test appendprop2 appendprop1.test.dtb
- run_dtc_test -I dts -O dtb -o appendprop.test.dtb appendprop.dts
+ run_dtc_test -I dts -O dtb -o appendprop.test.dtb "$SRCDIR/appendprop.dts"
run_test dtbs_equal_ordered appendprop2.test.dtb appendprop.test.dtb
libfdt_overlay_tests
@@ -363,99 +459,127 @@ libfdt_tests () {
tree1_tests_rw noppy.$basetree
done
- run_dtc_test -I dts -O dtb -o subnode_iterate.dtb subnode_iterate.dts
+ run_test rw_oom
+
+ run_dtc_test -I dts -O dtb -o subnode_iterate.dtb "$SRCDIR/subnode_iterate.dts"
run_test subnode_iterate subnode_iterate.dtb
- run_dtc_test -I dts -O dtb -o property_iterate.dtb property_iterate.dts
+ run_dtc_test -I dts -O dtb -o property_iterate.dtb "$SRCDIR/property_iterate.dts"
run_test property_iterate property_iterate.dtb
+ run_dtc_test -I dts -O dtb -o unit-addr-without-reg.dtb "$SRCDIR/unit-addr-without-reg.dts"
+ run_test appendprop_addrrange unit-addr-without-reg.dtb 1 1 1
+ run_test appendprop_addrrange unit-addr-without-reg.dtb 2 2 2
+ run_test appendprop_addrrange unit-addr-without-reg.dtb 2 1 3
+
# Tests for behaviour on various sorts of corrupted trees
run_test truncated_property
+ run_test truncated_string
+ run_test truncated_memrsv
# Check aliases support in fdt_path_offset
- run_dtc_test -I dts -O dtb -o aliases.dtb aliases.dts
+ run_dtc_test -I dts -O dtb -o aliases.dtb "$SRCDIR/aliases.dts"
run_test get_alias aliases.dtb
run_test path_offset_aliases aliases.dtb
# Specific bug tests
run_test add_subnode_with_nops
- run_dtc_test -I dts -O dts -o sourceoutput.test.dts sourceoutput.dts
- run_dtc_test -I dts -O dtb -o sourceoutput.test.dtb sourceoutput.dts
+ run_dtc_test -I dts -O dts -o sourceoutput.test.dts "$SRCDIR/sourceoutput.dts"
+ run_dtc_test -I dts -O dtb -o sourceoutput.test.dtb "$SRCDIR/sourceoutput.dts"
run_dtc_test -I dts -O dtb -o sourceoutput.test.dts.test.dtb sourceoutput.test.dts
run_test dtbs_equal_ordered sourceoutput.test.dtb sourceoutput.test.dts.test.dtb
- run_dtc_test -I dts -O dtb -o embedded_nul.test.dtb embedded_nul.dts
- run_dtc_test -I dts -O dtb -o embedded_nul_equiv.test.dtb embedded_nul_equiv.dts
+ run_dtc_test -I dts -O dtb -o embedded_nul.test.dtb "$SRCDIR/embedded_nul.dts"
+ run_dtc_test -I dts -O dtb -o embedded_nul_equiv.test.dtb "$SRCDIR/embedded_nul_equiv.dts"
run_test dtbs_equal_ordered embedded_nul.test.dtb embedded_nul_equiv.test.dtb
- run_dtc_test -I dts -O dtb bad-size-cells.dts
+ run_dtc_test -I dts -O dtb "$SRCDIR/bad-size-cells.dts"
run_wrap_error_test $DTC division-by-zero.dts
run_wrap_error_test $DTC bad-octal-literal.dts
- run_dtc_test -I dts -O dtb nul-in-escape.dts
+ run_dtc_test -I dts -O dtb "$SRCDIR/nul-in-escape.dts"
run_wrap_error_test $DTC nul-in-line-info1.dts
run_wrap_error_test $DTC nul-in-line-info2.dts
run_wrap_error_test $DTC -I dtb -O dts -o /dev/null ovf_size_strings.dtb
+
+ run_test check_header test_tree1.dtb
+
+ FSBASE=fs
+ rm -rf $FSBASE
+ mkdir -p $FSBASE
+ run_test fs_tree1 $FSBASE/test_tree1
+ run_dtc_test -I fs -O dts -o fs.test_tree1.test.dts $FSBASE/test_tree1
+ run_dtc_test -I fs -O dtb -o fs.test_tree1.test.dtb $FSBASE/test_tree1
+ run_test dtbs_equal_unordered -m fs.test_tree1.test.dtb test_tree1.dtb
+
+ # check full tests
+ for good in test_tree1.dtb; do
+ run_test check_full $good
+ done
+ for bad in truncated_property.dtb truncated_string.dtb \
+ truncated_memrsv.dtb; do
+ run_test check_full -n $bad
+ done
}
dtc_tests () {
- run_dtc_test -I dts -O dtb -o dtc_tree1.test.dtb test_tree1.dts
+ run_dtc_test -I dts -O dtb -o dtc_tree1.test.dtb "$SRCDIR/test_tree1.dts"
tree1_tests dtc_tree1.test.dtb
tree1_tests_rw dtc_tree1.test.dtb
run_test dtbs_equal_ordered dtc_tree1.test.dtb test_tree1.dtb
- run_dtc_test -I dts -O dtb -o dtc_escapes.test.dtb propname_escapes.dts
+ run_dtc_test -I dts -O dtb -o dtc_escapes.test.dtb "$SRCDIR/propname_escapes.dts"
run_test propname_escapes dtc_escapes.test.dtb
- run_dtc_test -I dts -O dtb -o line_directives.test.dtb line_directives.dts
+ run_dtc_test -I dts -O dtb -o line_directives.test.dtb "$SRCDIR/line_directives.dts"
- run_dtc_test -I dts -O dtb -o dtc_escapes.test.dtb escapes.dts
+ run_dtc_test -I dts -O dtb -o dtc_escapes.test.dtb "$SRCDIR/escapes.dts"
run_test string_escapes dtc_escapes.test.dtb
- run_dtc_test -I dts -O dtb -o dtc_char_literal.test.dtb char_literal.dts
+ run_dtc_test -I dts -O dtb -o dtc_char_literal.test.dtb "$SRCDIR/char_literal.dts"
run_test char_literal dtc_char_literal.test.dtb
- run_dtc_test -I dts -O dtb -o dtc_sized_cells.test.dtb sized_cells.dts
+ run_dtc_test -I dts -O dtb -o dtc_sized_cells.test.dtb "$SRCDIR/sized_cells.dts"
run_test sized_cells dtc_sized_cells.test.dtb
- run_dtc_test -I dts -O dtb -o dtc_extra-terminating-null.test.dtb extra-terminating-null.dts
+ run_dtc_test -I dts -O dtb -o dtc_extra-terminating-null.test.dtb "$SRCDIR/extra-terminating-null.dts"
run_test extra-terminating-null dtc_extra-terminating-null.test.dtb
- run_dtc_test -I dts -O dtb -o dtc_references.test.dtb references.dts
+ run_dtc_test -I dts -O dtb -o dtc_references.test.dtb "$SRCDIR/references.dts"
run_test references dtc_references.test.dtb
- run_dtc_test -I dts -O dtb -o dtc_path-references.test.dtb path-references.dts
+ run_dtc_test -I dts -O dtb -o dtc_path-references.test.dtb "$SRCDIR/path-references.dts"
run_test path-references dtc_path-references.test.dtb
run_test phandle_format dtc_references.test.dtb epapr
for f in legacy epapr both; do
- run_dtc_test -I dts -O dtb -H $f -o dtc_references.test.$f.dtb references.dts
+ run_dtc_test -I dts -O dtb -H $f -o dtc_references.test.$f.dtb "$SRCDIR/references.dts"
run_test phandle_format dtc_references.test.$f.dtb $f
done
- run_dtc_test -I dts -O dtb -o multilabel.test.dtb multilabel.dts
+ run_dtc_test -I dts -O dtb -o multilabel.test.dtb "$SRCDIR/multilabel.dts"
run_test references multilabel.test.dtb
- run_dtc_test -I dts -O dtb -o label_repeated.test.dtb label_repeated.dts
+ run_dtc_test -I dts -O dtb -o label_repeated.test.dtb "$SRCDIR/label_repeated.dts"
- run_dtc_test -I dts -O dtb -o dtc_comments.test.dtb comments.dts
- run_dtc_test -I dts -O dtb -o dtc_comments-cmp.test.dtb comments-cmp.dts
+ run_dtc_test -I dts -O dtb -o dtc_comments.test.dtb "$SRCDIR/comments.dts"
+ run_dtc_test -I dts -O dtb -o dtc_comments-cmp.test.dtb "$SRCDIR/comments-cmp.dts"
run_test dtbs_equal_ordered dtc_comments.test.dtb dtc_comments-cmp.test.dtb
# Check /include/ directive
- run_dtc_test -I dts -O dtb -o includes.test.dtb include0.dts
+ run_dtc_test -I dts -O dtb -o includes.test.dtb "$SRCDIR/include0.dts"
run_test dtbs_equal_ordered includes.test.dtb test_tree1.dtb
# Check /incbin/ directive
- run_dtc_test -I dts -O dtb -o incbin.test.dtb incbin.dts
- run_test incbin incbin.test.dtb
+ run_dtc_test -I dts -O dtb -o incbin.test.dtb "$SRCDIR/incbin.dts"
+ run_test incbin "$SRCDIR/incbin.bin" incbin.test.dtb
# Check boot_cpuid_phys handling
- run_dtc_test -I dts -O dtb -o boot_cpuid.test.dtb boot-cpuid.dts
+ run_dtc_test -I dts -O dtb -o boot_cpuid.test.dtb "$SRCDIR/boot-cpuid.dts"
run_test boot-cpuid boot_cpuid.test.dtb 16
- run_dtc_test -I dts -O dtb -b 17 -o boot_cpuid_17.test.dtb boot-cpuid.dts
+ run_dtc_test -I dts -O dtb -b 17 -o boot_cpuid_17.test.dtb "$SRCDIR/boot-cpuid.dts"
run_test boot-cpuid boot_cpuid_17.test.dtb 17
run_dtc_test -I dtb -O dtb -o preserve_boot_cpuid.test.dtb boot_cpuid.test.dtb
@@ -477,9 +601,9 @@ dtc_tests () {
for tree in test_tree1.dts escapes.dts references.dts path-references.dts \
comments.dts aliases.dts include0.dts incbin.dts \
value-labels.dts ; do
- run_dtc_test -I dts -O asm -o oasm_$tree.test.s $tree
+ run_dtc_test -I dts -O asm -o oasm_$tree.test.s "$SRCDIR/$tree"
asm_to_so_test oasm_$tree
- run_dtc_test -I dts -O dtb -o $tree.test.dtb $tree
+ run_dtc_test -I dts -O dtb -o $tree.test.dtb "$SRCDIR/$tree"
run_test asm_tree_dump ./oasm_$tree.test.so oasm_$tree.test.dtb
run_wrap_test cmp oasm_$tree.test.dtb $tree.test.dtb
done
@@ -494,6 +618,27 @@ dtc_tests () {
run_test dtbs_equal_ordered $tree odts_$tree.test.dtb
done
+ # Check -Odts preserving type information
+ for tree in type-preservation.dts; do
+ run_dtc_test -I dts -O dts -o $tree.test.dts "$SRCDIR/$tree"
+ run_dtc_test -I dts -O dts $tree.test.dts
+ run_wrap_test cmp "$SRCDIR/$tree" $tree.test.dts
+ done
+ for tree in path-references; do
+ run_dtc_test -I dts -O dtb -o $tree.test.dtb "$SRCDIR/$tree.dts"
+ run_dtc_test -I dts -O dts -o $tree.test.dts "$SRCDIR/$tree.dts"
+ run_dtc_test -I dts -O dtb -o $tree.test.dts.test.dtb $tree.test.dts
+ run_test dtbs_equal_ordered $tree.test.dtb $tree.test.dts.test.dtb
+ done
+
+ # Check -Oyaml output
+ if ! $no_yaml; then
+ for tree in type-preservation; do
+ run_dtc_test -I dts -O yaml -o $tree.test.dt.yaml "$SRCDIR/$tree.dts"
+ run_wrap_test cmp "$SRCDIR/$tree.dt.yaml" $tree.test.dt.yaml
+ done
+ fi
+
# Check version conversions
for tree in test_tree1.dtb ; do
for aver in 1 2 3 16 17; do
@@ -508,76 +653,104 @@ dtc_tests () {
done
# Check merge/overlay functionality
- run_dtc_test -I dts -O dtb -o dtc_tree1_merge.test.dtb test_tree1_merge.dts
+ run_dtc_test -I dts -O dtb -o dtc_tree1_merge.test.dtb "$SRCDIR/test_tree1_merge.dts"
tree1_tests dtc_tree1_merge.test.dtb test_tree1.dtb
- run_dtc_test -I dts -O dtb -o dtc_tree1_merge_labelled.test.dtb test_tree1_merge_labelled.dts
+ run_dtc_test -I dts -O dtb -o dtc_tree1_merge_labelled.test.dtb "$SRCDIR/test_tree1_merge_labelled.dts"
tree1_tests dtc_tree1_merge_labelled.test.dtb test_tree1.dtb
- run_dtc_test -I dts -O dtb -o dtc_tree1_label_noderef.test.dtb test_tree1_label_noderef.dts
+ run_dtc_test -I dts -O dtb -o dtc_tree1_label_noderef.test.dtb "$SRCDIR/test_tree1_label_noderef.dts"
run_test dtbs_equal_unordered dtc_tree1_label_noderef.test.dtb test_tree1.dtb
- run_dtc_test -I dts -O dtb -o multilabel_merge.test.dtb multilabel_merge.dts
+ run_dtc_test -I dts -O dtb -o multilabel_merge.test.dtb "$SRCDIR/multilabel_merge.dts"
run_test references multilabel.test.dtb
run_test dtbs_equal_ordered multilabel.test.dtb multilabel_merge.test.dtb
- run_dtc_test -I dts -O dtb -o dtc_tree1_merge_path.test.dtb test_tree1_merge_path.dts
+ run_dtc_test -I dts -O dtb -o dtc_tree1_merge_path.test.dtb "$SRCDIR/test_tree1_merge_path.dts"
tree1_tests dtc_tree1_merge_path.test.dtb test_tree1.dtb
- run_wrap_error_test $DTC -I dts -O dtb -o /dev/null test_label_ref.dts
+ run_wrap_error_test $DTC -I dts -O dtb -o /dev/null "$SRCDIR/test_label_ref.dts"
# Check prop/node delete functionality
- run_dtc_test -I dts -O dtb -o dtc_tree1_delete.test.dtb test_tree1_delete.dts
+ run_dtc_test -I dts -O dtb -o dtc_tree1_delete.test.dtb "$SRCDIR/test_tree1_delete.dts"
tree1_tests dtc_tree1_delete.test.dtb
- run_dtc_test -I dts -O dts -o delete_reinstate_multilabel.dts.test.dts delete_reinstate_multilabel.dts
- run_wrap_test cmp delete_reinstate_multilabel.dts.test.dts delete_reinstate_multilabel_ref.dts
+ # Check omit-if-no-ref functionality
+ run_dtc_test -I dts -O dtb -o omit-no-ref.test.dtb "$SRCDIR/omit-no-ref.dts"
+ run_test check_path omit-no-ref.test.dtb not-exists "/node1"
+ run_test check_path omit-no-ref.test.dtb not-exists "/node2"
+ run_test check_path omit-no-ref.test.dtb exists "/node3"
+ run_test check_path omit-no-ref.test.dtb exists "/node4"
+
+ run_dtc_test -I dts -O dts -o delete_reinstate_multilabel.dts.test.dts "$SRCDIR/delete_reinstate_multilabel.dts"
+ run_wrap_test cmp delete_reinstate_multilabel.dts.test.dts "$SRCDIR/delete_reinstate_multilabel_ref.dts"
# Check some checks
- check_tests dup-nodename.dts duplicate_node_names
- check_tests dup-propname.dts duplicate_property_names
- check_tests dup-phandle.dts explicit_phandles
- check_tests zero-phandle.dts explicit_phandles
- check_tests minusone-phandle.dts explicit_phandles
- run_sh_test dtc-checkfails.sh phandle_references -- -I dts -O dtb nonexist-node-ref.dts
- run_sh_test dtc-checkfails.sh phandle_references -- -I dts -O dtb nonexist-label-ref.dts
- run_sh_test dtc-fatal.sh -I dts -O dtb nonexist-node-ref2.dts
- check_tests bad-name-property.dts name_properties
-
- check_tests bad-ncells.dts address_cells_is_cell size_cells_is_cell interrupt_cells_is_cell
- check_tests bad-string-props.dts device_type_is_string model_is_string status_is_string
- check_tests bad-reg-ranges.dts reg_format ranges_format
- check_tests bad-empty-ranges.dts ranges_format
- check_tests reg-ranges-root.dts reg_format ranges_format
- check_tests default-addr-size.dts avoid_default_addr_size
- check_tests obsolete-chosen-interrupt-controller.dts obsolete_chosen_interrupt_controller
- check_tests reg-without-unit-addr.dts unit_address_vs_reg
- check_tests unit-addr-without-reg.dts unit_address_vs_reg
- check_tests unit-addr-leading-0x.dts unit_address_format
- check_tests unit-addr-leading-0s.dts unit_address_format
- run_sh_test dtc-checkfails.sh node_name_chars -- -I dtb -O dtb bad_node_char.dtb
- run_sh_test dtc-checkfails.sh node_name_format -- -I dtb -O dtb bad_node_format.dtb
- run_sh_test dtc-checkfails.sh prop_name_chars -- -I dtb -O dtb bad_prop_char.dtb
-
- run_sh_test dtc-checkfails.sh duplicate_label -- -I dts -O dtb reuse-label1.dts
- run_sh_test dtc-checkfails.sh duplicate_label -- -I dts -O dtb reuse-label2.dts
- run_sh_test dtc-checkfails.sh duplicate_label -- -I dts -O dtb reuse-label3.dts
- run_sh_test dtc-checkfails.sh duplicate_label -- -I dts -O dtb reuse-label4.dts
- run_sh_test dtc-checkfails.sh duplicate_label -- -I dts -O dtb reuse-label5.dts
- run_sh_test dtc-checkfails.sh duplicate_label -- -I dts -O dtb reuse-label6.dts
+ check_tests "$SRCDIR/dup-nodename.dts" duplicate_node_names
+ check_tests "$SRCDIR/dup-propname.dts" duplicate_property_names
+ check_tests "$SRCDIR/dup-phandle.dts" explicit_phandles
+ check_tests "$SRCDIR/zero-phandle.dts" explicit_phandles
+ check_tests "$SRCDIR/minusone-phandle.dts" explicit_phandles
+ run_sh_test "$SRCDIR/dtc-checkfails.sh" phandle_references -- -I dts -O dtb "$SRCDIR/nonexist-node-ref.dts"
+ run_sh_test "$SRCDIR/dtc-checkfails.sh" phandle_references -- -I dts -O dtb "$SRCDIR/nonexist-label-ref.dts"
+ run_sh_test "$SRCDIR/dtc-fatal.sh" -I dts -O dtb "$SRCDIR/nonexist-node-ref2.dts"
+ check_tests "$SRCDIR/bad-name-property.dts" name_properties
+
+ check_tests "$SRCDIR/bad-ncells.dts" address_cells_is_cell size_cells_is_cell interrupt_cells_is_cell
+ check_tests "$SRCDIR/bad-string-props.dts" device_type_is_string model_is_string status_is_string label_is_string compatible_is_string_list names_is_string_list
+ check_tests "$SRCDIR/bad-chosen.dts" chosen_node_is_root
+ check_tests "$SRCDIR/bad-chosen.dts" chosen_node_bootargs
+ check_tests "$SRCDIR/bad-chosen.dts" chosen_node_stdout_path
+ check_tests "$SRCDIR/bad-reg-ranges.dts" reg_format ranges_format
+ check_tests "$SRCDIR/bad-empty-ranges.dts" ranges_format
+ check_tests "$SRCDIR/reg-ranges-root.dts" reg_format ranges_format
+ check_tests "$SRCDIR/bad-dma-ranges.dts" dma_ranges_format
+ check_tests "$SRCDIR/default-addr-size.dts" avoid_default_addr_size
+ check_tests "$SRCDIR/obsolete-chosen-interrupt-controller.dts" obsolete_chosen_interrupt_controller
+ check_tests "$SRCDIR/reg-without-unit-addr.dts" unit_address_vs_reg
+ check_tests "$SRCDIR/unit-addr-without-reg.dts" unit_address_vs_reg
+ check_tests "$SRCDIR/unit-addr-leading-0x.dts" unit_address_format
+ check_tests "$SRCDIR/unit-addr-leading-0s.dts" unit_address_format
+ check_tests "$SRCDIR/unit-addr-unique.dts" unique_unit_address
+ check_tests "$SRCDIR/bad-phandle-cells.dts" interrupts_extended_property
+ check_tests "$SRCDIR/bad-gpio.dts" gpios_property
+ check_tests "$SRCDIR/bad-graph.dts" graph_child_address
+ check_tests "$SRCDIR/bad-graph.dts" graph_port
+ check_tests "$SRCDIR/bad-graph.dts" graph_endpoint
+ run_sh_test "$SRCDIR/dtc-checkfails.sh" deprecated_gpio_property -- -Wdeprecated_gpio_property -I dts -O dtb "$SRCDIR/bad-gpio.dts"
+ check_tests "$SRCDIR/bad-interrupt-cells.dts" interrupts_property
+ check_tests "$SRCDIR/bad-interrupt-controller.dts" interrupt_provider
+ run_sh_test "$SRCDIR/dtc-checkfails.sh" node_name_chars -- -I dtb -O dtb bad_node_char.dtb
+ run_sh_test "$SRCDIR/dtc-checkfails.sh" node_name_format -- -I dtb -O dtb bad_node_format.dtb
+ run_sh_test "$SRCDIR/dtc-checkfails.sh" property_name_chars -- -I dtb -O dtb bad_prop_char.dtb
+
+ run_sh_test "$SRCDIR/dtc-checkfails.sh" duplicate_label -- -I dts -O dtb "$SRCDIR/reuse-label1.dts"
+ run_sh_test "$SRCDIR/dtc-checkfails.sh" duplicate_label -- -I dts -O dtb "$SRCDIR/reuse-label2.dts"
+ run_sh_test "$SRCDIR/dtc-checkfails.sh" duplicate_label -- -I dts -O dtb "$SRCDIR/reuse-label3.dts"
+ run_sh_test "$SRCDIR/dtc-checkfails.sh" duplicate_label -- -I dts -O dtb "$SRCDIR/reuse-label4.dts"
+ run_sh_test "$SRCDIR/dtc-checkfails.sh" duplicate_label -- -I dts -O dtb "$SRCDIR/reuse-label5.dts"
+ run_sh_test "$SRCDIR/dtc-checkfails.sh" duplicate_label -- -I dts -O dtb "$SRCDIR/reuse-label6.dts"
run_test check_path test_tree1.dtb exists "/subnode@1"
run_test check_path test_tree1.dtb not-exists "/subnode@10"
+ check_tests "$SRCDIR/pci-bridge-ok.dts" -n pci_bridge
+ check_tests "$SRCDIR/pci-bridge-bad1.dts" pci_bridge
+ check_tests "$SRCDIR/pci-bridge-bad2.dts" pci_bridge
+
+ check_tests "$SRCDIR/unit-addr-simple-bus-reg-mismatch.dts" simple_bus_reg
+ check_tests "$SRCDIR/unit-addr-simple-bus-compatible.dts" simple_bus_reg
+
+
# Check warning options
- run_sh_test dtc-checkfails.sh address_cells_is_cell interrupt_cells_is_cell -n size_cells_is_cell -- -Wno_size_cells_is_cell -I dts -O dtb bad-ncells.dts
- run_sh_test dtc-fails.sh -n test-warn-output.test.dtb -I dts -O dtb bad-ncells.dts
- run_sh_test dtc-fails.sh test-error-output.test.dtb -I dts -O dtb bad-ncells.dts -Esize_cells_is_cell
- run_sh_test dtc-checkfails.sh always_fail -- -Walways_fail -I dts -O dtb test_tree1.dts
- run_sh_test dtc-checkfails.sh -n always_fail -- -Walways_fail -Wno_always_fail -I dts -O dtb test_tree1.dts
- run_sh_test dtc-fails.sh test-negation-1.test.dtb -Ealways_fail -I dts -O dtb test_tree1.dts
- run_sh_test dtc-fails.sh -n test-negation-2.test.dtb -Ealways_fail -Eno_always_fail -I dts -O dtb test_tree1.dts
- run_sh_test dtc-fails.sh test-negation-3.test.dtb -Ealways_fail -Wno_always_fail -I dts -O dtb test_tree1.dts
- run_sh_test dtc-fails.sh -n test-negation-4.test.dtb -Esize_cells_is_cell -Eno_size_cells_is_cell -I dts -O dtb bad-ncells.dts
- run_sh_test dtc-checkfails.sh size_cells_is_cell -- -Esize_cells_is_cell -Eno_size_cells_is_cell -I dts -O dtb bad-ncells.dts
+ run_sh_test "$SRCDIR/dtc-checkfails.sh" address_cells_is_cell interrupt_cells_is_cell -n size_cells_is_cell -- -Wno_size_cells_is_cell -I dts -O dtb "$SRCDIR/bad-ncells.dts"
+ run_sh_test "$SRCDIR/dtc-fails.sh" -n test-warn-output.test.dtb -I dts -O dtb "$SRCDIR/bad-ncells.dts"
+ run_sh_test "$SRCDIR/dtc-fails.sh" test-error-output.test.dtb -I dts -O dtb bad-ncells.dts -Esize_cells_is_cell
+ run_sh_test "$SRCDIR/dtc-checkfails.sh" always_fail -- -Walways_fail -I dts -O dtb "$SRCDIR/test_tree1.dts"
+ run_sh_test "$SRCDIR/dtc-checkfails.sh" -n always_fail -- -Walways_fail -Wno_always_fail -I dts -O dtb "$SRCDIR/test_tree1.dts"
+ run_sh_test "$SRCDIR/dtc-fails.sh" test-negation-1.test.dtb -Ealways_fail -I dts -O dtb "$SRCDIR/test_tree1.dts"
+ run_sh_test "$SRCDIR/dtc-fails.sh" -n test-negation-2.test.dtb -Ealways_fail -Eno_always_fail -I dts -O dtb "$SRCDIR/test_tree1.dts"
+ run_sh_test "$SRCDIR/dtc-fails.sh" test-negation-3.test.dtb -Ealways_fail -Wno_always_fail -I dts -O dtb "$SRCDIR/test_tree1.dts"
+ run_sh_test "$SRCDIR/dtc-fails.sh" -n test-negation-4.test.dtb -Esize_cells_is_cell -Eno_size_cells_is_cell -I dts -O dtb "$SRCDIR/bad-ncells.dts"
+ run_sh_test "$SRCDIR/dtc-checkfails.sh" size_cells_is_cell -- -Esize_cells_is_cell -Eno_size_cells_is_cell -I dts -O dtb "$SRCDIR/bad-ncells.dts"
# Check for proper behaviour reading from stdin
- run_dtc_test -I dts -O dtb -o stdin_dtc_tree1.test.dtb - < test_tree1.dts
+ run_dtc_test -I dts -O dtb -o stdin_dtc_tree1.test.dtb - < "$SRCDIR/test_tree1.dts"
run_wrap_test cmp stdin_dtc_tree1.test.dtb dtc_tree1.test.dtb
run_dtc_test -I dtb -O dts -o stdin_odts_test_tree1.dtb.test.dts - < test_tree1.dtb
run_wrap_test cmp stdin_odts_test_tree1.dtb.test.dts odts_test_tree1.dtb.test.dts
@@ -588,33 +761,34 @@ dtc_tests () {
run_test integer-expressions integer-expressions.test.dtb
# Check for graceful failure in some error conditions
- run_sh_test dtc-fatal.sh -I dts -O dtb nosuchfile.dts
- run_sh_test dtc-fatal.sh -I dtb -O dtb nosuchfile.dtb
- run_sh_test dtc-fatal.sh -I fs -O dtb nosuchfile
+ run_sh_test "$SRCDIR/dtc-fatal.sh" -I dts -O dtb nosuchfile.dts
+ run_sh_test "$SRCDIR/dtc-fatal.sh" -I dtb -O dtb nosuchfile.dtb
+ run_sh_test "$SRCDIR/dtc-fatal.sh" -I fs -O dtb nosuchfile
# Dependencies
- run_dtc_test -I dts -O dtb -o dependencies.test.dtb -d dependencies.test.d dependencies.dts
- run_wrap_test cmp dependencies.test.d dependencies.cmp
+ run_dtc_test -I dts -O dtb -o dependencies.test.dtb -d dependencies.test.d "$SRCDIR/dependencies.dts"
+ sed -i.bak "s,$SRCDIR/,,g" dependencies.test.d
+ run_wrap_test cmp dependencies.test.d "$SRCDIR/dependencies.cmp"
# Search paths
- run_wrap_error_test $DTC -I dts -O dtb -o search_paths.dtb search_paths.dts
- run_dtc_test -i search_dir -I dts -O dtb -o search_paths.dtb \
- search_paths.dts
- run_wrap_error_test $DTC -i search_dir_b -I dts -O dtb \
- -o search_paths_b.dtb search_paths_b.dts
- run_dtc_test -i search_dir_b -i search_dir -I dts -O dtb \
- -o search_paths_b.dtb search_paths_b.dts
+ run_wrap_error_test $DTC -I dts -O dtb -o search_paths.dtb "$SRCDIR/search_paths.dts"
+ run_dtc_test -i "$SRCDIR/search_dir" -I dts -O dtb -o search_paths.dtb \
+ "$SRCDIR/search_paths.dts"
+ run_wrap_error_test $DTC -i "$SRCDIR/search_dir_b" -I dts -O dtb \
+ -o search_paths_b.dtb "$SRCDIR/search_paths_b.dts"
+ run_dtc_test -i "$SRCDIR/search_dir_b" -i "$SRCDIR/search_dir" -I dts -O dtb \
+ -o search_paths_b.dtb "$SRCDIR/search_paths_b.dts"
run_dtc_test -I dts -O dtb -o search_paths_subdir.dtb \
- search_dir_b/search_paths_subdir.dts
+ "$SRCDIR/search_dir_b/search_paths_subdir.dts"
# Check -a option
for align in 2 4 8 16 32 64; do
# -p -a
- run_dtc_test -O dtb -p 1000 -a $align -o align0.dtb subnode_iterate.dts
- check_align align0.dtb $align
+ run_dtc_test -O dtb -p 1000 -a $align -o align0.dtb "$SRCDIR/subnode_iterate.dts"
+ base_run_test check_align align0.dtb $align
# -S -a
- run_dtc_test -O dtb -S 1999 -a $align -o align1.dtb subnode_iterate.dts
- check_align align1.dtb $align
+ run_dtc_test -O dtb -S 1999 -a $align -o align1.dtb "$SRCDIR/subnode_iterate.dts"
+ base_run_test check_align align1.dtb $align
done
# Tests for overlay/plugin generation
@@ -654,7 +828,7 @@ cmp_tests () {
dtbs_equal_tests () {
WRONG_TREE1=""
for x in 1 2 3 4 5 6 7 8 9; do
- run_dtc_test -I dts -O dtb -o test_tree1_wrong$x.test.dtb test_tree1_wrong$x.dts
+ run_dtc_test -I dts -O dtb -o test_tree1_wrong$x.test.dtb "$SRCDIR/test_tree1_wrong$x.dts"
WRONG_TREE1="$WRONG_TREE1 test_tree1_wrong$x.test.dtb"
done
cmp_tests test_tree1.dtb $WRONG_TREE1
@@ -663,7 +837,7 @@ dtbs_equal_tests () {
fdtget_tests () {
dts=label01.dts
dtb=$dts.fdtget.test.dtb
- run_dtc_test -O dtb -o $dtb $dts
+ run_dtc_test -O dtb -o $dtb "$SRCDIR/$dts"
# run_fdtget_test <expected-result> [<flags>] <file> <node> <property>
run_fdtget_test "MyBoardName" $dtb / model
@@ -697,10 +871,10 @@ fdtget_tests () {
fdtput_tests () {
dts=label01.dts
dtb=$dts.fdtput.test.dtb
- text=lorem.txt
+ text="$SRCDIR/lorem.txt"
# Allow just enough space for $text
- run_dtc_test -O dtb -p $(stat -c %s $text) -o $dtb $dts
+ run_dtc_test -O dtb -p $($STATSZ $text) -o $dtb "$SRCDIR/$dts"
# run_fdtput_test <expected-result> <file> <node> <property> <flags> <value>
run_fdtput_test "a_model" $dtb / model -ts "a_model"
@@ -719,7 +893,7 @@ fdtput_tests () {
run_fdtput_test "$(cat $text $text)" $dtb /randomnode blob -ts "$(cat $text $text)"
# Start again with a fresh dtb
- run_dtc_test -O dtb -p $(stat -c %s $text) -o $dtb $dts
+ run_dtc_test -O dtb -p $($STATSZ $text) -o $dtb "$SRCDIR/$dts"
# Node creation
run_wrap_error_test $DTPUT $dtb -c /baldrick sod
@@ -739,7 +913,7 @@ fdtput_tests () {
"-ts" "fine wine"
run_wrap_test $DTPUT $dtb -p /you/are/drunk/sir/winston slurp -ts twice
- # Test expansion of the blob when insufficent room for a new node
+ # Test expansion of the blob when insufficient room for a new node
run_wrap_test $DTPUT $dtb -cp "$(cat $text $text)/longish"
# Allowed to create an existing node with -p
@@ -747,7 +921,7 @@ fdtput_tests () {
run_wrap_test $DTPUT $dtb -cp /chosen/son
# Start again with a fresh dtb
- run_dtc_test -O dtb -p $(stat -c %s $text) -o $dtb $dts
+ run_dtc_test -O dtb -p $($STATSZ $text) -o $dtb "$SRCDIR/$dts"
# Node delete
run_wrap_test $DTPUT $dtb -c /chosen/node1 /chosen/node2 /chosen/node3
@@ -776,13 +950,13 @@ utilfdt_tests () {
}
fdtdump_tests () {
- run_fdtdump_test fdtdump.dts
+ run_fdtdump_test "$SRCDIR/fdtdump.dts"
}
fdtoverlay_tests() {
- base=overlay_base.dts
+ base="$SRCDIR/overlay_base.dts"
basedtb=overlay_base.fdoverlay.test.dtb
- overlay=overlay_overlay_manual_fixups.dts
+ overlay="$SRCDIR/overlay_overlay_manual_fixups.dts"
overlaydtb=overlay_overlay_manual_fixups.fdoverlay.test.dtb
targetdtb=target.fdoverlay.test.dtb
@@ -791,17 +965,57 @@ fdtoverlay_tests() {
# test that the new property is installed
run_fdtoverlay_test foobar "/test-node" "test-str-property" "-ts" ${basedtb} ${targetdtb} ${overlaydtb}
+
+ stacked_base="$SRCDIR/stacked_overlay_base.dts"
+ stacked_basedtb=stacked_overlay_base.fdtoverlay.test.dtb
+ stacked_bar="$SRCDIR/stacked_overlay_bar.dts"
+ stacked_bardtb=stacked_overlay_bar.fdtoverlay.test.dtb
+ stacked_baz="$SRCDIR/stacked_overlay_baz.dts"
+ stacked_bazdtb=stacked_overlay_baz.fdtoverlay.test.dtb
+ stacked_targetdtb=stacked_overlay_target.fdtoverlay.test.dtb
+
+ run_dtc_test -@ -I dts -O dtb -o $stacked_basedtb $stacked_base
+ run_dtc_test -@ -I dts -O dtb -o $stacked_bardtb $stacked_bar
+ run_dtc_test -@ -I dts -O dtb -o $stacked_bazdtb $stacked_baz
+
+ # test that baz correctly inserted the property
+ run_fdtoverlay_test baz "/foonode/barnode/baznode" "baz-property" "-ts" ${stacked_basedtb} ${stacked_targetdtb} ${stacked_bardtb} ${stacked_bazdtb}
+
+ # test that bar and baz are correctly appended to __symbols__
+ run_fdtoverlay_test "/foonode/barnode" "/__symbols__" "bar" "-ts" ${stacked_basedtb} ${stacked_targetdtb} ${stacked_bardtb}
+ run_fdtoverlay_test "/foonode/barnode/baznode" "/__symbols__" "baz" "-ts" ${stacked_basedtb} ${stacked_targetdtb} ${stacked_bardtb} ${stacked_bazdtb}
+
+ overlay_long_path="$SRCDIR/overlay_overlay_long_path.dts"
+ overlay_long_pathdtb=overlay_overlay_long_path.fdoverlay.test.dtb
+ target_long_pathdtb=overlay_overlay_long_path_target.fdoverlay.test.dtb
+ run_dtc_test -@ -I dts -O dtb -o $overlay_long_pathdtb $overlay_long_path
+
+ # test that fdtoverlay manages to apply overlays with long target path
+ run_fdtoverlay_test lpath "/test-node/sub-test-node/sub-test-node-with-very-long-target-path/test-0" "prop" "-ts" ${basedtb} ${target_long_pathdtb} ${overlay_long_pathdtb}
+
+ # test adding a label to the root of a fragment
+ stacked_base_nolabel="$SRCDIR/stacked_overlay_base_nolabel.dts"
+ stacked_base_nolabeldtb=stacked_overlay_base_nolabel.test.dtb
+ stacked_addlabel="$SRCDIR/stacked_overlay_addlabel.dts"
+ stacked_addlabeldtb=stacked_overlay_addlabel.test.dtb
+ stacked_addlabel_targetdtb=stacked_overlay_target_nolabel.fdtoverlay.test.dtb
+
+ run_dtc_test -@ -I dts -O dtb -o $stacked_base_nolabeldtb $stacked_base_nolabel
+ run_dtc_test -@ -I dts -O dtb -o $stacked_addlabeldtb $stacked_addlabel
+
+ run_fdtoverlay_test baz "/foonode/barnode/baznode" "baz-property" "-ts" ${stacked_base_nolabeldtb} ${stacked_addlabel_targetdtb} ${stacked_addlabeldtb} ${stacked_bardtb} ${stacked_bazdtb}
}
pylibfdt_tests () {
+ run_dtc_test -I dts -O dtb -o test_props.dtb "$SRCDIR/test_props.dts"
TMP=/tmp/tests.stderr.$$
- python pylibfdt_tests.py -v 2> $TMP
+ $PYTHON "$SRCDIR/pylibfdt_tests.py" -v 2> $TMP
# Use the 'ok' message meaning the test passed, 'ERROR' meaning it failed
# and the summary line for total tests (e.g. 'Ran 17 tests in 0.002s').
# We could add pass + fail to get total tests, but this provides a useful
# sanity check.
- pass_count=$(grep "\.\.\. ok$" $TMP | wc -l)
+ pass_count=$(grep "ok$" $TMP | wc -l)
fail_count=$(grep "^ERROR: " $TMP | wc -l)
total_tests=$(sed -n 's/^Ran \([0-9]*\) tests.*$/\1/p' $TMP)
cat $TMP
@@ -834,7 +1048,7 @@ if [ -z "$TESTSETS" ]; then
TESTSETS="libfdt utilfdt dtc dtbs_equal fdtget fdtput fdtdump fdtoverlay"
# Test pylibfdt if the libfdt Python module is available.
- if [ -f ../pylibfdt/_libfdt.so ]; then
+ if ! $no_python; then
TESTSETS="$TESTSETS pylibfdt"
fi
fi
@@ -885,3 +1099,4 @@ fi
echo "* Strange test result: $tot_strange"
echo "**********"
+[ "$tot_tests" -eq "$tot_pass" ] || exit 1
diff --git a/tests/rw_oom.c b/tests/rw_oom.c
new file mode 100644
index 0000000..39fc312
--- /dev/null
+++ b/tests/rw_oom.c
@@ -0,0 +1,83 @@
+// 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.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+/* This is not derived programmatically. May require adjustment to changes. */
+#define SPACE 285
+
+#define CHECK(code) \
+ { \
+ err = (code); \
+ if (err) \
+ FAIL(#code ": %s", fdt_strerror(err)); \
+ }
+
+#define OFF_CHECK(off, code) \
+ { \
+ (off) = (code); \
+ if (off < 0) \
+ FAIL(#code ": %s", fdt_strerror(off)); \
+ }
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+ int err;
+ int offset, s1;
+ int strsize1, strsize2;
+
+ /*
+ * Check OOM path, and check that property is cleaned up if it fails
+ * with OOM, rather than adding an orphan name.
+ *
+ * SW OOM is tested with the realloc/resize strategies.
+ */
+ test_init(argc, argv);
+
+ fdt = xmalloc(SPACE);
+
+ /* First create empty tree with SW */
+ CHECK(fdt_create_empty_tree(fdt, SPACE));
+
+ CHECK(fdt_add_mem_rsv(fdt, TEST_ADDR_1, TEST_SIZE_1));
+ CHECK(fdt_add_mem_rsv(fdt, TEST_ADDR_2, TEST_SIZE_2));
+
+ CHECK(fdt_setprop_string(fdt, 0, "compatible", "test_oom"));
+ CHECK(fdt_setprop_u32(fdt, 0, "prop-int", TEST_VALUE_1));
+ CHECK(fdt_setprop_u64(fdt, 0, "prop-int64", TEST_VALUE64_1));
+ CHECK(fdt_setprop_string(fdt, 0, "prop-str", TEST_STRING_1));
+
+ OFF_CHECK(offset, fdt_add_subnode(fdt, 0, "subnode@1"));
+ s1 = offset;
+
+ strsize1 = fdt_size_dt_strings(fdt);
+ err = fdt_setprop_string(fdt, s1, "unique", "subnode1");
+ if (err != -FDT_ERR_NOSPACE)
+ FAIL("fdt_setprop_string(fdt, s1, \"compatible\", \"subnode1\"): %s", fdt_strerror(err));
+ strsize2 = fdt_size_dt_strings(fdt);
+
+ if (strsize1 != strsize2)
+ FAIL("fdt_setprop NOSPACE error failed to clean up allocated string\n");
+ err = 0;
+
+ /* Ensure we failed in the right place */
+ CHECK(fdt_setprop_string(fdt, s1, "unique", ""));
+
+ CHECK(fdt_pack(fdt));
+
+ PASS();
+}
diff --git a/tests/rw_tree1.c b/tests/rw_tree1.c
index efd4718..1fe2351 100644
--- a/tests/rw_tree1.c
+++ b/tests/rw_tree1.c
@@ -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>
diff --git a/tests/set_name.c b/tests/set_name.c
index 9861587..a62cb58 100644
--- a/tests/set_name.c
+++ b/tests/set_name.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for fdt_set_name()
* 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>
#include <stdio.h>
diff --git a/tests/setprop.c b/tests/setprop.c
index be1b147..fa3938d 100644
--- a/tests/setprop.c
+++ b/tests/setprop.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for fdt_setprop()
* 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>
diff --git a/tests/setprop_inplace.c b/tests/setprop_inplace.c
index 80447a0..7e1198d 100644
--- a/tests/setprop_inplace.c
+++ b/tests/setprop_inplace.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for fdt_setprop_inplace()
* 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 <inttypes.h>
diff --git a/tests/sized_cells.c b/tests/sized_cells.c
index 0b2b8dc..9ca5a59 100644
--- a/tests/sized_cells.c
+++ b/tests/sized_cells.c
@@ -1,22 +1,9 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for variable sized cells 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>
diff --git a/tests/sourceoutput.dts b/tests/sourceoutput.dts
index 477762f..5a7459b 100644
--- a/tests/sourceoutput.dts
+++ b/tests/sourceoutput.dts
@@ -2,7 +2,7 @@
/ {
/* Some versions had an off-by-2 bug which caused an abort
- * when outputing labels within strings like this in source
+ * when outputting labels within strings like this in source
* format */
prop1: prop1 = start1: "foo", mid1: "bar" end1: ;
diff --git a/tests/stacked_overlay_addlabel.dts b/tests/stacked_overlay_addlabel.dts
new file mode 100644
index 0000000..e7187a3
--- /dev/null
+++ b/tests/stacked_overlay_addlabel.dts
@@ -0,0 +1,15 @@
+/dts-v1/;
+/plugin/;
+/ {
+ frag1: fragment@1 {
+ target-path = "/foonode";
+ local: localinfo {
+ };
+ foo: __overlay__ {
+ overlay-1-property;
+ bar: barnode {
+ bar-property = "bar";
+ };
+ };
+ };
+};
diff --git a/tests/stacked_overlay_bar.dts b/tests/stacked_overlay_bar.dts
new file mode 100644
index 0000000..c646399
--- /dev/null
+++ b/tests/stacked_overlay_bar.dts
@@ -0,0 +1,13 @@
+/dts-v1/;
+/plugin/;
+/ {
+ fragment@1 {
+ target = <&foo>;
+ __overlay__ {
+ overlay-1-property;
+ bar: barnode {
+ bar-property = "bar";
+ };
+ };
+ };
+};
diff --git a/tests/stacked_overlay_base.dts b/tests/stacked_overlay_base.dts
new file mode 100644
index 0000000..2916423
--- /dev/null
+++ b/tests/stacked_overlay_base.dts
@@ -0,0 +1,6 @@
+/dts-v1/;
+/ {
+ foo: foonode {
+ foo-property = "foo";
+ };
+};
diff --git a/tests/stacked_overlay_base_nolabel.dts b/tests/stacked_overlay_base_nolabel.dts
new file mode 100644
index 0000000..0c47f0d
--- /dev/null
+++ b/tests/stacked_overlay_base_nolabel.dts
@@ -0,0 +1,6 @@
+/dts-v1/;
+/ {
+ foonode {
+ foo-property = "foo";
+ };
+};
diff --git a/tests/stacked_overlay_baz.dts b/tests/stacked_overlay_baz.dts
new file mode 100644
index 0000000..a52f0cc
--- /dev/null
+++ b/tests/stacked_overlay_baz.dts
@@ -0,0 +1,13 @@
+/dts-v1/;
+/plugin/;
+/ {
+ fragment@1 {
+ target = <&bar>;
+ __overlay__ {
+ overlay-2-property;
+ baz: baznode {
+ baz-property = "baz";
+ };
+ };
+ };
+};
diff --git a/tests/string_escapes.c b/tests/string_escapes.c
index 8cdee4b..53c9dfc 100644
--- a/tests/string_escapes.c
+++ b/tests/string_escapes.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for string escapes in dtc
* 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>
#include <stdio.h>
diff --git a/tests/stringlist.c b/tests/stringlist.c
index a9d3e73..bbc3020 100644
--- a/tests/stringlist.c
+++ b/tests/stringlist.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for string handling
* Copyright (C) 2015 NVIDIA 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>
@@ -60,10 +47,11 @@ static void check_expected_failure(const void *fdt, const char *path,
FAIL("empty string not found in #address-cells: %d\n", err);
/*
- * fdt_get_string() can successfully extract strings from non-string
- * properties. This is because it doesn't necessarily parse the whole
- * property value, which would be necessary for it to determine if a
- * valid string or string list is present.
+ * fdt_getprop_string() can successfully extract strings from
+ * non-string properties. This is because it doesn't
+ * necessarily parse the whole property value, which would be
+ * necessary for it to determine if a valid string or string
+ * list is present.
*/
}
diff --git a/tests/subnode_iterate.c b/tests/subnode_iterate.c
index 7be5706..2dc9b2d 100644
--- a/tests/subnode_iterate.c
+++ b/tests/subnode_iterate.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Tests that fdt_next_subnode() works as expected
@@ -5,20 +6,6 @@
* Copyright (C) 2013 Google, Inc
*
* 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>
diff --git a/tests/subnode_offset.c b/tests/subnode_offset.c
index 231fcb5..1362f99 100644
--- a/tests/subnode_offset.c
+++ b/tests/subnode_offset.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for fdt_subnode_offset()
* 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>
#include <stdio.h>
diff --git a/tests/supernode_atdepth_offset.c b/tests/supernode_atdepth_offset.c
index 43e120d..4435b49 100644
--- a/tests/supernode_atdepth_offset.c
+++ b/tests/supernode_atdepth_offset.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for fdt_supernode_atdepth_offset()
* 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>
#include <stdio.h>
diff --git a/tests/sw_states.c b/tests/sw_states.c
new file mode 100644
index 0000000..42d57ae
--- /dev/null
+++ b/tests/sw_states.c
@@ -0,0 +1,127 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for error handling with sequential write states
+ * Copyright (C) 2018 David Gibson, Red Hat Inc.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+#define SPACE 65536
+
+#define CHECK_OK(code) \
+ do { \
+ verbose_printf(" OK: %s\n", #code); \
+ err = (code); \
+ if (err) \
+ FAIL(#code ": %s", fdt_strerror(err)); \
+ } while (0)
+
+#define CHECK_BADSTATE(code) \
+ do { \
+ verbose_printf("BAD: %s\n", #code); \
+ err = (code); \
+ if (err == 0) \
+ FAIL(#code ": succeeded in bad state"); \
+ else if (err != -FDT_ERR_BADSTATE) \
+ FAIL(#code ": %s", fdt_strerror(err)); \
+ } while (0)
+
+int main(int argc, char *argv[])
+{
+ void *fdt = NULL;
+ int err;
+
+ test_init(argc, argv);
+
+ fdt = xmalloc(SPACE);
+
+ err = fdt_create(fdt, SPACE);
+ if (err)
+ FAIL("fdt_create(): %s", fdt_strerror(err));
+
+ /* Memory reserve state */
+
+ CHECK_BADSTATE(fdt_begin_node(fdt, ""));
+ CHECK_BADSTATE(fdt_property_string(fdt, "bad-str", "TEST_STRING_1"));
+ CHECK_BADSTATE(fdt_end_node(fdt));
+ CHECK_BADSTATE(fdt_finish(fdt));
+
+ CHECK_OK(fdt_add_reservemap_entry(fdt, TEST_ADDR_1, TEST_SIZE_1));
+ CHECK_OK(fdt_add_reservemap_entry(fdt, TEST_ADDR_2, TEST_SIZE_2));
+
+ CHECK_BADSTATE(fdt_begin_node(fdt, ""));
+ CHECK_BADSTATE(fdt_property_string(fdt, "bad-str", "TEST_STRING_1"));
+ CHECK_BADSTATE(fdt_end_node(fdt));
+ CHECK_BADSTATE(fdt_finish(fdt));
+
+ CHECK_OK(fdt_finish_reservemap(fdt));
+
+ /* Structure state */
+
+ CHECK_BADSTATE(fdt_add_reservemap_entry(fdt, TEST_ADDR_1, TEST_SIZE_1));
+ CHECK_BADSTATE(fdt_finish_reservemap(fdt));
+
+ CHECK_OK(fdt_begin_node(fdt, ""));
+ CHECK_OK(fdt_property_string(fdt, "compatible", "test_tree1"));
+ CHECK_OK(fdt_property_u32(fdt, "prop-int", TEST_VALUE_1));
+ CHECK_OK(fdt_property_u64(fdt, "prop-int64", TEST_VALUE64_1));
+ CHECK_OK(fdt_property_string(fdt, "prop-str", TEST_STRING_1));
+ CHECK_OK(fdt_property_u32(fdt, "#address-cells", 1));
+ CHECK_OK(fdt_property_u32(fdt, "#size-cells", 0));
+
+ CHECK_OK(fdt_begin_node(fdt, "subnode@1"));
+ CHECK_OK(fdt_property_string(fdt, "compatible", "subnode1"));
+ CHECK_OK(fdt_property_u32(fdt, "reg", 1));
+ CHECK_OK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_1));
+ CHECK_OK(fdt_begin_node(fdt, "subsubnode"));
+ CHECK_OK(fdt_property(fdt, "compatible", "subsubnode1\0subsubnode",
+ 23));
+ CHECK_OK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_1));
+ CHECK_OK(fdt_end_node(fdt));
+ CHECK_OK(fdt_begin_node(fdt, "ss1"));
+ CHECK_OK(fdt_end_node(fdt));
+ CHECK_OK(fdt_end_node(fdt));
+
+ CHECK_OK(fdt_begin_node(fdt, "subnode@2"));
+ CHECK_OK(fdt_property_u32(fdt, "reg", 2));
+ CHECK_OK(fdt_property_cell(fdt, "linux,phandle", PHANDLE_1));
+ CHECK_OK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_2));
+ CHECK_OK(fdt_property_u32(fdt, "#address-cells", 1));
+ CHECK_OK(fdt_property_u32(fdt, "#size-cells", 0));
+ CHECK_OK(fdt_begin_node(fdt, "subsubnode@0"));
+ CHECK_OK(fdt_property_u32(fdt, "reg", 0));
+ CHECK_OK(fdt_property_cell(fdt, "phandle", PHANDLE_2));
+ CHECK_OK(fdt_property(fdt, "compatible", "subsubnode2\0subsubnode",
+ 23));
+ CHECK_OK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_2));
+ CHECK_OK(fdt_end_node(fdt));
+ CHECK_OK(fdt_begin_node(fdt, "ss2"));
+ CHECK_OK(fdt_end_node(fdt));
+
+ CHECK_OK(fdt_end_node(fdt));
+
+ CHECK_OK(fdt_end_node(fdt));
+
+ CHECK_OK(fdt_finish(fdt));
+
+ /* Completed state */
+
+ CHECK_BADSTATE(fdt_add_reservemap_entry(fdt, TEST_ADDR_1, TEST_SIZE_1));
+ CHECK_BADSTATE(fdt_finish_reservemap(fdt));
+ CHECK_BADSTATE(fdt_begin_node(fdt, ""));
+ CHECK_BADSTATE(fdt_property_string(fdt, "bad-str", "TEST_STRING_1"));
+ CHECK_BADSTATE(fdt_end_node(fdt));
+ CHECK_BADSTATE(fdt_finish(fdt));
+
+ PASS();
+}
diff --git a/tests/sw_tree1.c b/tests/sw_tree1.c
index 6a338fc..7069ace 100644
--- a/tests/sw_tree1.c
+++ b/tests/sw_tree1.c
@@ -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>
@@ -35,10 +22,13 @@ static enum {
FIXED = 0,
RESIZE,
REALLOC,
+ NEWALLOC,
} alloc_mode;
static void realloc_fdt(void **fdt, size_t *size, bool created)
{
+ int err;
+
switch (alloc_mode) {
case FIXED:
if (!(*fdt))
@@ -52,7 +42,10 @@ static void realloc_fdt(void **fdt, size_t *size, bool created)
*fdt = xmalloc(SPACE);
} else if (*size < SPACE) {
*size += 1;
- fdt_resize(*fdt, *fdt, *size);
+ err = fdt_resize(*fdt, *fdt, *size);
+ if (err < 0)
+ FAIL("fdt_resize() failed: %s",
+ fdt_strerror(err));
} else {
FAIL("Ran out of space");
}
@@ -61,9 +54,29 @@ static void realloc_fdt(void **fdt, size_t *size, bool created)
case REALLOC:
*size += 1;
*fdt = xrealloc(*fdt, *size);
- if (created)
- fdt_resize(*fdt, *fdt, *size);
+ if (created) {
+ err = fdt_resize(*fdt, *fdt, *size);
+ if (err < 0)
+ FAIL("fdt_resize() failed: %s",
+ fdt_strerror(err));
+ }
+ return;
+
+ case NEWALLOC: {
+ void *buf;
+
+ *size += 1;
+ buf = xmalloc(*size);
+ if (created) {
+ err = fdt_resize(*fdt, buf, *size);
+ if (err < 0)
+ FAIL("fdt_resize() failed: %s",
+ fdt_strerror(err));
+ }
+ free(*fdt);
+ *fdt = buf;
return;
+ }
default:
CONFIG("Bad allocation mode");
@@ -88,19 +101,27 @@ int main(int argc, char *argv[])
void *place;
const char place_str[] = "this is a placeholder string\0string2";
int place_len = sizeof(place_str);
+ int create_flags;
test_init(argc, argv);
- if (argc == 1) {
- alloc_mode = FIXED;
- size = SPACE;
- } else if (argc == 2) {
- if (streq(argv[1], "resize")) {
+ alloc_mode = FIXED;
+ size = SPACE;
+ create_flags = 0;
+
+ if (argc == 2 || argc == 3) {
+ if (streq(argv[1], "fixed")) {
+ alloc_mode = FIXED;
+ size = SPACE;
+ } else if (streq(argv[1], "resize")) {
alloc_mode = REALLOC;
size = 0;
} else if (streq(argv[1], "realloc")) {
alloc_mode = REALLOC;
size = 0;
+ } else if (streq(argv[1], "newalloc")) {
+ alloc_mode = NEWALLOC;
+ size = 0;
} else {
char *endp;
@@ -112,9 +133,35 @@ int main(int argc, char *argv[])
argv[1]);
}
}
+ if (argc == 3) {
+ char *str = argv[2], *saveptr, *tok;
+ bool default_flag = false;
+
+ while ((tok = strtok_r(str, ",", &saveptr)) != NULL) {
+ str = NULL;
+ if (streq(tok, "default")) {
+ default_flag = true;
+ } else if (streq(tok, "no_name_dedup")) {
+ create_flags |= FDT_CREATE_FLAG_NO_NAME_DEDUP;
+ } else if (streq(tok, "bad")) {
+ create_flags |= 0xffffffff;
+ } else {
+ CONFIG("Bad creation flags \"%s\" specified",
+ argv[2]);
+ }
+ }
+
+ if (default_flag && create_flags != 0)
+ CONFIG("Bad creation flags \"%s\" specified",
+ argv[2]);
+ }
+
+ if (argc > 3) {
+ CONFIG("sw_tree1 [<allocation mode>] [<create flags>]");
+ }
fdt = xmalloc(size);
- CHECK(fdt_create(fdt, size));
+ CHECK(fdt_create_with_flags(fdt, size, create_flags));
created = true;
diff --git a/tests/sw_tree1.supp b/tests/sw_tree1.supp
deleted file mode 100644
index 279f9e5..0000000
--- a/tests/sw_tree1.supp
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- allocation methods causes uninitialized data in alignment gap
- Memcheck:Param
- write(buf)
- fun:__write_nocancel
- fun:utilfdt_write_err
- fun:save_blob
- fun:main
-}
-{
- allocation methods causes uninitialized data in alignment gap
- Memcheck:Param
- write(buf)
- fun:__write_nocancel
- fun:utilfdt_write_err
- fun:save_blob
- fun:main
-}
diff --git a/tests/test_props.dts b/tests/test_props.dts
new file mode 100644
index 0000000..7e59bd1
--- /dev/null
+++ b/tests/test_props.dts
@@ -0,0 +1,11 @@
+/dts-v1/;
+
+/ {
+ compatible = "test_props";
+ prop-hex32 = <0xdeadbeef>;
+ prop-uint32 = <123>;
+ prop-int32 = <0xfffffffe>;
+ prop-hex64 = /bits/ 64 <0xdeadbeef01abcdef>;
+ prop-uint64 = /bits/ 64 <9223372036854775807>;
+ prop-int64 = /bits/ 64 <0xfffffffffffffffe>;
+};
diff --git a/tests/testdata.h b/tests/testdata.h
index 3588778..0d08efb 100644
--- a/tests/testdata.h
+++ b/tests/testdata.h
@@ -4,15 +4,25 @@
#define ASM_CONST_LL(x) (x##ULL)
#endif
-#define TEST_ADDR_1 ASM_CONST_LL(0xdeadbeef00000000)
-#define TEST_SIZE_1 ASM_CONST_LL(0x100000)
-#define TEST_ADDR_2 ASM_CONST_LL(123456789)
-#define TEST_SIZE_2 ASM_CONST_LL(010000)
+#define TEST_ADDR_1H ASM_CONST_LL(0xdeadbeef)
+#define TEST_ADDR_1L ASM_CONST_LL(0x00000000)
+#define TEST_ADDR_1 ((TEST_ADDR_1H << 32) | TEST_ADDR_1L)
+#define TEST_SIZE_1H ASM_CONST_LL(0x00000000)
+#define TEST_SIZE_1L ASM_CONST_LL(0x00100000)
+#define TEST_SIZE_1 ((TEST_SIZE_1H << 32) | TEST_SIZE_1L)
+#define TEST_ADDR_2H ASM_CONST_LL(0)
+#define TEST_ADDR_2L ASM_CONST_LL(123456789)
+#define TEST_ADDR_2 ((TEST_ADDR_2H << 32) | TEST_ADDR_2L)
+#define TEST_SIZE_2H ASM_CONST_LL(0)
+#define TEST_SIZE_2L ASM_CONST_LL(010000)
+#define TEST_SIZE_2 ((TEST_SIZE_2H << 32) | TEST_SIZE_2L)
#define TEST_VALUE_1 0xdeadbeef
#define TEST_VALUE_2 123456789
-#define TEST_VALUE64_1 ASM_CONST_LL(0xdeadbeef01abcdef)
+#define TEST_VALUE64_1H ASM_CONST_LL(0xdeadbeef)
+#define TEST_VALUE64_1L ASM_CONST_LL(0x01abcdef)
+#define TEST_VALUE64_1 ((TEST_VALUE64_1H << 32) | TEST_VALUE64_1L)
#define PHANDLE_1 0x2000
#define PHANDLE_2 0x2001
@@ -30,11 +40,19 @@
#define TEST_CHAR4 '\''
#define TEST_CHAR5 '\xff'
+#define TEST_MEMREGION_ADDR 0x12345678
+#define TEST_MEMREGION_ADDR_HI 0x8765432100000000
+#define TEST_MEMREGION_SIZE 0x9abcdef0
+#define TEST_MEMREGION_SIZE_HI 0x0fedcba900000000
+#define TEST_MEMREGION_SIZE_INC 0x1000
+
#ifndef __ASSEMBLY__
-extern struct fdt_header _test_tree1;
-extern struct fdt_header _truncated_property;
-extern struct fdt_header _bad_node_char;
-extern struct fdt_header _bad_node_format;
-extern struct fdt_header _bad_prop_char;
-extern struct fdt_header _ovf_size_strings;
+extern struct fdt_header test_tree1;
+extern struct fdt_header truncated_property;
+extern struct fdt_header bad_node_char;
+extern struct fdt_header bad_node_format;
+extern struct fdt_header bad_prop_char;
+extern struct fdt_header ovf_size_strings;
+extern struct fdt_header truncated_string;
+extern struct fdt_header truncated_memrsv;
#endif /* ! __ASSEMBLY */
diff --git a/tests/tests.h b/tests/tests.h
index c0e4d3c..1017366 100644
--- a/tests/tests.h
+++ b/tests/tests.h
@@ -1,23 +1,10 @@
-#ifndef _TESTS_H
-#define _TESTS_H
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#ifndef TESTS_H
+#define TESTS_H
/*
* libfdt - Flat Device Tree manipulation
* Testcase definitions
* 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
*/
#define DEBUG
@@ -118,7 +105,21 @@ const void *check_getprop(void *fdt, int nodeoffset, const char *name,
})
#define check_getprop_string(fdt, nodeoffset, name, s) \
check_getprop((fdt), (nodeoffset), (name), strlen(s)+1, (s))
+
+/* Returns non-NULL if the property at poffset has the name in_name */
+const void *check_get_prop_offset(void *fdt, int poffset, const char *in_name,
+ int in_len, const void *in_val);
+#define check_get_prop_offset_cell(fdt, poffset, name, val) \
+ ({ \
+ fdt32_t x = cpu_to_fdt32(val); \
+ check_get_prop_offset(fdt, poffset, name, sizeof(x), &x); \
+ })
+
+const void *check_getprop_addrrange(void *fdt, int parent, int nodeoffset,
+ const char *name, int num);
+
int nodename_eq(const char *s1, const char *s2);
+void vg_prepare_blob(void *fdt, size_t bufsize);
void *load_blob(const char *filename);
void *load_blob_arg(int argc, char *argv[]);
void save_blob(const char *filename, void *blob);
@@ -126,4 +127,4 @@ void *open_blob_rw(void *blob);
#include "util.h"
-#endif /* _TESTS_H */
+#endif /* TESTS_H */
diff --git a/tests/testutils.c b/tests/testutils.c
index 521f4f1..5e494c5 100644
--- a/tests/testutils.c
+++ b/tests/testutils.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase common utility functions
* 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
*/
#define _GNU_SOURCE /* for strsignal() in glibc. FreeBSD has it either way */
@@ -30,9 +17,25 @@
#include <unistd.h>
#include <fcntl.h>
+#if NO_VALGRIND
+static inline void VALGRIND_MAKE_MEM_UNDEFINED(void *p, size_t len)
+{
+}
+
+static inline void VALGRIND_MAKE_MEM_DEFINED(void *p, size_t len)
+{
+}
+#else
+#include <valgrind/memcheck.h>
+#endif
+
#include <libfdt.h>
#include "tests.h"
+#include "testdata.h"
+
+/* For FDT_SW_MAGIC */
+#include "libfdt_internal.h"
int verbose_test = 1;
char *test_name;
@@ -88,7 +91,7 @@ void check_property(void *fdt, int nodeoffset, const char *name,
int len, const void *val)
{
const struct fdt_property *prop;
- int retlen;
+ int retlen, namelen;
uint32_t tag, nameoff, proplen;
const char *propname;
@@ -96,7 +99,7 @@ void check_property(void *fdt, int nodeoffset, const char *name,
prop = fdt_get_property(fdt, nodeoffset, name, &retlen);
verbose_printf("pointer %p\n", prop);
if (! prop)
- FAIL("Error retreiving \"%s\" pointer: %s", name,
+ FAIL("Error retrieving \"%s\" pointer: %s", name,
fdt_strerror(retlen));
tag = fdt32_to_cpu(prop->tag);
@@ -106,8 +109,13 @@ void check_property(void *fdt, int nodeoffset, const char *name,
if (tag != FDT_PROP)
FAIL("Incorrect tag 0x%08x on property \"%s\"", tag, name);
- propname = fdt_string(fdt, nameoff);
- if (!propname || !streq(propname, name))
+ propname = fdt_get_string(fdt, nameoff, &namelen);
+ if (!propname)
+ FAIL("Couldn't get property name: %s", fdt_strerror(namelen));
+ if (namelen != strlen(propname))
+ FAIL("Incorrect prop name length: %d instead of %zd",
+ namelen, strlen(propname));
+ if (!streq(propname, name))
FAIL("Property name mismatch \"%s\" instead of \"%s\"",
propname, name);
if (proplen != retlen)
@@ -117,7 +125,7 @@ void check_property(void *fdt, int nodeoffset, const char *name,
if (proplen != len)
FAIL("Size mismatch on property \"%s\": %d insead of %d",
name, proplen, len);
- if (memcmp(val, prop->data, len) != 0)
+ if (len && memcmp(val, prop->data, len) != 0)
FAIL("Data mismatch on property \"%s\"", name);
}
@@ -134,12 +142,94 @@ const void *check_getprop(void *fdt, int nodeoffset, const char *name,
if (proplen != len)
FAIL("Size mismatch on property \"%s\": %d insead of %d",
name, proplen, len);
- if (memcmp(val, propval, len) != 0)
+ if (len && memcmp(val, propval, len) != 0)
FAIL("Data mismatch on property \"%s\"", name);
return propval;
}
+const void *check_get_prop_offset(void *fdt, int poffset, const char *exp_name,
+ int exp_len, const void *exp_val)
+{
+ const void *propval;
+ const char *name;
+ int proplen;
+
+ propval = fdt_getprop_by_offset(fdt, poffset, &name, &proplen);
+ if (!propval)
+ FAIL("fdt_getprop(\"%s\"): %s", name, fdt_strerror(proplen));
+
+ /* Not testing for this field, so ignore */
+ if (strcmp(name, exp_name))
+ return NULL;
+
+ if (proplen != exp_len)
+ FAIL("Size mismatch on property \"%s\": %d insead of %d",
+ name, proplen, exp_len);
+ if (exp_len && memcmp(exp_val, propval, exp_len))
+ FAIL("Data mismatch on property \"%s\"", name);
+
+ return propval;
+}
+
+const void *check_getprop_addrrange(void *fdt, int parent, int nodeoffset,
+ const char *name, int num)
+{
+ const void *propval;
+ int xac, xsc, buf_size, cells, i;
+ char *buf, *p;
+ uint64_t addr, size;
+ fdt32_t val;
+
+ xac = fdt_address_cells(fdt, parent);
+ xsc = fdt_size_cells(fdt, parent);
+
+ if (xac <= 0)
+ FAIL("Couldn't identify #address-cells: %s",
+ fdt_strerror(xac));
+ if (xsc <= 0)
+ FAIL("Couldn't identify #size-cells: %s",
+ fdt_strerror(xsc));
+
+ buf_size = (xac + xsc) * sizeof(fdt32_t) * num;
+ buf = malloc(buf_size);
+ if (!buf)
+ FAIL("Couldn't allocate temporary buffer");
+
+ /* expected value */
+ addr = TEST_MEMREGION_ADDR;
+ if (xac > 1)
+ addr += TEST_MEMREGION_ADDR_HI;
+ size = TEST_MEMREGION_SIZE;
+ if (xsc > 1)
+ size += TEST_MEMREGION_SIZE_HI;
+ for (p = buf, i = 0; i < num; i++) {
+ cells = xac;
+ while (cells) {
+ val = cpu_to_fdt32(addr >> (32 * (--cells)));
+ memcpy(p, &val, sizeof(val));
+ p += sizeof(val);
+ }
+ cells = xsc;
+ while (cells) {
+ val = cpu_to_fdt32(size >> (32 * (--cells)));
+ memcpy(p, &val, sizeof(val));
+ p += sizeof(val);
+ }
+
+ addr += size;
+ size += TEST_MEMREGION_SIZE_INC;
+ }
+
+ /* check */
+ propval = check_getprop(fdt, nodeoffset, name, buf_size,
+ (const void *)buf);
+
+ free(buf);
+
+ return propval;
+}
+
int nodename_eq(const char *s1, const char *s2)
{
int len = strlen(s2);
@@ -154,16 +244,66 @@ int nodename_eq(const char *s1, const char *s2)
return 0;
}
-#define CHUNKSIZE 128
+void vg_prepare_blob(void *fdt, size_t bufsize)
+{
+ char *blob = fdt;
+ int off_memrsv, off_strings, off_struct;
+ int num_memrsv;
+ size_t size_memrsv, size_strings, size_struct;
+
+ off_memrsv = fdt_off_mem_rsvmap(fdt);
+ num_memrsv = fdt_num_mem_rsv(fdt);
+ if (num_memrsv < 0)
+ size_memrsv = fdt_totalsize(fdt) - off_memrsv;
+ else
+ size_memrsv = (num_memrsv + 1)
+ * sizeof(struct fdt_reserve_entry);
+
+ VALGRIND_MAKE_MEM_UNDEFINED(blob, bufsize);
+ VALGRIND_MAKE_MEM_DEFINED(blob, FDT_V1_SIZE);
+ VALGRIND_MAKE_MEM_DEFINED(blob, fdt_header_size(fdt));
+
+ if (fdt_magic(fdt) == FDT_MAGIC) {
+ off_strings = fdt_off_dt_strings(fdt);
+ if (fdt_version(fdt) >= 3)
+ size_strings = fdt_size_dt_strings(fdt);
+ else
+ size_strings = fdt_totalsize(fdt) - off_strings;
+
+ off_struct = fdt_off_dt_struct(fdt);
+ if (fdt_version(fdt) >= 17)
+ size_struct = fdt_size_dt_struct(fdt);
+ else
+ size_struct = fdt_totalsize(fdt) - off_struct;
+ } else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
+ size_strings = fdt_size_dt_strings(fdt);
+ off_strings = fdt_off_dt_strings(fdt) - size_strings;
+
+ off_struct = fdt_off_dt_struct(fdt);
+ size_struct = fdt_size_dt_struct(fdt);
+ size_struct = fdt_totalsize(fdt) - off_struct;
+
+ } else {
+ CONFIG("Bad magic on vg_prepare_blob()");
+ }
+
+ VALGRIND_MAKE_MEM_DEFINED(blob + off_memrsv, size_memrsv);
+ VALGRIND_MAKE_MEM_DEFINED(blob + off_strings, size_strings);
+ VALGRIND_MAKE_MEM_DEFINED(blob + off_struct, size_struct);
+}
void *load_blob(const char *filename)
{
char *blob;
- int ret = utilfdt_read_err(filename, &blob);
+ size_t len;
+ int ret = utilfdt_read_err(filename, &blob, &len);
if (ret)
CONFIG("Couldn't open blob from \"%s\": %s", filename,
strerror(ret));
+
+ vg_prepare_blob(blob, len);
+
return blob;
}
@@ -176,11 +316,20 @@ void *load_blob_arg(int argc, char *argv[])
void save_blob(const char *filename, void *fdt)
{
- int ret = utilfdt_write_err(filename, fdt);
-
+ size_t size = fdt_totalsize(fdt);
+ void *tmp;
+ int ret;
+
+ /* Make a temp copy of the blob so that valgrind won't check
+ * about uninitialized bits in the pieces between blocks */
+ tmp = xmalloc(size);
+ fdt_move(fdt, tmp, size);
+ VALGRIND_MAKE_MEM_DEFINED(tmp, size);
+ ret = utilfdt_write_err(filename, tmp);
if (ret)
CONFIG("Couldn't write blob to \"%s\": %s", filename,
strerror(ret));
+ free(tmp);
}
void *open_blob_rw(void *blob)
diff --git a/tests/tests.sh b/tests/testutils.sh
index 8dda6e1..6b2f0d1 100644
--- a/tests/tests.sh
+++ b/tests/testutils.sh
@@ -18,11 +18,15 @@ FAIL_IF_SIGNAL () {
fi
}
-DTC=../dtc
-DTGET=../fdtget
-DTPUT=../fdtput
-FDTDUMP=../fdtdump
-FDTOVERLAY=../fdtoverlay
+if [ -z "$TEST_BINDIR" ]; then
+ TEST_BINDIR=..
+fi
+
+DTC=${TEST_BINDIR}/dtc
+DTGET=${TEST_BINDIR}/fdtget
+DTPUT=${TEST_BINDIR}/fdtput
+FDTDUMP=${TEST_BINDIR}/fdtdump
+FDTOVERLAY=${TEST_BINDIR}/fdtoverlay
verbose_run () {
if [ -z "$QUIET_TEST" ]; then
diff --git a/tests/trees.S b/tests/trees.S
index 9854d1d..efab287 100644
--- a/tests/trees.S
+++ b/tests/trees.S
@@ -7,20 +7,9 @@
.byte ((val) >> 8) & 0xff ; \
.byte (val) & 0xff ;
-#define FDTQUAD(val) \
- .byte ((val) >> 56) & 0xff ; \
- .byte ((val) >> 48) & 0xff ; \
- .byte ((val) >> 40) & 0xff ; \
- .byte ((val) >> 32) & 0xff ; \
- .byte ((val) >> 24) & 0xff ; \
- .byte ((val) >> 16) & 0xff ; \
- .byte ((val) >> 8) & 0xff ; \
- .byte (val) & 0xff ;
-
#define TREE_HDR(tree) \
.balign 8 ; \
- .globl _##tree ; \
-_##tree: \
+ .globl tree ; \
tree: \
FDTLONG(FDT_MAGIC) ; \
FDTLONG(tree##_end - tree) ; \
@@ -33,14 +22,16 @@ tree: \
FDTLONG(tree##_strings_end - tree##_strings) ; \
FDTLONG(tree##_struct_end - tree##_struct) ;
-#define RSVMAP_ENTRY(addr, len) \
- FDTQUAD(addr) ; \
- FDTQUAD(len) ; \
+#define RSVMAP_ENTRY(addrh, addrl, lenh, lenl) \
+ FDTLONG(addrh) ; \
+ FDTLONG(addrl) ; \
+ FDTLONG(lenh) ; \
+ FDTLONG(lenl)
#define EMPTY_RSVMAP(tree) \
.balign 8 ; \
tree##_rsvmap: ; \
- RSVMAP_ENTRY(0, 0) \
+ RSVMAP_ENTRY(0, 0, 0, 0) \
tree##_rsvmap_end: ;
#define PROPHDR(tree, name, len) \
@@ -48,13 +39,17 @@ tree##_rsvmap_end: ;
FDTLONG(len) ; \
FDTLONG(tree##_##name - tree##_strings) ;
+#define PROP_EMPTY(tree, name) \
+ PROPHDR(tree, name, 0) ;
+
#define PROP_INT(tree, name, val) \
PROPHDR(tree, name, 4) \
FDTLONG(val) ;
-#define PROP_INT64(tree, name, val) \
+#define PROP_INT64(tree, name, valh, vall) \
PROPHDR(tree, name, 8) \
- FDTQUAD(val) ;
+ FDTLONG(valh) ; \
+ FDTLONG(vall) ;
#define PROP_STR(tree, name, str) \
PROPHDR(tree, name, 55f - 54f) \
@@ -81,16 +76,16 @@ tree##_##name: ; \
.balign 8
test_tree1_rsvmap:
- RSVMAP_ENTRY(TEST_ADDR_1, TEST_SIZE_1)
- RSVMAP_ENTRY(TEST_ADDR_2, TEST_SIZE_2)
- RSVMAP_ENTRY(0, 0)
+ RSVMAP_ENTRY(TEST_ADDR_1H, TEST_ADDR_1L, TEST_SIZE_1H, TEST_SIZE_1L)
+ RSVMAP_ENTRY(TEST_ADDR_2H, TEST_ADDR_2L, TEST_SIZE_2H, TEST_SIZE_2L)
+ RSVMAP_ENTRY(0, 0, 0, 0)
test_tree1_rsvmap_end:
test_tree1_struct:
BEGIN_NODE("")
PROP_STR(test_tree1, compatible, "test_tree1")
PROP_INT(test_tree1, prop_int, TEST_VALUE_1)
- PROP_INT64(test_tree1, prop_int64, TEST_VALUE64_1)
+ PROP_INT64(test_tree1, prop_int64, TEST_VALUE64_1H, TEST_VALUE64_1L)
PROP_STR(test_tree1, prop_str, TEST_STRING_1)
PROP_INT(test_tree1, address_cells, 1)
PROP_INT(test_tree1, size_cells, 0)
@@ -215,8 +210,7 @@ bad_prop_char_end:
/* overflow_size_strings */
.balign 8
- .globl _ovf_size_strings
-_ovf_size_strings:
+ .globl ovf_size_strings
ovf_size_strings:
FDTLONG(FDT_MAGIC)
FDTLONG(ovf_size_strings_end - ovf_size_strings)
@@ -242,3 +236,46 @@ ovf_size_strings_strings:
ovf_size_strings_bad_string = ovf_size_strings_strings + 0x10000000
ovf_size_strings_strings_end:
ovf_size_strings_end:
+
+
+ /* truncated_string */
+ TREE_HDR(truncated_string)
+ EMPTY_RSVMAP(truncated_string)
+
+truncated_string_struct:
+ BEGIN_NODE("")
+ PROP_EMPTY(truncated_string, good_string)
+ PROP_EMPTY(truncated_string, bad_string)
+ END_NODE
+ FDTLONG(FDT_END)
+truncated_string_struct_end:
+
+truncated_string_strings:
+ STRING(truncated_string, good_string, "good")
+truncated_string_bad_string:
+ .byte 'b'
+ .byte 'a'
+ .byte 'd'
+ /* NOTE: terminating \0 deliberately missing */
+truncated_string_strings_end:
+truncated_string_end:
+
+
+ /* truncated_memrsv */
+ TREE_HDR(truncated_memrsv)
+
+truncated_memrsv_struct:
+ BEGIN_NODE("")
+ END_NODE
+ FDTLONG(FDT_END)
+truncated_memrsv_struct_end:
+
+truncated_memrsv_strings:
+truncated_memrsv_strings_end:
+
+ .balign 8
+truncated_memrsv_rsvmap:
+ RSVMAP_ENTRY(TEST_ADDR_1H, TEST_ADDR_1L, TEST_SIZE_1H, TEST_SIZE_1L)
+truncated_memrsv_rsvmap_end:
+
+truncated_memrsv_end:
diff --git a/tests/truncated_memrsv.c b/tests/truncated_memrsv.c
new file mode 100644
index 0000000..d78036c
--- /dev/null
+++ b/tests/truncated_memrsv.c
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for misbehaviour on a truncated string
+ * Copyright (C) 2018 David Gibson, IBM Corporation.
+ */
+
+#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 = &truncated_memrsv;
+ int err;
+ uint64_t addr, size;
+
+ test_init(argc, argv);
+
+ err = fdt_check_header(fdt);
+ if (err != 0)
+ FAIL("Bad header: %s", fdt_strerror(err));
+
+ err = fdt_num_mem_rsv(fdt);
+ if (err != -FDT_ERR_TRUNCATED)
+ FAIL("fdt_num_mem_rsv() returned %d instead of -FDT_ERR_TRUNCATED",
+ err);
+
+ err = fdt_get_mem_rsv(fdt, 0, &addr, &size);
+ if (err != 0)
+ FAIL("fdt_get_mem_rsv() failed on first entry: %s",
+ fdt_strerror(err));
+ if ((addr != TEST_ADDR_1) || (size != TEST_SIZE_1))
+ FAIL("Entry doesn't match: (0x%llx, 0x%llx) != (0x%llx, 0x%llx)",
+ (unsigned long long)addr, (unsigned long long)size,
+ TEST_ADDR_1, TEST_SIZE_1);
+
+ err = fdt_get_mem_rsv(fdt, 1, &addr, &size);
+ if (err != -FDT_ERR_BADOFFSET)
+ FAIL("fdt_get_mem_rsv(1) returned %d instead of -FDT_ERR_BADOFFSET",
+ err);
+
+ PASS();
+}
diff --git a/tests/truncated_property.c b/tests/truncated_property.c
index f820d99..d9d52b2 100644
--- a/tests/truncated_property.c
+++ b/tests/truncated_property.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for misbehaviour on a truncated property
* 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>
@@ -30,12 +17,14 @@
int main(int argc, char *argv[])
{
- void *fdt = &_truncated_property;
+ void *fdt = &truncated_property;
const void *prop;
int len;
test_init(argc, argv);
+ vg_prepare_blob(fdt, fdt_totalsize(fdt));
+
prop = fdt_getprop(fdt, 0, "truncated", &len);
if (prop)
FAIL("fdt_getprop() succeeded on truncated property");
diff --git a/tests/truncated_string.c b/tests/truncated_string.c
new file mode 100644
index 0000000..d745414
--- /dev/null
+++ b/tests/truncated_string.c
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for misbehaviour on a truncated string
+ * Copyright (C) 2018 David Gibson, IBM Corporation.
+ */
+
+#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 = &truncated_string;
+ const struct fdt_property *good, *bad;
+ int off, len;
+ const char *name;
+
+ test_init(argc, argv);
+
+ vg_prepare_blob(fdt, fdt_totalsize(fdt));
+
+ off = fdt_first_property_offset(fdt, 0);
+ good = fdt_get_property_by_offset(fdt, off, NULL);
+
+ off = fdt_next_property_offset(fdt, off);
+ bad = fdt_get_property_by_offset(fdt, off, NULL);
+
+ if (fdt32_to_cpu(good->len) != 0)
+ FAIL("Unexpected length for good property");
+ name = fdt_get_string(fdt, fdt32_to_cpu(good->nameoff), &len);
+ if (!name)
+ FAIL("fdt_get_string() failed on good property: %s",
+ fdt_strerror(len));
+ if (len != 4)
+ FAIL("fdt_get_string() returned length %d (not 4) on good property",
+ len);
+ if (!streq(name, "good"))
+ FAIL("fdt_get_string() returned \"%s\" (not \"good\") on good property",
+ name);
+
+ if (fdt32_to_cpu(bad->len) != 0)
+ FAIL("Unexpected length for bad property\n");
+ name = fdt_get_string(fdt, fdt32_to_cpu(bad->nameoff), &len);
+ if (name)
+ FAIL("fdt_get_string() succeeded incorrectly on bad property");
+ else if (len != -FDT_ERR_TRUNCATED)
+ FAIL("fdt_get_string() gave unexpected error on bad property: %s",
+ fdt_strerror(len));
+
+ /* Make sure the 'good' property breaks correctly if we
+ * truncate the strings section */
+ fdt_set_size_dt_strings(fdt, fdt32_to_cpu(good->nameoff) + 4);
+ name = fdt_get_string(fdt, fdt32_to_cpu(good->nameoff), &len);
+ if (name)
+ FAIL("fdt_get_string() succeeded incorrectly on mangled property");
+ else if (len != -FDT_ERR_TRUNCATED)
+ FAIL("fdt_get_string() gave unexpected error on mangled property: %s",
+ fdt_strerror(len));
+
+ PASS();
+}
diff --git a/tests/type-preservation.dt.yaml b/tests/type-preservation.dt.yaml
new file mode 100644
index 0000000..ee8cfde
--- /dev/null
+++ b/tests/type-preservation.dt.yaml
@@ -0,0 +1,20 @@
+---
+- '#address-cells': [[0x1]]
+ '#size-cells': [[0x0]]
+ subnode@1:
+ compatible: ["subnode1"]
+ reg: [[0x1]]
+ int-array: [[0x0, 0x1], [0x2, 0x3]]
+ int8: [!u8 [0x56]]
+ int8-array: [!u8 [0x0, 0x12, 0x34, 0x56]]
+ int16: [!u16 [0x3210]]
+ int16-array: [!u16 [0x1234, 0x5678, 0x90ab, 0xcdef]]
+ int16-matrix: [!u16 [0x1234, 0x5678], [0x90ab, 0xcdef]]
+ int64: [!u64 [0x200000000]]
+ int64-array: [!u64 [0x100000000, 0x0]]
+ a-string-with-nulls: ["foo\0bar", "baz"]
+ subsubnode:
+ compatible: ["subsubnode1", "subsubnode"]
+ subsubsubnode:
+ compatible: ["subsubsubnode1", [0x1234], "subsubsubnode"]
+...
diff --git a/tests/type-preservation.dts b/tests/type-preservation.dts
new file mode 100644
index 0000000..3e380ba
--- /dev/null
+++ b/tests/type-preservation.dts
@@ -0,0 +1,28 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <0x01>;
+ #size-cells = <0x00>;
+
+ sub1: subnode@1 {
+ prop_label: compatible = value_label: "subnode1";
+ reg = <0x01>;
+ int-array = <0x00 0x01>, int_value_label: <0x02 0x03>;
+ int8 = [56];
+ int8-array = [00 12 34 56] label:;
+ int16 = /bits/ 16 <0x3210>;
+ int16-array = /bits/ 16 <0x1234 0x5678 0x90ab 0xcdef>;
+ int16-matrix = /bits/ 16 <0x1234 0x5678>, <0x90ab 0xcdef>;
+ int64 = /bits/ 64 <0x200000000>;
+ int64-array = /bits/ 64 <0x100000000 0x00> int64_array_label_end:;
+ a-string-with-nulls = "foo\0bar", "baz";
+
+ subsub1: subsubnode {
+ compatible = "subsubnode1", "subsubnode";
+
+ subsubsub1: subsubsubnode {
+ compatible = "subsubsubnode1", <0x1234>, valuea: valueb: "subsubsubnode";
+ };
+ };
+ };
+};
diff --git a/tests/unit-addr-simple-bus-compatible.dts b/tests/unit-addr-simple-bus-compatible.dts
new file mode 100644
index 0000000..c8f9341
--- /dev/null
+++ b/tests/unit-addr-simple-bus-compatible.dts
@@ -0,0 +1,18 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ bus@10000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "foo-bus", "simple-bus";
+ ranges = <0x0 0x10000000 0x10000>;
+
+ node@100 {
+ reg = <0x1000 1>;
+ };
+ };
+
+};
diff --git a/tests/unit-addr-simple-bus-reg-mismatch.dts b/tests/unit-addr-simple-bus-reg-mismatch.dts
new file mode 100644
index 0000000..2823377
--- /dev/null
+++ b/tests/unit-addr-simple-bus-reg-mismatch.dts
@@ -0,0 +1,18 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ bus@10000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges = <0x0 0x10000000 0x10000>;
+
+ node@100 {
+ reg = <0x1000 1>;
+ };
+ };
+
+};
diff --git a/tests/unit-addr-unique.dts b/tests/unit-addr-unique.dts
new file mode 100644
index 0000000..7cc650b
--- /dev/null
+++ b/tests/unit-addr-unique.dts
@@ -0,0 +1,14 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ foo@1 {
+ reg = <1>;
+ };
+
+ bar@1 {
+ reg = <1>;
+ };
+};
diff --git a/tests/utilfdt_test.c b/tests/utilfdt_test.c
index 274c3d6..c621759 100644
--- a/tests/utilfdt_test.c
+++ b/tests/utilfdt_test.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* Copyright 2011 The Chromium Authors, All Rights Reserved.
*
* utilfdt_test - Tests for utilfdt library
- *
- * 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 <assert.h>
#include <stdlib.h>
diff --git a/tests/value-labels.c b/tests/value-labels.c
index 8aced74..e318357 100644
--- a/tests/value-labels.c
+++ b/tests/value-labels.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Test labels within values
* 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>
diff --git a/treesource.c b/treesource.c
index 2461a3d..061ba8c 100644
--- a/treesource.c
+++ b/treesource.c
@@ -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"
@@ -61,24 +46,18 @@ static bool isstring(char c)
|| strchr("\a\b\t\n\v\f\r", c));
}
-static void write_propval_string(FILE *f, struct data val)
+static void write_propval_string(FILE *f, const char *s, size_t len)
{
- const char *str = val.val;
- int i;
- struct marker *m = val.markers;
-
- assert(str[val.len-1] == '\0');
+ const char *end = s + len - 1;
- while (m && (m->offset == 0)) {
- if (m->type == LABEL)
- fprintf(f, "%s: ", m->ref);
- m = m->next;
- }
- fprintf(f, "\"");
+ if (!len)
+ return;
- for (i = 0; i < (val.len-1); i++) {
- char c = str[i];
+ assert(*end == '\0');
+ fprintf(f, "\"");
+ while (s < end) {
+ char c = *s++;
switch (c) {
case '\a':
fprintf(f, "\\a");
@@ -108,91 +87,80 @@ static void write_propval_string(FILE *f, struct data val)
fprintf(f, "\\\"");
break;
case '\0':
- fprintf(f, "\", ");
- while (m && (m->offset <= (i + 1))) {
- if (m->type == LABEL) {
- assert(m->offset == (i+1));
- fprintf(f, "%s: ", m->ref);
- }
- m = m->next;
- }
- fprintf(f, "\"");
+ fprintf(f, "\\0");
break;
default:
if (isprint((unsigned char)c))
fprintf(f, "%c", c);
else
- fprintf(f, "\\x%02hhx", c);
+ fprintf(f, "\\x%02"PRIx8, c);
}
}
fprintf(f, "\"");
-
- /* Wrap up any labels at the end of the value */
- for_each_marker_of_type(m, LABEL) {
- assert (m->offset == val.len);
- fprintf(f, " %s:", m->ref);
- }
}
-static void write_propval_cells(FILE *f, struct data val)
+static void write_propval_int(FILE *f, const char *p, size_t len, size_t width)
{
- void *propend = val.val + val.len;
- fdt32_t *cp = (fdt32_t *)val.val;
- struct marker *m = val.markers;
-
- fprintf(f, "<");
- for (;;) {
- while (m && (m->offset <= ((char *)cp - val.val))) {
- if (m->type == LABEL) {
- assert(m->offset == ((char *)cp - val.val));
- fprintf(f, "%s: ", m->ref);
- }
- m = m->next;
- }
+ const char *end = p + len;
+ assert(len % width == 0);
- fprintf(f, "0x%x", fdt32_to_cpu(*cp++));
- if ((void *)cp >= propend)
+ for (; p < end; p += width) {
+ switch (width) {
+ case 1:
+ fprintf(f, "%02"PRIx8, *(const uint8_t*)p);
+ break;
+ case 2:
+ fprintf(f, "0x%02"PRIx16, dtb_ld16(p));
break;
- fprintf(f, " ");
+ case 4:
+ fprintf(f, "0x%02"PRIx32, dtb_ld32(p));
+ break;
+ case 8:
+ fprintf(f, "0x%02"PRIx64, dtb_ld64(p));
+ break;
+ }
+ if (p + width < end)
+ fputc(' ', f);
}
+}
- /* Wrap up any labels at the end of the value */
- for_each_marker_of_type(m, LABEL) {
- assert (m->offset == val.len);
- fprintf(f, " %s:", m->ref);
- }
- fprintf(f, ">");
+static bool has_data_type_information(struct marker *m)
+{
+ return m->type >= TYPE_UINT8;
}
-static void write_propval_bytes(FILE *f, struct data val)
+static struct marker *next_type_marker(struct marker *m)
{
- void *propend = val.val + val.len;
- const char *bp = val.val;
- struct marker *m = val.markers;
-
- fprintf(f, "[");
- for (;;) {
- while (m && (m->offset == (bp-val.val))) {
- if (m->type == LABEL)
- fprintf(f, "%s: ", m->ref);
- m = m->next;
- }
+ while (m && !has_data_type_information(m))
+ m = m->next;
+ return m;
+}
- fprintf(f, "%02hhx", (unsigned char)(*bp++));
- if ((const void *)bp >= propend)
- break;
- fprintf(f, " ");
- }
+size_t type_marker_length(struct marker *m)
+{
+ struct marker *next = next_type_marker(m->next);
- /* Wrap up any labels at the end of the value */
- for_each_marker_of_type(m, LABEL) {
- assert (m->offset == val.len);
- fprintf(f, " %s:", m->ref);
- }
- fprintf(f, "]");
+ if (next)
+ return next->offset - m->offset;
+ return 0;
}
-static void write_propval(FILE *f, struct property *prop)
+static const char *delim_start[] = {
+ [TYPE_UINT8] = "[",
+ [TYPE_UINT16] = "/bits/ 16 <",
+ [TYPE_UINT32] = "<",
+ [TYPE_UINT64] = "/bits/ 64 <",
+ [TYPE_STRING] = "",
+};
+static const char *delim_end[] = {
+ [TYPE_UINT8] = "]",
+ [TYPE_UINT16] = ">",
+ [TYPE_UINT32] = ">",
+ [TYPE_UINT64] = ">",
+ [TYPE_STRING] = "",
+};
+
+static enum markertype guess_value_type(struct property *prop)
{
int len = prop->val.len;
const char *p = prop->val.val;
@@ -201,11 +169,6 @@ static void write_propval(FILE *f, struct property *prop)
int nnotstringlbl = 0, nnotcelllbl = 0;
int i;
- if (len == 0) {
- fprintf(f, ";\n");
- return;
- }
-
for (i = 0; i < len; i++) {
if (! isstring(p[i]))
nnotstring++;
@@ -220,17 +183,99 @@ static void write_propval(FILE *f, struct property *prop)
nnotcelllbl++;
}
- fprintf(f, " = ");
- if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul))
+ if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul <= (len-nnul))
&& (nnotstringlbl == 0)) {
- write_propval_string(f, prop->val);
+ return TYPE_STRING;
} else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) {
- write_propval_cells(f, prop->val);
- } else {
- write_propval_bytes(f, prop->val);
+ return TYPE_UINT32;
+ }
+
+ return TYPE_UINT8;
+}
+
+static void write_propval(FILE *f, struct property *prop)
+{
+ size_t len = prop->val.len;
+ struct marker *m = prop->val.markers;
+ struct marker dummy_marker;
+ enum markertype emit_type = TYPE_NONE;
+ char *srcstr;
+
+ if (len == 0) {
+ fprintf(f, ";");
+ if (annotate) {
+ srcstr = srcpos_string_first(prop->srcpos, annotate);
+ if (srcstr) {
+ fprintf(f, " /* %s */", srcstr);
+ free(srcstr);
+ }
+ }
+ fprintf(f, "\n");
+ return;
}
- fprintf(f, ";\n");
+ fprintf(f, " =");
+
+ if (!next_type_marker(m)) {
+ /* data type information missing, need to guess */
+ dummy_marker.type = guess_value_type(prop);
+ dummy_marker.next = prop->val.markers;
+ dummy_marker.offset = 0;
+ dummy_marker.ref = NULL;
+ m = &dummy_marker;
+ }
+
+ for_each_marker(m) {
+ size_t chunk_len = (m->next ? m->next->offset : len) - m->offset;
+ size_t data_len = type_marker_length(m) ? : len - m->offset;
+ const char *p = &prop->val.val[m->offset];
+
+ if (has_data_type_information(m)) {
+ emit_type = m->type;
+ fprintf(f, " %s", delim_start[emit_type]);
+ } else if (m->type == LABEL)
+ fprintf(f, " %s:", m->ref);
+ else if (m->offset)
+ fputc(' ', f);
+
+ if (emit_type == TYPE_NONE) {
+ assert(chunk_len == 0);
+ continue;
+ }
+
+ switch(emit_type) {
+ case TYPE_UINT16:
+ write_propval_int(f, p, chunk_len, 2);
+ break;
+ case TYPE_UINT32:
+ write_propval_int(f, p, chunk_len, 4);
+ break;
+ case TYPE_UINT64:
+ write_propval_int(f, p, chunk_len, 8);
+ break;
+ case TYPE_STRING:
+ write_propval_string(f, p, chunk_len);
+ break;
+ default:
+ write_propval_int(f, p, chunk_len, 1);
+ }
+
+ if (chunk_len == data_len) {
+ size_t pos = m->offset + chunk_len;
+ fprintf(f, pos == len ? "%s" : "%s,",
+ delim_end[emit_type] ? : "");
+ emit_type = TYPE_NONE;
+ }
+ }
+ fprintf(f, ";");
+ if (annotate) {
+ srcstr = srcpos_string_first(prop->srcpos, annotate);
+ if (srcstr) {
+ fprintf(f, " /* %s */", srcstr);
+ free(srcstr);
+ }
+ }
+ fprintf(f, "\n");
}
static void write_tree_source_node(FILE *f, struct node *tree, int level)
@@ -238,14 +283,24 @@ static void write_tree_source_node(FILE *f, struct node *tree, int level)
struct property *prop;
struct node *child;
struct label *l;
+ char *srcstr;
write_prefix(f, level);
for_each_label(tree->labels, l)
fprintf(f, "%s: ", l->label);
if (tree->name && (*tree->name))
- fprintf(f, "%s {\n", tree->name);
+ fprintf(f, "%s {", tree->name);
else
- fprintf(f, "/ {\n");
+ fprintf(f, "/ {");
+
+ if (annotate) {
+ srcstr = srcpos_string_first(tree->srcpos, annotate);
+ if (srcstr) {
+ fprintf(f, " /* %s */", srcstr);
+ free(srcstr);
+ }
+ }
+ fprintf(f, "\n");
for_each_property(tree, prop) {
write_prefix(f, level+1);
@@ -259,10 +314,17 @@ static void write_tree_source_node(FILE *f, struct node *tree, int level)
write_tree_source_node(f, child, level+1);
}
write_prefix(f, level);
- fprintf(f, "};\n");
+ fprintf(f, "};");
+ if (annotate) {
+ srcstr = srcpos_string_last(tree->srcpos, annotate);
+ if (srcstr) {
+ fprintf(f, " /* %s */", srcstr);
+ free(srcstr);
+ }
+ }
+ fprintf(f, "\n");
}
-
void dt_to_source(FILE *f, struct dt_info *dti)
{
struct reserve_info *re;
@@ -281,4 +343,3 @@ void dt_to_source(FILE *f, struct dt_info *dti)
write_tree_source_node(f, dti->dt, 0);
}
-
diff --git a/util.c b/util.c
index 6ae5976..62feff4 100644
--- a/util.c
+++ b/util.c
@@ -1,24 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright 2011 The Chromium Authors, All Rights Reserved.
* Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
*
* util_is_printable_string contributed by
* Pantelis Antoniou <pantelis.antoniou AT gmail.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 <ctype.h>
@@ -27,6 +13,7 @@
#include <stdarg.h>
#include <string.h>
#include <assert.h>
+#include <inttypes.h>
#include <errno.h>
#include <fcntl.h>
@@ -46,36 +33,54 @@ char *xstrdup(const char *s)
return d;
}
-/* based in part from (3) vsnprintf */
-int xasprintf(char **strp, const char *fmt, ...)
+int xavsprintf_append(char **strp, const char *fmt, va_list ap)
{
- int n, size = 128; /* start with 128 bytes */
+ int n, size = 0; /* start with 128 bytes */
char *p;
- va_list ap;
+ va_list ap_copy;
- /* initial pointer is NULL making the fist realloc to be malloc */
- p = NULL;
- while (1) {
- p = xrealloc(p, size);
+ p = *strp;
+ if (p)
+ size = strlen(p);
- /* Try to print in the allocated space. */
- va_start(ap, fmt);
- n = vsnprintf(p, size, fmt, ap);
- va_end(ap);
+ va_copy(ap_copy, ap);
+ n = vsnprintf(NULL, 0, fmt, ap_copy) + 1;
+ va_end(ap_copy);
+
+ p = xrealloc(p, size + n);
+
+ n = vsnprintf(p + size, n, fmt, ap);
- /* If that worked, return the string. */
- if (n > -1 && n < size)
- break;
- /* Else try again with more space. */
- if (n > -1) /* glibc 2.1 */
- size = n + 1; /* precisely what is needed */
- else /* glibc 2.0 */
- size *= 2; /* twice the old size */
- }
*strp = p;
return strlen(p);
}
+int xasprintf_append(char **strp, const char *fmt, ...)
+{
+ int n;
+ va_list ap;
+
+ va_start(ap, fmt);
+ n = xavsprintf_append(strp, fmt, ap);
+ va_end(ap);
+
+ return n;
+}
+
+int xasprintf(char **strp, const char *fmt, ...)
+{
+ int n;
+ va_list ap;
+
+ *strp = NULL;
+
+ va_start(ap, fmt);
+ n = xavsprintf_append(strp, fmt, ap);
+ va_end(ap);
+
+ return n;
+}
+
char *join_path(const char *path, const char *name)
{
int lenp = strlen(path);
@@ -227,11 +232,11 @@ char get_escape_char(const char *s, int *i)
return val;
}
-int utilfdt_read_err_len(const char *filename, char **buffp, off_t *len)
+int utilfdt_read_err(const char *filename, char **buffp, size_t *len)
{
int fd = 0; /* assume stdin */
char *buf = NULL;
- off_t bufsize = 1024, offset = 0;
+ size_t bufsize = 1024, offset = 0;
int ret = 0;
*buffp = NULL;
@@ -264,20 +269,15 @@ int utilfdt_read_err_len(const char *filename, char **buffp, off_t *len)
free(buf);
else
*buffp = buf;
- *len = bufsize;
+ if (len)
+ *len = bufsize;
return ret;
}
-int utilfdt_read_err(const char *filename, char **buffp)
-{
- off_t len;
- return utilfdt_read_err_len(filename, buffp, &len);
-}
-
-char *utilfdt_read_len(const char *filename, off_t *len)
+char *utilfdt_read(const char *filename, size_t *len)
{
char *buff;
- int ret = utilfdt_read_err_len(filename, &buff, len);
+ int ret = utilfdt_read_err(filename, &buff, len);
if (ret) {
fprintf(stderr, "Couldn't open blob from '%s': %s\n", filename,
@@ -288,12 +288,6 @@ char *utilfdt_read_len(const char *filename, off_t *len)
return buff;
}
-char *utilfdt_read(const char *filename)
-{
- off_t len;
- return utilfdt_read_len(filename, &len);
-}
-
int utilfdt_write_err(const char *filename, const void *blob)
{
int fd = 1; /* assume stdout */
@@ -400,7 +394,7 @@ void utilfdt_print_data(const char *data, int len)
printf(" = <");
for (i = 0, len /= 4; i < len; i++)
- printf("0x%08x%s", fdt32_to_cpu(cell[i]),
+ printf("0x%08" PRIx32 "%s", fdt32_to_cpu(cell[i]),
i < (len - 1) ? " " : "");
printf(">");
} else {
diff --git a/util.h b/util.h
index ad5f411..5a4172d 100644
--- a/util.h
+++ b/util.h
@@ -1,5 +1,6 @@
-#ifndef _UTIL_H
-#define _UTIL_H
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#ifndef UTIL_H
+#define UTIL_H
#include <stdarg.h>
#include <stdbool.h>
@@ -8,25 +9,14 @@
/*
* Copyright 2011 The Chromium Authors, All Rights Reserved.
* Copyright 2008 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
*/
#ifdef __GNUC__
+#ifdef __clang__
#define PRINTF(i, j) __attribute__((format (printf, i, j)))
+#else
+#define PRINTF(i, j) __attribute__((format (gnu_printf, i, j)))
+#endif
#define NORETURN __attribute__((noreturn))
#else
#define PRINTF(i, j)
@@ -35,6 +25,9 @@
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#define stringify(s) stringify_(s)
+#define stringify_(s) #s
+
static inline void NORETURN PRINTF(1, 2) die(const char *str, ...)
{
va_list ap;
@@ -69,6 +62,8 @@ static inline void *xrealloc(void *p, size_t len)
extern char *xstrdup(const char *s);
extern int PRINTF(2, 3) xasprintf(char **strp, const char *fmt, ...);
+extern int PRINTF(2, 3) xasprintf_append(char **strp, const char *fmt, ...);
+extern int xavsprintf_append(char **strp, const char *fmt, va_list ap);
extern char *join_path(const char *path, const char *name);
/**
@@ -95,16 +90,10 @@ char get_escape_char(const char *s, int *i);
* stderr.
*
* @param filename The filename to read, or - for stdin
- * @return Pointer to allocated buffer containing fdt, or NULL on error
- */
-char *utilfdt_read(const char *filename);
-
-/**
- * Like utilfdt_read(), but also passes back the size of the file read.
- *
* @param len If non-NULL, the amount of data we managed to read
+ * @return Pointer to allocated buffer containing fdt, or NULL on error
*/
-char *utilfdt_read_len(const char *filename, off_t *len);
+char *utilfdt_read(const char *filename, size_t *len);
/**
* Read a device tree file into a buffer. Does not report errors, but only
@@ -113,23 +102,17 @@ char *utilfdt_read_len(const char *filename, off_t *len);
*
* @param filename The filename to read, or - for stdin
* @param buffp Returns pointer to buffer containing fdt
- * @return 0 if ok, else an errno value representing the error
- */
-int utilfdt_read_err(const char *filename, char **buffp);
-
-/**
- * Like utilfdt_read_err(), but also passes back the size of the file read.
- *
* @param len If non-NULL, the amount of data we managed to read
+ * @return 0 if ok, else an errno value representing the error
*/
-int utilfdt_read_err_len(const char *filename, char **buffp, off_t *len);
+int utilfdt_read_err(const char *filename, char **buffp, size_t *len);
/**
* Write a device tree buffer to a file. This will report any errors on
* stderr.
*
* @param filename The filename to write, or - for stdout
- * @param blob Poiner to buffer containing fdt
+ * @param blob Pointer to buffer containing fdt
* @return 0 if ok, -1 on error
*/
int utilfdt_write(const char *filename, const void *blob);
@@ -140,7 +123,7 @@ int utilfdt_write(const char *filename, const void *blob);
* an error message for the user.
*
* @param filename The filename to write, or - for stdout
- * @param blob Poiner to buffer containing fdt
+ * @param blob Pointer to buffer containing fdt
* @return 0 if ok, else an errno value representing the error
*/
int utilfdt_write_err(const char *filename, const void *blob);
@@ -260,4 +243,4 @@ void NORETURN util_usage(const char *errmsg, const char *synopsis,
case 'V': util_version(); \
case '?': usage("unknown option");
-#endif /* _UTIL_H */
+#endif /* UTIL_H */
diff --git a/version_non_gen.h b/version_non_gen.h
index 71d542d..3376b35 100644
--- a/version_non_gen.h
+++ b/version_non_gen.h
@@ -1 +1 @@
-#define DTC_VERSION "DTC 1.4.4-Android-build"
+#define DTC_VERSION "DTC 1.6.0-Android-build"
diff --git a/yamltree.c b/yamltree.c
new file mode 100644
index 0000000..4e93c12
--- /dev/null
+++ b/yamltree.c
@@ -0,0 +1,233 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * (C) Copyright Linaro, Ltd. 2018
+ * (C) Copyright Arm Holdings. 2017
+ * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
+ */
+
+#include <stdlib.h>
+#include <yaml.h>
+#include "dtc.h"
+#include "srcpos.h"
+
+char *yaml_error_name[] = {
+ [YAML_NO_ERROR] = "no error",
+ [YAML_MEMORY_ERROR] = "memory error",
+ [YAML_READER_ERROR] = "reader error",
+ [YAML_SCANNER_ERROR] = "scanner error",
+ [YAML_PARSER_ERROR] = "parser error",
+ [YAML_COMPOSER_ERROR] = "composer error",
+ [YAML_WRITER_ERROR] = "writer error",
+ [YAML_EMITTER_ERROR] = "emitter error",
+};
+
+#define yaml_emitter_emit_or_die(emitter, event) ( \
+{ \
+ if (!yaml_emitter_emit(emitter, event)) \
+ die("yaml '%s': %s in %s, line %i\n", \
+ yaml_error_name[(emitter)->error], \
+ (emitter)->problem, __func__, __LINE__); \
+})
+
+static void yaml_propval_int(yaml_emitter_t *emitter, struct marker *markers, char *data, int len, int width)
+{
+ yaml_event_t event;
+ void *tag;
+ int off, start_offset = markers->offset;
+
+ switch(width) {
+ case 1: tag = "!u8"; break;
+ case 2: tag = "!u16"; break;
+ case 4: tag = "!u32"; break;
+ case 8: tag = "!u64"; break;
+ default:
+ die("Invalid width %i", width);
+ }
+ assert(len % width == 0);
+
+ yaml_sequence_start_event_initialize(&event, NULL,
+ (yaml_char_t *)tag, width == 4, YAML_FLOW_SEQUENCE_STYLE);
+ yaml_emitter_emit_or_die(emitter, &event);
+
+ for (off = 0; off < len; off += width) {
+ char buf[32];
+ struct marker *m;
+ bool is_phandle = false;
+
+ switch(width) {
+ case 1:
+ sprintf(buf, "0x%"PRIx8, *(uint8_t*)(data + off));
+ break;
+ case 2:
+ sprintf(buf, "0x%"PRIx16, dtb_ld16(data + off));
+ break;
+ case 4:
+ sprintf(buf, "0x%"PRIx32, dtb_ld32(data + off));
+ m = markers;
+ is_phandle = false;
+ for_each_marker_of_type(m, REF_PHANDLE) {
+ if (m->offset == (start_offset + off)) {
+ is_phandle = true;
+ break;
+ }
+ }
+ break;
+ case 8:
+ sprintf(buf, "0x%"PRIx64, dtb_ld64(data + off));
+ break;
+ }
+
+ if (is_phandle)
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t*)"!phandle", (yaml_char_t *)buf,
+ strlen(buf), 0, 0, YAML_PLAIN_SCALAR_STYLE);
+ else
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t*)YAML_INT_TAG, (yaml_char_t *)buf,
+ strlen(buf), 1, 1, YAML_PLAIN_SCALAR_STYLE);
+ yaml_emitter_emit_or_die(emitter, &event);
+ }
+
+ yaml_sequence_end_event_initialize(&event);
+ yaml_emitter_emit_or_die(emitter, &event);
+}
+
+static void yaml_propval_string(yaml_emitter_t *emitter, char *str, int len)
+{
+ yaml_event_t event;
+ int i;
+
+ assert(str[len-1] == '\0');
+
+ /* Make sure the entire string is in the lower 7-bit ascii range */
+ for (i = 0; i < len; i++)
+ assert(isascii(str[i]));
+
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_STR_TAG, (yaml_char_t*)str,
+ len-1, 0, 1, YAML_DOUBLE_QUOTED_SCALAR_STYLE);
+ yaml_emitter_emit_or_die(emitter, &event);
+}
+
+static void yaml_propval(yaml_emitter_t *emitter, struct property *prop)
+{
+ yaml_event_t event;
+ int len = prop->val.len;
+ struct marker *m = prop->val.markers;
+
+ /* Emit the property name */
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_STR_TAG, (yaml_char_t*)prop->name,
+ strlen(prop->name), 1, 1, YAML_PLAIN_SCALAR_STYLE);
+ yaml_emitter_emit_or_die(emitter, &event);
+
+ /* Boolean properties are easiest to deal with. Length is zero, so just emit 'true' */
+ if (len == 0) {
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_BOOL_TAG,
+ (yaml_char_t*)"true",
+ strlen("true"), 1, 0, YAML_PLAIN_SCALAR_STYLE);
+ yaml_emitter_emit_or_die(emitter, &event);
+ return;
+ }
+
+ if (!m)
+ die("No markers present in property '%s' value\n", prop->name);
+
+ yaml_sequence_start_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_SEQ_TAG, 1, YAML_FLOW_SEQUENCE_STYLE);
+ yaml_emitter_emit_or_die(emitter, &event);
+
+ for_each_marker(m) {
+ int chunk_len;
+ char *data = &prop->val.val[m->offset];
+
+ if (m->type < TYPE_UINT8)
+ continue;
+
+ chunk_len = type_marker_length(m) ? : len;
+ assert(chunk_len > 0);
+ len -= chunk_len;
+
+ switch(m->type) {
+ case TYPE_UINT16:
+ yaml_propval_int(emitter, m, data, chunk_len, 2);
+ break;
+ case TYPE_UINT32:
+ yaml_propval_int(emitter, m, data, chunk_len, 4);
+ break;
+ case TYPE_UINT64:
+ yaml_propval_int(emitter, m, data, chunk_len, 8);
+ break;
+ case TYPE_STRING:
+ yaml_propval_string(emitter, data, chunk_len);
+ break;
+ default:
+ yaml_propval_int(emitter, m, data, chunk_len, 1);
+ break;
+ }
+ }
+
+ yaml_sequence_end_event_initialize(&event);
+ yaml_emitter_emit_or_die(emitter, &event);
+}
+
+
+static void yaml_tree(struct node *tree, yaml_emitter_t *emitter)
+{
+ struct property *prop;
+ struct node *child;
+ yaml_event_t event;
+
+ if (tree->deleted)
+ return;
+
+ yaml_mapping_start_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_MAP_TAG, 1, YAML_ANY_MAPPING_STYLE);
+ yaml_emitter_emit_or_die(emitter, &event);
+
+ for_each_property(tree, prop)
+ yaml_propval(emitter, prop);
+
+ /* Loop over all the children, emitting them into the map */
+ for_each_child(tree, child) {
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_STR_TAG, (yaml_char_t*)child->name,
+ strlen(child->name), 1, 0, YAML_PLAIN_SCALAR_STYLE);
+ yaml_emitter_emit_or_die(emitter, &event);
+ yaml_tree(child, emitter);
+ }
+
+ yaml_mapping_end_event_initialize(&event);
+ yaml_emitter_emit_or_die(emitter, &event);
+}
+
+void dt_to_yaml(FILE *f, struct dt_info *dti)
+{
+ yaml_emitter_t emitter;
+ yaml_event_t event;
+
+ yaml_emitter_initialize(&emitter);
+ yaml_emitter_set_output_file(&emitter, f);
+ yaml_stream_start_event_initialize(&event, YAML_UTF8_ENCODING);
+ yaml_emitter_emit_or_die(&emitter, &event);
+
+ yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
+ yaml_emitter_emit_or_die(&emitter, &event);
+
+ yaml_sequence_start_event_initialize(&event, NULL, (yaml_char_t *)YAML_SEQ_TAG, 1, YAML_ANY_SEQUENCE_STYLE);
+ yaml_emitter_emit_or_die(&emitter, &event);
+
+ yaml_tree(dti->dt, &emitter);
+
+ yaml_sequence_end_event_initialize(&event);
+ yaml_emitter_emit_or_die(&emitter, &event);
+
+ yaml_document_end_event_initialize(&event, 0);
+ yaml_emitter_emit_or_die(&emitter, &event);
+
+ yaml_stream_end_event_initialize(&event);
+ yaml_emitter_emit_or_die(&emitter, &event);
+
+ yaml_emitter_delete(&emitter);
+}