aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-07-07 07:07:45 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-07-07 07:07:45 +0000
commitc6a60fc35e5ff14105f276ef4fa170090e471618 (patch)
tree8a29c39390325d33e0d80fe2d925c9e8d04df630
parenta896d29f7afb8b7d3191ee572bc33cb2c92c5322 (diff)
parentd8fdcce387491b9957453c213deffbe92e53ea3c (diff)
downloaddtc-aml_odp_341610000.tar.gz
Snap for 10453938 from d8fdcce387491b9957453c213deffbe92e53ea3c to mainline-odp-releaseaml_odp_341717000aml_odp_341610000
Change-Id: I1b8ba08606319e1fc7820fa8bc38120666802a04
-rw-r--r--.cirrus.yml4
-rw-r--r--.gitignore10
-rw-r--r--Android.bp47
-rw-r--r--CONTRIBUTING.md79
-rw-r--r--Documentation/manual.txt4
-rw-r--r--LGPL503
-rw-r--r--LICENSE880
-rw-r--r--MANIFEST.in11
-rw-r--r--METADATA16
-rw-r--r--MODULE_LICENSE_BSD0
-rw-r--r--MODULE_LICENSE_LGPL0
-rw-r--r--Makefile22
-rw-r--r--NOTICE340
-rw-r--r--OWNERS3
-rw-r--r--README91
-rw-r--r--README.md100
-rw-r--r--checks.c241
-rw-r--r--convert-dtsv0-lexer.l2
-rw-r--r--data.c6
-rw-r--r--dtc-lexer.l4
-rw-r--r--dtc-parser.y17
-rw-r--r--dtc.c6
-rw-r--r--dtc.h48
-rw-r--r--fdtdump.c10
-rw-r--r--fdtget.c15
-rw-r--r--fdtput.c2
-rw-r--r--flattree.c19
-rw-r--r--fuzzing/Android.bp9
-rw-r--r--fuzzing/corpus/crash-a5b94d95681291f3057eea7f0233c8f1529b2f59bin0 -> 1369 bytes
-rw-r--r--fuzzing/corpus/hardy-octopusbin0 -> 1171 bytes
-rw-r--r--fuzzing/corpus/header-truncatedbin0 -> 40 bytes
-rw-r--r--fuzzing/corpus/header-v-1bin0 -> 40 bytes
-rw-r--r--fuzzing/corpus/header-v0bin0 -> 40 bytes
-rw-r--r--fuzzing/corpus/meson-g12a-sei510-android.dtbbin0 -> 1363 bytes
-rw-r--r--fuzzing/corpus/oob_by_onebin0 -> 256 bytes
-rw-r--r--fuzzing/corpus/quirks.dtbbin0 -> 327 bytes
-rw-r--r--fuzzing/libfdt_fuzzer.c170
-rw-r--r--fuzzing/libfdt_fuzzer.cpp42
-rw-r--r--libfdt/Android.bp6
-rw-r--r--libfdt/acpi.c7
-rw-r--r--libfdt/fdt.c58
-rw-r--r--libfdt/fdt_addresses.c2
-rw-r--r--libfdt/fdt_check.c19
-rw-r--r--libfdt/fdt_overlay.c32
-rw-r--r--libfdt/fdt_ro.c72
-rw-r--r--libfdt/fdt_rw.c24
-rw-r--r--libfdt/fdt_strerror.c5
-rw-r--r--libfdt/fdt_sw.c29
-rw-r--r--libfdt/fdt_wip.c2
-rw-r--r--libfdt/libfdt.h149
-rw-r--r--libfdt/libfdt_internal.h19
-rw-r--r--libfdt/meson.build61
-rw-r--r--libfdt/rules.mk53
-rw-r--r--libfdt/version.lds1
-rw-r--r--livetree.c41
-rw-r--r--meson.build139
-rw-r--r--meson_options.txt12
-rw-r--r--pylibfdt/Makefile.pylibfdt7
-rw-r--r--pylibfdt/libfdt.i64
-rw-r--r--pylibfdt/meson.build12
-rwxr-xr-xpylibfdt/setup.py48
-rwxr-xr-xsetup.py77
-rw-r--r--srcpos.c2
-rw-r--r--tests/.gitignore1
-rw-r--r--tests/Android.bp12
-rw-r--r--tests/Makefile.tests18
-rw-r--r--tests/bad-interrupt-map-mask.dts20
-rw-r--r--tests/bad-interrupt-map-parent.dts17
-rw-r--r--tests/bad-interrupt-map.dts19
-rw-r--r--tests/base01.asm38
-rw-r--r--tests/dumptrees.c4
-rw-r--r--tests/fs_tree1.c2
-rw-r--r--tests/get_name.c4
-rw-r--r--tests/good-gpio.dts12
-rw-r--r--tests/integer-expressions.c2
-rw-r--r--tests/meson.build137
-rw-r--r--tests/nopulate.c3
-rw-r--r--tests/overlay.c6
-rw-r--r--tests/overlay_overlay_nosugar.dts8
-rw-r--r--tests/path-references.c8
-rw-r--r--tests/path-references.dts9
-rw-r--r--tests/phandle-args-overflow.dts18
-rw-r--r--tests/phandle_format.c2
-rw-r--r--tests/property_iterate.c2
-rw-r--r--tests/pylibfdt_tests.py32
-rw-r--r--tests/references.c2
-rw-r--r--tests/relref_merge.c51
-rw-r--r--tests/relref_merge.dts40
-rwxr-xr-xtests/run_tests.sh33
-rw-r--r--tests/set_name.c10
-rw-r--r--tests/setprop_inplace.c2
-rw-r--r--tests/subnode_iterate.c2
-rw-r--r--tests/test01.asm52
-rw-r--r--tests/test_props.dts4
-rw-r--r--tests/testdata.h2
-rw-r--r--tests/tests.h2
-rw-r--r--tests/testutils.c12
-rw-r--r--tests/trees.S415
-rw-r--r--tests/type-preservation.dt.yaml3
-rw-r--r--tests/type-preservation.dts3
-rw-r--r--tests/utilfdt_test.c5
-rw-r--r--treesource.c48
-rw-r--r--util.c15
-rw-r--r--util.h11
-rw-r--r--version_gen.h.in1
-rw-r--r--yamltree.c18
106 files changed, 3644 insertions, 1103 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index c270a09..d2dc34e 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -1,9 +1,9 @@
env:
CIRRUS_CLONE_DEPTH: 1
-freebsd_12_task:
+freebsd_13_task:
freebsd_instance:
- image: freebsd-12-1-release-amd64
+ image: freebsd-13-0-release-amd64
install_script:
pkg install -y bison gmake pkgconf
build_script:
diff --git a/.gitignore b/.gitignore
index 1f2a0f2..d90656b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,6 +8,8 @@
*.tab.[ch]
lex.yy.c
*.lex.c
+.*.swp
+dtc-parser.h
/dtc
/fdtdump
/convert-dtsv0
@@ -17,3 +19,11 @@ lex.yy.c
/fdtoverlay
/patches
/.pc
+
+# cscope files
+cscope.*
+ncscope.*
+
+.eggs/
+build/
+dist/
diff --git a/Android.bp b/Android.bp
index 149ac75..cb13748 100644
--- a/Android.bp
+++ b/Android.bp
@@ -25,19 +25,22 @@ package {
license {
name: "external_dtc_license",
visibility: [":__subpackages__"],
- license_kinds: [
- "SPDX-license-identifier-BSD",
- "SPDX-license-identifier-BSD-2-Clause",
- "SPDX-license-identifier-GPL",
- "SPDX-license-identifier-GPL-2.0",
- "SPDX-license-identifier-ISC",
- "SPDX-license-identifier-LGPL",
- "SPDX-license-identifier-LGPL-2.1",
- ],
- license_text: [
- "NOTICE",
- "README.license",
- ],
+ license_kinds: ["SPDX-license-identifier-GPL-2.0"],
+ license_text: ["GPL"],
+}
+
+license {
+ name: "external_dtc_libfdt_license",
+ visibility: [":__subpackages__"],
+ license_kinds: ["SPDX-license-identifier-BSD-2-Clause"],
+ license_text: ["BSD-2-Clause"],
+}
+
+license {
+ name: "external_dtc_tests_license",
+ visibility: [":__subpackages__"],
+ license_kinds: ["SPDX-license-identifier-LGPL-2.1+"],
+ license_text: ["LGPL"],
}
cc_defaults {
@@ -88,3 +91,21 @@ cc_binary_host {
"util.c",
],
}
+
+cc_binary_host {
+ name: "fdtoverlay",
+ defaults: ["dt_defaults"],
+ srcs: [
+ "fdtoverlay.c",
+ "util.c",
+ ],
+}
+
+cc_binary_host {
+ name: "fdtdump",
+ defaults: ["dt_defaults"],
+ srcs: [
+ "fdtdump.c",
+ "util.c",
+ ],
+}
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..940dd1a
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,79 @@
+# Contributing to dtc or libfdt
+
+There are two ways to submit changes for dtc or libfdt:
+
+* Post patches directly to the the
+ [devicetree-compiler](mailto:devicetree-compiler@vger.kernel.org)
+ mailing list.
+* Submit pull requests via
+ [Github](https://github.com/dgibson/dtc/pulls)
+
+## Adding a new function to libfdt.h
+
+The shared library uses `libfdt/version.lds` to list the exported
+functions, so add your new function there. Check that your function
+works with pylibfdt. If it cannot be supported, put the declaration in
+`libfdt.h` behind `#ifndef SWIG` so that swig ignores it.
+
+## Tests
+
+Test files are kept in the `tests/` directory. Use `make check` to build and run
+all tests.
+
+If you want to adjust a test file, be aware that `tree_tree1.dts` is compiled
+and checked against a binary tree from assembler macros in `trees.S`. So
+if you change that file you must change `tree.S` also.
+
+## Developer's Certificate of Origin
+
+Like many other projects, dtc and libfdt have adopted the "Developer's
+Certificate of Origin" (Signed-off-by) process created by the Linux
+kernel community to improve tracking of who did what. Here's how it
+works (this is a very slight modification of the description from
+`Documentation/process/submitting-patches.rst` in the kernel tree):
+
+The sign-off is a simple line at the end of the explanation for the
+patch, which certifies that you wrote it or otherwise have the right
+to pass it on as an open-source patch. The rules are pretty simple:
+if you can certify the below:
+
+ Developer's Certificate of Origin 1.1
+
+ By making a contribution to this project, I certify that:
+
+ (a) The contribution was created in whole or in part by me and I
+ have the right to submit it under the open source license
+ indicated in the file; or
+
+ (b) The contribution is based upon previous work that, to the best
+ of my knowledge, is covered under an appropriate open source
+ license and I have the right under that license to submit that
+ work with modifications, whether created in whole or in part
+ by me, under the same open source license (unless I am
+ permitted to submit under a different license), as indicated
+ in the file; or
+
+ (c) The contribution was provided directly to me by some other
+ person who certified (a), (b) or (c) and I have not modified
+ it.
+
+ (d) I understand and agree that this project and the contribution
+ are public and that a record of the contribution (including all
+ personal information I submit with it, including my sign-off) is
+ maintained indefinitely and may be redistributed consistent with
+ this project or the open source license(s) involved.
+
+then you just add a line saying::
+
+ Signed-off-by: Random J Developer <random@developer.example.org>
+
+using your real name (sorry, no pseudonyms or anonymous
+contributions.) This will be done for you automatically if you use
+`git commit -s`. Reverts should also include "Signed-off-by". `git
+revert -s` does that for you.
+
+Any further SoBs (Signed-off-by:'s) following the author's SoB are
+from people handling and transporting the patch, but were not involved
+in its development. SoB chains should reflect the **real** route a
+patch took as it was propagated to the maintainers, with the first SoB
+entry signalling primary authorship of a single author.
diff --git a/Documentation/manual.txt b/Documentation/manual.txt
index adf5ccb..cf4b253 100644
--- a/Documentation/manual.txt
+++ b/Documentation/manual.txt
@@ -45,7 +45,7 @@ The gitweb interface for the upstream repository is:
Patches should be sent to the maintainers:
David Gibson <david@gibson.dropbear.id.au>
- Jon Loeliger <jdl@jdl.com>
+ Jon Loeliger <loeliger@gmail.com>
and CCed to <devicetree-compiler@vger.kernel.org>.
2) Description
@@ -712,7 +712,7 @@ The syntax of the fdtget command is:
where options are:
- <type> s=string, i=int, u=unsigned, x=hex
+ <type> s=string, i=int, u=unsigned, x=hex, r=raw
Optional modifier prefix:
hh or b=byte, h=2 byte, l=4 byte (default)
diff --git a/LGPL b/LGPL
new file mode 100644
index 0000000..27bb434
--- /dev/null
+++ b/LGPL
@@ -0,0 +1,503 @@
+Valid-License-Identifier: LGPL-2.1
+Valid-License-Identifier: LGPL-2.1+
+SPDX-URL: https://spdx.org/licenses/LGPL-2.1.html
+Usage-Guide:
+ To use this license in source code, put one of the following SPDX
+ tag/value pairs into a comment according to the placement
+ guidelines in the licensing rules documentation.
+ For 'GNU Lesser General Public License (LGPL) version 2.1 only' use:
+ SPDX-License-Identifier: LGPL-2.1
+ For 'GNU Lesser General Public License (LGPL) version 2.1 or any later
+ version' use:
+ SPDX-License-Identifier: LGPL-2.1+
+License-Text:
+
+GNU LESSER GENERAL PUBLIC LICENSE
+Version 2.1, February 1999
+
+Copyright (C) 1991, 1999 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.
+
+[This is the first released version of the Lesser GPL. It also counts as
+the successor of the GNU Library Public License, version 2, hence the
+version number 2.1.]
+
+Preamble
+
+The licenses for most software are designed to take away your freedom to
+share and change it. By contrast, the GNU General Public Licenses are
+intended to guarantee your freedom to share and change free software--to
+make sure the software is free for all its users.
+
+This license, the Lesser General Public License, applies to some specially
+designated software packages--typically libraries--of the Free Software
+Foundation and other authors who decide to use it. You can use it too, but
+we suggest you first think carefully about whether this license or the
+ordinary General Public License is the better strategy to use in any
+particular case, based on the explanations below.
+
+When we speak of free software, we are referring to freedom of use, not
+price. Our General Public Licenses are designed to make sure that you have
+the freedom to distribute copies of free software (and charge for this
+service if you wish); that you receive source code or can get it if you
+want it; that you can change the software and use pieces of it in new free
+programs; and that you are informed that you can do these things.
+
+To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for you if
+you distribute copies of the library or if you modify it.
+
+For example, if you distribute copies of the library, whether gratis or for
+a fee, you must give the recipients all the rights that we gave you. You
+must make sure that they, too, receive or can get the source code. If you
+link other code with the library, you must provide complete object files to
+the recipients, so that they can relink them with the library after making
+changes to the library and recompiling it. And you must show them these
+terms so they know their rights.
+
+We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+To protect each distributor, we want to make it very clear that there is no
+warranty for the free library. Also, if the library is modified by someone
+else and passed on, the recipients should know that what they have is not
+the original version, so that the original author's reputation will not be
+affected by problems that might be introduced by others.
+
+Finally, software patents pose a constant threat to the existence of any
+free program. We wish to make sure that a company cannot effectively
+restrict the users of a free program by obtaining a restrictive license
+from a patent holder. Therefore, we insist that any patent license obtained
+for a version of the library must be consistent with the full freedom of
+use specified in this license.
+
+Most GNU software, including some libraries, is covered by the ordinary GNU
+General Public License. This license, the GNU Lesser General Public
+License, applies to certain designated libraries, and is quite different
+from the ordinary General Public License. We use this license for certain
+libraries in order to permit linking those libraries into non-free
+programs.
+
+When a program is linked with a library, whether statically or using a
+shared library, the combination of the two is legally speaking a combined
+work, a derivative of the original library. The ordinary General Public
+License therefore permits such linking only if the entire combination fits
+its criteria of freedom. The Lesser General Public License permits more lax
+criteria for linking other code with the library.
+
+We call this license the "Lesser" General Public License because it does
+Less to protect the user's freedom than the ordinary General Public
+License. It also provides other free software developers Less of an
+advantage over competing non-free programs. These disadvantages are the
+reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+For example, on rare occasions, there may be a special need to encourage
+the widest possible use of a certain library, so that it becomes a de-facto
+standard. To achieve this, non-free programs must be allowed to use the
+library. A more frequent case is that a free library does the same job as
+widely used non-free libraries. In this case, there is little to gain by
+limiting the free library to free software only, so we use the Lesser
+General Public License.
+
+In other cases, permission to use a particular library in non-free programs
+enables a greater number of people to use a large body of free
+software. For example, permission to use the GNU C Library in non-free
+programs enables many more people to use the whole GNU operating system, as
+well as its variant, the GNU/Linux operating system.
+
+Although the Lesser General Public License is Less protective of the users'
+freedom, it does ensure that the user of a program that is linked with the
+Library has the freedom and the wherewithal to run that program using a
+modified version of the Library.
+
+The precise terms and conditions for copying, distribution and modification
+follow. Pay close attention to the difference between a "work based on the
+library" and a "work that uses the library". The former contains code
+derived from the library, whereas the latter must be combined with the
+library in order to run.
+
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+0. This License Agreement applies to any software library or other program
+ which contains a notice placed by the copyright holder or other
+ authorized party saying it may be distributed under the terms of this
+ Lesser General Public License (also called "this License"). Each
+ licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+ prepared so as to be conveniently linked with application programs
+ (which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work which
+ has been distributed under these terms. A "work based on the Library"
+ means either the Library or any derivative work under copyright law:
+ that is to say, a work containing the Library or a portion of it, either
+ verbatim or with modifications and/or translated straightforwardly into
+ another language. (Hereinafter, translation is included without
+ limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for making
+ modifications to it. For a library, complete source code means all the
+ source code for all modules it contains, plus any associated interface
+ definition files, plus the scripts used to control compilation and
+ installation of the library.
+
+ Activities other than copying, distribution and modification are not
+ covered by this License; they are outside its scope. The act of running
+ a program using the Library is not restricted, and output from such a
+ program is covered only if its contents constitute a work based on the
+ Library (independent of the use of the Library in a tool for writing
+ it). Whether that is true depends on what the Library does and what the
+ program that uses the Library does.
+
+1. You may copy and distribute verbatim copies of the Library's complete
+ source code as you receive it, in any medium, provided that you
+ conspicuously and appropriately publish on each copy an appropriate
+ copyright notice and disclaimer of warranty; keep intact all the notices
+ that refer to this License and to the absence of any warranty; and
+ distribute a copy of this License along with the Library.
+
+ You may charge a fee for the physical act of transferring a copy, and
+ you may at your option offer warranty protection in exchange for a fee.
+
+2. You may modify your copy or copies of the Library or any portion of it,
+ thus forming a work based on the Library, and copy and distribute such
+ modifications or work under the terms of Section 1 above, provided that
+ you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices stating
+ that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no charge to
+ all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a table
+ of data to be supplied by an application program that uses the
+ facility, other than as an argument passed when the facility is
+ invoked, then you must make a good faith effort to ensure that, in
+ the event an application does not supply such function or table, the
+ facility still operates, and performs whatever part of its purpose
+ remains meaningful.
+
+ (For example, a function in a library to compute square roots has a
+ purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must be
+ optional: if the application does not supply it, the square root
+ function must still compute square roots.)
+
+ These requirements apply to the modified work as a whole. If
+ identifiable sections of that work are not derived from the Library, and
+ can be reasonably considered independent and separate works in
+ themselves, then this License, and its terms, do not apply to those
+ sections when you distribute them as separate works. But when you
+ distribute the same sections as part of a whole which is a work based on
+ the Library, the distribution of the whole must be on the terms of this
+ License, whose permissions for other licensees extend to the entire
+ whole, and thus to each and every part regardless of who wrote it.
+
+ Thus, it is not the intent of this section to claim rights or contest
+ your rights to work written entirely by you; rather, the intent is to
+ exercise the right to control the distribution of derivative or
+ collective works based on the Library.
+
+ In addition, mere aggregation of another work not based on the Library
+ with the Library (or with a work based on the Library) on a volume of a
+ storage or distribution medium does not bring the other work under the
+ scope of this License.
+
+3. You may opt to apply the terms of the ordinary GNU General Public
+ License instead of this License to a given copy of the Library. To do
+ this, you must alter all the notices that refer to this License, so that
+ they refer to the ordinary GNU General Public License, version 2,
+ instead of to this License. (If a newer version than version 2 of the
+ ordinary GNU General Public License has appeared, then you can specify
+ that version instead if you wish.) Do not make any other change in these
+ notices.
+
+ Once this change is made in a given copy, it is irreversible for that
+ copy, so the ordinary GNU General Public License applies to all
+ subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of the
+ Library into a program that is not a library.
+
+4. You may copy and distribute the Library (or a portion or derivative of
+ it, under Section 2) in object code or executable form under the terms
+ of Sections 1 and 2 above provided that you accompany it with the
+ complete corresponding machine-readable source code, which must be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy from a
+ designated place, then offering equivalent access to copy the source
+ code from the same place satisfies the requirement to distribute the
+ source code, even though third parties are not compelled to copy the
+ source along with the object code.
+
+5. A program that contains no derivative of any portion of the Library, but
+ is designed to work with the Library by being compiled or linked with
+ it, is called a "work that uses the Library". Such a work, in isolation,
+ is not a derivative work of the Library, and therefore falls outside the
+ scope of this License.
+
+ However, linking a "work that uses the Library" with the Library creates
+ an executable that is a derivative of the Library (because it contains
+ portions of the Library), rather than a "work that uses the
+ library". The executable is therefore covered by this License. Section 6
+ states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+ that is part of the Library, the object code for the work may be a
+ derivative work of the Library even though the source code is
+ not. Whether this is true is especially significant if the work can be
+ linked without the Library, or if the work is itself a library. The
+ threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data structure
+ layouts and accessors, and small macros and small inline functions (ten
+ lines or less in length), then the use of the object file is
+ unrestricted, regardless of whether it is legally a derivative
+ work. (Executables containing this object code plus portions of the
+ Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+ distribute the object code for the work under the terms of Section
+ 6. Any executables containing that work also fall under Section 6,
+ whether or not they are linked directly with the Library itself.
+
+6. As an exception to the Sections above, you may also combine or link a
+ "work that uses the Library" with the Library to produce a work
+ containing portions of the Library, and distribute that work under terms
+ of your choice, provided that the terms permit modification of the work
+ for the customer's own use and reverse engineering for debugging such
+ modifications.
+
+ You must give prominent notice with each copy of the work that the
+ Library is used in it and that the Library and its use are covered by
+ this License. You must supply a copy of this License. If the work during
+ execution displays copyright notices, you must include the copyright
+ notice for the Library among them, as well as a reference directing the
+ user to the copy of this License. Also, you must do one of these things:
+
+ a) Accompany the work with the complete corresponding machine-readable
+ source code for the Library including whatever changes were used in
+ the work (which must be distributed under Sections 1 and 2 above);
+ and, if the work is an executable linked with the Library, with the
+ complete machine-readable "work that uses the Library", as object
+ code and/or source code, so that the user can modify the Library and
+ then relink to produce a modified executable containing the modified
+ Library. (It is understood that the user who changes the contents of
+ definitions files in the Library will not necessarily be able to
+ recompile the application to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a copy
+ of the library already present on the user's computer system, rather
+ than copying library functions into the executable, and (2) will
+ operate properly with a modified version of the library, if the user
+ installs one, as long as the modified version is interface-compatible
+ with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at least three
+ years, to give the same user the materials specified in Subsection
+ 6a, above, for a charge no more than the cost of performing this
+ distribution.
+
+ d) If distribution of the work is made by offering access to copy from a
+ designated place, offer equivalent access to copy the above specified
+ materials from the same place.
+
+ e) Verify that the user has already received a copy of these materials
+ or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the Library"
+ must include any data and utility programs needed for reproducing the
+ executable from it. However, as a special exception, the materials to be
+ distributed need not include anything that is normally distributed (in
+ either source or binary form) with the major components (compiler,
+ kernel, and so on) of the operating system on which the executable runs,
+ unless that component itself accompanies the executable.
+
+ It may happen that this requirement contradicts the license restrictions
+ of other proprietary libraries that do not normally accompany the
+ operating system. Such a contradiction means you cannot use both them
+ and the Library together in an executable that you distribute.
+
+7. You may place library facilities that are a work based on the Library
+ side-by-side in a single library together with other library facilities
+ not covered by this License, and distribute such a combined library,
+ provided that the separate distribution of the work based on the Library
+ and of the other library facilities is otherwise permitted, and provided
+ that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work based on
+ the Library, uncombined with any other library facilities. This must
+ be distributed under the terms of the Sections above.
+
+ b) Give prominent notice with the combined library of the fact that part
+ of it is a work based on the Library, and explaining where to find
+ the accompanying uncombined form of the same work.
+
+8. You may not copy, modify, sublicense, link with, or distribute the
+ Library except as expressly provided under this License. Any attempt
+ otherwise to copy, modify, sublicense, link with, or distribute the
+ Library is void, and will automatically terminate your rights under this
+ License. However, parties who have received copies, or rights, from you
+ under this License will not have their licenses terminated so long as
+ such parties remain in full compliance.
+
+9. You are not required to accept this License, since you have not signed
+ it. However, nothing else grants you permission to modify or distribute
+ the Library or its derivative works. These actions are prohibited by law
+ if you do not accept this License. Therefore, by modifying or
+ distributing the Library (or any work based on the Library), you
+ indicate your acceptance of this License to do so, and all its terms and
+ conditions for copying, distributing or modifying the Library or works
+ based on it.
+
+10. Each time you redistribute the Library (or any work based on the
+ Library), the recipient automatically receives a license from the
+ original licensor to copy, distribute, link with or modify the Library
+ subject to these terms and conditions. You may not impose any further
+ restrictions on the recipients' exercise of the rights granted
+ herein. You are not responsible for enforcing compliance by third
+ parties with this License.
+
+11. If, as a consequence of a court judgment or allegation of patent
+ infringement or for any other reason (not limited to patent issues),
+ conditions are imposed on you (whether by court order, agreement or
+ otherwise) that contradict the conditions of this License, they do not
+ excuse you from the conditions of this License. If you cannot
+ distribute so as to satisfy simultaneously your obligations under this
+ License and any other pertinent obligations, then as a consequence you
+ may not distribute the Library at all. For example, if a patent license
+ would not permit royalty-free redistribution of the Library by all
+ those who receive copies directly or indirectly through you, then the
+ only way you could satisfy both it and this License would be to refrain
+ entirely from distribution of the Library.
+
+ If any portion of this section is held invalid or unenforceable under
+ any particular circumstance, the balance of the section is intended to
+ apply, and the section as a whole is intended to apply in other
+ circumstances.
+
+ It is not the purpose of this section to induce you to infringe any
+ patents or other property right claims or to contest validity of any
+ such claims; this section has the sole purpose of protecting the
+ integrity of the free software distribution system which is implemented
+ by public license practices. Many people have made generous
+ contributions to the wide range of software distributed through that
+ system in reliance on consistent application of that system; it is up
+ to the author/donor to decide if he or she is willing to distribute
+ software through any other system and a licensee cannot impose that
+ choice.
+
+ This section is intended to make thoroughly clear what is believed to
+ be a consequence of the rest of this License.
+
+12. If the distribution and/or use of the Library is restricted in certain
+ countries either by patents or by copyrighted interfaces, the original
+ copyright holder who places the Library under this License may add an
+ explicit geographical distribution limitation excluding those
+ countries, so that distribution is permitted only in or among countries
+ not thus excluded. In such case, this License incorporates the
+ limitation as if written in the body of this License.
+
+13. The Free Software Foundation may publish revised and/or new versions of
+ the Lesser General Public License from time to time. Such new versions
+ will be similar in spirit to the present version, but may differ in
+ detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the Library
+ specifies a version number of this License which applies to it and "any
+ later version", you have the option of following the terms and
+ conditions either of that version or of any later version published by
+ the Free Software Foundation. If the Library does not specify a license
+ version number, you may choose any version ever published by the Free
+ Software Foundation.
+
+14. If you wish to incorporate parts of the Library into other free
+ programs whose distribution conditions are incompatible with these,
+ write to the author to ask for permission. For software which is
+ copyrighted by the Free Software Foundation, write to the Free Software
+ Foundation; we sometimes 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
+
+15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+ FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+ OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+ PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+ EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH
+ YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+ NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+ WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+ REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR
+ DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL
+ DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY
+ (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
+ INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF
+ THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), 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 Libraries
+
+If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+one line to give the library's name and an idea of what it does.
+Copyright (C) year name of author
+
+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 Street, Fifth Floor, Boston, MA 02110-1301 USA Also add
+information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+Yoyodyne, Inc., hereby disclaims all copyright interest in
+the library `Frob' (a library for tweaking knobs) written
+by James Random Hacker.
+
+signature of Ty Coon, 1 April 1990
+Ty Coon, President of Vice
+That's all there is to it!
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..8ce2e18
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,880 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ 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
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+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 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
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+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
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ 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
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+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
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+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
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+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
+
+ 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
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+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
+
+ 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
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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.,
+ 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 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.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+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 Lesser General
+Public License instead of this License.
+
+=================================================================
+
+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.
+
+=================================================================
+
+Valid-License-Identifier: LGPL-2.1
+Valid-License-Identifier: LGPL-2.1+
+SPDX-URL: https://spdx.org/licenses/LGPL-2.1.html
+Usage-Guide:
+ To use this license in source code, put one of the following SPDX
+ tag/value pairs into a comment according to the placement
+ guidelines in the licensing rules documentation.
+ For 'GNU Lesser General Public License (LGPL) version 2.1 only' use:
+ SPDX-License-Identifier: LGPL-2.1
+ For 'GNU Lesser General Public License (LGPL) version 2.1 or any later
+ version' use:
+ SPDX-License-Identifier: LGPL-2.1+
+License-Text:
+
+GNU LESSER GENERAL PUBLIC LICENSE
+Version 2.1, February 1999
+
+Copyright (C) 1991, 1999 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.
+
+[This is the first released version of the Lesser GPL. It also counts as
+the successor of the GNU Library Public License, version 2, hence the
+version number 2.1.]
+
+Preamble
+
+The licenses for most software are designed to take away your freedom to
+share and change it. By contrast, the GNU General Public Licenses are
+intended to guarantee your freedom to share and change free software--to
+make sure the software is free for all its users.
+
+This license, the Lesser General Public License, applies to some specially
+designated software packages--typically libraries--of the Free Software
+Foundation and other authors who decide to use it. You can use it too, but
+we suggest you first think carefully about whether this license or the
+ordinary General Public License is the better strategy to use in any
+particular case, based on the explanations below.
+
+When we speak of free software, we are referring to freedom of use, not
+price. Our General Public Licenses are designed to make sure that you have
+the freedom to distribute copies of free software (and charge for this
+service if you wish); that you receive source code or can get it if you
+want it; that you can change the software and use pieces of it in new free
+programs; and that you are informed that you can do these things.
+
+To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for you if
+you distribute copies of the library or if you modify it.
+
+For example, if you distribute copies of the library, whether gratis or for
+a fee, you must give the recipients all the rights that we gave you. You
+must make sure that they, too, receive or can get the source code. If you
+link other code with the library, you must provide complete object files to
+the recipients, so that they can relink them with the library after making
+changes to the library and recompiling it. And you must show them these
+terms so they know their rights.
+
+We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+To protect each distributor, we want to make it very clear that there is no
+warranty for the free library. Also, if the library is modified by someone
+else and passed on, the recipients should know that what they have is not
+the original version, so that the original author's reputation will not be
+affected by problems that might be introduced by others.
+
+Finally, software patents pose a constant threat to the existence of any
+free program. We wish to make sure that a company cannot effectively
+restrict the users of a free program by obtaining a restrictive license
+from a patent holder. Therefore, we insist that any patent license obtained
+for a version of the library must be consistent with the full freedom of
+use specified in this license.
+
+Most GNU software, including some libraries, is covered by the ordinary GNU
+General Public License. This license, the GNU Lesser General Public
+License, applies to certain designated libraries, and is quite different
+from the ordinary General Public License. We use this license for certain
+libraries in order to permit linking those libraries into non-free
+programs.
+
+When a program is linked with a library, whether statically or using a
+shared library, the combination of the two is legally speaking a combined
+work, a derivative of the original library. The ordinary General Public
+License therefore permits such linking only if the entire combination fits
+its criteria of freedom. The Lesser General Public License permits more lax
+criteria for linking other code with the library.
+
+We call this license the "Lesser" General Public License because it does
+Less to protect the user's freedom than the ordinary General Public
+License. It also provides other free software developers Less of an
+advantage over competing non-free programs. These disadvantages are the
+reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+For example, on rare occasions, there may be a special need to encourage
+the widest possible use of a certain library, so that it becomes a de-facto
+standard. To achieve this, non-free programs must be allowed to use the
+library. A more frequent case is that a free library does the same job as
+widely used non-free libraries. In this case, there is little to gain by
+limiting the free library to free software only, so we use the Lesser
+General Public License.
+
+In other cases, permission to use a particular library in non-free programs
+enables a greater number of people to use a large body of free
+software. For example, permission to use the GNU C Library in non-free
+programs enables many more people to use the whole GNU operating system, as
+well as its variant, the GNU/Linux operating system.
+
+Although the Lesser General Public License is Less protective of the users'
+freedom, it does ensure that the user of a program that is linked with the
+Library has the freedom and the wherewithal to run that program using a
+modified version of the Library.
+
+The precise terms and conditions for copying, distribution and modification
+follow. Pay close attention to the difference between a "work based on the
+library" and a "work that uses the library". The former contains code
+derived from the library, whereas the latter must be combined with the
+library in order to run.
+
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+0. This License Agreement applies to any software library or other program
+ which contains a notice placed by the copyright holder or other
+ authorized party saying it may be distributed under the terms of this
+ Lesser General Public License (also called "this License"). Each
+ licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+ prepared so as to be conveniently linked with application programs
+ (which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work which
+ has been distributed under these terms. A "work based on the Library"
+ means either the Library or any derivative work under copyright law:
+ that is to say, a work containing the Library or a portion of it, either
+ verbatim or with modifications and/or translated straightforwardly into
+ another language. (Hereinafter, translation is included without
+ limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for making
+ modifications to it. For a library, complete source code means all the
+ source code for all modules it contains, plus any associated interface
+ definition files, plus the scripts used to control compilation and
+ installation of the library.
+
+ Activities other than copying, distribution and modification are not
+ covered by this License; they are outside its scope. The act of running
+ a program using the Library is not restricted, and output from such a
+ program is covered only if its contents constitute a work based on the
+ Library (independent of the use of the Library in a tool for writing
+ it). Whether that is true depends on what the Library does and what the
+ program that uses the Library does.
+
+1. You may copy and distribute verbatim copies of the Library's complete
+ source code as you receive it, in any medium, provided that you
+ conspicuously and appropriately publish on each copy an appropriate
+ copyright notice and disclaimer of warranty; keep intact all the notices
+ that refer to this License and to the absence of any warranty; and
+ distribute a copy of this License along with the Library.
+
+ You may charge a fee for the physical act of transferring a copy, and
+ you may at your option offer warranty protection in exchange for a fee.
+
+2. You may modify your copy or copies of the Library or any portion of it,
+ thus forming a work based on the Library, and copy and distribute such
+ modifications or work under the terms of Section 1 above, provided that
+ you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices stating
+ that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no charge to
+ all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a table
+ of data to be supplied by an application program that uses the
+ facility, other than as an argument passed when the facility is
+ invoked, then you must make a good faith effort to ensure that, in
+ the event an application does not supply such function or table, the
+ facility still operates, and performs whatever part of its purpose
+ remains meaningful.
+
+ (For example, a function in a library to compute square roots has a
+ purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must be
+ optional: if the application does not supply it, the square root
+ function must still compute square roots.)
+
+ These requirements apply to the modified work as a whole. If
+ identifiable sections of that work are not derived from the Library, and
+ can be reasonably considered independent and separate works in
+ themselves, then this License, and its terms, do not apply to those
+ sections when you distribute them as separate works. But when you
+ distribute the same sections as part of a whole which is a work based on
+ the Library, the distribution of the whole must be on the terms of this
+ License, whose permissions for other licensees extend to the entire
+ whole, and thus to each and every part regardless of who wrote it.
+
+ Thus, it is not the intent of this section to claim rights or contest
+ your rights to work written entirely by you; rather, the intent is to
+ exercise the right to control the distribution of derivative or
+ collective works based on the Library.
+
+ In addition, mere aggregation of another work not based on the Library
+ with the Library (or with a work based on the Library) on a volume of a
+ storage or distribution medium does not bring the other work under the
+ scope of this License.
+
+3. You may opt to apply the terms of the ordinary GNU General Public
+ License instead of this License to a given copy of the Library. To do
+ this, you must alter all the notices that refer to this License, so that
+ they refer to the ordinary GNU General Public License, version 2,
+ instead of to this License. (If a newer version than version 2 of the
+ ordinary GNU General Public License has appeared, then you can specify
+ that version instead if you wish.) Do not make any other change in these
+ notices.
+
+ Once this change is made in a given copy, it is irreversible for that
+ copy, so the ordinary GNU General Public License applies to all
+ subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of the
+ Library into a program that is not a library.
+
+4. You may copy and distribute the Library (or a portion or derivative of
+ it, under Section 2) in object code or executable form under the terms
+ of Sections 1 and 2 above provided that you accompany it with the
+ complete corresponding machine-readable source code, which must be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy from a
+ designated place, then offering equivalent access to copy the source
+ code from the same place satisfies the requirement to distribute the
+ source code, even though third parties are not compelled to copy the
+ source along with the object code.
+
+5. A program that contains no derivative of any portion of the Library, but
+ is designed to work with the Library by being compiled or linked with
+ it, is called a "work that uses the Library". Such a work, in isolation,
+ is not a derivative work of the Library, and therefore falls outside the
+ scope of this License.
+
+ However, linking a "work that uses the Library" with the Library creates
+ an executable that is a derivative of the Library (because it contains
+ portions of the Library), rather than a "work that uses the
+ library". The executable is therefore covered by this License. Section 6
+ states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+ that is part of the Library, the object code for the work may be a
+ derivative work of the Library even though the source code is
+ not. Whether this is true is especially significant if the work can be
+ linked without the Library, or if the work is itself a library. The
+ threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data structure
+ layouts and accessors, and small macros and small inline functions (ten
+ lines or less in length), then the use of the object file is
+ unrestricted, regardless of whether it is legally a derivative
+ work. (Executables containing this object code plus portions of the
+ Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+ distribute the object code for the work under the terms of Section
+ 6. Any executables containing that work also fall under Section 6,
+ whether or not they are linked directly with the Library itself.
+
+6. As an exception to the Sections above, you may also combine or link a
+ "work that uses the Library" with the Library to produce a work
+ containing portions of the Library, and distribute that work under terms
+ of your choice, provided that the terms permit modification of the work
+ for the customer's own use and reverse engineering for debugging such
+ modifications.
+
+ You must give prominent notice with each copy of the work that the
+ Library is used in it and that the Library and its use are covered by
+ this License. You must supply a copy of this License. If the work during
+ execution displays copyright notices, you must include the copyright
+ notice for the Library among them, as well as a reference directing the
+ user to the copy of this License. Also, you must do one of these things:
+
+ a) Accompany the work with the complete corresponding machine-readable
+ source code for the Library including whatever changes were used in
+ the work (which must be distributed under Sections 1 and 2 above);
+ and, if the work is an executable linked with the Library, with the
+ complete machine-readable "work that uses the Library", as object
+ code and/or source code, so that the user can modify the Library and
+ then relink to produce a modified executable containing the modified
+ Library. (It is understood that the user who changes the contents of
+ definitions files in the Library will not necessarily be able to
+ recompile the application to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a copy
+ of the library already present on the user's computer system, rather
+ than copying library functions into the executable, and (2) will
+ operate properly with a modified version of the library, if the user
+ installs one, as long as the modified version is interface-compatible
+ with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at least three
+ years, to give the same user the materials specified in Subsection
+ 6a, above, for a charge no more than the cost of performing this
+ distribution.
+
+ d) If distribution of the work is made by offering access to copy from a
+ designated place, offer equivalent access to copy the above specified
+ materials from the same place.
+
+ e) Verify that the user has already received a copy of these materials
+ or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the Library"
+ must include any data and utility programs needed for reproducing the
+ executable from it. However, as a special exception, the materials to be
+ distributed need not include anything that is normally distributed (in
+ either source or binary form) with the major components (compiler,
+ kernel, and so on) of the operating system on which the executable runs,
+ unless that component itself accompanies the executable.
+
+ It may happen that this requirement contradicts the license restrictions
+ of other proprietary libraries that do not normally accompany the
+ operating system. Such a contradiction means you cannot use both them
+ and the Library together in an executable that you distribute.
+
+7. You may place library facilities that are a work based on the Library
+ side-by-side in a single library together with other library facilities
+ not covered by this License, and distribute such a combined library,
+ provided that the separate distribution of the work based on the Library
+ and of the other library facilities is otherwise permitted, and provided
+ that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work based on
+ the Library, uncombined with any other library facilities. This must
+ be distributed under the terms of the Sections above.
+
+ b) Give prominent notice with the combined library of the fact that part
+ of it is a work based on the Library, and explaining where to find
+ the accompanying uncombined form of the same work.
+
+8. You may not copy, modify, sublicense, link with, or distribute the
+ Library except as expressly provided under this License. Any attempt
+ otherwise to copy, modify, sublicense, link with, or distribute the
+ Library is void, and will automatically terminate your rights under this
+ License. However, parties who have received copies, or rights, from you
+ under this License will not have their licenses terminated so long as
+ such parties remain in full compliance.
+
+9. You are not required to accept this License, since you have not signed
+ it. However, nothing else grants you permission to modify or distribute
+ the Library or its derivative works. These actions are prohibited by law
+ if you do not accept this License. Therefore, by modifying or
+ distributing the Library (or any work based on the Library), you
+ indicate your acceptance of this License to do so, and all its terms and
+ conditions for copying, distributing or modifying the Library or works
+ based on it.
+
+10. Each time you redistribute the Library (or any work based on the
+ Library), the recipient automatically receives a license from the
+ original licensor to copy, distribute, link with or modify the Library
+ subject to these terms and conditions. You may not impose any further
+ restrictions on the recipients' exercise of the rights granted
+ herein. You are not responsible for enforcing compliance by third
+ parties with this License.
+
+11. If, as a consequence of a court judgment or allegation of patent
+ infringement or for any other reason (not limited to patent issues),
+ conditions are imposed on you (whether by court order, agreement or
+ otherwise) that contradict the conditions of this License, they do not
+ excuse you from the conditions of this License. If you cannot
+ distribute so as to satisfy simultaneously your obligations under this
+ License and any other pertinent obligations, then as a consequence you
+ may not distribute the Library at all. For example, if a patent license
+ would not permit royalty-free redistribution of the Library by all
+ those who receive copies directly or indirectly through you, then the
+ only way you could satisfy both it and this License would be to refrain
+ entirely from distribution of the Library.
+
+ If any portion of this section is held invalid or unenforceable under
+ any particular circumstance, the balance of the section is intended to
+ apply, and the section as a whole is intended to apply in other
+ circumstances.
+
+ It is not the purpose of this section to induce you to infringe any
+ patents or other property right claims or to contest validity of any
+ such claims; this section has the sole purpose of protecting the
+ integrity of the free software distribution system which is implemented
+ by public license practices. Many people have made generous
+ contributions to the wide range of software distributed through that
+ system in reliance on consistent application of that system; it is up
+ to the author/donor to decide if he or she is willing to distribute
+ software through any other system and a licensee cannot impose that
+ choice.
+
+ This section is intended to make thoroughly clear what is believed to
+ be a consequence of the rest of this License.
+
+12. If the distribution and/or use of the Library is restricted in certain
+ countries either by patents or by copyrighted interfaces, the original
+ copyright holder who places the Library under this License may add an
+ explicit geographical distribution limitation excluding those
+ countries, so that distribution is permitted only in or among countries
+ not thus excluded. In such case, this License incorporates the
+ limitation as if written in the body of this License.
+
+13. The Free Software Foundation may publish revised and/or new versions of
+ the Lesser General Public License from time to time. Such new versions
+ will be similar in spirit to the present version, but may differ in
+ detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the Library
+ specifies a version number of this License which applies to it and "any
+ later version", you have the option of following the terms and
+ conditions either of that version or of any later version published by
+ the Free Software Foundation. If the Library does not specify a license
+ version number, you may choose any version ever published by the Free
+ Software Foundation.
+
+14. If you wish to incorporate parts of the Library into other free
+ programs whose distribution conditions are incompatible with these,
+ write to the author to ask for permission. For software which is
+ copyrighted by the Free Software Foundation, write to the Free Software
+ Foundation; we sometimes 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
+
+15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+ FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+ OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+ PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+ EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH
+ YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+ NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+ WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+ REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR
+ DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL
+ DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY
+ (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
+ INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF
+ THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), 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 Libraries
+
+If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+one line to give the library's name and an idea of what it does.
+Copyright (C) year name of author
+
+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 Street, Fifth Floor, Boston, MA 02110-1301 USA Also add
+information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+Yoyodyne, Inc., hereby disclaims all copyright interest in
+the library `Frob' (a library for tweaking knobs) written
+by James Random Hacker.
+
+signature of Ty Coon, 1 April 1990
+Ty Coon, President of Vice
+That's all there is to it!
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..0eee931
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
+
+global-exclude *
+include README
+include GPL
+include BSD-2-Clause
+include setup.py
+include pylibfdt/libfdt.i
+include libfdt/libfdt.h
+include libfdt/fdt.h
+include libfdt/libfdt_env.h
diff --git a/METADATA b/METADATA
index 6d8601b..a716954 100644
--- a/METADATA
+++ b/METADATA
@@ -1,3 +1,19 @@
+# This project was upgraded with external_updater.
+# Usage: tools/external_updater/updater.sh update dtc
+# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md
+
+name: "dtc"
+description: "Device tree compiler tools (dtc) and libfdt."
third_party {
+ url {
+ type: GIT
+ value: "https://git.kernel.org/pub/scm/utils/dtc/dtc.git"
+ }
+ version: "v1.6.1"
license_type: RESTRICTED
+ last_upgrade_date {
+ year: 2023
+ month: 1
+ day: 18
+ }
}
diff --git a/MODULE_LICENSE_BSD b/MODULE_LICENSE_BSD
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/MODULE_LICENSE_BSD
diff --git a/MODULE_LICENSE_LGPL b/MODULE_LICENSE_LGPL
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/MODULE_LICENSE_LGPL
diff --git a/Makefile b/Makefile
index cb256e8..7fe25f6 100644
--- a/Makefile
+++ b/Makefile
@@ -11,7 +11,7 @@
#
VERSION = 1
PATCHLEVEL = 6
-SUBLEVEL = 0
+SUBLEVEL = 1
EXTRAVERSION =
LOCAL_VERSION =
CONFIG_LOCALVERSION =
@@ -21,7 +21,7 @@ CONFIG_LOCALVERSION =
ASSUME_MASK ?= 0
CPPFLAGS = -I libfdt -I . -DFDT_ASSUME_MASK=$(ASSUME_MASK)
-WARNINGS = -Wall -Wpointer-arith -Wcast-qual -Wnested-externs \
+WARNINGS = -Wall -Wpointer-arith -Wcast-qual -Wnested-externs -Wsign-compare \
-Wstrict-prototypes -Wmissing-prototypes -Wredundant-decls -Wshadow
CFLAGS = -g -Os $(SHAREDLIB_CFLAGS) -Werror $(WARNINGS) $(EXTRA_CFLAGS)
@@ -59,6 +59,7 @@ ifeq ($(NO_YAML),1)
CFLAGS += -DNO_YAML
else
LDLIBS_dtc += $(shell $(PKG_CONFIG) --libs yaml-0.1)
+ CFLAGS += $(shell $(PKG_CONFIG) --cflags yaml-0.1)
endif
ifeq ($(HOSTOS),darwin)
@@ -197,6 +198,13 @@ LIBFDT_lib = $(LIBFDT_dir)/$(LIBFDT_LIB)
LIBFDT_include = $(addprefix $(LIBFDT_dir)/,$(LIBFDT_INCLUDES))
LIBFDT_version = $(addprefix $(LIBFDT_dir)/,$(LIBFDT_VERSION))
+ifeq ($(STATIC_BUILD),1)
+ CFLAGS += -static
+ LIBFDT_dep = $(LIBFDT_archive)
+else
+ LIBFDT_dep = $(LIBFDT_lib)
+endif
+
include $(LIBFDT_dir)/Makefile.libfdt
.PHONY: libfdt
@@ -260,11 +268,11 @@ convert-dtsv0: $(CONVERT_OBJS)
fdtdump: $(FDTDUMP_OBJS)
-fdtget: $(FDTGET_OBJS) $(LIBFDT_lib)
+fdtget: $(FDTGET_OBJS) $(LIBFDT_dep)
-fdtput: $(FDTPUT_OBJS) $(LIBFDT_lib)
+fdtput: $(FDTPUT_OBJS) $(LIBFDT_dep)
-fdtoverlay: $(FDTOVERLAY_OBJS) $(LIBFDT_lib)
+fdtoverlay: $(FDTOVERLAY_OBJS) $(LIBFDT_dep)
dist:
git archive --format=tar --prefix=dtc-$(dtc_version)/ HEAD \
@@ -380,4 +388,8 @@ clean: libfdt_clean pylibfdt_clean tests_clean
@$(VECHO) BISON $@
$(BISON) -b $(basename $(basename $@)) -d $<
+# Some checks expect dtc-parser.h, so create link
+dtc-parser.h: dtc-parser.tab.h
+ ln -s $^ $@
+
FORCE:
diff --git a/NOTICE b/NOTICE
deleted file mode 100644
index d60c31a..0000000
--- a/NOTICE
+++ /dev/null
@@ -1,340 +0,0 @@
- 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
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-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
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-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
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- 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
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-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
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-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
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-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
-
- 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
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-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
-
- 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
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- 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
-
-
-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 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.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
- <signature of Ty Coon>, 1 April 1989
- Ty Coon, President of Vice
-
-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
-Public License instead of this License.
diff --git a/OWNERS b/OWNERS
index af7079c..62b9704 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,4 +1,5 @@
+mikemcternan@google.com
+ptosi@google.com
# Default code reviewers picked from top 3 or more developers.
-# Please update this list if you find better candidates.
szuweilin@google.com
bowgotsai@google.com
diff --git a/README b/README
deleted file mode 100644
index 9465ee5..0000000
--- a/README
+++ /dev/null
@@ -1,91 +0,0 @@
-The source tree contains the Device Tree Compiler (dtc) toolchain for
-working with device tree source and binary files and also libfdt, a
-utility library for reading and manipulating the binary format.
-
-DTC and LIBFDT are maintained by:
-
-David Gibson <david@gibson.dropbear.id.au>
-Jon Loeliger <jdl@jdl.com>
-
-
-Python library
---------------
-
-A Python library is also available. To build this you will need to install
-swig and Python development files. On Debian distributions:
-
- sudo apt-get install swig python3-dev
-
-The library provides an Fdt class which you can use like this:
-
-$ PYTHONPATH=../pylibfdt python3
->>> import libfdt
->>> fdt = libfdt.Fdt(open('test_tree1.dtb', mode='rb').read())
->>> node = fdt.path_offset('/subnode@1')
->>> print(node)
-124
->>> prop_offset = fdt.first_property_offset(node)
->>> prop = fdt.get_property_by_offset(prop_offset)
->>> print('%s=%s' % (prop.name, prop.as_str()))
-compatible=subnode1
->>> node2 = fdt.path_offset('/')
->>> print(fdt.getprop(node2, 'compatible').as_str())
-test_tree1
-
-You will find tests in tests/pylibfdt_tests.py showing how to use each
-method. Help is available using the Python help command, e.g.:
-
- $ cd pylibfdt
- $ python3 -c "import libfdt; help(libfdt)"
-
-If you add new features, please check code coverage:
-
- $ sudo apt-get install python3-coverage
- $ cd tests
- # It's just 'coverage' on most other distributions
- $ python3-coverage run pylibfdt_tests.py
- $ python3-coverage html
- # Open 'htmlcov/index.html' in your browser
-
-
-To install the library via the normal setup.py method, use:
-
- ./pylibfdt/setup.py install [--prefix=/path/to/install_dir]
-
-If --prefix is not provided, the default prefix is used, typically '/usr'
-or '/usr/local'. See Python's distutils documentation for details. You can
-also install via the Makefile if you like, but the above is more common.
-
-To install both libfdt and pylibfdt you can use:
-
- make install [SETUP_PREFIX=/path/to/install_dir] \
- [PREFIX=/path/to/install_dir]
-
-To disable building the python library, even if swig and Python are available,
-use:
-
- make NO_PYTHON=1
-
-
-More work remains to support all of libfdt, including access to numeric
-values.
-
-
-Tests
------
-
-Test files are kept in the tests/ directory. Use 'make check' to build and run
-all tests.
-
-If you want to adjust a test file, be aware that tree_tree1.dts is compiled
-and checked against a binary tree from assembler macros in trees.S. So
-if you change that file you must change tree.S also.
-
-
-Mailing list
-------------
-The following list is for discussion about dtc and libfdt implementation
-mailto:devicetree-compiler@vger.kernel.org
-
-Core device tree bindings are discussed on the devicetree-spec list:
-mailto:devicetree-spec@vger.kernel.org
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..8f1a5d2
--- /dev/null
+++ b/README.md
@@ -0,0 +1,100 @@
+# Device Tree Compiler and libfdt
+
+The source tree contains the Device Tree Compiler (dtc) toolchain for
+working with device tree source and binary files and also libfdt, a
+utility library for reading and manipulating the binary format.
+
+dtc and libfdt are maintained by:
+
+* [David Gibson `<david@gibson.dropbear.id.au>`](mailto:david@gibson.dropbear.id.au)
+
+## Python library
+
+A Python library wrapping libfdt is also available. To build this you
+will need to install `swig` and Python development files. On Debian
+distributions:
+
+```
+$ sudo apt-get install swig python3-dev
+```
+
+The library provides an `Fdt` class which you can use like this:
+
+```
+$ PYTHONPATH=../pylibfdt python3
+>>> import libfdt
+>>> fdt = libfdt.Fdt(open('test_tree1.dtb', mode='rb').read())
+>>> node = fdt.path_offset('/subnode@1')
+>>> print(node)
+124
+>>> prop_offset = fdt.first_property_offset(node)
+>>> prop = fdt.get_property_by_offset(prop_offset)
+>>> print('%s=%s' % (prop.name, prop.as_str()))
+compatible=subnode1
+>>> node2 = fdt.path_offset('/')
+>>> print(fdt.getprop(node2, 'compatible').as_str())
+test_tree1
+```
+
+You will find tests in `tests/pylibfdt_tests.py` showing how to use each
+method. Help is available using the Python help command, e.g.:
+
+```
+$ cd pylibfdt
+$ python3 -c "import libfdt; help(libfdt)"
+```
+
+If you add new features, please check code coverage:
+
+```
+$ sudo apt-get install python3-coverage
+$ cd tests
+# It's just 'coverage' on most other distributions
+$ python3-coverage run pylibfdt_tests.py
+$ python3-coverage html
+# Open 'htmlcov/index.html' in your browser
+```
+
+The library can be installed with pip from a local source tree:
+
+```
+$ pip install . [--user|--prefix=/path/to/install_dir]
+```
+
+Or directly from a remote git repo:
+
+```
+$ pip install git+git://git.kernel.org/pub/scm/utils/dtc/dtc.git@main
+```
+
+The install depends on libfdt shared library being installed on the
+host system first. Generally, using `--user` or `--prefix` is not
+necessary and pip will use the default location for the Python
+installation which varies if the user is root or not.
+
+You can also install everything via make if you like, but pip is
+recommended.
+
+To install both libfdt and pylibfdt you can use:
+
+```
+$ make install [PREFIX=/path/to/install_dir]
+```
+
+To disable building the python library, even if swig and Python are available,
+use:
+
+```
+$ make NO_PYTHON=1
+```
+
+More work remains to support all of libfdt, including access to numeric
+values.
+
+## Mailing lists
+
+* The [devicetree-compiler](mailto:devicetree-compiler@vger.kernel.org)
+ list is for discussion about dtc and libfdt implementation.
+* Core device tree bindings are discussed on the
+ [devicetree-spec](mailto:devicetree-spec@vger.kernel.org) list.
+
diff --git a/checks.c b/checks.c
index b7955db..9f31d26 100644
--- a/checks.c
+++ b/checks.c
@@ -143,6 +143,14 @@ static void check_nodes_props(struct check *c, struct dt_info *dti, struct node
check_nodes_props(c, dti, child);
}
+static bool is_multiple_of(int multiple, int divisor)
+{
+ if (divisor == 0)
+ return multiple == 0;
+ else
+ return (multiple % divisor) == 0;
+}
+
static bool run_check(struct check *c, struct dt_info *dti)
{
struct node *dt = dti->dt;
@@ -297,19 +305,20 @@ ERROR(duplicate_property_names, check_duplicate_property_names, NULL);
#define LOWERCASE "abcdefghijklmnopqrstuvwxyz"
#define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
#define DIGITS "0123456789"
-#define PROPNODECHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-"
+#define NODECHARS LOWERCASE UPPERCASE DIGITS ",._+-@"
+#define PROPCHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-"
#define PROPNODECHARSSTRICT LOWERCASE UPPERCASE DIGITS ",-"
static void check_node_name_chars(struct check *c, struct dt_info *dti,
struct node *node)
{
- int n = strspn(node->name, c->data);
+ size_t n = strspn(node->name, c->data);
if (n < strlen(node->name))
FAIL(c, dti, node, "Bad character '%c' in node name",
node->name[n]);
}
-ERROR(node_name_chars, check_node_name_chars, PROPNODECHARS "@");
+ERROR(node_name_chars, check_node_name_chars, NODECHARS);
static void check_node_name_chars_strict(struct check *c, struct dt_info *dti,
struct node *node)
@@ -330,6 +339,20 @@ static void check_node_name_format(struct check *c, struct dt_info *dti,
}
ERROR(node_name_format, check_node_name_format, NULL, &node_name_chars);
+static void check_node_name_vs_property_name(struct check *c,
+ struct dt_info *dti,
+ struct node *node)
+{
+ if (!node->parent)
+ return;
+
+ if (get_property(node->parent, node->name)) {
+ FAIL(c, dti, node, "node name and property name conflict");
+ }
+}
+WARNING(node_name_vs_property_name, check_node_name_vs_property_name,
+ NULL, &node_name_chars);
+
static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti,
struct node *node)
{
@@ -363,14 +386,14 @@ static void check_property_name_chars(struct check *c, struct dt_info *dti,
struct property *prop;
for_each_property(node, prop) {
- int n = strspn(prop->name, c->data);
+ size_t n = strspn(prop->name, c->data);
if (n < strlen(prop->name))
FAIL_PROP(c, dti, node, prop, "Bad character '%c' in property name",
prop->name[n]);
}
}
-ERROR(property_name_chars, check_property_name_chars, PROPNODECHARS);
+ERROR(property_name_chars, check_property_name_chars, PROPCHARS);
static void check_property_name_chars_strict(struct check *c,
struct dt_info *dti,
@@ -380,7 +403,7 @@ static void check_property_name_chars_strict(struct check *c,
for_each_property(node, prop) {
const char *name = prop->name;
- int n = strspn(name, c->data);
+ size_t n = strspn(name, c->data);
if (n == strlen(prop->name))
continue;
@@ -497,7 +520,7 @@ static cell_t check_phandle_prop(struct check *c, struct dt_info *dti,
phandle = propval_cell(prop);
- if ((phandle == 0) || (phandle == -1)) {
+ if (!phandle_is_valid(phandle)) {
FAIL_PROP(c, dti, node, prop, "bad value (0x%x) in %s property",
phandle, prop->name);
return 0;
@@ -556,7 +579,7 @@ static void check_name_properties(struct check *c, struct dt_info *dti,
if (!prop)
return; /* No name property, that's fine */
- if ((prop->val.len != node->basenamelen+1)
+ if ((prop->val.len != node->basenamelen + 1U)
|| (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) {
FAIL(c, dti, node, "\"name\" property is incorrect (\"%s\" instead"
" of base node name)", prop->val.val);
@@ -657,7 +680,6 @@ ERROR(omit_unused_nodes, fixup_omit_unused_nodes, NULL, &phandle_references, &pa
*/
WARNING_IF_NOT_CELL(address_cells_is_cell, "#address-cells");
WARNING_IF_NOT_CELL(size_cells_is_cell, "#size-cells");
-WARNING_IF_NOT_CELL(interrupt_cells_is_cell, "#interrupt-cells");
WARNING_IF_NOT_STRING(device_type_is_string, "device_type");
WARNING_IF_NOT_STRING(model_is_string, "model");
@@ -672,8 +694,7 @@ static void check_names_is_string_list(struct check *c, struct dt_info *dti,
struct property *prop;
for_each_property(node, prop) {
- const char *s = strrchr(prop->name, '-');
- if (!s || !streq(s, "-names"))
+ if (!strends(prop->name, "-names"))
continue;
c->data = prop->name;
@@ -753,7 +774,7 @@ static void check_reg_format(struct check *c, struct dt_info *dti,
size_cells = node_size_cells(node->parent);
entrylen = (addr_cells + size_cells) * sizeof(cell_t);
- if (!entrylen || (prop->val.len % entrylen) != 0)
+ if (!is_multiple_of(prop->val.len, entrylen))
FAIL_PROP(c, dti, node, prop, "property has invalid length (%d bytes) "
"(#address-cells == %d, #size-cells == %d)",
prop->val.len, addr_cells, size_cells);
@@ -794,7 +815,7 @@ static void check_ranges_format(struct check *c, struct dt_info *dti,
"#size-cells (%d) differs from %s (%d)",
ranges, c_size_cells, node->parent->fullpath,
p_size_cells);
- } else if ((prop->val.len % entrylen) != 0) {
+ } else if (!is_multiple_of(prop->val.len, entrylen)) {
FAIL_PROP(c, dti, node, prop, "\"%s\" property has invalid length (%d bytes) "
"(parent #address-cells == %d, child #address-cells == %d, "
"#size-cells == %d)", ranges, prop->val.len,
@@ -871,7 +892,7 @@ static void check_pci_device_bus_num(struct check *c, struct dt_info *dti, struc
} else {
cells = (cell_t *)prop->val.val;
min_bus = fdt32_to_cpu(cells[0]);
- max_bus = fdt32_to_cpu(cells[0]);
+ max_bus = fdt32_to_cpu(cells[1]);
}
if ((bus_num < min_bus) || (bus_num > max_bus))
FAIL_PROP(c, dti, node, prop, "PCI bus number %d out of range, expected (%d - %d)",
@@ -891,10 +912,8 @@ static void check_pci_device_reg(struct check *c, struct dt_info *dti, struct no
return;
prop = get_property(node, "reg");
- if (!prop) {
- FAIL(c, dti, node, "missing PCI reg property");
+ if (!prop)
return;
- }
cells = (cell_t *)prop->val.val;
if (cells[1] || cells[2])
@@ -1363,15 +1382,15 @@ struct provider {
};
static void check_property_phandle_args(struct check *c,
- struct dt_info *dti,
- struct node *node,
- struct property *prop,
- const struct provider *provider)
+ struct dt_info *dti,
+ struct node *node,
+ struct property *prop,
+ const struct provider *provider)
{
struct node *root = dti->dt;
- int cell, cellsize = 0;
+ unsigned int cell, cellsize = 0;
- if (prop->val.len % sizeof(cell_t)) {
+ if (!is_multiple_of(prop->val.len, sizeof(cell_t))) {
FAIL_PROP(c, dti, node, prop,
"property size (%d) is invalid, expected multiple of %zu",
prop->val.len, sizeof(cell_t));
@@ -1381,14 +1400,15 @@ static void check_property_phandle_args(struct check *c,
for (cell = 0; cell < prop->val.len / sizeof(cell_t); cell += cellsize + 1) {
struct node *provider_node;
struct property *cellprop;
- int phandle;
+ cell_t phandle;
+ unsigned int expected;
phandle = propval_cell_n(prop, cell);
/*
* Some bindings use a cell value 0 or -1 to skip over optional
* entries when each index position has a specific definition.
*/
- if (phandle == 0 || phandle == -1) {
+ if (!phandle_is_valid(phandle)) {
/* Give up if this is an overlay with external references */
if (dti->dtsflags & DTSF_PLUGIN)
break;
@@ -1431,10 +1451,12 @@ static void check_property_phandle_args(struct check *c,
break;
}
- if (prop->val.len < ((cell + cellsize + 1) * sizeof(cell_t))) {
+ expected = (cell + cellsize + 1) * sizeof(cell_t);
+ if ((expected <= cell) || prop->val.len < expected) {
FAIL_PROP(c, dti, node, prop,
- "property size (%d) too small for cell size %d",
+ "property size (%d) too small for cell size %u",
prop->val.len, cellsize);
+ break;
}
}
}
@@ -1454,7 +1476,8 @@ static void check_provider_cells_property(struct check *c,
}
#define WARNING_PROPERTY_PHANDLE_CELLS(nm, propname, cells_name, ...) \
static struct provider nm##_provider = { (propname), (cells_name), __VA_ARGS__ }; \
- WARNING(nm##_property, check_provider_cells_property, &nm##_provider, &phandle_references);
+ WARNING_IF_NOT_CELL(nm##_is_cell, cells_name); \
+ WARNING(nm##_property, check_provider_cells_property, &nm##_provider, &nm##_is_cell, &phandle_references);
WARNING_PROPERTY_PHANDLE_CELLS(clocks, "clocks", "#clock-cells");
WARNING_PROPERTY_PHANDLE_CELLS(cooling_device, "cooling-device", "#cooling-cells");
@@ -1475,24 +1498,17 @@ WARNING_PROPERTY_PHANDLE_CELLS(thermal_sensors, "thermal-sensors", "#thermal-sen
static bool prop_is_gpio(struct property *prop)
{
- char *str;
-
/*
* *-gpios and *-gpio can appear in property names,
* so skip over any false matches (only one known ATM)
*/
- if (strstr(prop->name, "nr-gpio"))
- return false;
-
- str = strrchr(prop->name, '-');
- if (str)
- str++;
- else
- str = prop->name;
- if (!(streq(str, "gpios") || streq(str, "gpio")))
+ if (strends(prop->name, ",nr-gpios"))
return false;
- return true;
+ return strends(prop->name, "-gpios") ||
+ streq(prop->name, "gpios") ||
+ strends(prop->name, "-gpio") ||
+ streq(prop->name, "gpio");
}
static void check_gpios_property(struct check *c,
@@ -1527,13 +1543,10 @@ static void check_deprecated_gpio_property(struct check *c,
struct property *prop;
for_each_property(node, prop) {
- char *str;
-
if (!prop_is_gpio(prop))
continue;
- str = strstr(prop->name, "gpio");
- if (!streq(str, "gpio"))
+ if (!strends(prop->name, "gpio"))
continue;
FAIL_PROP(c, dti, node, prop,
@@ -1563,21 +1576,106 @@ static void check_interrupt_provider(struct check *c,
struct node *node)
{
struct property *prop;
+ bool irq_provider = node_is_interrupt_provider(node);
- if (!node_is_interrupt_provider(node))
+ prop = get_property(node, "#interrupt-cells");
+ if (irq_provider && !prop) {
+ FAIL(c, dti, node,
+ "Missing '#interrupt-cells' in interrupt provider");
return;
+ }
- prop = get_property(node, "#interrupt-cells");
- if (!prop)
+ if (!irq_provider && prop) {
FAIL(c, dti, node,
- "Missing #interrupt-cells in interrupt provider");
+ "'#interrupt-cells' found, but node is not an interrupt provider");
+ return;
+ }
+}
+WARNING(interrupt_provider, check_interrupt_provider, NULL, &interrupts_extended_is_cell);
- prop = get_property(node, "#address-cells");
- if (!prop)
+static void check_interrupt_map(struct check *c,
+ struct dt_info *dti,
+ struct node *node)
+{
+ struct node *root = dti->dt;
+ struct property *prop, *irq_map_prop;
+ size_t cellsize, cell, map_cells;
+
+ irq_map_prop = get_property(node, "interrupt-map");
+ if (!irq_map_prop)
+ return;
+
+ if (node->addr_cells < 0) {
FAIL(c, dti, node,
- "Missing #address-cells in interrupt provider");
+ "Missing '#address-cells' in interrupt-map provider");
+ return;
+ }
+ cellsize = node_addr_cells(node);
+ cellsize += propval_cell(get_property(node, "#interrupt-cells"));
+
+ prop = get_property(node, "interrupt-map-mask");
+ if (prop && (prop->val.len != (cellsize * sizeof(cell_t))))
+ FAIL_PROP(c, dti, node, prop,
+ "property size (%d) is invalid, expected %zu",
+ prop->val.len, cellsize * sizeof(cell_t));
+
+ if (!is_multiple_of(irq_map_prop->val.len, sizeof(cell_t))) {
+ FAIL_PROP(c, dti, node, irq_map_prop,
+ "property size (%d) is invalid, expected multiple of %zu",
+ irq_map_prop->val.len, sizeof(cell_t));
+ return;
+ }
+
+ map_cells = irq_map_prop->val.len / sizeof(cell_t);
+ for (cell = 0; cell < map_cells; ) {
+ struct node *provider_node;
+ struct property *cellprop;
+ int phandle;
+ size_t parent_cellsize;
+
+ if ((cell + cellsize) >= map_cells) {
+ FAIL_PROP(c, dti, node, irq_map_prop,
+ "property size (%d) too small, expected > %zu",
+ irq_map_prop->val.len, (cell + cellsize) * sizeof(cell_t));
+ break;
+ }
+ cell += cellsize;
+
+ phandle = propval_cell_n(irq_map_prop, cell);
+ if (!phandle_is_valid(phandle)) {
+ /* Give up if this is an overlay with external references */
+ if (!(dti->dtsflags & DTSF_PLUGIN))
+ FAIL_PROP(c, dti, node, irq_map_prop,
+ "Cell %zu is not a phandle(%d)",
+ cell, phandle);
+ break;
+ }
+
+ provider_node = get_node_by_phandle(root, phandle);
+ if (!provider_node) {
+ FAIL_PROP(c, dti, node, irq_map_prop,
+ "Could not get phandle(%d) node for (cell %zu)",
+ phandle, cell);
+ break;
+ }
+
+ cellprop = get_property(provider_node, "#interrupt-cells");
+ if (cellprop) {
+ parent_cellsize = propval_cell(cellprop);
+ } else {
+ FAIL(c, dti, node, "Missing property '#interrupt-cells' in node %s or bad phandle (referred from interrupt-map[%zu])",
+ provider_node->fullpath, cell);
+ break;
+ }
+
+ cellprop = get_property(provider_node, "#address-cells");
+ if (cellprop)
+ parent_cellsize += propval_cell(cellprop);
+
+ cell += 1 + parent_cellsize;
+ }
}
-WARNING(interrupt_provider, check_interrupt_provider, NULL);
+WARNING(interrupt_map, check_interrupt_map, NULL, &phandle_references, &addr_size_cells, &interrupt_provider);
static void check_interrupts_property(struct check *c,
struct dt_info *dti,
@@ -1586,13 +1684,13 @@ static void check_interrupts_property(struct check *c,
struct node *root = dti->dt;
struct node *irq_node = NULL, *parent = node;
struct property *irq_prop, *prop = NULL;
- int irq_cells, phandle;
+ cell_t irq_cells, phandle;
irq_prop = get_property(node, "interrupts");
if (!irq_prop)
return;
- if (irq_prop->val.len % sizeof(cell_t))
+ if (!is_multiple_of(irq_prop->val.len, sizeof(cell_t)))
FAIL_PROP(c, dti, node, irq_prop, "size (%d) is invalid, expected multiple of %zu",
irq_prop->val.len, sizeof(cell_t));
@@ -1605,7 +1703,7 @@ static void check_interrupts_property(struct check *c,
prop = get_property(parent, "interrupt-parent");
if (prop) {
phandle = propval_cell(prop);
- if ((phandle == 0) || (phandle == -1)) {
+ if (!phandle_is_valid(phandle)) {
/* Give up if this is an overlay with
* external references */
if (dti->dtsflags & DTSF_PLUGIN)
@@ -1641,7 +1739,7 @@ static void check_interrupts_property(struct check *c,
}
irq_cells = propval_cell(prop);
- if (irq_prop->val.len % (irq_cells * sizeof(cell_t))) {
+ if (!is_multiple_of(irq_prop->val.len, irq_cells * sizeof(cell_t))) {
FAIL_PROP(c, dti, node, prop,
"size is (%d), expected multiple of %d",
irq_prop->val.len, (int)(irq_cells * sizeof(cell_t)));
@@ -1752,7 +1850,7 @@ WARNING(graph_port, check_graph_port, NULL, &graph_nodes);
static struct node *get_remote_endpoint(struct check *c, struct dt_info *dti,
struct node *endpoint)
{
- int phandle;
+ cell_t phandle;
struct node *node;
struct property *prop;
@@ -1762,7 +1860,7 @@ static struct node *get_remote_endpoint(struct check *c, struct dt_info *dti,
phandle = propval_cell(prop);
/* Give up if this is an overlay with external references */
- if (phandle == 0 || phandle == -1)
+ if (!phandle_is_valid(phandle))
return NULL;
node = get_node_by_phandle(dti->dt, phandle);
@@ -1798,7 +1896,7 @@ WARNING(graph_endpoint, check_graph_endpoint, NULL, &graph_nodes);
static struct check *check_table[] = {
&duplicate_node_names, &duplicate_property_names,
&node_name_chars, &node_name_format, &property_name_chars,
- &name_is_string, &name_properties,
+ &name_is_string, &name_properties, &node_name_vs_property_name,
&duplicate_label,
@@ -1806,7 +1904,7 @@ static struct check *check_table[] = {
&phandle_references, &path_references,
&omit_unused_nodes,
- &address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell,
+ &address_cells_is_cell, &size_cells_is_cell,
&device_type_is_string, &model_is_string, &status_is_string,
&label_is_string,
@@ -1841,26 +1939,43 @@ static struct check *check_table[] = {
&chosen_node_is_root, &chosen_node_bootargs, &chosen_node_stdout_path,
&clocks_property,
+ &clocks_is_cell,
&cooling_device_property,
+ &cooling_device_is_cell,
&dmas_property,
+ &dmas_is_cell,
&hwlocks_property,
+ &hwlocks_is_cell,
&interrupts_extended_property,
+ &interrupts_extended_is_cell,
&io_channels_property,
+ &io_channels_is_cell,
&iommus_property,
+ &iommus_is_cell,
&mboxes_property,
+ &mboxes_is_cell,
&msi_parent_property,
+ &msi_parent_is_cell,
&mux_controls_property,
+ &mux_controls_is_cell,
&phys_property,
+ &phys_is_cell,
&power_domains_property,
+ &power_domains_is_cell,
&pwms_property,
+ &pwms_is_cell,
&resets_property,
+ &resets_is_cell,
&sound_dai_property,
+ &sound_dai_is_cell,
&thermal_sensors_property,
+ &thermal_sensors_is_cell,
&deprecated_gpio_property,
&gpios_property,
&interrupts_property,
&interrupt_provider,
+ &interrupt_map,
&alias_paths,
@@ -1884,7 +1999,7 @@ static void enable_warning_error(struct check *c, bool warn, bool error)
static void disable_warning_error(struct check *c, bool warn, bool error)
{
- int i;
+ unsigned int i;
/* Lowering level, also lower it for things this is the prereq
* for */
@@ -1905,7 +2020,7 @@ static void disable_warning_error(struct check *c, bool warn, bool error)
void parse_checks_option(bool warn, bool error, const char *arg)
{
- int i;
+ unsigned int i;
const char *name = arg;
bool enable = true;
@@ -1932,7 +2047,7 @@ void parse_checks_option(bool warn, bool error, const char *arg)
void process_checks(bool force, struct dt_info *dti)
{
- int i;
+ unsigned int i;
int error = 0;
for (i = 0; i < ARRAY_SIZE(check_table); i++) {
diff --git a/convert-dtsv0-lexer.l b/convert-dtsv0-lexer.l
index f52e8a1..7a66f57 100644
--- a/convert-dtsv0-lexer.l
+++ b/convert-dtsv0-lexer.l
@@ -94,7 +94,7 @@ static const struct {
<INITIAL>[0-9a-fA-F]+ {
unsigned long long val;
int obase = 16, width = 0;
- int i;
+ unsigned int i;
val = strtoull(yytext, NULL, cbase);
diff --git a/data.c b/data.c
index 0a43b6d..1473423 100644
--- a/data.c
+++ b/data.c
@@ -21,10 +21,10 @@ void data_free(struct data d)
free(d.val);
}
-struct data data_grow_for(struct data d, int xlen)
+struct data data_grow_for(struct data d, unsigned int xlen)
{
struct data nd;
- int newsize;
+ unsigned int newsize;
if (xlen == 0)
return d;
@@ -84,7 +84,7 @@ struct data data_copy_file(FILE *f, size_t maxlen)
while (!feof(f) && (d.len < maxlen)) {
size_t chunksize, ret;
- if (maxlen == -1)
+ if (maxlen == (size_t)-1)
chunksize = 4096;
else
chunksize = maxlen - d.len;
diff --git a/dtc-lexer.l b/dtc-lexer.l
index f0faa28..758ce5c 100644
--- a/dtc-lexer.l
+++ b/dtc-lexer.l
@@ -57,7 +57,7 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
push_input_file(name);
}
-<*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)? {
+<*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)* {
char *line, *fnstart, *fnend;
struct data fn;
/* skip text before line # */
@@ -200,7 +200,7 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
return DT_LABEL_REF;
}
-<*>"&{/"{PATHCHAR}*\} { /* new-style path reference */
+<*>"&{"{PATHCHAR}*\} { /* new-style path reference */
yytext[yyleng-1] = '\0';
DPRINT("Ref: %s\n", yytext+2);
yylval.labelref = xstrdup(yytext+2);
diff --git a/dtc-parser.y b/dtc-parser.y
index cf0e361..b4acf7f 100644
--- a/dtc-parser.y
+++ b/dtc-parser.y
@@ -23,6 +23,12 @@ extern void yyerror(char const *s);
extern struct dt_info *parser_output;
extern bool treesource_error;
+
+static bool is_ref_relative(const char *ref)
+{
+ return ref[0] != '/' && strchr(&ref[1], '/');
+}
+
%}
%union {
@@ -169,6 +175,8 @@ devicetree:
*/
if (!($<flags>-1 & DTSF_PLUGIN))
ERROR(&@2, "Label or path %s not found", $1);
+ else if (is_ref_relative($1))
+ ERROR(&@2, "Label-relative reference %s not supported in plugin", $1);
$$ = add_orphan_node(
name_node(build_node(NULL, NULL, NULL),
""),
@@ -178,6 +186,9 @@ devicetree:
{
struct node *target = get_node_by_ref($1, $3);
+ if (($<flags>-1 & DTSF_PLUGIN) && is_ref_relative($3))
+ ERROR(&@2, "Label-relative reference %s not supported in plugin", $3);
+
if (target) {
add_label(&target->labels, $2);
merge_nodes(target, $4);
@@ -193,6 +204,8 @@ devicetree:
* so $-1 is what we want (plugindecl)
*/
if ($<flags>-1 & DTSF_PLUGIN) {
+ if (is_ref_relative($2))
+ ERROR(&@2, "Label-relative reference %s not supported in plugin", $2);
add_orphan_node($1, $3, $2);
} else {
struct node *target = get_node_by_ref($1, $2);
@@ -481,8 +494,8 @@ integer_rela:
;
integer_shift:
- integer_shift DT_LSHIFT integer_add { $$ = $1 << $3; }
- | integer_shift DT_RSHIFT integer_add { $$ = $1 >> $3; }
+ integer_shift DT_LSHIFT integer_add { $$ = ($3 < 64) ? ($1 << $3) : 0; }
+ | integer_shift DT_RSHIFT integer_add { $$ = ($3 < 64) ? ($1 >> $3) : 0; }
| integer_add
;
diff --git a/dtc.c b/dtc.c
index bdb3f59..bc786c5 100644
--- a/dtc.c
+++ b/dtc.c
@@ -12,7 +12,7 @@
* Command line options
*/
int quiet; /* Level of quietness */
-int reservenum; /* Number of memory reservation slots */
+unsigned int reservenum;/* Number of memory reservation slots */
int minsize; /* Minimum blob size */
int padsize; /* Additional padding to blob */
int alignsize; /* Additional padding to blob accroding to the alignsize */
@@ -122,6 +122,8 @@ static const char *guess_type_by_name(const char *fname, const char *fallback)
return "dts";
if (!strcasecmp(s, ".yaml"))
return "yaml";
+ if (!strcasecmp(s, ".dtbo"))
+ return "dtb";
if (!strcasecmp(s, ".dtb"))
return "dtb";
return fallback;
@@ -195,7 +197,7 @@ int main(int argc, char *argv[])
depname = optarg;
break;
case 'R':
- reservenum = strtol(optarg, NULL, 0);
+ reservenum = strtoul(optarg, NULL, 0);
break;
case 'S':
minsize = strtol(optarg, NULL, 0);
diff --git a/dtc.h b/dtc.h
index a08f415..0a1f549 100644
--- a/dtc.h
+++ b/dtc.h
@@ -35,7 +35,7 @@
* Command line options
*/
extern int quiet; /* Level of quietness */
-extern int reservenum; /* Number of memory reservation slots */
+extern unsigned int reservenum; /* Number of memory reservation slots */
extern int minsize; /* Minimum blob size */
extern int padsize; /* Additional padding to blob */
extern int alignsize; /* Additional padding to blob accroding to the alignsize */
@@ -51,6 +51,11 @@ extern int annotate; /* annotate .dts with input source location */
typedef uint32_t cell_t;
+static inline bool phandle_is_valid(cell_t phandle)
+{
+ return phandle != 0 && phandle != ~0U;
+}
+
static inline uint16_t dtb_ld16(const void *p)
{
const uint8_t *bp = (const uint8_t *)p;
@@ -86,6 +91,16 @@ static inline uint64_t dtb_ld64(const void *p)
#define streq(a, b) (strcmp((a), (b)) == 0)
#define strstarts(s, prefix) (strncmp((s), (prefix), strlen(prefix)) == 0)
#define strprefixeq(a, n, b) (strlen(b) == (n) && (memcmp(a, b, n) == 0))
+static inline bool strends(const char *str, const char *suffix)
+{
+ unsigned int len, suffix_len;
+
+ len = strlen(str);
+ suffix_len = strlen(suffix);
+ if (len < suffix_len)
+ return false;
+ return streq(str + len - suffix_len, suffix);
+}
#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
@@ -101,17 +116,23 @@ enum markertype {
TYPE_UINT64,
TYPE_STRING,
};
+
+static inline bool is_type_marker(enum markertype type)
+{
+ return type >= TYPE_UINT8;
+}
+
extern const char *markername(enum markertype markertype);
struct marker {
enum markertype type;
- int offset;
+ unsigned int offset;
char *ref;
struct marker *next;
};
struct data {
- int len;
+ unsigned int len;
char *val;
struct marker *markers;
};
@@ -125,11 +146,26 @@ struct data {
for_each_marker(m) \
if ((m)->type == (t))
-size_t type_marker_length(struct marker *m);
+static inline struct marker *next_type_marker(struct marker *m)
+{
+ for_each_marker(m)
+ if (is_type_marker(m->type))
+ break;
+ return m;
+}
+
+static inline size_t type_marker_length(struct marker *m)
+{
+ struct marker *next = next_type_marker(m->next);
+
+ if (next)
+ return next->offset - m->offset;
+ return 0;
+}
void data_free(struct data d);
-struct data data_grow_for(struct data d, int xlen);
+struct data data_grow_for(struct data d, unsigned int xlen);
struct data data_copy_mem(const char *mem, int len);
struct data data_copy_escape_string(const char *s, int len);
@@ -253,7 +289,7 @@ void append_to_property(struct node *node,
const char *get_unitname(struct node *node);
struct property *get_property(struct node *node, const char *propname);
cell_t propval_cell(struct property *prop);
-cell_t propval_cell_n(struct property *prop, int n);
+cell_t propval_cell_n(struct property *prop, unsigned int n);
struct property *get_property_by_label(struct node *tree, const char *label,
struct node **node);
struct marker *get_marker_label(struct node *tree, const char *label,
diff --git a/fdtdump.c b/fdtdump.c
index 9613bef..d424869 100644
--- a/fdtdump.c
+++ b/fdtdump.c
@@ -18,10 +18,10 @@
#include "util.h"
#define FDT_MAGIC_SIZE 4
-#define MAX_VERSION 17
+#define MAX_VERSION 17U
#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
-#define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a))))
+#define PALIGN(p, a) ((void *)(ALIGN((uintptr_t)(p), (a))))
#define GET_CELL(p) (p += 4, *((const fdt32_t *)(p-4)))
static const char *tagname(uint32_t tag)
@@ -163,7 +163,7 @@ static const char * const usage_opts_help[] = {
USAGE_COMMON_OPTS_HELP
};
-static bool valid_header(char *p, off_t len)
+static bool valid_header(char *p, size_t len)
{
if (len < sizeof(struct fdt_header) ||
fdt_magic(p) != FDT_MAGIC ||
@@ -217,7 +217,7 @@ int main(int argc, char *argv[])
char *p = buf;
char *endp = buf + len;
- fdt_set_magic(smagic, FDT_MAGIC);
+ fdt32_st(smagic, FDT_MAGIC);
/* poor man's memmem */
while ((endp - p) >= FDT_MAGIC_SIZE) {
@@ -235,7 +235,7 @@ int main(int argc, char *argv[])
}
++p;
}
- if (!p || endp - p < sizeof(struct fdt_header))
+ if (!p || (size_t)(endp - p) < sizeof(struct fdt_header))
die("%s: could not locate fdt magic\n", file);
printf("%s: found fdt at offset %#tx\n", file, p - buf);
buf = p;
diff --git a/fdtget.c b/fdtget.c
index 777582e..dd70985 100644
--- a/fdtget.c
+++ b/fdtget.c
@@ -62,8 +62,14 @@ static int show_cell_list(struct display_info *disp, const char *data, int len,
for (i = 0; i < len; i += size, p += size) {
if (i)
printf(" ");
- value = size == 4 ? fdt32_ld((const fdt32_t *)p) :
- size == 2 ? (*p << 8) | p[1] : *p;
+ switch (size) {
+ case 4: value = fdt32_ld((const fdt32_t *)p); break;
+ case 2: value = fdt16_ld((const fdt16_t *)p); break;
+ case 1:
+ default:
+ value = *p;
+ break;
+ }
printf(fmt, value);
}
@@ -91,6 +97,11 @@ static int show_data(struct display_info *disp, const char *data, int len)
if (len == 0)
return 0;
+ if (disp->type == 'r') {
+ fwrite(data, 1, len, stdout);
+ return 0;
+ }
+
is_string = (disp->type) == 's' ||
(!disp->type && util_is_printable_string(data, len));
if (is_string) {
diff --git a/fdtput.c b/fdtput.c
index 428745a..c2fecf4 100644
--- a/fdtput.c
+++ b/fdtput.c
@@ -433,6 +433,8 @@ int main(int argc, char *argv[])
if (utilfdt_decode_type(optarg, &disp.type,
&disp.size))
usage("Invalid type string");
+ if (disp.type == 'r')
+ usage("Unsupported raw data type");
break;
case 'v':
diff --git a/flattree.c b/flattree.c
index 07f10d2..95e43d3 100644
--- a/flattree.c
+++ b/flattree.c
@@ -124,7 +124,8 @@ static void asm_emit_cell(void *e, cell_t val)
{
FILE *f = e;
- fprintf(f, "\t.byte 0x%02x; .byte 0x%02x; .byte 0x%02x; .byte 0x%02x\n",
+ fprintf(f, "\t.byte\t0x%02x\n" "\t.byte\t0x%02x\n"
+ "\t.byte\t0x%02x\n" "\t.byte\t0x%02x\n",
(val >> 24) & 0xff, (val >> 16) & 0xff,
(val >> 8) & 0xff, val & 0xff);
}
@@ -134,9 +135,9 @@ static void asm_emit_string(void *e, const char *str, int len)
FILE *f = e;
if (len != 0)
- fprintf(f, "\t.string\t\"%.*s\"\n", len, str);
+ fprintf(f, "\t.asciz\t\"%.*s\"\n", len, str);
else
- fprintf(f, "\t.string\t\"%s\"\n", str);
+ fprintf(f, "\t.asciz\t\"%s\"\n", str);
}
static void asm_emit_align(void *e, int a)
@@ -149,7 +150,7 @@ static void asm_emit_align(void *e, int a)
static void asm_emit_data(void *e, struct data d)
{
FILE *f = e;
- int off = 0;
+ unsigned int off = 0;
struct marker *m = d.markers;
for_each_marker_of_type(m, LABEL)
@@ -219,7 +220,7 @@ static struct emitter asm_emitter = {
static int stringtable_insert(struct data *d, const char *str)
{
- int i;
+ unsigned int i;
/* FIXME: do this more efficiently? */
@@ -295,7 +296,7 @@ static struct data flatten_reserve_list(struct reserve_info *reservelist,
{
struct reserve_info *re;
struct data d = empty_data;
- int j;
+ unsigned int j;
for (re = reservelist; re; re = re->next) {
d = data_append_re(d, re->address, re->size);
@@ -345,7 +346,7 @@ static void make_fdt_header(struct fdt_header *fdt,
void dt_to_blob(FILE *f, struct dt_info *dti, int version)
{
struct version_info *vi = NULL;
- int i;
+ unsigned int i;
struct data blob = empty_data;
struct data reservebuf = empty_data;
struct data dtbuf = empty_data;
@@ -438,7 +439,7 @@ static void dump_stringtable_asm(FILE *f, struct data strbuf)
while (p < (strbuf.val + strbuf.len)) {
len = strlen(p);
- fprintf(f, "\t.string \"%s\"\n", p);
+ fprintf(f, "\t.asciz \"%s\"\n", p);
p += len+1;
}
}
@@ -446,7 +447,7 @@ static void dump_stringtable_asm(FILE *f, struct data strbuf)
void dt_to_asm(FILE *f, struct dt_info *dti, int version)
{
struct version_info *vi = NULL;
- int i;
+ unsigned int i;
struct data strbuf = empty_data;
struct reserve_info *re;
const char *symprefix = "dt";
diff --git a/fuzzing/Android.bp b/fuzzing/Android.bp
index ddda130..857c611 100644
--- a/fuzzing/Android.bp
+++ b/fuzzing/Android.bp
@@ -6,10 +6,17 @@ package {
cc_fuzz {
name: "libfdt_fuzzer",
srcs: [
- "libfdt_fuzzer.cpp",
+ "libfdt_fuzzer.c",
],
static_libs: [
"libfdt",
],
+ corpus: ["corpus/*"],
+ fuzz_config: {
+ cc: [
+ "ptosi@google.com",
+ ],
+ },
host_supported: true,
}
+
diff --git a/fuzzing/corpus/crash-a5b94d95681291f3057eea7f0233c8f1529b2f59 b/fuzzing/corpus/crash-a5b94d95681291f3057eea7f0233c8f1529b2f59
new file mode 100644
index 0000000..dbab42e
--- /dev/null
+++ b/fuzzing/corpus/crash-a5b94d95681291f3057eea7f0233c8f1529b2f59
Binary files differ
diff --git a/fuzzing/corpus/hardy-octopus b/fuzzing/corpus/hardy-octopus
new file mode 100644
index 0000000..81615e9
--- /dev/null
+++ b/fuzzing/corpus/hardy-octopus
Binary files differ
diff --git a/fuzzing/corpus/header-truncated b/fuzzing/corpus/header-truncated
new file mode 100644
index 0000000..1db29d8
--- /dev/null
+++ b/fuzzing/corpus/header-truncated
Binary files differ
diff --git a/fuzzing/corpus/header-v-1 b/fuzzing/corpus/header-v-1
new file mode 100644
index 0000000..a773d07
--- /dev/null
+++ b/fuzzing/corpus/header-v-1
Binary files differ
diff --git a/fuzzing/corpus/header-v0 b/fuzzing/corpus/header-v0
new file mode 100644
index 0000000..f22ec6a
--- /dev/null
+++ b/fuzzing/corpus/header-v0
Binary files differ
diff --git a/fuzzing/corpus/meson-g12a-sei510-android.dtb b/fuzzing/corpus/meson-g12a-sei510-android.dtb
new file mode 100644
index 0000000..317175d
--- /dev/null
+++ b/fuzzing/corpus/meson-g12a-sei510-android.dtb
Binary files differ
diff --git a/fuzzing/corpus/oob_by_one b/fuzzing/corpus/oob_by_one
new file mode 100644
index 0000000..216523c
--- /dev/null
+++ b/fuzzing/corpus/oob_by_one
Binary files differ
diff --git a/fuzzing/corpus/quirks.dtb b/fuzzing/corpus/quirks.dtb
new file mode 100644
index 0000000..676024a
--- /dev/null
+++ b/fuzzing/corpus/quirks.dtb
Binary files differ
diff --git a/fuzzing/libfdt_fuzzer.c b/fuzzing/libfdt_fuzzer.c
new file mode 100644
index 0000000..b271714
--- /dev/null
+++ b/fuzzing/libfdt_fuzzer.c
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Ensure assert() catches logical errors during fuzzing */
+#ifdef NDEBUG
+#undef NDEBUG
+#endif
+
+#include <inttypes.h>
+#include <assert.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <sanitizer/asan_interface.h>
+#include <sanitizer/msan_interface.h>
+
+#include "libfdt.h"
+#include "libfdt_env.h"
+
+/* check memory region is valid, for the purpose of tooling such as asan */
+static void check_mem(const void *mem, size_t len) {
+
+ assert(mem);
+
+#if __has_feature(memory_sanitizer)
+ /* dumps if check fails */
+ __msan_check_mem_is_initialized((void *)mem, len);
+#endif
+
+#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
+ assert(!__asan_region_is_poisoned((void *)mem, len));
+#else
+ const volatile uint8_t *mem8 = mem;
+
+ /* Read each byte of memory for instrumentation */
+ for(size_t i = 0; i < len; i++) {
+ (void)mem8[i];
+ }
+#endif
+}
+
+static bool phandle_is_valid(uint32_t phandle) {
+ return phandle != 0 && phandle != UINT32_MAX;
+}
+
+static void walk_node_properties(const void *device_tree, int node) {
+ int property, len = 0;
+
+ fdt_for_each_property_offset(property, device_tree, node) {
+ const struct fdt_property *prop = fdt_get_property_by_offset(device_tree,
+ property, &len);
+ if (!prop)
+ continue;
+ check_mem(prop->data, fdt32_to_cpu(prop->len));
+
+ const char *prop_name = fdt_string(device_tree, prop->nameoff);
+ if (prop_name != NULL) {
+ check_mem(prop_name, strlen(prop_name));
+ }
+ }
+}
+
+
+static void walk_device_tree(const void *device_tree, int parent_node) {
+ int len = 0;
+ const char *node_name = fdt_get_name(device_tree, parent_node, &len);
+ if (node_name != NULL) {
+ check_mem(node_name, len);
+ }
+
+ uint32_t phandle = fdt_get_phandle(device_tree, parent_node);
+ if (phandle_is_valid(phandle)) {
+ int node = fdt_node_offset_by_phandle(device_tree, phandle);
+ assert(node >= 0); // it should at least find parent_node
+ }
+
+ char path_buf[64];
+ if(fdt_get_path(device_tree, parent_node, path_buf, sizeof(path_buf)) == 0) {
+ fdt_path_offset(device_tree, path_buf);
+ }
+
+ fdt_parent_offset(device_tree, parent_node);
+
+ // Exercise sub-node search string functions
+ fdt_subnode_offset(device_tree, parent_node, "a");
+ fdt_get_property(device_tree, parent_node, "reg", &len);
+
+ // Check for a stringlist node called 'stringlist' (added to corpus)
+ const int sl_count = fdt_stringlist_count(device_tree,
+ parent_node, "stringlist");
+ if (sl_count > 0) {
+ for (int i = 0; i < sl_count; i++) {
+ fdt_stringlist_get(device_tree, parent_node, "stringlist", i, &len);
+ }
+
+ fdt_stringlist_search(device_tree, parent_node, "stringlist", "a");
+ }
+
+ walk_node_properties(device_tree, parent_node);
+
+ // recursively walk the node's children
+ for (int node = fdt_first_subnode(device_tree, parent_node); node >= 0;
+ node = fdt_next_subnode(device_tree, node)) {
+ walk_device_tree(device_tree, node);
+ }
+}
+
+
+static void walk_mem_rsv(const void *device_tree) {
+ const int n = fdt_num_mem_rsv(device_tree);
+ uint64_t address, size;
+
+ for (int i = 0; i < n; i++) {
+ fdt_get_mem_rsv(device_tree, i, &address, &size);
+ }
+}
+
+
+// Information on device tree is available in external/dtc/Documentation/
+// folder.
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ int rc;
+
+ // Non-zero return values are reserved for future use.
+ if (size < FDT_V17_SIZE) return 0;
+
+ // Produce coverage of checking function
+ rc = fdt_check_full(data, size);
+ fdt_strerror(rc);
+
+ // Don't continue if the library rejected the input
+ if (rc != 0) return 0;
+
+ // Cover reading functions
+ walk_device_tree(data, /* parent_node */ 0);
+ walk_mem_rsv(data);
+
+ // Cover phandle functions
+ uint32_t phandle;
+ fdt_generate_phandle(data, &phandle);
+
+ // Try and get a path by alias
+ fdt_path_offset(data, "a");
+
+ // Try to get an alias
+ fdt_get_alias(data, "a");
+
+ // Exercise common search functions
+ fdt_node_offset_by_compatible(data, 0, "a");
+ fdt_node_offset_by_prop_value(data, 0, "x", "42", 3);
+
+ return 0;
+}
+
diff --git a/fuzzing/libfdt_fuzzer.cpp b/fuzzing/libfdt_fuzzer.cpp
deleted file mode 100644
index 4a0b1fc..0000000
--- a/fuzzing/libfdt_fuzzer.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-#include <assert.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "libfdt.h"
-#include "libfdt_env.h"
-
-void walk_device_tree(const void *device_tree, int parent_node) {
- int len = 0;
- const char *node_name = fdt_get_name(device_tree, parent_node, &len);
- if (node_name != NULL) {
- // avoid clang complaining about unused variable node_name and force
- // ASan to validate string pointer in strlen call.
- assert(strlen(node_name) == len);
- }
-
- uint32_t phandle = fdt_get_phandle(device_tree, parent_node);
- if (phandle != 0) {
- assert(parent_node == fdt_node_offset_by_phandle(device_tree, phandle));
- }
-
- // recursively walk the node's children
- for (int node = fdt_first_subnode(device_tree, parent_node); node >= 0;
- node = fdt_next_subnode(device_tree, node)) {
- walk_device_tree(device_tree, node);
- }
-}
-
-// Information on device tree is available in external/dtc/Documentation/
-// folder.
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- // Non-zero return values are reserved for future use.
- if (size < FDT_V17_SIZE) return 0;
-
- if (fdt_check_header(data) != 0) return 0;
-
- int root_node_offset = 0;
- walk_device_tree(data, root_node_offset);
-
- return 0;
-} \ No newline at end of file
diff --git a/libfdt/Android.bp b/libfdt/Android.bp
index 8f729b4..8f4bdfd 100644
--- a/libfdt/Android.bp
+++ b/libfdt/Android.bp
@@ -1,11 +1,7 @@
package {
// See: http://go/android-license-faq
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "external_dtc_license"
- // to get the below license kinds:
- // SPDX-license-identifier-BSD
// SPDX-license-identifier-BSD-2-Clause
- default_applicable_licenses: ["external_dtc_license"],
+ default_applicable_licenses: ["external_dtc_libfdt_license"],
}
cc_library {
diff --git a/libfdt/acpi.c b/libfdt/acpi.c
index ba51734..5869726 100644
--- a/libfdt/acpi.c
+++ b/libfdt/acpi.c
@@ -31,13 +31,10 @@
#include "libacpi.h"
uint8_t acpi_csum(const void *base, int n) {
- uint8_t *p;
- uint8_t sum;
+ const uint8_t *p = base;
+ uint8_t sum = 0;
int bytesDone;
- p = (uint8_t*)base;
-
- sum = 0;
for (bytesDone = 0; bytesDone < n; bytesDone++) {
sum += *p;
p++;
diff --git a/libfdt/fdt.c b/libfdt/fdt.c
index c28fcc1..c17cad5 100644
--- a/libfdt/fdt.c
+++ b/libfdt/fdt.c
@@ -22,6 +22,10 @@ int32_t fdt_ro_probe_(const void *fdt)
if (can_assume(VALID_DTB))
return totalsize;
+ /* The device tree must be at an 8-byte aligned address */
+ if ((uintptr_t)fdt & 7)
+ return -FDT_ERR_ALIGNMENT;
+
if (fdt_magic(fdt) == FDT_MAGIC) {
/* Complete tree */
if (!can_assume(LATEST)) {
@@ -86,6 +90,10 @@ int fdt_check_header(const void *fdt)
{
size_t hdrsize;
+ /* The device tree must be at an 8-byte aligned address */
+ if ((uintptr_t)fdt & 7)
+ return -FDT_ERR_ALIGNMENT;
+
if (fdt_magic(fdt) != FDT_MAGIC)
return -FDT_ERR_BADMAGIC;
if (!can_assume(LATEST)) {
@@ -134,16 +142,20 @@ int fdt_check_header(const void *fdt)
const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
{
- unsigned absoffset = offset + fdt_off_dt_struct(fdt);
+ unsigned int uoffset = offset;
+ unsigned int absoffset = offset + fdt_off_dt_struct(fdt);
+
+ if (offset < 0)
+ return NULL;
if (!can_assume(VALID_INPUT))
- if ((absoffset < offset)
+ if ((absoffset < uoffset)
|| ((absoffset + len) < absoffset)
|| (absoffset + len) > fdt_totalsize(fdt))
return NULL;
if (can_assume(LATEST) || fdt_version(fdt) >= 0x11)
- if (((offset + len) < offset)
+ if (((uoffset + len) < uoffset)
|| ((offset + len) > fdt_size_dt_struct(fdt)))
return NULL;
@@ -176,12 +188,20 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
break;
case FDT_PROP:
- lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
+ lenp = fdt_offset_ptr(fdt, offset, sizeof(struct fdt_property) - FDT_TAGSIZE);
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);
+
+ /* skip name offset, length */
+ offset += sizeof(struct fdt_property) - FDT_TAGSIZE;
+
+ if (!can_assume(VALID_DTB)
+ && !fdt_offset_ptr(fdt, offset, fdt32_to_cpu(*lenp)))
+ return FDT_END; /* premature end */
+
+ /* skip value */
+ offset += fdt32_to_cpu(*lenp);
+
if (!can_assume(LATEST) &&
fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 &&
((offset - fdt32_to_cpu(*lenp)) % 8) != 0)
@@ -197,7 +217,8 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
return FDT_END;
}
- if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset))
+ if (!can_assume(VALID_DTB) && (offset <= startoffset
+ || !fdt_offset_ptr(fdt, startoffset, offset - startoffset)))
return FDT_END; /* premature end */
*nextoffset = FDT_TAGALIGN(offset);
@@ -206,10 +227,11 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
int fdt_check_node_offset_(const void *fdt, int offset)
{
- if (can_assume(VALID_INPUT))
- return offset;
- if ((offset < 0) || (offset % FDT_TAGSIZE)
- || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE))
+ if (!can_assume(VALID_INPUT)
+ && ((offset < 0) || (offset % FDT_TAGSIZE)))
+ return -FDT_ERR_BADOFFSET;
+
+ if (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE)
return -FDT_ERR_BADOFFSET;
return offset;
@@ -217,8 +239,11 @@ int fdt_check_node_offset_(const void *fdt, int offset)
int fdt_check_prop_offset_(const void *fdt, int offset)
{
- if ((offset < 0) || (offset % FDT_TAGSIZE)
- || (fdt_next_tag(fdt, offset, &offset) != FDT_PROP))
+ if (!can_assume(VALID_INPUT)
+ && ((offset < 0) || (offset % FDT_TAGSIZE)))
+ return -FDT_ERR_BADOFFSET;
+
+ if (fdt_next_tag(fdt, offset, &offset) != FDT_PROP)
return -FDT_ERR_BADOFFSET;
return offset;
@@ -306,9 +331,12 @@ const char *fdt_find_string_(const char *strtab, int tabsize, const char *s)
int fdt_move(const void *fdt, void *buf, int bufsize)
{
+ if (!can_assume(VALID_INPUT) && bufsize < 0)
+ return -FDT_ERR_NOSPACE;
+
FDT_RO_PROBE(fdt);
- if (fdt_totalsize(fdt) > bufsize)
+ if (fdt_totalsize(fdt) > (unsigned int)bufsize)
return -FDT_ERR_NOSPACE;
memmove(buf, fdt, fdt_totalsize(fdt));
diff --git a/libfdt/fdt_addresses.c b/libfdt/fdt_addresses.c
index 9a82cd0..c40ba09 100644
--- a/libfdt/fdt_addresses.c
+++ b/libfdt/fdt_addresses.c
@@ -73,7 +73,7 @@ int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset,
/* check validity of address */
prop = data;
if (addr_cells == 1) {
- if ((addr > UINT32_MAX) || ((UINT32_MAX + 1 - addr) < size))
+ if ((addr > UINT32_MAX) || (((uint64_t) UINT32_MAX + 1 - addr) < size))
return -FDT_ERR_BADVALUE;
fdt32_st(prop, (uint32_t)addr);
diff --git a/libfdt/fdt_check.c b/libfdt/fdt_check.c
index 7f6a96c..71390ee 100644
--- a/libfdt/fdt_check.c
+++ b/libfdt/fdt_check.c
@@ -19,9 +19,12 @@ int fdt_check_full(const void *fdt, size_t bufsize)
unsigned int depth = 0;
const void *prop;
const char *propname;
+ bool expect_end = false;
if (bufsize < FDT_V1_SIZE)
return -FDT_ERR_TRUNCATED;
+ if (bufsize < fdt_header_size(fdt))
+ return -FDT_ERR_TRUNCATED;
err = fdt_check_header(fdt);
if (err != 0)
return err;
@@ -39,6 +42,10 @@ int fdt_check_full(const void *fdt, size_t bufsize)
if (nextoffset < 0)
return nextoffset;
+ /* If we see two root nodes, something is wrong */
+ if (expect_end && tag != FDT_END)
+ return -FDT_ERR_BADSTRUCTURE;
+
switch (tag) {
case FDT_NOP:
break;
@@ -52,12 +59,24 @@ int fdt_check_full(const void *fdt, size_t bufsize)
depth++;
if (depth > INT_MAX)
return -FDT_ERR_BADSTRUCTURE;
+
+ /* The root node must have an empty name */
+ if (depth == 1) {
+ const char *name;
+ int len;
+
+ name = fdt_get_name(fdt, offset, &len);
+ if (!name || *name || len)
+ return -FDT_ERR_BADSTRUCTURE;
+ }
break;
case FDT_END_NODE:
if (depth == 0)
return -FDT_ERR_BADSTRUCTURE;
depth--;
+ if (depth == 0)
+ expect_end = true;
break;
case FDT_PROP:
diff --git a/libfdt/fdt_overlay.c b/libfdt/fdt_overlay.c
index b310e49..5c0c398 100644
--- a/libfdt/fdt_overlay.c
+++ b/libfdt/fdt_overlay.c
@@ -40,37 +40,22 @@ static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
return fdt32_to_cpu(*val);
}
-/**
- * overlay_get_target - retrieves the offset of a fragment's target
- * @fdt: Base device tree blob
- * @fdto: Device tree overlay blob
- * @fragment: node offset of the fragment in the overlay
- * @pathp: pointer which receives the path of the target (or NULL)
- *
- * overlay_get_target() retrieves the target offset in the base
- * device tree of a fragment, no matter how the actual targeting is
- * done (through a phandle or a path)
- *
- * returns:
- * the targeted node offset in the base device tree
- * Negative error code on error
- */
-static int overlay_get_target(const void *fdt, const void *fdto,
- int fragment, char const **pathp)
+int fdt_overlay_target_offset(const void *fdt, const void *fdto,
+ int fragment_offset, char const **pathp)
{
uint32_t phandle;
const char *path = NULL;
int path_len = 0, ret;
/* Try first to do a phandle based lookup */
- phandle = overlay_get_target_phandle(fdto, fragment);
+ phandle = overlay_get_target_phandle(fdto, fragment_offset);
if (phandle == (uint32_t)-1)
return -FDT_ERR_BADPHANDLE;
/* no phandle, try path */
if (!phandle) {
/* And then a path based lookup */
- path = fdt_getprop(fdto, fragment, "target-path", &path_len);
+ path = fdt_getprop(fdto, fragment_offset, "target-path", &path_len);
if (path)
ret = fdt_path_offset(fdt, path);
else
@@ -241,6 +226,7 @@ static int overlay_update_local_node_references(void *fdto,
if (fixup_len % sizeof(uint32_t))
return -FDT_ERR_BADOVERLAY;
+ fixup_len /= sizeof(uint32_t);
tree_val = fdt_getprop(fdto, tree_node, name, &tree_len);
if (!tree_val) {
@@ -250,7 +236,7 @@ static int overlay_update_local_node_references(void *fdto,
return tree_len;
}
- for (i = 0; i < (fixup_len / sizeof(uint32_t)); i++) {
+ for (i = 0; i < fixup_len; i++) {
fdt32_t adj_val;
uint32_t poffset;
@@ -635,7 +621,7 @@ static int overlay_merge(void *fdt, void *fdto)
if (overlay < 0)
return overlay;
- target = overlay_get_target(fdt, fdto, fragment, NULL);
+ target = fdt_overlay_target_offset(fdt, fdto, fragment, NULL);
if (target < 0)
return target;
@@ -778,7 +764,7 @@ static int overlay_symbol_update(void *fdt, void *fdto)
return -FDT_ERR_BADOVERLAY;
/* get the target of the fragment */
- ret = overlay_get_target(fdt, fdto, fragment, &target_path);
+ ret = fdt_overlay_target_offset(fdt, fdto, fragment, &target_path);
if (ret < 0)
return ret;
target = ret;
@@ -800,7 +786,7 @@ static int overlay_symbol_update(void *fdt, void *fdto)
if (!target_path) {
/* again in case setprop_placeholder changed it */
- ret = overlay_get_target(fdt, fdto, fragment, &target_path);
+ ret = fdt_overlay_target_offset(fdt, fdto, fragment, &target_path);
if (ret < 0)
return ret;
target = ret;
diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c
index e03570a..a62ec78 100644
--- a/libfdt/fdt_ro.c
+++ b/libfdt/fdt_ro.c
@@ -10,6 +10,14 @@
#include "libfdt_internal.h"
+/* Check if a buffer contains a nul-terminated string.
+ * Used for checking property values which should be strings.
+ */
+static bool is_nul_string(const char *buf, const size_t buf_len) {
+ return buf_len > 0 && buf[buf_len - 1] == '\0' &&
+ strnlen(buf, buf_len) == buf_len - 1;
+}
+
static int fdt_nodename_eq_(const void *fdt, int offset,
const char *s, int len)
{
@@ -53,7 +61,7 @@ const char *fdt_get_string(const void *fdt, int stroffset, int *lenp)
err = -FDT_ERR_BADOFFSET;
absoffset = stroffset + fdt_off_dt_strings(fdt);
- if (absoffset >= totalsize)
+ if (absoffset >= (unsigned)totalsize)
goto fail;
len = totalsize - absoffset;
@@ -61,17 +69,19 @@ const char *fdt_get_string(const void *fdt, int stroffset, int *lenp)
if (stroffset < 0)
goto fail;
if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
- if (stroffset >= fdt_size_dt_strings(fdt))
+ if ((unsigned)stroffset >= fdt_size_dt_strings(fdt))
goto fail;
if ((fdt_size_dt_strings(fdt) - stroffset) < len)
len = fdt_size_dt_strings(fdt) - stroffset;
}
} else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
- if ((stroffset >= 0)
- || (stroffset < -fdt_size_dt_strings(fdt)))
+ unsigned int sw_stroffset = -stroffset;
+
+ if ((stroffset >= 0) ||
+ (sw_stroffset > fdt_size_dt_strings(fdt)))
goto fail;
- if ((-stroffset) < len)
- len = -stroffset;
+ if (sw_stroffset < len)
+ len = sw_stroffset;
} else {
err = -FDT_ERR_INTERNAL;
goto fail;
@@ -157,8 +167,8 @@ int fdt_generate_phandle(const void *fdt, uint32_t *phandle)
static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n)
{
- int offset = n * sizeof(struct fdt_reserve_entry);
- int absoffset = fdt_off_mem_rsvmap(fdt) + offset;
+ unsigned int offset = n * sizeof(struct fdt_reserve_entry);
+ unsigned int absoffset = fdt_off_mem_rsvmap(fdt) + offset;
if (!can_assume(VALID_INPUT)) {
if (absoffset < fdt_off_mem_rsvmap(fdt))
@@ -179,8 +189,8 @@ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
if (!can_assume(VALID_INPUT) && !re)
return -FDT_ERR_BADOFFSET;
- *address = fdt64_ld(&re->address);
- *size = fdt64_ld(&re->size);
+ *address = fdt64_ld_(&re->address);
+ *size = fdt64_ld_(&re->size);
return 0;
}
@@ -190,7 +200,7 @@ int fdt_num_mem_rsv(const void *fdt)
const struct fdt_reserve_entry *re;
for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) {
- if (fdt64_ld(&re->size) == 0)
+ if (fdt64_ld_(&re->size) == 0)
return i;
}
return -FDT_ERR_TRUNCATED;
@@ -253,6 +263,12 @@ int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen)
FDT_RO_PROBE(fdt);
+ if (namelen < 1)
+ return -FDT_ERR_BADPATH;
+
+ if (namelen < 1)
+ return -FDT_ERR_BADPATH;
+
/* see if we have an alias */
if (*path != '/') {
const char *q = memchr(path, '/', end - p);
@@ -368,7 +384,7 @@ static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt,
prop = fdt_offset_ptr_(fdt, offset);
if (lenp)
- *lenp = fdt32_ld(&prop->len);
+ *lenp = fdt32_ld_(&prop->len);
return prop;
}
@@ -406,7 +422,7 @@ static const struct fdt_property *fdt_get_property_namelen_(const void *fdt,
offset = -FDT_ERR_INTERNAL;
break;
}
- if (fdt_string_eq_(fdt, fdt32_ld(&prop->nameoff),
+ if (fdt_string_eq_(fdt, fdt32_ld_(&prop->nameoff),
name, namelen)) {
if (poffset)
*poffset = offset;
@@ -459,7 +475,7 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
/* Handle realignment */
if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
- (poffset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
+ (poffset + sizeof(*prop)) % 8 && fdt32_ld_(&prop->len) >= 8)
return prop->data + 4;
return prop->data;
}
@@ -477,22 +493,22 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
int namelen;
if (!can_assume(VALID_INPUT)) {
- name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff),
+ name = fdt_get_string(fdt, fdt32_ld_(&prop->nameoff),
&namelen);
+ *namep = name;
if (!name) {
if (lenp)
*lenp = namelen;
return NULL;
}
- *namep = name;
} else {
- *namep = fdt_string(fdt, fdt32_ld(&prop->nameoff));
+ *namep = fdt_string(fdt, fdt32_ld_(&prop->nameoff));
}
}
/* Handle realignment */
if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
- (offset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
+ (offset + sizeof(*prop)) % 8 && fdt32_ld_(&prop->len) >= 8)
return prop->data + 4;
return prop->data;
}
@@ -517,19 +533,33 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
return 0;
}
- return fdt32_ld(php);
+ return fdt32_ld_(php);
}
const char *fdt_get_alias_namelen(const void *fdt,
const char *name, int namelen)
{
+ const char *prop;
int aliasoffset;
+ int prop_len;
aliasoffset = fdt_path_offset(fdt, "/aliases");
if (aliasoffset < 0)
return NULL;
- return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL);
+ prop = fdt_getprop_namelen(fdt, aliasoffset, name, namelen, &prop_len);
+ if (prop && !can_assume(VALID_INPUT)) {
+ /* Validate the alias value. From the devicetree spec v0.3:
+ * "An alias value is a device path and is encoded as a string.
+ * The value representes the full path to a node, ..."
+ * A full path must start at the root to prevent recursion.
+ */
+ if (prop_len == 0 || *prop != '/' || !is_nul_string(prop, prop_len)) {
+ prop = NULL;
+ }
+ }
+
+ return prop;
}
const char *fdt_get_alias(const void *fdt, const char *name)
@@ -680,7 +710,7 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
{
int offset;
- if ((phandle == 0) || (phandle == -1))
+ if ((phandle == 0) || (phandle == ~0U))
return -FDT_ERR_BADPHANDLE;
FDT_RO_PROBE(fdt);
diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c
index 93e4a2b..3621d36 100644
--- a/libfdt/fdt_rw.c
+++ b/libfdt/fdt_rw.c
@@ -59,7 +59,7 @@ static int fdt_splice_(void *fdt, void *splicepoint, int oldlen, int newlen)
if ((oldlen < 0) || (soff + oldlen < soff) || (soff + oldlen > dsize))
return -FDT_ERR_BADOFFSET;
- if ((p < (char *)fdt) || (dsize + newlen < oldlen))
+ if ((p < (char *)fdt) || (dsize + newlen < (unsigned)oldlen))
return -FDT_ERR_BADOFFSET;
if (dsize - oldlen + newlen > fdt_totalsize(fdt))
return -FDT_ERR_NOSPACE;
@@ -349,7 +349,10 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
return offset;
/* Try to place the new node after the parent's properties */
- fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */
+ tag = fdt_next_tag(fdt, parentoffset, &nextoffset);
+ /* the fdt_subnode_offset_namelen() should ensure this never hits */
+ if (!can_assume(LIBFDT_FLAWLESS) && (tag != FDT_BEGIN_NODE))
+ return -FDT_ERR_INTERNAL;
do {
offset = nextoffset;
tag = fdt_next_tag(fdt, offset, &nextoffset);
@@ -391,7 +394,9 @@ int fdt_del_node(void *fdt, int nodeoffset)
}
static void fdt_packblocks_(const char *old, char *new,
- int mem_rsv_size, int struct_size)
+ int mem_rsv_size,
+ int struct_size,
+ int strings_size)
{
int mem_rsv_off, struct_off, strings_off;
@@ -406,8 +411,7 @@ static void fdt_packblocks_(const char *old, char *new,
fdt_set_off_dt_struct(new, struct_off);
fdt_set_size_dt_struct(new, struct_size);
- memmove(new + strings_off, old + fdt_off_dt_strings(old),
- fdt_size_dt_strings(old));
+ memmove(new + strings_off, old + fdt_off_dt_strings(old), strings_size);
fdt_set_off_dt_strings(new, strings_off);
fdt_set_size_dt_strings(new, fdt_size_dt_strings(old));
}
@@ -428,12 +432,14 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
struct_size = fdt_size_dt_struct(fdt);
- } else {
+ } else if (fdt_version(fdt) == 16) {
struct_size = 0;
while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END)
;
if (struct_size < 0)
return struct_size;
+ } else {
+ return -FDT_ERR_BADVERSION;
}
if (can_assume(LIBFDT_ORDER) ||
@@ -465,7 +471,8 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
return -FDT_ERR_NOSPACE;
}
- fdt_packblocks_(fdt, tmp, mem_rsv_size, struct_size);
+ fdt_packblocks_(fdt, tmp, mem_rsv_size, struct_size,
+ fdt_size_dt_strings(fdt));
memmove(buf, tmp, newsize);
fdt_set_magic(buf, FDT_MAGIC);
@@ -485,7 +492,8 @@ int fdt_pack(void *fdt)
mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
* sizeof(struct fdt_reserve_entry);
- fdt_packblocks_(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt));
+ fdt_packblocks_(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt),
+ fdt_size_dt_strings(fdt));
fdt_set_totalsize(fdt, fdt_data_size_(fdt));
return 0;
diff --git a/libfdt/fdt_strerror.c b/libfdt/fdt_strerror.c
index 768db66..d852b77 100644
--- a/libfdt/fdt_strerror.c
+++ b/libfdt/fdt_strerror.c
@@ -39,8 +39,9 @@ static struct fdt_errtabent fdt_errtable[] = {
FDT_ERRTABENT(FDT_ERR_BADOVERLAY),
FDT_ERRTABENT(FDT_ERR_NOPHANDLES),
FDT_ERRTABENT(FDT_ERR_BADFLAGS),
+ FDT_ERRTABENT(FDT_ERR_ALIGNMENT),
};
-#define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0]))
+#define FDT_ERRTABSIZE ((int)(sizeof(fdt_errtable) / sizeof(fdt_errtable[0])))
const char *fdt_strerror(int errval)
{
@@ -48,7 +49,7 @@ const char *fdt_strerror(int errval)
return "<valid offset/length>";
else if (errval == 0)
return "<no error>";
- else if (errval > -FDT_ERRTABSIZE) {
+ else if (-errval < FDT_ERRTABSIZE) {
const char *s = fdt_errtable[-errval].str;
if (s)
diff --git a/libfdt/fdt_sw.c b/libfdt/fdt_sw.c
index 94ce4bb..4c569ee 100644
--- a/libfdt/fdt_sw.c
+++ b/libfdt/fdt_sw.c
@@ -93,8 +93,8 @@ static inline uint32_t sw_flags(void *fdt)
static void *fdt_grab_space_(void *fdt, size_t len)
{
- int offset = fdt_size_dt_struct(fdt);
- int spaceleft;
+ unsigned int offset = fdt_size_dt_struct(fdt);
+ unsigned int spaceleft;
spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt)
- fdt_size_dt_strings(fdt);
@@ -108,8 +108,8 @@ static void *fdt_grab_space_(void *fdt, size_t len)
int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags)
{
- const size_t hdrsize = FDT_ALIGN(sizeof(struct fdt_header),
- sizeof(struct fdt_reserve_entry));
+ const int hdrsize = FDT_ALIGN(sizeof(struct fdt_header),
+ sizeof(struct fdt_reserve_entry));
void *fdt = buf;
if (bufsize < hdrsize)
@@ -152,6 +152,9 @@ int fdt_resize(void *fdt, void *buf, int bufsize)
FDT_SW_PROBE(fdt);
+ if (bufsize < 0)
+ return -FDT_ERR_NOSPACE;
+
headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
tailsize = fdt_size_dt_strings(fdt);
@@ -159,7 +162,7 @@ int fdt_resize(void *fdt, void *buf, int bufsize)
headsize + tailsize > fdt_totalsize(fdt))
return -FDT_ERR_INTERNAL;
- if ((headsize + tailsize) > bufsize)
+ if ((headsize + tailsize) > (unsigned)bufsize)
return -FDT_ERR_NOSPACE;
oldtail = (char *)fdt + fdt_totalsize(fdt) - tailsize;
@@ -247,18 +250,18 @@ int fdt_end_node(void *fdt)
static int fdt_add_string_(void *fdt, const char *s)
{
char *strtab = (char *)fdt + fdt_totalsize(fdt);
- int strtabsize = fdt_size_dt_strings(fdt);
- int len = strlen(s) + 1;
- int struct_top, offset;
+ unsigned int strtabsize = fdt_size_dt_strings(fdt);
+ unsigned int len = strlen(s) + 1;
+ unsigned int struct_top, offset;
- offset = -strtabsize - len;
+ offset = strtabsize + len;
struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
- if (fdt_totalsize(fdt) + offset < struct_top)
+ if (fdt_totalsize(fdt) - offset < struct_top)
return 0; /* no more room :( */
- memcpy(strtab + offset, s, len);
+ memcpy(strtab - offset, s, len);
fdt_set_size_dt_strings(fdt, strtabsize + len);
- return offset;
+ return -offset;
}
/* Must only be used to roll back in case of error */
@@ -374,7 +377,7 @@ int fdt_finish(void *fdt)
fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
/* And fix up fields that were keeping intermediate state. */
- fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
+ fdt_set_last_comp_version(fdt, FDT_LAST_COMPATIBLE_VERSION);
fdt_set_magic(fdt, FDT_MAGIC);
return 0;
diff --git a/libfdt/fdt_wip.c b/libfdt/fdt_wip.c
index f64139e..c2d7566 100644
--- a/libfdt/fdt_wip.c
+++ b/libfdt/fdt_wip.c
@@ -23,7 +23,7 @@ int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
if (!propval)
return proplen;
- if (proplen < (len + idx))
+ if ((unsigned)proplen < (len + idx))
return -FDT_ERR_NOSPACE;
memcpy((char *)propval + idx, val, len);
diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h
index 544d3ef..a7f432c 100644
--- a/libfdt/libfdt.h
+++ b/libfdt/libfdt.h
@@ -14,6 +14,7 @@ extern "C" {
#endif
#define FDT_FIRST_SUPPORTED_VERSION 0x02
+#define FDT_LAST_COMPATIBLE_VERSION 0x10
#define FDT_LAST_SUPPORTED_VERSION 0x11
/* Error codes: informative error codes */
@@ -101,7 +102,11 @@ extern "C" {
/* 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
+#define FDT_ERR_ALIGNMENT 19
+ /* FDT_ERR_ALIGNMENT: The device tree base address is not 8-byte
+ * aligned. */
+
+#define FDT_ERR_MAX 19
/* constants */
#define FDT_MAX_PHANDLE 0xfffffffe
@@ -122,11 +127,16 @@ static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)
uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
/*
- * Alignment helpers:
- * These helpers access words from a device tree blob. They're
- * built to work even with unaligned pointers on platforms (ike
- * ARM) that don't like unaligned loads and stores
+ * External helpers to access words from a device tree blob. They're built
+ * to work even with unaligned pointers on platforms (such as ARMv5) that don't
+ * like unaligned loads and stores.
*/
+static inline uint16_t fdt16_ld(const fdt16_t *p)
+{
+ const uint8_t *bp = (const uint8_t *)p;
+
+ return ((uint16_t)bp[0] << 8) | bp[1];
+}
static inline uint32_t fdt32_ld(const fdt32_t *p)
{
@@ -184,23 +194,23 @@ int fdt_next_node(const void *fdt, int offset, int *depth);
/**
* fdt_first_subnode() - get offset of first direct subnode
- *
* @fdt: FDT blob
* @offset: Offset of node to check
- * @return offset of first subnode, or -FDT_ERR_NOTFOUND if there is none
+ *
+ * Return: offset of first subnode, or -FDT_ERR_NOTFOUND if there is none
*/
int fdt_first_subnode(const void *fdt, int offset);
/**
* fdt_next_subnode() - get offset of next direct subnode
+ * @fdt: FDT blob
+ * @offset: Offset of previous subnode
*
* After first calling fdt_first_subnode(), call this function repeatedly to
* get direct subnodes of a parent node.
*
- * @fdt: FDT blob
- * @offset: Offset of previous subnode
- * @return offset of next subnode, or -FDT_ERR_NOTFOUND if there are no more
- * subnodes
+ * Return: offset of next subnode, or -FDT_ERR_NOTFOUND if there are no more
+ * subnodes
*/
int fdt_next_subnode(const void *fdt, int offset);
@@ -225,7 +235,6 @@ int fdt_next_subnode(const void *fdt, int offset);
* Note that this is implemented as a macro and @node is used as
* iterator in the loop. The parent variable be constant or even a
* literal.
- *
*/
#define fdt_for_each_subnode(node, fdt, parent) \
for (node = fdt_first_subnode(fdt, parent); \
@@ -269,17 +278,21 @@ fdt_set_hdr_(size_dt_struct);
/**
* fdt_header_size - return the size of the tree's header
* @fdt: pointer to a flattened device tree
+ *
+ * Return: size of DTB header in bytes
*/
size_t fdt_header_size(const void *fdt);
/**
- * fdt_header_size_ - internal function which takes a version number
+ * fdt_header_size_ - internal function to get header size from a version number
+ * @version: devicetree version number
+ *
+ * Return: size of DTB header in bytes
*/
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
@@ -404,8 +417,7 @@ static inline uint32_t fdt_get_max_phandle(const void *fdt)
* 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
+ * Return: 0 on success or a negative error-code on failure
*/
int fdt_generate_phandle(const void *fdt, uint32_t *phandle);
@@ -425,9 +437,11 @@ int fdt_num_mem_rsv(const void *fdt);
/**
* fdt_get_mem_rsv - retrieve one memory reserve map entry
* @fdt: pointer to the device tree blob
- * @address, @size: pointers to 64-bit variables
+ * @n: index of reserve map entry
+ * @address: pointer to 64-bit variable to hold the start address
+ * @size: pointer to 64-bit variable to hold the size of the entry
*
- * On success, *address and *size will contain the address and size of
+ * On success, @address and @size will contain the address and size of
* the n-th reserve map entry from the device tree blob, in
* native-endian format.
*
@@ -450,6 +464,8 @@ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size);
* namelen characters of name for matching the subnode name. This is
* useful for finding subnodes based on a portion of a larger string,
* such as a full path.
+ *
+ * Return: offset of the subnode or -FDT_ERR_NOTFOUND if name not found.
*/
#ifndef SWIG /* Not available in Python */
int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
@@ -489,6 +505,8 @@ int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
*
* Identical to fdt_path_offset(), but only consider the first namelen
* characters of path as the path name.
+ *
+ * Return: offset of the node or negative libfdt error value otherwise
*/
#ifndef SWIG /* Not available in Python */
int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen);
@@ -588,9 +606,9 @@ int fdt_next_property_offset(const void *fdt, int offset);
/**
* fdt_for_each_property_offset - iterate over all properties of a node
*
- * @property_offset: property offset (int, lvalue)
- * @fdt: FDT blob (const void *)
- * @node: node offset (int)
+ * @property: property offset (int, lvalue)
+ * @fdt: FDT blob (const void *)
+ * @node: node offset (int)
*
* This is actually a wrapper around a for loop and would be used like so:
*
@@ -653,6 +671,9 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
*
* Identical to fdt_get_property(), but only examine the first namelen
* characters of name for matching the property name.
+ *
+ * Return: pointer to the structure representing the property, or NULL
+ * if not found
*/
#ifndef SWIG /* Not available in Python */
const struct fdt_property *fdt_get_property_namelen(const void *fdt,
@@ -745,6 +766,8 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
*
* Identical to fdt_getprop(), but only examine the first namelen
* characters of name for matching the property name.
+ *
+ * Return: pointer to the property's value or NULL on error
*/
#ifndef SWIG /* Not available in Python */
const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
@@ -766,10 +789,10 @@ static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset,
* @lenp: pointer to an integer variable (will be overwritten) or NULL
*
* fdt_getprop() retrieves a pointer to the value of the property
- * named 'name' of the node at offset nodeoffset (this will be a
+ * named @name of the node at offset @nodeoffset (this will be a
* pointer to within the device blob itself, not a copy of the value).
- * If lenp is non-NULL, the length of the property value is also
- * returned, in the integer pointed to by lenp.
+ * If @lenp is non-NULL, the length of the property value is also
+ * returned, in the integer pointed to by @lenp.
*
* returns:
* pointer to the property's value
@@ -814,8 +837,11 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset);
* @name: name of the alias th look up
* @namelen: number of characters of name to consider
*
- * Identical to fdt_get_alias(), but only examine the first namelen
- * characters of name for matching the alias name.
+ * Identical to fdt_get_alias(), but only examine the first @namelen
+ * characters of @name for matching the alias name.
+ *
+ * Return: a pointer to the expansion of the alias named @name, if it exists,
+ * NULL otherwise
*/
#ifndef SWIG /* Not available in Python */
const char *fdt_get_alias_namelen(const void *fdt,
@@ -828,7 +854,7 @@ const char *fdt_get_alias_namelen(const void *fdt,
* @name: name of the alias th look up
*
* fdt_get_alias() retrieves the value of a given alias. That is, the
- * value of the property named 'name' in the node /aliases.
+ * value of the property named @name in the node /aliases.
*
* returns:
* a pointer to the expansion of the alias named 'name', if it exists
@@ -1004,14 +1030,13 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle);
/**
- * fdt_node_check_compatible: check a node's compatible property
+ * fdt_node_check_compatible - check a node's compatible property
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of a tree node
* @compatible: string to match against
*
- *
* fdt_node_check_compatible() returns 0 if the given node contains a
- * 'compatible' property with the given string as one of its elements,
+ * @compatible property with the given string as one of its elements,
* it returns non-zero otherwise, or on error.
*
* returns:
@@ -1075,7 +1100,7 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
* one or more strings, each terminated by \0, as is found in a device tree
* "compatible" property.
*
- * @return: 1 if the string is found in the list, 0 not found, or invalid list
+ * Return: 1 if the string is found in the list, 0 not found, or invalid list
*/
int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
@@ -1084,7 +1109,8 @@ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of a tree node
* @property: name of the property containing the string list
- * @return:
+ *
+ * Return:
* the number of strings in the given property
* -FDT_ERR_BADVALUE if the property value is not NUL-terminated
* -FDT_ERR_NOTFOUND if the property does not exist
@@ -1104,7 +1130,7 @@ int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property);
* small-valued cell properties, such as #address-cells, when searching for
* the empty string.
*
- * @return:
+ * return:
* the index of the string in the list of strings
* -FDT_ERR_BADVALUE if the property value is not NUL-terminated
* -FDT_ERR_NOTFOUND if the property does not exist or does not contain
@@ -1128,7 +1154,7 @@ int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,
* If non-NULL, the length of the string (on success) or a negative error-code
* (on failure) will be stored in the integer pointer to by lenp.
*
- * @return:
+ * Return:
* A pointer to the string at the given index in the string list or NULL on
* failure. On success the length of the string will be stored in the memory
* location pointed to by the lenp parameter, if non-NULL. On failure one of
@@ -1217,6 +1243,8 @@ int fdt_size_cells(const void *fdt, int nodeoffset);
* starting from the given index, and using only the first characters
* of the name. It is useful when you want to manipulate only one value of
* an array and you have a string that doesn't end with \0.
+ *
+ * Return: 0 on success, negative libfdt error value otherwise
*/
#ifndef SWIG /* Not available in Python */
int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
@@ -1330,8 +1358,13 @@ static inline int fdt_setprop_inplace_u64(void *fdt, int nodeoffset,
/**
* fdt_setprop_inplace_cell - change the value of a single-cell property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node containing the property
+ * @name: name of the property to change the value of
+ * @val: new value of the 32-bit cell
*
* This is an alternative name for fdt_setprop_inplace_u32()
+ * Return: 0 on success, negative libfdt error number otherwise.
*/
static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset,
const char *name, uint32_t val)
@@ -1403,7 +1436,7 @@ int fdt_nop_node(void *fdt, int nodeoffset);
/**
* fdt_create_with_flags - begin creation of a new fdt
- * @fdt: pointer to memory allocated where fdt will be created
+ * @buf: pointer to memory allocated where fdt will be created
* @bufsize: size of the memory space at fdt
* @flags: a valid combination of FDT_CREATE_FLAG_ flags, or 0.
*
@@ -1421,7 +1454,7 @@ 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
+ * @buf: pointer to memory allocated where fdt will be created
* @bufsize: size of the memory space at fdt
*
* fdt_create() is equivalent to fdt_create_with_flags() with flags=0.
@@ -1486,7 +1519,8 @@ int fdt_pack(void *fdt);
/**
* fdt_add_mem_rsv - add one memory reserve map entry
* @fdt: pointer to the device tree blob
- * @address, @size: 64-bit values (native endian)
+ * @address: 64-bit start address of the reserve map entry
+ * @size: 64-bit size of the reserved region
*
* Adds a reserve map entry to the given blob reserving a region at
* address address of length size.
@@ -1691,8 +1725,14 @@ static inline int fdt_setprop_u64(void *fdt, int nodeoffset, const char *name,
/**
* fdt_setprop_cell - set a property to a single cell value
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 32-bit integer value for the property (native endian)
*
* This is an alternative name for fdt_setprop_u32()
+ *
+ * Return: 0 on success, negative libfdt error value otherwise.
*/
static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
uint32_t val)
@@ -1863,8 +1903,14 @@ static inline int fdt_appendprop_u64(void *fdt, int nodeoffset,
/**
* fdt_appendprop_cell - append a single cell value to a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 32-bit integer value to append to the property (native endian)
*
* This is an alternative name for fdt_appendprop_u32()
+ *
+ * Return: 0 on success, negative libfdt error value otherwise.
*/
static inline int fdt_appendprop_cell(void *fdt, int nodeoffset,
const char *name, uint32_t val)
@@ -1967,13 +2013,16 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name);
* fdt_add_subnode_namelen - creates a new node based on substring
* @fdt: pointer to the device tree blob
* @parentoffset: structure block offset of a node
- * @name: name of the subnode to locate
+ * @name: name of the subnode to create
* @namelen: number of characters of name to consider
*
- * Identical to fdt_add_subnode(), but use only the first namelen
- * characters of name as the name of the new node. This is useful for
+ * Identical to fdt_add_subnode(), but use only the first @namelen
+ * characters of @name as the name of the new node. This is useful for
* creating subnodes based on a portion of a larger string, such as a
* full path.
+ *
+ * Return: structure block offset of the created subnode (>=0),
+ * negative libfdt error value otherwise
*/
#ifndef SWIG /* Not available in Python */
int fdt_add_subnode_namelen(void *fdt, int parentoffset,
@@ -1992,7 +2041,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
*
* This function will insert data into the blob, and will therefore
* change the offsets of some existing nodes.
-
+ *
* returns:
* structure block offset of the created nodeequested subnode (>=0), on
* success
@@ -2067,6 +2116,24 @@ int fdt_del_node(void *fdt, int nodeoffset);
*/
int fdt_overlay_apply(void *fdt, void *fdto);
+/**
+ * fdt_overlay_target_offset - retrieves the offset of a fragment's target
+ * @fdt: Base device tree blob
+ * @fdto: Device tree overlay blob
+ * @fragment_offset: node offset of the fragment in the overlay
+ * @pathp: pointer which receives the path of the target (or NULL)
+ *
+ * fdt_overlay_target_offset() retrieves the target offset in the base
+ * device tree of a fragment, no matter how the actual targeting is
+ * done (through a phandle or a path)
+ *
+ * returns:
+ * the targeted node offset in the base device tree
+ * Negative error code on error
+ */
+int fdt_overlay_target_offset(const void *fdt, const void *fdto,
+ int fragment_offset, char const **pathp);
+
/**********************************************************************/
/* Debugging / informational functions */
/**********************************************************************/
diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h
index d4e0bd4..16bda19 100644
--- a/libfdt/libfdt_internal.h
+++ b/libfdt/libfdt_internal.h
@@ -46,6 +46,25 @@ static inline struct fdt_reserve_entry *fdt_mem_rsv_w_(void *fdt, int n)
return (void *)(uintptr_t)fdt_mem_rsv_(fdt, n);
}
+/*
+ * Internal helpers to access tructural elements of the device tree
+ * blob (rather than for exaple reading integers from within property
+ * values). We assume that we are either given a naturally aligned
+ * address for the platform or if we are not, we are on a platform
+ * where unaligned memory reads will be handled in a graceful manner.
+ * If not the external helpers fdtXX_ld() from libfdt.h can be used
+ * instead.
+ */
+static inline uint32_t fdt32_ld_(const fdt32_t *p)
+{
+ return fdt32_to_cpu(*p);
+}
+
+static inline uint64_t fdt64_ld_(const fdt64_t *p)
+{
+ return fdt64_to_cpu(*p);
+}
+
#define FDT_SW_MAGIC (~FDT_MAGIC)
/**********************************************************************/
diff --git a/libfdt/meson.build b/libfdt/meson.build
new file mode 100644
index 0000000..240bdf4
--- /dev/null
+++ b/libfdt/meson.build
@@ -0,0 +1,61 @@
+version_script = '-Wl,--version-script=@0@'.format(meson.current_source_dir() / 'version.lds')
+if not cc.has_link_argument(version_script)
+ version_script = []
+endif
+
+sources = files(
+ 'fdt.c',
+ 'fdt_addresses.c',
+ 'fdt_check.c',
+ 'fdt_empty_tree.c',
+ 'fdt_overlay.c',
+ 'fdt_ro.c',
+ 'fdt_rw.c',
+ 'fdt_strerror.c',
+ 'fdt_sw.c',
+ 'fdt_wip.c',
+)
+
+libfdt = library(
+ 'fdt', sources,
+ version: '1.6.0',
+ link_args: ['-Wl,--no-undefined', version_script],
+ link_depends: 'version.lds',
+ install: true,
+)
+
+libfdt_a = static_library(
+ 'fdt', sources,
+ install: true,
+)
+
+libfdt_inc = include_directories('.')
+
+if static_build
+ link_with = libfdt_a
+else
+ link_with = libfdt
+endif
+
+libfdt_dep = declare_dependency(
+ include_directories: libfdt_inc,
+ link_with: link_with,
+)
+
+install_headers(
+ files(
+ 'fdt.h',
+ 'libfdt.h',
+ 'libfdt_env.h',
+ )
+)
+
+pkgconfig = import('pkgconfig')
+
+pkgconfig.generate(
+ libraries: libfdt,
+ version: meson.project_version(),
+ filebase: 'libfdt',
+ name: 'libfdt',
+ description: 'Flat Device Tree manipulation',
+)
diff --git a/libfdt/rules.mk b/libfdt/rules.mk
new file mode 100644
index 0000000..c785aa2
--- /dev/null
+++ b/libfdt/rules.mk
@@ -0,0 +1,53 @@
+# Copyright (c) 2022, Google, Inc. 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.
+
+# This file is not used in the Android build process! It's used only by Trusty.
+
+
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+MODULE := $(LOCAL_DIR)
+
+MODULE_SRCS := \
+ $(LOCAL_DIR)/fdt.c \
+ $(LOCAL_DIR)/fdt_check.c \
+ $(LOCAL_DIR)/fdt_ro.c \
+ $(LOCAL_DIR)/fdt_wip.c \
+ $(LOCAL_DIR)/fdt_sw.c \
+ $(LOCAL_DIR)/fdt_rw.c \
+ $(LOCAL_DIR)/fdt_strerror.c \
+ $(LOCAL_DIR)/fdt_empty_tree.c \
+ $(LOCAL_DIR)/fdt_addresses.c \
+ $(LOCAL_DIR)/fdt_overlay.c \
+ $(LOCAL_DIR)/acpi.c \
+
+
+MODULE_COMPILEFLAGS += \
+ -Wno-sign-compare \
+ -Wno-macro-redefined \
+
+MODULE_EXPORT_INCLUDES += \
+ $(LOCAL_DIR) \
+
+include make/library.mk
diff --git a/libfdt/version.lds b/libfdt/version.lds
index 7ab85f1..cbce5d4 100644
--- a/libfdt/version.lds
+++ b/libfdt/version.lds
@@ -77,6 +77,7 @@ LIBFDT_1.2 {
fdt_appendprop_addrrange;
fdt_setprop_inplace_namelen_partial;
fdt_create_with_flags;
+ fdt_overlay_target_offset;
local:
*;
};
diff --git a/livetree.c b/livetree.c
index 032df58..169462d 100644
--- a/livetree.c
+++ b/livetree.c
@@ -438,7 +438,7 @@ cell_t propval_cell(struct property *prop)
return fdt32_to_cpu(*((fdt32_t *)prop->val.val));
}
-cell_t propval_cell_n(struct property *prop, int n)
+cell_t propval_cell_n(struct property *prop, unsigned int n)
{
assert(prop->val.len / sizeof(cell_t) >= n);
return fdt32_to_cpu(*((fdt32_t *)prop->val.val + n));
@@ -526,7 +526,7 @@ struct node *get_node_by_path(struct node *tree, const char *path)
p = strchr(path, '/');
for_each_child(tree, child) {
- if (p && strprefixeq(path, p - path, child->name))
+ if (p && strprefixeq(path, (size_t)(p - path), child->name))
return get_node_by_path(child, p+1);
else if (!p && streq(path, child->name))
return child;
@@ -559,7 +559,7 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
{
struct node *child, *node;
- if ((phandle == 0) || (phandle == -1)) {
+ if (!phandle_is_valid(phandle)) {
assert(generate_fixups);
return NULL;
}
@@ -581,12 +581,39 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
struct node *get_node_by_ref(struct node *tree, const char *ref)
{
+ struct node *target = tree;
+ const char *label = NULL, *path = NULL;
+
if (streq(ref, "/"))
return tree;
- else if (ref[0] == '/')
- return get_node_by_path(tree, ref);
+
+ if (ref[0] == '/')
+ path = ref;
else
- return get_node_by_label(tree, ref);
+ label = ref;
+
+ if (label) {
+ const char *slash = strchr(label, '/');
+ char *buf = NULL;
+
+ if (slash) {
+ buf = xstrndup(label, slash - label);
+ label = buf;
+ path = slash + 1;
+ }
+
+ target = get_node_by_label(tree, label);
+
+ free(buf);
+
+ if (!target)
+ return NULL;
+ }
+
+ if (path)
+ target = get_node_by_path(target, path);
+
+ return target;
}
cell_t get_node_phandle(struct node *root, struct node *node)
@@ -594,7 +621,7 @@ cell_t get_node_phandle(struct node *root, struct node *node)
static cell_t phandle = 1; /* FIXME: ick, static local */
struct data d = empty_data;
- if ((node->phandle != 0) && (node->phandle != -1))
+ if (phandle_is_valid(node->phandle))
return node->phandle;
while (get_node_by_phandle(root, phandle))
diff --git a/meson.build b/meson.build
new file mode 100644
index 0000000..78251eb
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,139 @@
+project('dtc', 'c',
+ version: '1.6.0',
+ license: ['GPL2+', 'BSD-2'],
+ default_options: 'werror=true',
+)
+
+cc = meson.get_compiler('c')
+
+add_project_arguments(
+ cc.get_supported_arguments([
+ '-Wpointer-arith',
+ '-Wcast-qual',
+ '-Wnested-externs',
+ '-Wstrict-prototypes',
+ '-Wmissing-prototypes',
+ '-Wredundant-decls',
+ '-Wshadow'
+ ]),
+ language: 'c'
+)
+
+if host_machine.system() == 'windows'
+ add_project_arguments(
+ '-D__USE_MINGW_ANSI_STDIO=1',
+ language: 'c'
+ )
+endif
+
+add_project_arguments(
+ '-DFDT_ASSUME_MASK=' + get_option('assume-mask').to_string(),
+ language: 'c'
+)
+
+if get_option('static-build')
+ static_build = true
+ extra_link_args = ['-static']
+else
+ static_build = false
+ extra_link_args = []
+endif
+
+yamltree = 'yamltree.c'
+yaml = dependency('yaml-0.1', required: get_option('yaml'), static: static_build)
+if not yaml.found()
+ add_project_arguments('-DNO_YAML', language: 'c')
+ yamltree = []
+endif
+
+valgrind = dependency('valgrind', required: get_option('valgrind'))
+if not valgrind.found()
+ add_project_arguments('-DNO_VALGRIND', language: 'c')
+endif
+
+py = import('python')
+py = py.find_installation(required: get_option('python'))
+swig = find_program('swig', required: get_option('python'))
+
+version_gen_h = vcs_tag(
+ input: 'version_gen.h.in',
+ output: 'version_gen.h',
+)
+
+subdir('libfdt')
+
+if get_option('tools')
+ flex = find_program('flex', required: true)
+ bison = find_program('bison', required: true)
+
+ util_dep = declare_dependency(
+ sources: ['util.c', version_gen_h],
+ include_directories: '.',
+ dependencies: libfdt_dep
+ )
+
+ lgen = generator(
+ flex,
+ output: '@PLAINNAME@.lex.c',
+ arguments: ['-o', '@OUTPUT@', '@INPUT@'],
+ )
+
+ pgen = generator(
+ bison,
+ output: ['@BASENAME@.tab.c', '@BASENAME@.tab.h'],
+ arguments: ['@INPUT@', '--defines=@OUTPUT1@', '--output=@OUTPUT0@'],
+ )
+
+ if cc.check_header('fnmatch.h')
+ executable(
+ 'convert-dtsv0',
+ [
+ lgen.process('convert-dtsv0-lexer.l'),
+ 'srcpos.c',
+ ],
+ dependencies: util_dep,
+ install: true,
+ link_args: extra_link_args,
+ )
+ endif
+
+ executable(
+ 'dtc',
+ [
+ lgen.process('dtc-lexer.l'),
+ pgen.process('dtc-parser.y'),
+ 'checks.c',
+ 'data.c',
+ 'dtc.c',
+ 'flattree.c',
+ 'fstree.c',
+ 'livetree.c',
+ 'srcpos.c',
+ 'treesource.c',
+ yamltree,
+ ],
+ dependencies: [util_dep, yaml],
+ install: true,
+ link_args: extra_link_args,
+ )
+
+ foreach e: ['fdtdump', 'fdtget', 'fdtput', 'fdtoverlay']
+ executable(e, files(e + '.c'), dependencies: util_dep, install: true, link_args: extra_link_args)
+ endforeach
+
+ install_data(
+ 'dtdiff',
+ install_dir: get_option('prefix') / get_option('bindir'),
+ install_mode: 'rwxr-xr-x',
+ )
+endif
+
+if not meson.is_cross_build()
+ if py.found() and swig.found()
+ subdir('pylibfdt')
+ endif
+
+ if get_option('tools')
+ subdir('tests')
+ endif
+endif
diff --git a/meson_options.txt b/meson_options.txt
new file mode 100644
index 0000000..82621c3
--- /dev/null
+++ b/meson_options.txt
@@ -0,0 +1,12 @@
+option('tools', type: 'boolean', value: true,
+ description: 'Build tools')
+option('assume-mask', type: 'integer', value: 0,
+ description: 'Control the assumptions made (e.g. risking security issues) in the code.')
+option('yaml', type: 'feature', value: 'auto',
+ description: 'YAML support')
+option('valgrind', type: 'feature', value: 'auto',
+ description: 'Valgrind support')
+option('python', type: 'feature', value: 'auto',
+ description: 'Build pylibfdt Python library')
+option('static-build', type: 'boolean', value: false,
+ description: 'Build static binaries')
diff --git a/pylibfdt/Makefile.pylibfdt b/pylibfdt/Makefile.pylibfdt
index 6866a0b..82f565e 100644
--- a/pylibfdt/Makefile.pylibfdt
+++ b/pylibfdt/Makefile.pylibfdt
@@ -9,16 +9,15 @@ PYLIBFDT_CLEANFILES = $(PYLIBFDT_CLEANFILES_L:%=$(PYLIBFDT_dir)/%)
PYLIBFDT_CLEANDIRS_L = build __pycache__
PYLIBFDT_CLEANDIRS = $(PYLIBFDT_CLEANDIRS_L:%=$(PYLIBFDT_dir)/%)
-SETUP = $(PYLIBFDT_dir)/setup.py
-SETUPFLAGS =
+SETUP = ./setup.py
ifndef V
SETUPFLAGS += --quiet
endif
-$(PYMODULE): $(PYLIBFDT_srcs) $(LIBFDT_archive) $(SETUP) $(VERSION_FILE)
+$(PYMODULE): $(PYLIBFDT_srcs) $(LIBFDT_archive) $(SETUP)
@$(VECHO) PYMOD $@
- $(PYTHON) $(SETUP) $(SETUPFLAGS) build_ext --build-lib=../$(PYLIBFDT_dir)
+ $(PYTHON) $(SETUP) $(SETUPFLAGS) build_ext --build-lib=$(PYLIBFDT_dir)
install_pylibfdt: $(PYMODULE)
@$(VECHO) INSTALL-PYLIB
diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i
index 3e09d3a..f9f7e7e 100644
--- a/pylibfdt/libfdt.i
+++ b/pylibfdt/libfdt.i
@@ -443,6 +443,29 @@ class FdtRo(object):
"""
return fdt_get_alias(self._fdt, name)
+ def get_path(self, nodeoffset, quiet=()):
+ """Get the full path of a node
+
+ Args:
+ nodeoffset: Node offset to check
+
+ Returns:
+ Full path to the node
+
+ Raises:
+ FdtException if an error occurs
+ """
+ size = 1024
+ while True:
+ ret, path = fdt_get_path(self._fdt, nodeoffset, size)
+ if ret == -NOSPACE:
+ size = size * 2
+ continue
+ err = check_err(ret, quiet)
+ if err:
+ return err
+ return path
+
def parent_offset(self, nodeoffset, quiet=()):
"""Get the offset of a node's parent
@@ -716,6 +739,21 @@ class Property(bytearray):
def as_int64(self):
return self.as_cell('q')
+ def as_list(self, fmt):
+ return list(map(lambda x: x[0], struct.iter_unpack('>' + fmt, self)))
+
+ def as_uint32_list(self):
+ return self.as_list('L')
+
+ def as_int32_list(self):
+ return self.as_list('l')
+
+ def as_uint64_list(self):
+ return self.as_list('Q')
+
+ def as_int64_list(self):
+ return self.as_list('q')
+
def as_str(self):
"""Unicode is supported by decoding from UTF-8"""
if self[-1] != 0:
@@ -724,6 +762,13 @@ class Property(bytearray):
raise ValueError('Property contains embedded nul characters')
return self[:-1].decode('utf-8')
+ def as_stringlist(self):
+ """Unicode is supported by decoding from UTF-8"""
+ if self[-1] != 0:
+ raise ValueError('Property lacks nul termination')
+ parts = self[:-1].split(b'\x00')
+ return list(map(lambda x: x.decode('utf-8'), parts))
+
class FdtSw(FdtRo):
"""Software interface to create a device tree from scratch
@@ -1009,7 +1054,7 @@ typedef uint32_t fdt32_t;
}
$1 = (void *)PyByteArray_AsString($input);
fdt = $1;
- fdt = fdt; /* avoid unused variable warning */
+ (void)fdt; /* avoid unused variable warning */
}
/* Some functions do change the device tree, so use void * */
@@ -1020,7 +1065,7 @@ typedef uint32_t fdt32_t;
}
$1 = PyByteArray_AsString($input);
fdt = $1;
- fdt = fdt; /* avoid unused variable warning */
+ (void)fdt; /* avoid unused variable warning */
}
/* typemap used for fdt_get_property_by_offset() */
@@ -1040,14 +1085,16 @@ typedef uint32_t fdt32_t;
/* typemap used for fdt_getprop() */
%typemap(out) (const void *) {
- if (!$1)
+ if (!$1) {
$result = Py_None;
- else
+ Py_INCREF($result);
+ } else {
%#if PY_VERSION_HEX >= 0x03000000
- $result = Py_BuildValue("y#", $1, *arg4);
+ $result = Py_BuildValue("y#", $1, (Py_ssize_t)*arg4);
%#else
- $result = Py_BuildValue("s#", $1, *arg4);
+ $result = Py_BuildValue("s#", $1, (Py_ssize_t)*arg4);
%#endif
+ }
}
/* typemap used for fdt_setprop() */
@@ -1091,6 +1138,11 @@ typedef uint32_t fdt32_t;
}
}
+%include "cstring.i"
+
+%cstring_output_maxsize(char *buf, int buflen);
+int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen);
+
/* We have both struct fdt_property and a function fdt_property() */
%warnfilter(302) fdt_property;
diff --git a/pylibfdt/meson.build b/pylibfdt/meson.build
new file mode 100644
index 0000000..f684cbb
--- /dev/null
+++ b/pylibfdt/meson.build
@@ -0,0 +1,12 @@
+setup_py = find_program('../setup.py')
+setup_py = [setup_py.path(), '--quiet', '--top-builddir', meson.project_build_root()]
+
+custom_target(
+ 'pylibfdt',
+ input: 'libfdt.i',
+ output: '_libfdt.so',
+ command: [setup_py, 'build_ext', '--build-lib=' + meson.current_build_dir()],
+ build_by_default: true,
+)
+
+meson.add_install_script(setup_py, 'install', '--prefix=' + get_option('prefix'), '--root=$DESTDIR')
diff --git a/pylibfdt/setup.py b/pylibfdt/setup.py
deleted file mode 100755
index 53f2bef..0000000
--- a/pylibfdt/setup.py
+++ /dev/null
@@ -1,48 +0,0 @@
-#!/usr/bin/env python3
-# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
-
-# While Python 3 is the default, it's also possible to invoke
-# this setup.py script with Python 2.
-
-"""
-setup.py file for SWIG libfdt
-Copyright (C) 2017 Google, Inc.
-Written by Simon Glass <sjg@chromium.org>
-"""
-
-from distutils.core import setup, Extension
-import os
-import re
-import sys
-
-
-VERSION_PATTERN = '^#define DTC_VERSION "DTC ([^"]*)"$'
-
-
-def get_version():
- version_file = "../version_gen.h"
- f = open(version_file, 'rt')
- m = re.match(VERSION_PATTERN, f.readline())
- return m.group(1)
-
-
-setupdir = os.path.dirname(os.path.abspath(sys.argv[0]))
-os.chdir(setupdir)
-
-libfdt_module = Extension(
- '_libfdt',
- sources=['libfdt.i'],
- include_dirs=['../libfdt'],
- libraries=['fdt'],
- library_dirs=['../libfdt'],
- swig_opts=['-I../libfdt'],
-)
-
-setup(
- name='libfdt',
- version=get_version(),
- author='Simon Glass <sjg@chromium.org>',
- description='Python binding for libfdt',
- ext_modules=[libfdt_module],
- py_modules=['libfdt'],
-)
diff --git a/setup.py b/setup.py
new file mode 100755
index 0000000..a8e54a3
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,77 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
+
+# While Python 3 is the default, it's also possible to invoke
+# this setup.py script with Python 2.
+
+"""
+setup.py file for SWIG libfdt
+Copyright (C) 2017 Google, Inc.
+Written by Simon Glass <sjg@chromium.org>
+"""
+
+from setuptools import setup, Extension
+from setuptools.command.build_py import build_py as _build_py
+
+import os
+import re
+import sys
+
+srcdir = os.path.dirname(__file__)
+
+with open(os.path.join(srcdir, "README"), "r") as fh:
+ long_description = fh.read()
+
+def get_top_builddir():
+ if '--top-builddir' in sys.argv:
+ index = sys.argv.index('--top-builddir')
+ sys.argv.pop(index)
+ return sys.argv.pop(index)
+ else:
+ return srcdir
+
+top_builddir = get_top_builddir()
+
+libfdt_module = Extension(
+ '_libfdt',
+ sources=[os.path.join(srcdir, 'pylibfdt/libfdt.i')],
+ define_macros=[('PY_SSIZE_T_CLEAN', None)],
+ include_dirs=[os.path.join(srcdir, 'libfdt')],
+ libraries=['fdt'],
+ library_dirs=[os.path.join(top_builddir, 'libfdt')],
+ swig_opts=['-I' + os.path.join(srcdir, 'libfdt')],
+)
+
+class build_py(_build_py):
+ def run(self):
+ self.run_command("build_ext")
+ return super().run()
+
+setup(
+ name='libfdt',
+ use_scm_version={
+ "root": srcdir,
+ },
+ cmdclass = {'build_py' : build_py},
+ setup_requires = ['setuptools_scm'],
+ author='Simon Glass',
+ author_email='sjg@chromium.org',
+ description='Python binding for libfdt',
+ ext_modules=[libfdt_module],
+ package_dir={'': os.path.join(srcdir, 'pylibfdt')},
+ py_modules=['libfdt'],
+
+ long_description=long_description,
+ long_description_content_type="text/plain",
+ url="https://git.kernel.org/pub/scm/utils/dtc/dtc.git",
+ license="BSD",
+ license_files=["GPL", "BSD-2-Clause"],
+
+ classifiers=[
+ "Programming Language :: Python :: 3",
+ "License :: OSI Approved :: BSD License",
+ "License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)",
+ "Operating System :: OS Independent",
+ ],
+
+)
diff --git a/srcpos.c b/srcpos.c
index f5205fb..4fdb22a 100644
--- a/srcpos.c
+++ b/srcpos.c
@@ -20,7 +20,7 @@ struct search_path {
static struct search_path *search_path_head, **search_path_tail;
/* Detect infinite include recursion. */
-#define MAX_SRCFILE_DEPTH (100)
+#define MAX_SRCFILE_DEPTH (200)
static int srcfile_depth; /* = 0 */
static char *get_dirname(const char *path)
diff --git a/tests/.gitignore b/tests/.gitignore
index d3f1434..03bdde2 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -54,6 +54,7 @@ tmp.*
/property_iterate
/propname_escapes
/references
+/relref_merge
/root_node
/rw_tree1
/rw_oom
diff --git a/tests/Android.bp b/tests/Android.bp
new file mode 100644
index 0000000..70fa746
--- /dev/null
+++ b/tests/Android.bp
@@ -0,0 +1,12 @@
+// Copyright 2022 The Android Open Source Project
+package {
+ default_applicable_licenses: [
+ "external_dtc_license",
+ "external_dtc_tests_license",
+ ],
+}
+
+filegroup {
+ name: "external_dtc_tests",
+ srcs: ["**/*"],
+}
diff --git a/tests/Makefile.tests b/tests/Makefile.tests
index cb66c9f..2d36c5d 100644
--- a/tests/Makefile.tests
+++ b/tests/Makefile.tests
@@ -18,7 +18,7 @@ LIB_TESTS_L = get_mem_rsv \
open_pack rw_tree1 rw_oom set_name setprop del_property del_node \
appendprop1 appendprop2 propname_escapes \
string_escapes references path-references phandle_format \
- boot-cpuid incbin \
+ boot-cpuid incbin relref_merge \
extra-terminating-null \
dtbs_equal_ordered \
dtb_reverse dtbs_equal_unordered \
@@ -32,11 +32,15 @@ LIB_TESTS_L = get_mem_rsv \
fs_tree1
LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%)
-LIBTREE_TESTS_L = truncated_property truncated_string truncated_memrsv
+LIBTREE_TESTS_L = truncated_property truncated_string truncated_memrsv \
+ two_roots named_root
+
LIBTREE_TESTS = $(LIBTREE_TESTS_L:%=$(TESTS_PREFIX)%)
-DL_LIB_TESTS_L = asm_tree_dump value-labels
-DL_LIB_TESTS = $(DL_LIB_TESTS_L:%=$(TESTS_PREFIX)%)
+ifneq ($(STATIC_BUILD),1)
+ DL_LIB_TESTS_L = asm_tree_dump value-labels
+ DL_LIB_TESTS = $(DL_LIB_TESTS_L:%=$(TESTS_PREFIX)%)
+endif
TESTS = $(LIB_TESTS) $(LIBTREE_TESTS) $(DL_LIB_TESTS)
@@ -58,17 +62,17 @@ TESTS_CLEANDIRS = $(TESTS_CLEANDIRS_L:%=$(TESTS_PREFIX)%)
.PHONY: tests
tests: $(TESTS) $(TESTS_TREES)
-$(LIB_TESTS): %: $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_lib)
+$(LIB_TESTS): %: $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_dep)
# Not necessary on all platforms; allow -ldl to be excluded instead of forcing
# other platforms to patch it out.
LIBDL = -ldl
-$(DL_LIB_TESTS): %: %.o $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_lib)
+$(DL_LIB_TESTS): %: %.o $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_dep)
@$(VECHO) LD [libdl] $@
$(LINK.c) -o $@ $^ $(LIBDL)
$(LIBTREE_TESTS): %: $(TESTS_PREFIX)testutils.o $(TESTS_PREFIX)trees.o \
- util.o $(LIBFDT_lib)
+ util.o $(LIBFDT_dep)
$(TESTS_PREFIX)dumptrees: $(TESTS_PREFIX)trees.o
diff --git a/tests/bad-interrupt-map-mask.dts b/tests/bad-interrupt-map-mask.dts
new file mode 100644
index 0000000..10eaffd
--- /dev/null
+++ b/tests/bad-interrupt-map-mask.dts
@@ -0,0 +1,20 @@
+/dts-v1/;
+
+/ {
+ interrupt-parent = <&intc>;
+ intc: interrupt-controller {
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ };
+
+ node {
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ interrupt-map = <1 &intc 1 2 3>;
+ interrupt-map-mask = <0 0>;
+
+ child {
+ interrupts = <1>;
+ };
+ };
+};
diff --git a/tests/bad-interrupt-map-parent.dts b/tests/bad-interrupt-map-parent.dts
new file mode 100644
index 0000000..fe88ce2
--- /dev/null
+++ b/tests/bad-interrupt-map-parent.dts
@@ -0,0 +1,17 @@
+/dts-v1/;
+
+/ {
+ interrupt-parent = <&intc>;
+ intc: interrupt-controller {
+ };
+
+ node {
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ interrupt-map = <1 &intc 1 2 3>;
+
+ child {
+ interrupts = <1>;
+ };
+ };
+};
diff --git a/tests/bad-interrupt-map.dts b/tests/bad-interrupt-map.dts
new file mode 100644
index 0000000..6df8f93
--- /dev/null
+++ b/tests/bad-interrupt-map.dts
@@ -0,0 +1,19 @@
+/dts-v1/;
+
+/ {
+ interrupt-parent = <&intc>;
+ intc: interrupt-controller {
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ };
+
+ node {
+ /* Missing #address-cells = <0>; */
+ #interrupt-cells = <1>;
+ interrupt-map = <1 &intc 1 2 3>;
+
+ child {
+ interrupts = <1>;
+ };
+ };
+};
diff --git a/tests/base01.asm b/tests/base01.asm
index 266e446..63f2eca 100644
--- a/tests/base01.asm
+++ b/tests/base01.asm
@@ -32,7 +32,7 @@ _dt_reserve_map:
dt_struct_start:
_dt_struct_start:
.long OF_DT_BEGIN_NODE
- .string ""
+ .asciz ""
.balign 4
.long OF_DT_PROP
.long 0xa
@@ -58,7 +58,7 @@ _dt_struct_start:
.long 0x2
.balign 4
.long OF_DT_BEGIN_NODE
- .string "memory@0"
+ .asciz "memory@0"
.balign 4
.long OF_DT_PROP
.long 0x7
@@ -77,7 +77,7 @@ _dt_struct_start:
.balign 4
.long OF_DT_END_NODE
.long OF_DT_BEGIN_NODE
- .string "cpus"
+ .asciz "cpus"
.balign 4
.long OF_DT_PROP
.long 0x4
@@ -151,22 +151,22 @@ _dt_struct_end:
.globl dt_strings_start
dt_strings_start:
_dt_strings_start:
- .string "model"
- .string "compatible"
- .string "#address-cells"
- .string "#size-cells"
- .string "device_type"
- .string "reg"
- .string "d10"
- .string "d23"
- .string "b101"
- .string "o17"
- .string "hd00d"
- .string "stuff"
- .string "bad-d-1"
- .string "bad-d-2"
- .string "bad-o-1"
- .string "bad-o-2"
+ .asciz "model"
+ .asciz "compatible"
+ .asciz "#address-cells"
+ .asciz "#size-cells"
+ .asciz "device_type"
+ .asciz "reg"
+ .asciz "d10"
+ .asciz "d23"
+ .asciz "b101"
+ .asciz "o17"
+ .asciz "hd00d"
+ .asciz "stuff"
+ .asciz "bad-d-1"
+ .asciz "bad-d-2"
+ .asciz "bad-o-1"
+ .asciz "bad-o-2"
.globl dt_strings_end
dt_strings_end:
_dt_strings_end:
diff --git a/tests/dumptrees.c b/tests/dumptrees.c
index aecb326..08967b3 100644
--- a/tests/dumptrees.c
+++ b/tests/dumptrees.c
@@ -24,13 +24,15 @@ static struct {
TREE(ovf_size_strings),
TREE(truncated_property), TREE(truncated_string),
TREE(truncated_memrsv),
+ TREE(two_roots),
+ TREE(named_root)
};
#define NUM_TREES (sizeof(trees) / sizeof(trees[0]))
int main(int argc, char *argv[])
{
- int i;
+ unsigned int i;
if (argc != 2) {
fprintf(stderr, "Missing output directory argument\n");
diff --git a/tests/fs_tree1.c b/tests/fs_tree1.c
index dff3880..978f6a3 100644
--- a/tests/fs_tree1.c
+++ b/tests/fs_tree1.c
@@ -54,7 +54,7 @@ static void mkfile(const char *name, void *data, size_t len)
rc = write(fd, data, len);
if (rc < 0)
FAIL("write(\"%s\"): %s", name, strerror(errno));
- if (rc != len)
+ if ((unsigned)rc != len)
FAIL("write(\"%s\"): short write", name);
rc = close(fd);
diff --git a/tests/get_name.c b/tests/get_name.c
index 5a35103..d20bf30 100644
--- a/tests/get_name.c
+++ b/tests/get_name.c
@@ -34,12 +34,14 @@ static void check_name(void *fdt, const char *path)
offset, getname, len);
if (!getname)
FAIL("fdt_get_name(%d): %s", offset, fdt_strerror(len));
+ if (len < 0)
+ FAIL("negative name length (%d) for returned node name\n", len);
if (strcmp(getname, checkname) != 0)
FAIL("fdt_get_name(%s) returned \"%s\" instead of \"%s\"",
path, getname, checkname);
- if (len != strlen(getname))
+ if ((unsigned)len != strlen(getname))
FAIL("fdt_get_name(%s) returned length %d instead of %zd",
path, len, strlen(getname));
diff --git a/tests/good-gpio.dts b/tests/good-gpio.dts
new file mode 100644
index 0000000..65d1c17
--- /dev/null
+++ b/tests/good-gpio.dts
@@ -0,0 +1,12 @@
+/dts-v1/;
+
+/ {
+ gpio: gpio-controller {
+ #gpio-cells = <3>;
+ };
+
+ node {
+ foo,nr-gpios = <1>;
+ foo-gpios = <&gpio 1 2 3>;
+ };
+};
diff --git a/tests/integer-expressions.c b/tests/integer-expressions.c
index 6f33d81..2f164d9 100644
--- a/tests/integer-expressions.c
+++ b/tests/integer-expressions.c
@@ -59,7 +59,7 @@ int main(int argc, char *argv[])
void *fdt;
const fdt32_t *res;
int reslen;
- int i;
+ unsigned int i;
test_init(argc, argv);
diff --git a/tests/meson.build b/tests/meson.build
new file mode 100644
index 0000000..4ac154a
--- /dev/null
+++ b/tests/meson.build
@@ -0,0 +1,137 @@
+trees = static_library('trees', files('trees.S'), c_args: '-D__ASSEMBLY__',
+ include_directories: libfdt_inc)
+
+dumptrees = executable('dumptrees', files('dumptrees.c'),
+ link_with: trees, dependencies: libfdt_dep)
+
+dumptrees_dtb = custom_target(
+ 'dumptrees',
+ command: [dumptrees, meson.current_build_dir()],
+ output: [
+ 'test_tree1.dtb',
+ 'bad_node_char.dtb',
+ 'bad_node_format.dtb',
+ 'bad_prop_char.dtb',
+ 'ovf_size_strings.dtb',
+ 'truncated_property.dtb',
+ 'truncated_string.dtb',
+ 'truncated_memrsv.dtb',
+ ]
+)
+
+testutil_dep = declare_dependency(sources: ['testutils.c'], link_with: trees)
+
+tests = [
+ 'add_subnode_with_nops',
+ 'addr_size_cells',
+ 'addr_size_cells2',
+ 'appendprop1',
+ 'appendprop2',
+ 'appendprop_addrrange',
+ 'boot-cpuid',
+ 'char_literal',
+ 'check_full',
+ 'check_header',
+ 'check_path',
+ 'del_node',
+ 'del_property',
+ 'dtb_reverse',
+ 'dtbs_equal_ordered',
+ 'dtbs_equal_unordered',
+ 'extra-terminating-null',
+ 'find_property',
+ 'fs_tree1',
+ 'get_alias',
+ 'get_mem_rsv',
+ 'get_name',
+ 'get_path',
+ 'get_phandle',
+ 'get_prop_offset',
+ 'getprop',
+ 'incbin',
+ 'integer-expressions',
+ 'mangle-layout',
+ 'move_and_save',
+ 'node_check_compatible',
+ 'node_offset_by_compatible',
+ 'node_offset_by_phandle',
+ 'node_offset_by_prop_value',
+ 'nop_node',
+ 'nop_property',
+ 'nopulate',
+ 'notfound',
+ 'open_pack',
+ 'overlay',
+ 'overlay_bad_fixup',
+ 'parent_offset',
+ 'path-references',
+ 'path_offset',
+ 'path_offset_aliases',
+ 'phandle_format',
+ 'property_iterate',
+ 'propname_escapes',
+ 'references',
+ 'relref_merge',
+ 'root_node',
+ 'rw_oom',
+ 'rw_tree1',
+ 'set_name',
+ 'setprop',
+ 'setprop_inplace',
+ 'sized_cells',
+ 'string_escapes',
+ 'stringlist',
+ 'subnode_iterate',
+ 'subnode_offset',
+ 'supernode_atdepth_offset',
+ 'sw_states',
+ 'sw_tree1',
+ 'utilfdt_test',
+]
+
+tests += [
+ 'truncated_memrsv',
+ 'truncated_property',
+ 'truncated_string',
+]
+
+dl = cc.find_library('dl', required: false)
+if dl.found() and not static_build
+ tests += [
+ 'asm_tree_dump',
+ 'value-labels',
+ ]
+endif
+
+test_deps = [testutil_dep, util_dep, libfdt_dep]
+if not static_build
+ test_deps += [dl]
+endif
+
+foreach t: tests
+ executable(t, files(t + '.c'), dependencies: test_deps, link_args: extra_link_args)
+endforeach
+
+run_tests = find_program('run_tests.sh')
+
+env = []
+if not py.found()
+ env += 'NO_PYTHON=1'
+else
+ env += [
+ 'PYTHON=' + py.path(),
+ 'PYTHONPATH=' + meson.source_root() / 'pylibfdt',
+ ]
+endif
+if not yaml.found()
+ env += 'NO_YAML=1'
+endif
+
+test(
+ 'run-test',
+ run_tests,
+ workdir: meson.current_build_dir(),
+ depends: dumptrees_dtb,
+ env: env,
+ timeout: 1800, # mostly for valgrind
+)
diff --git a/tests/nopulate.c b/tests/nopulate.c
index 2ae1753..e06a0b3 100644
--- a/tests/nopulate.c
+++ b/tests/nopulate.c
@@ -43,7 +43,8 @@ static int nopulate_struct(char *buf, const char *fdt)
int main(int argc, char *argv[])
{
char *fdt, *fdt2, *buf;
- int newsize, struct_start, struct_end_old, struct_end_new, delta;
+ int newsize, struct_end_old, struct_end_new, delta;
+ unsigned int struct_start;
const char *inname;
char outname[PATH_MAX];
diff --git a/tests/overlay.c b/tests/overlay.c
index 91afa72..f3dd310 100644
--- a/tests/overlay.c
+++ b/tests/overlay.c
@@ -35,7 +35,11 @@ static int fdt_getprop_u32_by_poffset(void *fdt, const char *path,
return node_off;
val = fdt_getprop(fdt, node_off, name, &len);
- if (!val || (len < (sizeof(uint32_t) * (poffset + 1))))
+ if (val && len < 0)
+ FAIL("fdt_getprop() returns negative length");
+ if (!val && len < 0)
+ return len;
+ if (!val || ((unsigned)len < (sizeof(uint32_t) * (poffset + 1))))
return -FDT_ERR_NOTFOUND;
*out = fdt32_to_cpu(*(val + poffset));
diff --git a/tests/overlay_overlay_nosugar.dts b/tests/overlay_overlay_nosugar.dts
index b6d841b..b5947e9 100644
--- a/tests/overlay_overlay_nosugar.dts
+++ b/tests/overlay_overlay_nosugar.dts
@@ -48,7 +48,7 @@
};
};
- fragment@5 {
+ fragment@4 {
target = <&test>;
__overlay__ {
@@ -58,7 +58,7 @@
};
};
- fragment@6 {
+ fragment@5 {
target = <&test>;
__overlay__ {
@@ -66,7 +66,7 @@
};
};
- fragment@7 {
+ fragment@6 {
target = <&test>;
__overlay__ {
@@ -74,7 +74,7 @@
};
};
- fragment@8 {
+ fragment@7 {
target = <&test>;
__overlay__ {
diff --git a/tests/path-references.c b/tests/path-references.c
index 4db61a5..b914576 100644
--- a/tests/path-references.c
+++ b/tests/path-references.c
@@ -53,7 +53,7 @@ int main(int argc, char *argv[])
void *fdt;
const char *p;
int len, multilen;
- int n1, n2, n3, n4;
+ int n1, n2, n3, n4, n5;
test_init(argc, argv);
fdt = load_blob_arg(argc, argv);
@@ -89,6 +89,12 @@ int main(int argc, char *argv[])
check_ref(fdt, n3, "/foobar/baz");
check_ref(fdt, n4, "/foo/baz");
+ n5 = fdt_path_offset(fdt, "/bar/baz");
+ if (n5 < 0)
+ FAIL("fdt_path_offset(/bar/baz): %s", fdt_strerror(n5));
+
+ check_ref(fdt, n5, "/bar/baz");
+
check_rref(fdt);
PASS();
diff --git a/tests/path-references.dts b/tests/path-references.dts
index 1fb7d70..dd9ccfc 100644
--- a/tests/path-references.dts
+++ b/tests/path-references.dts
@@ -25,4 +25,13 @@
lref = &n3;
};
};
+ n5: bar {
+ baz {
+ };
+ };
+};
+
+n6: &{n5/baz} {
+ ref = &{n6/};
+ lref = &{n5/baz};
};
diff --git a/tests/phandle-args-overflow.dts b/tests/phandle-args-overflow.dts
new file mode 100644
index 0000000..8c8c5d7
--- /dev/null
+++ b/tests/phandle-args-overflow.dts
@@ -0,0 +1,18 @@
+/dts-v1/;
+
+/*
+ * https://github.com/dgibson/dtc/issues/64
+ *
+ * Certain dtc versions had a bug where this input caused an infinite
+ * loop in check_property_phandle_args().
+ *
+ */
+
+/ {
+ clocks = <&ref &ref>;
+
+ ref: poc {
+ phandle = <1>;
+ #clock-cells = <0xffffffff>;
+ };
+};
diff --git a/tests/phandle_format.c b/tests/phandle_format.c
index d00618f..0febb32 100644
--- a/tests/phandle_format.c
+++ b/tests/phandle_format.c
@@ -45,7 +45,7 @@ int main(int argc, char *argv[])
FAIL("fdt_path_offset(/node4): %s", fdt_strerror(n4));
h4 = fdt_get_phandle(fdt, n4);
- if ((h4 == 0) || (h4 == -1))
+ if ((h4 == 0) || (h4 == ~0U))
FAIL("/node4 has bad phandle 0x%x\n", h4);
if (phandle_format & PHANDLE_LEGACY)
diff --git a/tests/property_iterate.c b/tests/property_iterate.c
index 9a67f49..0b6af9b 100644
--- a/tests/property_iterate.c
+++ b/tests/property_iterate.c
@@ -23,7 +23,7 @@ static void test_node(void *fdt, int parent_offset)
uint32_t properties;
const fdt32_t *prop;
int offset, property;
- int count;
+ unsigned int count;
int len;
/*
diff --git a/tests/pylibfdt_tests.py b/tests/pylibfdt_tests.py
index 64b5bd1..68d6aaa 100644
--- a/tests/pylibfdt_tests.py
+++ b/tests/pylibfdt_tests.py
@@ -348,6 +348,19 @@ class PyLibfdtBasicTests(unittest.TestCase):
self.assertEqual("/subnode@1/subsubnode", self.fdt3.get_alias('ss1'))
self.assertEqual("/subnode@1/subsubnode/subsubsubnode", self.fdt3.get_alias('sss1'))
+ def testGetPath(self):
+ """Test for the get_path() method"""
+ node = self.fdt.path_offset('/subnode@1')
+ node2 = self.fdt.path_offset('/subnode@1/subsubnode')
+ self.assertEqual("/subnode@1", self.fdt.get_path(node))
+ self.assertEqual("/subnode@1/subsubnode", self.fdt.get_path(node2))
+
+ with self.assertRaises(FdtException) as e:
+ self.fdt.get_path(-1)
+ self.assertEqual(e.exception.err, -libfdt.BADOFFSET)
+
+ self.assertEqual(-libfdt.BADOFFSET, self.fdt.get_path(-1, quiet=(libfdt.BADOFFSET,)))
+
def testParentOffset(self):
"""Test for the parent_offset() method"""
self.assertEqual(-libfdt.NOTFOUND,
@@ -382,6 +395,25 @@ class PyLibfdtBasicTests(unittest.TestCase):
self.get_prop("prop-uint64").as_uint64())
self.assertEqual(-2, self.get_prop("prop-int64").as_int64())
+ def testGetIntListProperties(self):
+ """Test that we can access properties as integer lists"""
+ self.assertEqual([128, -16, -2],
+ self.get_prop("prop-int32-array").as_int32_list())
+ self.assertEqual([0x1, 0x98765432, 0xdeadbeef],
+ self.get_prop("prop-uint32-array").as_uint32_list())
+ self.assertEqual([0x100000000, -2],
+ self.get_prop("prop-int64-array").as_int64_list())
+ self.assertEqual([0x100000000, 0x1],
+ self.get_prop("prop-uint64-array").as_uint64_list())
+
+ def testGetStringlistProperties(self):
+ """Test that we can access properties as string list"""
+ node = self.fdt.path_offset('/subnode@1/subsubnode')
+ self.assertEqual(["subsubnode1", "subsubnode"],
+ self.fdt.getprop(node, "compatible").as_stringlist())
+ self.assertEqual(["this is a placeholder string", "string2"],
+ self.fdt.getprop(node, "placeholder").as_stringlist())
+
def testReserveMap(self):
"""Test that we can access the memory reserve map"""
self.assertEqual(2, self.fdt.num_mem_rsv())
diff --git a/tests/references.c b/tests/references.c
index d18e722..cb1daaa 100644
--- a/tests/references.c
+++ b/tests/references.c
@@ -106,7 +106,7 @@ int main(int argc, char *argv[])
if ((h4 == 0x2000) || (h4 == 0x1) || (h4 == 0))
FAIL("/node4 has bad phandle, 0x%x", h4);
- if ((h5 == 0) || (h5 == -1))
+ if ((h5 == 0) || (h5 == ~0U))
FAIL("/node5 has bad phandle, 0x%x", h5);
if ((h5 == h4) || (h5 == h2) || (h5 == h1))
FAIL("/node5 has duplicate phandle, 0x%x", h5);
diff --git a/tests/relref_merge.c b/tests/relref_merge.c
new file mode 100644
index 0000000..5daab2e
--- /dev/null
+++ b/tests/relref_merge.c
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for label relative child references in dtc
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ * Copyright (C) 2020 Ahmad Fatoum, Pengutronix.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+static void check_exist(void *fdt, const char *path)
+{
+ int sn = fdt_path_offset(fdt, path);
+ if (sn < 0)
+ FAIL("%s expected but not found: %s", path, fdt_strerror(sn));
+}
+
+static void check_doesnt_exist(void *fdt, const char *path)
+{
+ int sn = fdt_path_offset(fdt, path);
+ if (sn >= 0)
+ FAIL("%s found but not expected %d", path, sn);
+}
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+
+ test_init(argc, argv);
+ fdt = load_blob_arg(argc, argv);
+
+ check_exist(fdt, "/node/subnode1");
+ check_exist(fdt, "/node/keep-me");
+ check_doesnt_exist(fdt, "/node/remove-me");
+
+ check_doesnt_exist(fdt, "/node2");
+ check_doesnt_exist(fdt, "/node/subnode3");
+
+ check_exist(fdt, "/node/subnode4");
+
+ check_exist(fdt, "/node/subnode1/add-me");
+
+ PASS();
+}
diff --git a/tests/relref_merge.dts b/tests/relref_merge.dts
new file mode 100644
index 0000000..d8660eb
--- /dev/null
+++ b/tests/relref_merge.dts
@@ -0,0 +1,40 @@
+/dts-v1/;
+
+/ {
+ node_label: node {
+ keep-me {};
+ remove-me {};
+
+ subnode1 {
+ property-inline1;
+ property-inline2;
+ property-inline3;
+ };
+
+ subnode2 {
+ property-inline1;
+ };
+
+ subnode3 {
+ property-inline1;
+ };
+ };
+
+ node2_label: node2 {
+ property-inline1;
+ };
+};
+/omit-if-no-ref/ &{node_label/subnode1};
+/omit-if-no-ref/ &node2_label;
+/delete-node/ &{node_label/subnode3};
+
+&{node_label/} {
+ /delete-node/ remove-me;
+
+ subnode4 { };
+};
+
+label: &{node_label/subnode1} {
+ selfref = &{node_label/subnode1};
+ add-me { };
+};
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index 294585b..0cabd13 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -195,7 +195,7 @@ asm_to_so_test () {
run_fdtget_test () {
expect="$1"
shift
- printf "fdtget-runtest.sh %s $*: " "$(echo $expect)"
+ printf "fdtget-runtest.sh \"%s\" $*: " "$expect"
base_run_test sh "$SRCDIR/fdtget-runtest.sh" "$expect" "$@"
}
@@ -288,7 +288,7 @@ dtc_overlay_tests () {
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_dtc_test -I dts -O dtb -o overlay_overlay_nosugar.test.dtb "$SRCDIR/overlay_overlay_nosugar.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__"
@@ -513,12 +513,15 @@ libfdt_tests () {
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
+ ## https://github.com/dgibson/dtc/issues/64
+ check_tests "$SRCDIR/phandle-args-overflow.dts" clocks_property
+
# 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
+ truncated_memrsv.dtb two_roots.dtb named_root.dtb; do
run_test check_full -n $bad
done
}
@@ -604,11 +607,15 @@ dtc_tests () {
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 "$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
+ if [ -x ./asm_tree_dump ]; then
+ run_test asm_tree_dump ./oasm_$tree.test.so oasm_$tree.test.dtb
+ run_wrap_test cmp oasm_$tree.test.dtb $tree.test.dtb
+ fi
done
- run_test value-labels ./oasm_value-labels.dts.test.so
+ if [ -x ./value-labels ]; then
+ run_test value-labels ./oasm_value-labels.dts.test.so
+ fi
# Check -Odts mode preserve all dtb information
for tree in test_tree1.dtb dtc_tree1.test.dtb dtc_escapes.test.dtb \
@@ -666,6 +673,9 @@ dtc_tests () {
tree1_tests dtc_tree1_merge_path.test.dtb test_tree1.dtb
run_wrap_error_test $DTC -I dts -O dtb -o /dev/null "$SRCDIR/test_label_ref.dts"
+ run_dtc_test -I dts -O dtb -o dtc_relref_merge.test.dtb "$SRCDIR/relref_merge.dts"
+ run_test relref_merge dtc_relref_merge.test.dtb
+
# Check prop/node delete functionality
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
@@ -691,7 +701,7 @@ dtc_tests () {
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-ncells.dts" address_cells_is_cell size_cells_is_cell interrupts_extended_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
@@ -709,12 +719,17 @@ dtc_tests () {
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/good-gpio.dts" -n 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"
+ run_sh_test "$SRCDIR/dtc-checkfails.sh" -n deprecated_gpio_property -- -Wdeprecated_gpio_property -I dts -O dtb "$SRCDIR/good-gpio.dts"
check_tests "$SRCDIR/bad-interrupt-cells.dts" interrupts_property
check_tests "$SRCDIR/bad-interrupt-controller.dts" interrupt_provider
+ check_tests "$SRCDIR/bad-interrupt-map.dts" interrupt_map
+ check_tests "$SRCDIR/bad-interrupt-map-parent.dts" interrupt_map
+ check_tests "$SRCDIR/bad-interrupt-map-mask.dts" interrupt_map
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
@@ -738,7 +753,7 @@ dtc_tests () {
# Check warning options
- 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-checkfails.sh" address_cells_is_cell interrupts_extended_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"
@@ -850,6 +865,8 @@ fdtget_tests () {
run_fdtget_test 8000 -tx $dtb /cpus/PowerPC,970@1 d-cache-size
run_fdtget_test "61 62 63 0" -tbx $dtb /randomnode tricky1
run_fdtget_test "a b c d de ea ad be ef" -tbx $dtb /randomnode blob
+ run_fdtget_test "MyBoardName\0MyBoardFamilyName\0" -tr $dtb / compatible
+ run_fdtget_test "\012\013\014\015\336\352\255\276\357" -tr $dtb /randomnode blob
# Here the property size is not a multiple of 4 bytes, so it should fail
run_wrap_error_test $DTGET -tlx $dtb /randomnode mixed
diff --git a/tests/set_name.c b/tests/set_name.c
index a62cb58..5020305 100644
--- a/tests/set_name.c
+++ b/tests/set_name.c
@@ -39,7 +39,11 @@ static void check_set_name(void *fdt, const char *path, const char *newname)
FAIL("fdt_get_name(%s) returned \"%s\" instead of \"%s\"",
path, getname, oldname);
- if (len != strlen(getname))
+ if (len < 0)
+ FAIL("fdt_get_name(%s) returned negative length: %d",
+ path, len);
+
+ if ((unsigned)len != strlen(getname))
FAIL("fdt_get_name(%s) returned length %d instead of %zd",
path, len, strlen(getname));
@@ -51,12 +55,14 @@ static void check_set_name(void *fdt, const char *path, const char *newname)
getname = fdt_get_name(fdt, offset, &len);
if (!getname)
FAIL("fdt_get_name(%d): %s", offset, fdt_strerror(len));
+ if (len < 0)
+ FAIL("negative name length (%d) for returned node name\n", len);
if (strcmp(getname, newname) != 0)
FAIL("fdt_get_name(%s) returned \"%s\" instead of \"%s\"",
path, getname, newname);
- if (len != strlen(getname))
+ if ((unsigned)len != strlen(getname))
FAIL("fdt_get_name(%s) returned length %d instead of %zd",
path, len, strlen(getname));
}
diff --git a/tests/setprop_inplace.c b/tests/setprop_inplace.c
index 7e1198d..61a0da1 100644
--- a/tests/setprop_inplace.c
+++ b/tests/setprop_inplace.c
@@ -58,7 +58,7 @@ int main(int argc, char *argv[])
TEST_STRING_1);
verbose_printf("Old string value was \"%s\"\n", strp);
- xstr = strdup(strp);
+ xstr = xstrdup(strp);
xlen = strlen(xstr);
for (i = 0; i < xlen; i++)
xstr[i] = toupper(xstr[i]);
diff --git a/tests/subnode_iterate.c b/tests/subnode_iterate.c
index 2dc9b2d..2553a51 100644
--- a/tests/subnode_iterate.c
+++ b/tests/subnode_iterate.c
@@ -23,7 +23,7 @@ static void test_node(void *fdt, int parent_offset)
uint32_t subnodes;
const fdt32_t *prop;
int offset;
- int count;
+ unsigned int count;
int len;
/* This property indicates the number of subnodes to expect */
diff --git a/tests/test01.asm b/tests/test01.asm
index bbf66c7..73fa603 100644
--- a/tests/test01.asm
+++ b/tests/test01.asm
@@ -44,7 +44,7 @@ _dt_reserve_map:
dt_struct_start:
_dt_struct_start:
.long OF_DT_BEGIN_NODE
- .string ""
+ .asciz ""
.balign 4
.long OF_DT_PROP
.long 0xc
@@ -76,7 +76,7 @@ _dt_struct_start:
.long 0x2
.balign 4
.long OF_DT_BEGIN_NODE
- .string "cpus"
+ .asciz "cpus"
.balign 4
.long OF_DT_PROP
.long 0x4
@@ -94,7 +94,7 @@ _dt_struct_start:
.long 0x0
.balign 4
.long OF_DT_BEGIN_NODE
- .string "PowerPC,970@0"
+ .asciz "PowerPC,970@0"
.balign 4
.long OF_DT_PROP
.long 0xc
@@ -139,7 +139,7 @@ _dt_struct_start:
.balign 4
.long OF_DT_END_NODE
.long OF_DT_BEGIN_NODE
- .string "PowerPC,970@1"
+ .asciz "PowerPC,970@1"
.balign 4
.long OF_DT_PROP
.long 0xc
@@ -181,7 +181,7 @@ _dt_struct_start:
.long OF_DT_END_NODE
.long OF_DT_END_NODE
.long OF_DT_BEGIN_NODE
- .string "randomnode"
+ .asciz "randomnode"
.balign 4
.long OF_DT_PROP
.long 0x13
@@ -216,7 +216,7 @@ _dt_struct_start:
.balign 4
.long OF_DT_END_NODE
.long OF_DT_BEGIN_NODE
- .string "memory@0"
+ .asciz "memory@0"
.balign 4
.long OF_DT_PROP
.long 0x7
@@ -242,7 +242,7 @@ memreg:
.balign 4
.long OF_DT_END_NODE
.long OF_DT_BEGIN_NODE
- .string "chosen"
+ .asciz "chosen"
.balign 4
.long OF_DT_PROP
.long 0xf
@@ -267,25 +267,25 @@ _dt_struct_end:
.globl dt_strings_start
dt_strings_start:
_dt_strings_start:
- .string "model"
- .string "compatible"
- .string "#address-cells"
- .string "#size-cells"
- .string "linux,phandle"
- .string "name"
- .string "device_type"
- .string "reg"
- .string "clock-frequency"
- .string "timebase-frequency"
- .string "linux,boot-cpu"
- .string "i-cache-size"
- .string "d-cache-size"
- .string "string"
- .string "blob"
- .string "ref"
- .string "mixed"
- .string "bootargs"
- .string "linux,platform"
+ .asciz "model"
+ .asciz "compatible"
+ .asciz "#address-cells"
+ .asciz "#size-cells"
+ .asciz "linux,phandle"
+ .asciz "name"
+ .asciz "device_type"
+ .asciz "reg"
+ .asciz "clock-frequency"
+ .asciz "timebase-frequency"
+ .asciz "linux,boot-cpu"
+ .asciz "i-cache-size"
+ .asciz "d-cache-size"
+ .asciz "string"
+ .asciz "blob"
+ .asciz "ref"
+ .asciz "mixed"
+ .asciz "bootargs"
+ .asciz "linux,platform"
.globl dt_strings_end
dt_strings_end:
_dt_strings_end:
diff --git a/tests/test_props.dts b/tests/test_props.dts
index 7e59bd1..5089023 100644
--- a/tests/test_props.dts
+++ b/tests/test_props.dts
@@ -8,4 +8,8 @@
prop-hex64 = /bits/ 64 <0xdeadbeef01abcdef>;
prop-uint64 = /bits/ 64 <9223372036854775807>;
prop-int64 = /bits/ 64 <0xfffffffffffffffe>;
+ prop-int32-array = <128>, <(-16)>, <0xfffffffe>;
+ prop-uint32-array = <0x1>, <0x98765432>, <0xdeadbeef>;
+ prop-int64-array = /bits/ 64 <0x100000000 0xfffffffffffffffe>;
+ prop-uint64-array = /bits/ 64 <0x100000000 0x1>;
};
diff --git a/tests/testdata.h b/tests/testdata.h
index 0d08efb..4f9e3ba 100644
--- a/tests/testdata.h
+++ b/tests/testdata.h
@@ -55,4 +55,6 @@ 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;
+extern struct fdt_header two_roots;
+extern struct fdt_header named_root;
#endif /* ! __ASSEMBLY */
diff --git a/tests/tests.h b/tests/tests.h
index 1017366..bf8f23c 100644
--- a/tests/tests.h
+++ b/tests/tests.h
@@ -83,7 +83,7 @@ void cleanup(void);
void check_mem_rsv(void *fdt, int n, uint64_t addr, uint64_t size);
void check_property(void *fdt, int nodeoffset, const char *name,
- int len, const void *val);
+ unsigned int len, const void *val);
#define check_property_cell(fdt, nodeoffset, name, val) \
({ \
fdt32_t x = cpu_to_fdt32(val); \
diff --git a/tests/testutils.c b/tests/testutils.c
index 5e494c5..10129c0 100644
--- a/tests/testutils.c
+++ b/tests/testutils.c
@@ -88,7 +88,7 @@ void check_mem_rsv(void *fdt, int n, uint64_t addr, uint64_t size)
}
void check_property(void *fdt, int nodeoffset, const char *name,
- int len, const void *val)
+ unsigned int len, const void *val)
{
const struct fdt_property *prop;
int retlen, namelen;
@@ -101,6 +101,9 @@ void check_property(void *fdt, int nodeoffset, const char *name,
if (! prop)
FAIL("Error retrieving \"%s\" pointer: %s", name,
fdt_strerror(retlen));
+ if (retlen < 0)
+ FAIL("negative name length (%d) for returned property\n",
+ retlen);
tag = fdt32_to_cpu(prop->tag);
nameoff = fdt32_to_cpu(prop->nameoff);
@@ -112,13 +115,16 @@ void check_property(void *fdt, int nodeoffset, const char *name,
propname = fdt_get_string(fdt, nameoff, &namelen);
if (!propname)
FAIL("Couldn't get property name: %s", fdt_strerror(namelen));
- if (namelen != strlen(propname))
+ if (namelen < 0)
+ FAIL("negative name length (%d) for returned string\n",
+ namelen);
+ if ((unsigned)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)
+ if (proplen != (unsigned)retlen)
FAIL("Length retrieved for \"%s\" by fdt_get_property()"
" differs from stored length (%d != %d)",
name, retlen, proplen);
diff --git a/tests/trees.S b/tests/trees.S
index efab287..d69f7f1 100644
--- a/tests/trees.S
+++ b/tests/trees.S
@@ -1,174 +1,187 @@
#include <fdt.h>
#include "testdata.h"
-#define FDTLONG(val) \
- .byte ((val) >> 24) & 0xff ; \
- .byte ((val) >> 16) & 0xff ; \
- .byte ((val) >> 8) & 0xff ; \
- .byte (val) & 0xff ;
-
-#define TREE_HDR(tree) \
- .balign 8 ; \
- .globl tree ; \
-tree: \
- FDTLONG(FDT_MAGIC) ; \
- FDTLONG(tree##_end - tree) ; \
- FDTLONG(tree##_struct - tree) ; \
- FDTLONG(tree##_strings - tree) ; \
- FDTLONG(tree##_rsvmap - tree) ; \
- FDTLONG(0x11) ; \
- FDTLONG(0x10) ; \
- FDTLONG(0) ; \
- FDTLONG(tree##_strings_end - tree##_strings) ; \
- FDTLONG(tree##_struct_end - tree##_struct) ;
-
-#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, 0, 0) \
-tree##_rsvmap_end: ;
-
-#define PROPHDR(tree, name, len) \
- FDTLONG(FDT_PROP) ; \
- 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, valh, vall) \
- PROPHDR(tree, name, 8) \
- FDTLONG(valh) ; \
- FDTLONG(vall) ;
-
-#define PROP_STR(tree, name, str) \
- PROPHDR(tree, name, 55f - 54f) \
-54: \
- .string str ; \
-55: \
- .balign 4 ;
-
-#define BEGIN_NODE(name) \
- FDTLONG(FDT_BEGIN_NODE) ; \
- .string name ; \
- .balign 4 ;
-
-#define END_NODE \
- FDTLONG(FDT_END_NODE) ;
-
-#define STRING(tree, name, str) \
-tree##_##name: ; \
- .string str ;
+ .macro fdtlong val
+ .byte ((\val) >> 24) & 0xff
+ .byte ((\val) >> 16) & 0xff
+ .byte ((\val) >> 8) & 0xff
+ .byte (\val) & 0xff
+ .endm
+
+ .macro treehdr tree
+ .balign 8
+ .globl \tree
+\tree :
+ fdtlong FDT_MAGIC
+ fdtlong (\tree\()_end - \tree)
+ fdtlong (\tree\()_struct - \tree)
+ fdtlong (\tree\()_strings - \tree)
+ fdtlong (\tree\()_rsvmap - \tree)
+ fdtlong 0x11
+ fdtlong 0x10
+ fdtlong 0
+ fdtlong (\tree\()_strings_end - \tree\()_strings)
+ fdtlong (\tree\()_struct_end - \tree\()_struct)
+ .endm
+
+ .macro rsvmape addrh, addrl, lenh, lenl
+ fdtlong \addrh
+ fdtlong \addrl
+ fdtlong \lenh
+ fdtlong \lenl
+ .endm
+
+ .macro empty_rsvmap tree
+ .balign 8
+\tree\()_rsvmap:
+ rsvmape 0, 0, 0, 0
+\tree\()_rsvmap_end:
+ .endm
+
+ .macro prophdr tree, name, len
+ fdtlong FDT_PROP
+ fdtlong \len
+ fdtlong (\tree\()_\name - \tree\()_strings)
+ .endm
+
+ .macro propnil tree, name
+ prophdr \tree, \name, 0
+ .endm
+
+ .macro propu32 tree, name, val
+ prophdr \tree, \name, 4
+ fdtlong \val
+ .endm
+
+ .macro propu64 tree, name, valh, vall
+ prophdr \tree, \name, 8
+ fdtlong \valh
+ fdtlong \vall
+ .endm
+
+ .macro propstr tree, name, str:vararg
+ prophdr \tree, \name, (55f - 54f)
+54:
+ .asciz \str
+55:
+ .balign 4
+ .endm
+
+ .macro beginn name:vararg
+ fdtlong FDT_BEGIN_NODE
+ .asciz \name
+ .balign 4
+ .endm
+
+ .macro endn
+ fdtlong FDT_END_NODE
+ .endm
+
+ .macro string tree, name, str:vararg
+\tree\()_\name :
+ .asciz \str
+ .endm
+
.data
- TREE_HDR(test_tree1)
+ treehdr test_tree1
.balign 8
test_tree1_rsvmap:
- 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)
+ rsvmape TEST_ADDR_1H, TEST_ADDR_1L, TEST_SIZE_1H, TEST_SIZE_1L
+ rsvmape TEST_ADDR_2H, TEST_ADDR_2L, TEST_SIZE_2H, TEST_SIZE_2L
+ rsvmape 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_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)
-
- BEGIN_NODE("subnode@1")
- PROP_STR(test_tree1, compatible, "subnode1")
- PROP_INT(test_tree1, reg, 1)
- PROP_INT(test_tree1, prop_int, TEST_VALUE_1)
-
- BEGIN_NODE("subsubnode")
- PROP_STR(test_tree1, compatible, "subsubnode1\0subsubnode")
- PROP_STR(test_tree1, placeholder, "this is a placeholder string\0string2")
- PROP_INT(test_tree1, prop_int, TEST_VALUE_1)
- END_NODE
-
- BEGIN_NODE("ss1")
- END_NODE
-
- END_NODE
-
- BEGIN_NODE("subnode@2")
- PROP_INT(test_tree1, reg, 2)
- PROP_INT(test_tree1, linux_phandle, PHANDLE_1)
- PROP_INT(test_tree1, prop_int, TEST_VALUE_2)
- PROP_INT(test_tree1, address_cells, 1)
- PROP_INT(test_tree1, size_cells, 0)
-
- BEGIN_NODE("subsubnode@0")
- PROP_INT(test_tree1, reg, 0)
- PROP_INT(test_tree1, phandle, PHANDLE_2)
- PROP_STR(test_tree1, compatible, "subsubnode2\0subsubnode")
- PROP_INT(test_tree1, prop_int, TEST_VALUE_2)
- END_NODE
-
- BEGIN_NODE("ss2")
- END_NODE
-
- END_NODE
-
- END_NODE
- FDTLONG(FDT_END)
+ beginn ""
+ propstr test_tree1, compatible, "test_tree1"
+ propu32 test_tree1, prop_int, TEST_VALUE_1
+ propu64 test_tree1, prop_int64, TEST_VALUE64_1H, TEST_VALUE64_1L
+ propstr test_tree1, prop_str, TEST_STRING_1
+ propu32 test_tree1, address_cells, 1
+ propu32 test_tree1, size_cells, 0
+
+ beginn "subnode@1"
+ propstr test_tree1, compatible, "subnode1"
+ propu32 test_tree1, reg, 1
+ propu32 test_tree1, prop_int, TEST_VALUE_1
+
+ beginn "subsubnode"
+ propstr test_tree1, compatible, "subsubnode1\0subsubnode"
+ propstr test_tree1, placeholder, "this is a placeholder string\0string2"
+ propu32 test_tree1, prop_int, TEST_VALUE_1
+ endn
+
+ beginn "ss1"
+ endn
+
+ endn
+
+ beginn "subnode@2"
+ propu32 test_tree1, reg, 2
+ propu32 test_tree1, linux_phandle, PHANDLE_1
+ propu32 test_tree1, prop_int, TEST_VALUE_2
+ propu32 test_tree1, address_cells, 1
+ propu32 test_tree1, size_cells, 0
+
+ beginn "subsubnode@0"
+ propu32 test_tree1, reg, 0
+ propu32 test_tree1, phandle, PHANDLE_2
+ propstr test_tree1, compatible, "subsubnode2\0subsubnode"
+ propu32 test_tree1, prop_int, TEST_VALUE_2
+ endn
+
+ beginn "ss2"
+ endn
+
+ endn
+
+ endn
+ fdtlong FDT_END
test_tree1_struct_end:
test_tree1_strings:
- STRING(test_tree1, compatible, "compatible")
- STRING(test_tree1, prop_int, "prop-int")
- STRING(test_tree1, prop_int64, "prop-int64")
- STRING(test_tree1, prop_str, "prop-str")
- STRING(test_tree1, linux_phandle, "linux,phandle")
- STRING(test_tree1, phandle, "phandle")
- STRING(test_tree1, reg, "reg")
- STRING(test_tree1, placeholder, "placeholder")
- STRING(test_tree1, address_cells, "#address-cells")
- STRING(test_tree1, size_cells, "#size-cells")
+ string test_tree1, compatible, "compatible"
+ string test_tree1, prop_int, "prop-int"
+ string test_tree1, prop_int64, "prop-int64"
+ string test_tree1, prop_str, "prop-str"
+ string test_tree1, linux_phandle, "linux,phandle"
+ string test_tree1, phandle, "phandle"
+ string test_tree1, reg, "reg"
+ string test_tree1, placeholder, "placeholder"
+ string test_tree1, address_cells, "#address-cells"
+ string test_tree1, size_cells, "#size-cells"
test_tree1_strings_end:
test_tree1_end:
- TREE_HDR(truncated_property)
- EMPTY_RSVMAP(truncated_property)
+ treehdr truncated_property
+ empty_rsvmap truncated_property
truncated_property_struct:
- BEGIN_NODE("")
- PROPHDR(truncated_property, prop_truncated, 4)
+ beginn ""
+ prophdr truncated_property, prop_truncated, 4
/* Oops, no actual property data here */
truncated_property_struct_end:
truncated_property_strings:
- STRING(truncated_property, prop_truncated, "truncated")
+ string truncated_property, prop_truncated, "truncated"
truncated_property_strings_end:
truncated_property_end:
- TREE_HDR(bad_node_char)
- EMPTY_RSVMAP(bad_node_char)
+ treehdr bad_node_char
+ empty_rsvmap bad_node_char
bad_node_char_struct:
- BEGIN_NODE("")
- BEGIN_NODE("sub$node")
- END_NODE
- END_NODE
- FDTLONG(FDT_END)
+ beginn ""
+ beginn "sub$node"
+ endn
+ endn
+ fdtlong FDT_END
bad_node_char_struct_end:
bad_node_char_strings:
@@ -176,15 +189,15 @@ bad_node_char_strings_end:
bad_node_char_end:
- TREE_HDR(bad_node_format)
- EMPTY_RSVMAP(bad_node_format)
+ treehdr bad_node_format
+ empty_rsvmap bad_node_format
bad_node_format_struct:
- BEGIN_NODE("")
- BEGIN_NODE("subnode@1@2")
- END_NODE
- END_NODE
- FDTLONG(FDT_END)
+ beginn ""
+ beginn "subnode@1@2"
+ endn
+ endn
+ fdtlong FDT_END
bad_node_format_struct_end:
bad_node_format_strings:
@@ -192,18 +205,18 @@ bad_node_format_strings_end:
bad_node_format_end:
- TREE_HDR(bad_prop_char)
- EMPTY_RSVMAP(bad_prop_char)
+ treehdr bad_prop_char
+ empty_rsvmap bad_prop_char
bad_prop_char_struct:
- BEGIN_NODE("")
- PROP_INT(bad_prop_char, prop, TEST_VALUE_1)
- END_NODE
- FDTLONG(FDT_END)
+ beginn ""
+ propu32 bad_prop_char, prop, TEST_VALUE_1
+ endn
+ fdtlong FDT_END
bad_prop_char_struct_end:
bad_prop_char_strings:
- STRING(bad_prop_char, prop, "prop$erty")
+ string bad_prop_char, prop, "prop$erty"
bad_prop_char_strings_end:
bad_prop_char_end:
@@ -212,62 +225,60 @@ bad_prop_char_end:
.balign 8
.globl ovf_size_strings
ovf_size_strings:
- FDTLONG(FDT_MAGIC)
- FDTLONG(ovf_size_strings_end - ovf_size_strings)
- FDTLONG(ovf_size_strings_struct - ovf_size_strings)
- FDTLONG(ovf_size_strings_strings - ovf_size_strings)
- FDTLONG(ovf_size_strings_rsvmap - ovf_size_strings)
- FDTLONG(0x11)
- FDTLONG(0x10)
- FDTLONG(0)
- FDTLONG(0xffffffff)
- FDTLONG(ovf_size_strings_struct_end - ovf_size_strings_struct)
- EMPTY_RSVMAP(ovf_size_strings)
+ fdtlong FDT_MAGIC
+ fdtlong (ovf_size_strings_end - ovf_size_strings)
+ fdtlong (ovf_size_strings_struct - ovf_size_strings)
+ fdtlong (ovf_size_strings_strings - ovf_size_strings)
+ fdtlong (ovf_size_strings_rsvmap - ovf_size_strings)
+ fdtlong 0x11
+ fdtlong 0x10
+ fdtlong 0
+ fdtlong 0xffffffff
+ fdtlong (ovf_size_strings_struct_end - ovf_size_strings_struct)
+ empty_rsvmap ovf_size_strings
ovf_size_strings_struct:
- BEGIN_NODE("")
- PROP_INT(ovf_size_strings, bad_string, 0)
- END_NODE
- FDTLONG(FDT_END)
+ beginn ""
+ propu32 ovf_size_strings, bad_string, 0
+ endn
+ fdtlong FDT_END
ovf_size_strings_struct_end:
ovf_size_strings_strings:
- STRING(ovf_size_strings, x, "x")
+ string ovf_size_strings, x, "x"
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)
+ treehdr 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)
+ beginn ""
+ propnil truncated_string, good_string
+ propnil truncated_string, bad_string
+ endn
+ fdtlong FDT_END
truncated_string_struct_end:
truncated_string_strings:
- STRING(truncated_string, good_string, "good")
+ string truncated_string, good_string, "good"
truncated_string_bad_string:
- .byte 'b'
- .byte 'a'
- .byte 'd'
+ .ascii "bad"
/* NOTE: terminating \0 deliberately missing */
truncated_string_strings_end:
truncated_string_end:
/* truncated_memrsv */
- TREE_HDR(truncated_memrsv)
+ treehdr truncated_memrsv
truncated_memrsv_struct:
- BEGIN_NODE("")
- END_NODE
- FDTLONG(FDT_END)
+ beginn ""
+ endn
+ fdtlong FDT_END
truncated_memrsv_struct_end:
truncated_memrsv_strings:
@@ -275,7 +286,41 @@ truncated_memrsv_strings_end:
.balign 8
truncated_memrsv_rsvmap:
- RSVMAP_ENTRY(TEST_ADDR_1H, TEST_ADDR_1L, TEST_SIZE_1H, TEST_SIZE_1L)
+ rsvmape TEST_ADDR_1H, TEST_ADDR_1L, TEST_SIZE_1H, TEST_SIZE_1L
truncated_memrsv_rsvmap_end:
truncated_memrsv_end:
+
+
+ /* two root nodes */
+ treehdr two_roots
+ empty_rsvmap two_roots
+
+two_roots_struct:
+ beginn ""
+ endn
+ beginn ""
+ endn
+ fdtlong FDT_END
+two_roots_struct_end:
+
+two_roots_strings:
+two_roots_strings_end:
+
+two_roots_end:
+
+
+ /* root node with a non-empty name */
+ treehdr named_root
+ empty_rsvmap named_root
+
+named_root_struct:
+ beginn "fake"
+ endn
+ fdtlong FDT_END
+named_root_struct_end:
+
+named_root_strings:
+named_root_strings_end:
+
+named_root_end:
diff --git a/tests/type-preservation.dt.yaml b/tests/type-preservation.dt.yaml
index ee8cfde..a0cc64c 100644
--- a/tests/type-preservation.dt.yaml
+++ b/tests/type-preservation.dt.yaml
@@ -13,8 +13,11 @@
int64: [!u64 [0x200000000]]
int64-array: [!u64 [0x100000000, 0x0]]
a-string-with-nulls: ["foo\0bar", "baz"]
+ a-phandle: [[!phandle 0x1]]
+ a-phandle-with-args: [[!phandle 0x1, 0x0, 0x1], [!phandle 0x1, 0x2, 0x3]]
subsubnode:
compatible: ["subsubnode1", "subsubnode"]
+ phandle: [[0x1]]
subsubsubnode:
compatible: ["subsubsubnode1", [0x1234], "subsubsubnode"]
...
diff --git a/tests/type-preservation.dts b/tests/type-preservation.dts
index 3e380ba..921ea21 100644
--- a/tests/type-preservation.dts
+++ b/tests/type-preservation.dts
@@ -16,9 +16,12 @@
int64 = /bits/ 64 <0x200000000>;
int64-array = /bits/ 64 <0x100000000 0x00> int64_array_label_end:;
a-string-with-nulls = "foo\0bar", "baz";
+ a-phandle = <&subsub1>;
+ a-phandle-with-args = <&subsub1 0x00 0x01>, <&subsub1 0x02 0x03>;
subsub1: subsubnode {
compatible = "subsubnode1", "subsubnode";
+ phandle = <0x01>;
subsubsub1: subsubsubnode {
compatible = "subsubsubnode1", <0x1234>, valuea: valueb: "subsubsubnode";
diff --git a/tests/utilfdt_test.c b/tests/utilfdt_test.c
index c621759..ba6462f 100644
--- a/tests/utilfdt_test.c
+++ b/tests/utilfdt_test.c
@@ -73,6 +73,9 @@ static void check_sizes(char *modifier, int expected_size)
*ptr = 's';
check(fmt, 's', -1);
+
+ *ptr = 'r';
+ check(fmt, 'r', -1);
}
static void test_utilfdt_decode_type(void)
@@ -90,7 +93,7 @@ static void test_utilfdt_decode_type(void)
/* try every other character */
checkfail("");
for (ch = ' '; ch < 127; ch++) {
- if (!strchr("iuxs", ch)) {
+ if (!strchr("iuxsr", ch)) {
*fmt = ch;
fmt[1] = '\0';
checkfail(fmt);
diff --git a/treesource.c b/treesource.c
index 061ba8c..33fedee 100644
--- a/treesource.c
+++ b/treesource.c
@@ -124,27 +124,6 @@ static void write_propval_int(FILE *f, const char *p, size_t len, size_t width)
}
}
-static bool has_data_type_information(struct marker *m)
-{
- return m->type >= TYPE_UINT8;
-}
-
-static struct marker *next_type_marker(struct marker *m)
-{
- while (m && !has_data_type_information(m))
- m = m->next;
- return m;
-}
-
-size_t type_marker_length(struct marker *m)
-{
- struct marker *next = next_type_marker(m->next);
-
- if (next)
- return next->offset - m->offset;
- return 0;
-}
-
static const char *delim_start[] = {
[TYPE_UINT8] = "[",
[TYPE_UINT16] = "/bits/ 16 <",
@@ -229,26 +208,39 @@ static void write_propval(FILE *f, struct property *prop)
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];
+ struct marker *m_phandle;
- if (has_data_type_information(m)) {
+ if (is_type_marker(m->type)) {
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);
+ if (emit_type == TYPE_NONE || 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);
+ m_phandle = prop->val.markers;
+ for_each_marker_of_type(m_phandle, REF_PHANDLE)
+ if (m->offset == m_phandle->offset)
+ break;
+
+ if (m_phandle) {
+ if (m_phandle->ref[0] == '/')
+ fprintf(f, "&{%s}", m_phandle->ref);
+ else
+ fprintf(f, "&%s", m_phandle->ref);
+ if (chunk_len > 4) {
+ fputc(' ', f);
+ write_propval_int(f, p + 4, chunk_len - 4, 4);
+ }
+ } else {
+ write_propval_int(f, p, chunk_len, 4);
+ }
break;
case TYPE_UINT64:
write_propval_int(f, p, chunk_len, 8);
diff --git a/util.c b/util.c
index 62feff4..197fb19 100644
--- a/util.c
+++ b/util.c
@@ -33,6 +33,17 @@ char *xstrdup(const char *s)
return d;
}
+char *xstrndup(const char *s, size_t n)
+{
+ size_t len = strnlen(s, n) + 1;
+ char *d = xmalloc(len);
+
+ memcpy(d, s, len - 1);
+ d[len - 1] = '\0';
+
+ return d;
+}
+
int xavsprintf_append(char **strp, const char *fmt, va_list ap)
{
int n, size = 0; /* start with 128 bytes */
@@ -353,11 +364,11 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size)
}
/* we should now have a type */
- if ((*fmt == '\0') || !strchr("iuxs", *fmt))
+ if ((*fmt == '\0') || !strchr("iuxsr", *fmt))
return -1;
/* convert qualifier (bhL) to byte size */
- if (*fmt != 's')
+ if (*fmt != 's' && *fmt != 'r')
*size = qualifier == 'b' ? 1 :
qualifier == 'h' ? 2 :
qualifier == 'l' ? 4 : -1;
diff --git a/util.h b/util.h
index 5a4172d..9d38ede 100644
--- a/util.h
+++ b/util.h
@@ -2,6 +2,7 @@
#ifndef UTIL_H
#define UTIL_H
+#include <stdlib.h>
#include <stdarg.h>
#include <stdbool.h>
#include <getopt.h>
@@ -12,10 +13,10 @@
*/
#ifdef __GNUC__
-#ifdef __clang__
-#define PRINTF(i, j) __attribute__((format (printf, i, j)))
-#else
+#if __GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)
#define PRINTF(i, j) __attribute__((format (gnu_printf, i, j)))
+#else
+#define PRINTF(i, j) __attribute__((format (printf, i, j)))
#endif
#define NORETURN __attribute__((noreturn))
#else
@@ -60,6 +61,7 @@ static inline void *xrealloc(void *p, size_t len)
}
extern char *xstrdup(const char *s);
+extern char *xstrndup(const char *s, size_t len);
extern int PRINTF(2, 3) xasprintf(char **strp, const char *fmt, ...);
extern int PRINTF(2, 3) xasprintf_append(char **strp, const char *fmt, ...);
@@ -142,6 +144,7 @@ int utilfdt_write_err(const char *filename, const void *blob);
* i signed integer
* u unsigned integer
* x hex
+ * r raw
*
* TODO: Implement ll modifier (8 bytes)
* TODO: Implement o type (octal)
@@ -159,7 +162,7 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size);
*/
#define USAGE_TYPE_MSG \
- "<type>\ts=string, i=int, u=unsigned, x=hex\n" \
+ "<type>\ts=string, i=int, u=unsigned, x=hex, r=raw\n" \
"\tOptional modifier prefix:\n" \
"\t\thh or b=byte, h=2 byte, l=4 byte (default)";
diff --git a/version_gen.h.in b/version_gen.h.in
new file mode 100644
index 0000000..7771abb
--- /dev/null
+++ b/version_gen.h.in
@@ -0,0 +1 @@
+#define DTC_VERSION "DTC @VCS_TAG@"
diff --git a/yamltree.c b/yamltree.c
index 4e93c12..55908c8 100644
--- a/yamltree.c
+++ b/yamltree.c
@@ -29,11 +29,12 @@ char *yaml_error_name[] = {
(emitter)->problem, __func__, __LINE__); \
})
-static void yaml_propval_int(yaml_emitter_t *emitter, struct marker *markers, char *data, int len, int width)
+static void yaml_propval_int(yaml_emitter_t *emitter, struct marker *markers,
+ char *data, unsigned int seq_offset, unsigned int len, int width)
{
yaml_event_t event;
void *tag;
- int off, start_offset = markers->offset;
+ unsigned int off;
switch(width) {
case 1: tag = "!u8"; break;
@@ -66,7 +67,7 @@ static void yaml_propval_int(yaml_emitter_t *emitter, struct marker *markers, ch
m = markers;
is_phandle = false;
for_each_marker_of_type(m, REF_PHANDLE) {
- if (m->offset == (start_offset + off)) {
+ if (m->offset == (seq_offset + off)) {
is_phandle = true;
break;
}
@@ -112,8 +113,9 @@ static void yaml_propval_string(yaml_emitter_t *emitter, char *str, int len)
static void yaml_propval(yaml_emitter_t *emitter, struct property *prop)
{
yaml_event_t event;
- int len = prop->val.len;
+ unsigned int len = prop->val.len;
struct marker *m = prop->val.markers;
+ struct marker *markers = prop->val.markers;
/* Emit the property name */
yaml_scalar_event_initialize(&event, NULL,
@@ -151,19 +153,19 @@ static void yaml_propval(yaml_emitter_t *emitter, struct property *prop)
switch(m->type) {
case TYPE_UINT16:
- yaml_propval_int(emitter, m, data, chunk_len, 2);
+ yaml_propval_int(emitter, markers, data, m->offset, chunk_len, 2);
break;
case TYPE_UINT32:
- yaml_propval_int(emitter, m, data, chunk_len, 4);
+ yaml_propval_int(emitter, markers, data, m->offset, chunk_len, 4);
break;
case TYPE_UINT64:
- yaml_propval_int(emitter, m, data, chunk_len, 8);
+ yaml_propval_int(emitter, markers, data, m->offset, 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);
+ yaml_propval_int(emitter, markers, data, m->offset, chunk_len, 1);
break;
}
}