summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
l---------[-rw-r--r--]COPYING281
-rw-r--r--DCO2
-rw-r--r--LICENSES/CC0-1.0.txt121
-rw-r--r--LICENSES/GPL-2.0-only.txt350
-rw-r--r--LICENSES/GPL-2.0-or-later.txt351
-rw-r--r--LICENSES/GPL-3.0-or-later.txt672
-rw-r--r--LICENSES/LicenseRef-DCO.txt2
-rw-r--r--LICENSES/Zlib.txt19
-rw-r--r--Makefile.am30
-rw-r--r--NEWS270
-rw-r--r--README84
-rwxr-xr-xautogen.sh2
-rwxr-xr-xcheck-news.sh82
-rw-r--r--configure.ac57
-rw-r--r--m4/.gitignore2
-rw-r--r--meson.build178
-rw-r--r--meson_options.txt27
-rw-r--r--scripts/barebox-mark-successful-boot.sh2
-rw-r--r--sizes.h56
-rw-r--r--src/.gitignore2
-rw-r--r--src/asm/unaligned.h2
-rw-r--r--src/barebox-state.c110
-rw-r--r--src/barebox-state.h5
-rw-r--r--src/barebox-state/backend_bucket_circular.c18
-rw-r--r--src/barebox-state/backend_bucket_direct.c64
-rw-r--r--src/barebox-state/backend_format_dtb.c1
-rw-r--r--src/barebox-state/backend_format_raw.c7
-rw-r--r--src/barebox-state/backend_storage.c11
-rw-r--r--src/barebox-state/state.c73
-rw-r--r--src/barebox-state/state.h31
-rw-r--r--src/barebox-state/state_variables.c39
-rw-r--r--src/base64.c3
-rw-r--r--src/base64.h3
-rw-r--r--src/crc.h2
-rw-r--r--src/crc32.c3
-rw-r--r--src/crypto/digest.c4
-rw-r--r--src/crypto/hmac.c3
-rw-r--r--src/crypto/internal.h3
-rw-r--r--src/crypto/keystore.h4
-rw-r--r--src/crypto/sha.h2
-rw-r--r--src/crypto/sha1.c1
-rw-r--r--src/crypto/sha2.c1
-rw-r--r--src/digest.h4
-rw-r--r--src/driver.h2
-rw-r--r--src/dt/common.h53
-rw-r--r--src/dt/dt.h14
-rw-r--r--src/dt/fdt.h3
-rw-r--r--src/dt/list.h3
-rw-r--r--src/dtblint-imx-pinmux.c1
-rw-r--r--src/dtblint.c1
-rw-r--r--src/dtblint.h2
-rw-r--r--src/fdt.c4
-rw-r--r--src/fdt.h3
-rw-r--r--src/fdtdump.c3
-rw-r--r--src/fs.h2
-rw-r--r--src/init.h2
-rw-r--r--src/keystore-blob.c7
-rw-r--r--src/libbb.h3
-rw-r--r--src/libdt-utils.sym7
-rw-r--r--src/libdt.c526
-rw-r--r--src/libfile.h2
-rw-r--r--src/linux/err.h2
-rw-r--r--src/linux/list.h2
-rw-r--r--src/linux/mtd/mtd-abi.h2
-rw-r--r--src/linux/uuid.h25
-rw-r--r--src/module.h2
-rw-r--r--src/mtd/mtd-peb.h2
-rw-r--r--src/net.h2
-rw-r--r--src/of.h2
-rw-r--r--src/printk.h2
-rw-r--r--src/state.h49
-rw-r--r--test/01-fixed-partition-no-gpt.dts36
-rw-r--r--test/02-fixed-partition-before-gpt-partition.dts36
-rw-r--r--test/03-fixed-partition-is-gpt-partition.dts36
-rw-r--r--test/04-gpt-partition-by-partuuid.dts33
-rw-r--r--test/05-gpt-partition-by-typeuuid.dts25
-rw-r--r--test/06-fixed-partition-by-diskuuid.dts35
-rw-r--r--test/07-raw-disk-fail.dts20
-rw-r--r--test/08-gpt-disk-no-typeuuid-fail.dts20
-rw-r--r--test/09-no-disk-fail.dts28
-rw-r--r--test/31-fixed-partition-overlaps-two-gpt-partitions.dts36
-rw-r--r--test/32-fixed-partition-overlaps-two-gpt-partitions-partially.dts36
-rw-r--r--test/33-fixed-partition-part-of-gpt-partition.dts36
-rw-r--r--test/barebox-state.dtsi55
-rwxr-xr-xtest/barebox-state.t231
-rw-r--r--test/crc32.c20
-rw-r--r--test/gpt-no-typeuuid.config35
-rw-r--r--test/gpt.config37
-rw-r--r--test/meson.build38
-rw-r--r--test/raw.config26
-rwxr-xr-xtest/sharness.sh858
-rwxr-xr-xversion-gen5
-rw-r--r--version.h.in5
94 files changed, 4795 insertions, 608 deletions
diff --git a/.gitignore b/.gitignore
index 5ee5535..c7b8d9d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-only
+# Copyright 2013-2023 The DT-Utils Authors <oss-tools@pengutronix.de>
*~
*.o
.deps/
@@ -15,6 +17,8 @@ Makefile.in
/stamp-h1
/tags
/TAGS
+/build/
+/test/test-results
/fdtdump
/src/libdt-utils.pc
diff --git a/COPYING b/COPYING
index 5a965fb..c674998 100644..120000
--- a/COPYING
+++ b/COPYING
@@ -1,280 +1 @@
- 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
+LICENSES/GPL-2.0-only.txt \ No newline at end of file
diff --git a/DCO b/DCO
index 8201f99..75e56dd 100644
--- a/DCO
+++ b/DCO
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: LicenseRef-DCO
+
Developer Certificate of Origin
Version 1.1
diff --git a/LICENSES/CC0-1.0.txt b/LICENSES/CC0-1.0.txt
new file mode 100644
index 0000000..0e259d4
--- /dev/null
+++ b/LICENSES/CC0-1.0.txt
@@ -0,0 +1,121 @@
+Creative Commons Legal Code
+
+CC0 1.0 Universal
+
+ CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
+ LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
+ ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
+ INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
+ REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
+ PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
+ THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
+ HEREUNDER.
+
+Statement of Purpose
+
+The laws of most jurisdictions throughout the world automatically confer
+exclusive Copyright and Related Rights (defined below) upon the creator
+and subsequent owner(s) (each and all, an "owner") of an original work of
+authorship and/or a database (each, a "Work").
+
+Certain owners wish to permanently relinquish those rights to a Work for
+the purpose of contributing to a commons of creative, cultural and
+scientific works ("Commons") that the public can reliably and without fear
+of later claims of infringement build upon, modify, incorporate in other
+works, reuse and redistribute as freely as possible in any form whatsoever
+and for any purposes, including without limitation commercial purposes.
+These owners may contribute to the Commons to promote the ideal of a free
+culture and the further production of creative, cultural and scientific
+works, or to gain reputation or greater distribution for their Work in
+part through the use and efforts of others.
+
+For these and/or other purposes and motivations, and without any
+expectation of additional consideration or compensation, the person
+associating CC0 with a Work (the "Affirmer"), to the extent that he or she
+is an owner of Copyright and Related Rights in the Work, voluntarily
+elects to apply CC0 to the Work and publicly distribute the Work under its
+terms, with knowledge of his or her Copyright and Related Rights in the
+Work and the meaning and intended legal effect of CC0 on those rights.
+
+1. Copyright and Related Rights. A Work made available under CC0 may be
+protected by copyright and related or neighboring rights ("Copyright and
+Related Rights"). Copyright and Related Rights include, but are not
+limited to, the following:
+
+ i. the right to reproduce, adapt, distribute, perform, display,
+ communicate, and translate a Work;
+ ii. moral rights retained by the original author(s) and/or performer(s);
+iii. publicity and privacy rights pertaining to a person's image or
+ likeness depicted in a Work;
+ iv. rights protecting against unfair competition in regards to a Work,
+ subject to the limitations in paragraph 4(a), below;
+ v. rights protecting the extraction, dissemination, use and reuse of data
+ in a Work;
+ vi. database rights (such as those arising under Directive 96/9/EC of the
+ European Parliament and of the Council of 11 March 1996 on the legal
+ protection of databases, and under any national implementation
+ thereof, including any amended or successor version of such
+ directive); and
+vii. other similar, equivalent or corresponding rights throughout the
+ world based on applicable law or treaty, and any national
+ implementations thereof.
+
+2. Waiver. To the greatest extent permitted by, but not in contravention
+of, applicable law, Affirmer hereby overtly, fully, permanently,
+irrevocably and unconditionally waives, abandons, and surrenders all of
+Affirmer's Copyright and Related Rights and associated claims and causes
+of action, whether now known or unknown (including existing as well as
+future claims and causes of action), in the Work (i) in all territories
+worldwide, (ii) for the maximum duration provided by applicable law or
+treaty (including future time extensions), (iii) in any current or future
+medium and for any number of copies, and (iv) for any purpose whatsoever,
+including without limitation commercial, advertising or promotional
+purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
+member of the public at large and to the detriment of Affirmer's heirs and
+successors, fully intending that such Waiver shall not be subject to
+revocation, rescission, cancellation, termination, or any other legal or
+equitable action to disrupt the quiet enjoyment of the Work by the public
+as contemplated by Affirmer's express Statement of Purpose.
+
+3. Public License Fallback. Should any part of the Waiver for any reason
+be judged legally invalid or ineffective under applicable law, then the
+Waiver shall be preserved to the maximum extent permitted taking into
+account Affirmer's express Statement of Purpose. In addition, to the
+extent the Waiver is so judged Affirmer hereby grants to each affected
+person a royalty-free, non transferable, non sublicensable, non exclusive,
+irrevocable and unconditional license to exercise Affirmer's Copyright and
+Related Rights in the Work (i) in all territories worldwide, (ii) for the
+maximum duration provided by applicable law or treaty (including future
+time extensions), (iii) in any current or future medium and for any number
+of copies, and (iv) for any purpose whatsoever, including without
+limitation commercial, advertising or promotional purposes (the
+"License"). The License shall be deemed effective as of the date CC0 was
+applied by Affirmer to the Work. Should any part of the License for any
+reason be judged legally invalid or ineffective under applicable law, such
+partial invalidity or ineffectiveness shall not invalidate the remainder
+of the License, and in such case Affirmer hereby affirms that he or she
+will not (i) exercise any of his or her remaining Copyright and Related
+Rights in the Work or (ii) assert any associated claims and causes of
+action with respect to the Work, in either case contrary to Affirmer's
+express Statement of Purpose.
+
+4. Limitations and Disclaimers.
+
+ a. No trademark or patent rights held by Affirmer are waived, abandoned,
+ surrendered, licensed or otherwise affected by this document.
+ b. Affirmer offers the Work as-is and makes no representations or
+ warranties of any kind concerning the Work, express, implied,
+ statutory or otherwise, including without limitation warranties of
+ title, merchantability, fitness for a particular purpose, non
+ infringement, or the absence of latent or other defects, accuracy, or
+ the present or absence of errors, whether or not discoverable, all to
+ the greatest extent permissible under applicable law.
+ c. Affirmer disclaims responsibility for clearing rights of other persons
+ that may apply to the Work or any use thereof, including without
+ limitation any person's Copyright and Related Rights in the Work.
+ Further, Affirmer disclaims responsibility for obtaining any necessary
+ consents, permissions or other rights required for any use of the
+ Work.
+ d. Affirmer understands and acknowledges that Creative Commons is not a
+ party to this document and has no duty or obligation with respect to
+ this CC0 or use of the Work.
diff --git a/LICENSES/GPL-2.0-only.txt b/LICENSES/GPL-2.0-only.txt
new file mode 100644
index 0000000..9a6e1fb
--- /dev/null
+++ b/LICENSES/GPL-2.0-only.txt
@@ -0,0 +1,350 @@
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+version 2, as published by the Free Software Foundation.
+
+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.
+
+
+ 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., 51 Franklin St, 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 Library General
+Public License instead of this License.
diff --git a/LICENSES/GPL-2.0-or-later.txt b/LICENSES/GPL-2.0-or-later.txt
new file mode 100644
index 0000000..7fe1b47
--- /dev/null
+++ b/LICENSES/GPL-2.0-or-later.txt
@@ -0,0 +1,351 @@
+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.
+
+
+ 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., 51 Franklin St, 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 Library General
+Public License instead of this License.
diff --git a/LICENSES/GPL-3.0-or-later.txt b/LICENSES/GPL-3.0-or-later.txt
new file mode 100644
index 0000000..45edb01
--- /dev/null
+++ b/LICENSES/GPL-3.0-or-later.txt
@@ -0,0 +1,672 @@
+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 3 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.
+
+
+GNU GENERAL PUBLIC LICENSE
+Version 3, 29 June 2007
+
+Copyright © 2007 Free Software Foundation, Inc. <http://fsf.org/>
+
+Everyone is permitted to copy and distribute verbatim copies of this
+license document, but changing it is not allowed.
+
+Preamble
+
+The GNU General Public License is a free, copyleft license for software
+and other kinds of works.
+
+The licenses for most software and other practical works are designed to
+take away your freedom to share and change the works. By contrast, the
+GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. 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 them 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 prevent others from denying you these
+rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+For example, if you distribute copies of such a program, whether gratis
+or for a fee, you must pass on to the recipients the same freedoms that
+you received. 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.
+
+Developers that use the GNU GPL protect your rights with two steps: (1)
+assert copyright on the software, and (2) offer you this License giving
+you legal permission to copy, distribute and/or modify it.
+
+For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of protecting
+users' freedom to change the software. The systematic pattern of such
+abuse occurs in the area of products for individuals to use, which is
+precisely where it is most unacceptable. Therefore, we have designed
+this version of the GPL to prohibit the practice for those products. If
+such problems arise substantially in other domains, we stand ready to
+extend this provision to those domains in future versions of the GPL, as
+needed to protect the freedom of users.
+
+Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+The precise terms and conditions for copying, distribution and
+modification follow.
+
+TERMS AND CONDITIONS
+
+0. Definitions.
+
+“This License” refers to version 3 of the GNU General Public License.
+
+“Copyright” also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+“The Program” refers to any copyrightable work licensed under this
+License. Each licensee is addressed as “you”. “Licensees” and
+“recipients” may be individuals or organizations.
+
+To “modify” a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a “modified version” of the
+earlier work or a work “based on” the earlier work.
+
+A “covered work” means either the unmodified Program or a work based on
+the Program.
+
+To “propagate” a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+To “convey” a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+An interactive user interface displays “Appropriate Legal Notices” to
+the extent that it includes a convenient and prominently visible feature
+that (1) displays an appropriate copyright notice, and (2) tells the
+user that there is no warranty for the work (except to the extent that
+warranties are provided), that licensees may convey the work under this
+License, and how to view a copy of this License. If the interface
+presents a list of user commands or options, such as a menu, a prominent
+item in the list meets this criterion.
+
+1. Source Code.
+The “source code” for a work means the preferred form of the work for
+making modifications to it. “Object code” means any non-source form of a
+work.
+
+A “Standard Interface” means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that is
+widely used among developers working in that language.
+
+The “System Libraries” of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that Major
+Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A “Major
+Component”, in this context, means a major essential component (kernel,
+window system, and so on) of the specific operating system (if any) on
+which the executable work runs, or a compiler used to produce the work,
+or an object code interpreter used to run it.
+
+The “Corresponding Source” for a work in object code form means all the
+source code needed to generate, install, and (for an executable work)
+run the object code and to modify the work, including scripts to control
+those activities. However, it does not include the work's System
+Libraries, or general-purpose tools or generally available free programs
+which are used unmodified in performing those activities but which are
+not part of the work. For example, Corresponding Source includes
+interface definition files associated with source files for the work,
+and the source code for shared libraries and dynamically linked
+subprograms that the work is specifically designed to require, such as
+by intimate data communication or control flow between those subprograms
+and other parts of the work.
+
+The Corresponding Source need not include anything that users can
+regenerate automatically from other parts of the Corresponding Source.
+
+The Corresponding Source for a work in source code form is that same
+work.
+
+2. Basic Permissions.
+All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+You may make, run and propagate covered works that you do not convey,
+without conditions so long as your license otherwise remains in force.
+You may convey covered works to others for the sole purpose of having
+them make modifications exclusively for you, or provide you with
+facilities for running those works, provided that you comply with the
+terms of this License in conveying all material for which you do not
+control copyright. Those thus making or running the covered works for
+you must do so exclusively on your behalf, under your direction and
+control, on terms that prohibit them from making any copies of your
+copyrighted material outside their relationship with you.
+
+Conveying under any other circumstances is permitted solely under the
+conditions stated below. Sublicensing is not allowed; section 10 makes
+it unnecessary.
+
+3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article 11
+of the WIPO copyright treaty adopted on 20 December 1996, or similar
+laws prohibiting or restricting circumvention of such measures.
+
+When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to the
+covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+4. Conveying Verbatim Copies.
+You may convey 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; keep
+intact all notices stating that this License and any non-permissive
+terms added in accord with section 7 apply to the code; keep intact all
+notices of the absence of any warranty; and give all recipients a copy
+of this License along with the Program.
+
+You may charge any price or no price for each copy that you convey, and
+you may offer support or warranty protection for a fee.
+
+5. Conveying Modified Source Versions.
+You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the terms
+of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under
+ section 7. This requirement modifies the requirement in section
+ 4 to “keep intact all notices”.
+
+ c) You must license the entire work, as a whole, under this License
+ to anyone who comes into possession of a copy. This License will
+ therefore apply, along with any applicable section 7 additional
+ terms, to the whole of the work, and all its parts, regardless
+ of how they are packaged. This License gives no permission to
+ license the work in any other way, but it does not invalidate
+ such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has
+ interactive interfaces that do not display Appropriate Legal
+ Notices, your work need not make them do so.
+
+A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work, and
+which are not combined with it such as to form a larger program, in or
+on a volume of a storage or distribution medium, is called an
+“aggregate” if the compilation and its resulting copyright are not used
+to limit the access or legal rights of the compilation's users beyond
+what the individual works permit. Inclusion of a covered work in an
+aggregate does not cause this License to apply to the other parts of the
+aggregate.
+
+6. Conveying Non-Source Forms.
+You may convey a covered work in object code form under the terms of
+sections 4 and 5, provided that you also convey the machine-readable
+Corresponding Source under the terms of this License, in one of these
+ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that
+ product model, to give anyone who possesses the object code
+ either (1) a copy of the Corresponding Source for all the
+ software in the product that is covered by this License, on a
+ durable physical medium customarily used for software
+ interchange, for a price no more than your reasonable cost of
+ physically performing this conveying of source, or (2) access to
+ copy the Corresponding Source from a network server at no
+ charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially,
+ and only if you received the object code with such an offer, in
+ accord with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to
+ the Corresponding Source in the same way through the same place
+ at no further charge. You need not require recipients to copy
+ the Corresponding Source along with the object code. If the
+ place to copy the object code is a network server, the
+ Corresponding Source may be on a different server (operated by
+ you or a third party) that supports equivalent copying
+ facilities, provided you maintain clear directions next to the
+ object code saying where to find the Corresponding Source.
+ Regardless of what server hosts the Corresponding Source, you
+ remain obligated to ensure that it is available for as long as
+ needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be included
+in conveying the object code work.
+
+A “User Product” is either (1) a “consumer product”, which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for
+incorporation into a dwelling. In determining whether a product is a
+consumer product, doubtful cases shall be resolved in favor of coverage.
+For a particular product received by a particular user, “normally used”
+refers to a typical or common use of that class of product, regardless
+of the status of the particular user or of the way in which the
+particular user actually uses, or expects or is expected to use, the
+product. A product is a consumer product regardless of whether the
+product has substantial commercial, industrial or non-consumer uses,
+unless such uses represent the only significant mode of use of the
+product.
+
+“Installation Information” for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product
+from a modified version of its Corresponding Source. The information
+must suffice to ensure that the continued functioning of the modified
+object code is in no case prevented or interfered with solely because
+modification has been made.
+
+If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied by
+the Installation Information. But this requirement does not apply if
+neither you nor any third party retains the ability to install modified
+object code on the User Product (for example, the work has been
+installed in ROM).
+
+The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+Corresponding Source conveyed, and Installation Information provided, in
+accord with this section must be in a format that is publicly documented
+(and with an implementation available to the public in source code
+form), and must require no special password or key for unpacking,
+reading or copying.
+
+7. Additional Terms.
+“Additional permissions” are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by this
+License without regard to the additional permissions.
+
+When you convey a copy of a covered work, you may at your option remove
+any additional permissions from that copy, or from any part of it.
+(Additional permissions may be written to require their own removal in
+certain cases when you modify the work.) You may place additional
+permissions on material, added by you to a covered work, for which you
+have or can give appropriate copyright permission.
+
+Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders
+of that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified
+ versions of it) with contractual assumptions of liability to the
+ recipient, for any liability that these contractual assumptions
+ directly impose on those licensors and authors.
+
+All other non-permissive additional terms are considered “further
+restrictions” within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains a
+further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms of
+that license document, provided that the further restriction does not
+survive such relicensing or conveying.
+
+If you add terms to a covered work in accord with this section, you must
+place, in the relevant source files, a statement of the additional terms
+that apply to those files, or a notice indicating where to find the
+applicable terms.
+
+Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions; the above
+requirements apply either way.
+
+8. Termination.
+You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+However, if you cease all violation of this License, then your license
+from a particular copyright holder is reinstated (a) provisionally,
+unless and until the copyright holder explicitly and finally terminates
+your license, and (b) permanently, if the copyright holder fails to
+notify you of the violation by some reasonable means prior to 60 days
+after the cessation.
+
+Moreover, your license from a particular copyright holder is reinstated
+permanently if the copyright holder notifies you of the violation by
+some reasonable means, this is the first time you have received notice
+of violation of this License (for any work) from that copyright holder,
+and you cure the violation prior to 30 days after your receipt of the
+notice.
+
+Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+9. Acceptance Not Required for Having Copies.
+You are not required to accept this License in order to receive or run a
+copy of the Program. Ancillary propagation of a covered work occurring
+solely as a consequence of using peer-to-peer transmission to receive a
+copy likewise does not require acceptance. However, nothing other than
+this License grants you permission to propagate or modify any covered
+work. These actions infringe copyright if you do not accept this
+License. Therefore, by modifying or propagating a covered work, you
+indicate your acceptance of this License to do so.
+
+10. Automatic Licensing of Downstream Recipients.
+Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+An “entity transaction” is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered work
+results from an entity transaction, each party to that transaction who
+receives a copy of the work also receives whatever licenses to the work
+the party's predecessor in interest had or could give under the previous
+paragraph, plus a right to possession of the Corresponding Source of the
+work from the predecessor in interest, if the predecessor has it or can
+get it with reasonable efforts.
+
+You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may not
+impose a license fee, royalty, or other charge for exercise of rights
+granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that any
+patent claim is infringed by making, using, selling, offering for sale,
+or importing the Program or any portion of it.
+
+11. Patents.
+A “contributor” is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The work
+thus licensed is called the contributor's “contributor version”.
+
+A contributor's “essential patent claims” are all patent claims owned or
+controlled by the contributor, whether already acquired or hereafter
+acquired, that would be infringed by some manner, permitted by this
+License, of making, using, or selling its contributor version, but do
+not include claims that would be infringed only as a consequence of
+further modification of the contributor version. For purposes of this
+definition, “control” includes the right to grant patent sublicenses in
+a manner consistent with the requirements of this License.
+
+Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to make,
+use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+In the following three paragraphs, a “patent license” is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To “grant” such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+If you convey a covered work, knowingly relying on a patent license, and
+the Corresponding Source of the work is not available for anyone to
+copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. “Knowingly relying” means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify or
+convey a specific copy of the covered work, then the patent license you
+grant is automatically extended to all recipients of the covered work
+and works based on it.
+
+A patent license is “discriminatory” if it does not include within the
+scope of its coverage, prohibits the exercise of, or is conditioned on
+the non-exercise of one or more of the rights that are specifically
+granted under this License. You may not convey a covered work if you are
+a party to an arrangement with a third party that is in the business of
+distributing software, under which you make payment to the third party
+based on the extent of your activity of conveying the work, and under
+which the third party grants, to any of the parties who would receive
+the covered work from you, a discriminatory patent license (a) in
+connection with copies of the covered work conveyed by you (or copies
+made from those copies), or (b) primarily for and in connection with
+specific products or compilations that contain the covered work, unless
+you entered into that arrangement, or that patent license was granted,
+prior to 28 March 2007.
+
+Nothing in this License shall be construed as excluding or limiting any
+implied license or other defenses to infringement that may otherwise be
+available to you under applicable patent law.
+
+12. No Surrender of Others' Freedom.
+If 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 convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not convey it at all. For example, if you agree to terms that
+obligate you to collect a royalty for further conveying from those to
+whom you convey the Program, the only way you could satisfy both those
+terms and this License would be to refrain entirely from conveying the
+Program.
+
+13. Use with the GNU Affero General Public License.
+Notwithstanding any other provision of this License, you have permission
+to link or combine any covered work with a work licensed under version 3
+of the GNU Affero General Public License into a single combined work,
+and to convey the resulting work. The terms of this License will
+continue to apply to the part which is the covered work, but the special
+requirements of the GNU Affero General Public License, section 13,
+concerning interaction through a network will apply to the combination
+as such.
+
+14. Revised Versions of this License.
+The Free Software Foundation may publish revised and/or new versions of
+the GNU 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 that a certain numbered version of the GNU General Public
+License “or any later version” applies to it, you have the option of
+following the terms and conditions either of that numbered version or of
+any later version published by the Free Software Foundation. If the
+Program does not specify a version number of the GNU General Public
+License, you may choose any version ever published by the Free Software
+Foundation.
+
+If the Program specifies that a proxy can decide which future versions
+of the GNU General Public License can be used, that proxy's public
+statement of acceptance of a version permanently authorizes you to
+choose that version for the Program.
+
+Later license versions may give you additional or different permissions.
+However, no additional obligations are imposed on any author or
+copyright holder as a result of your choosing to follow a later version.
+
+15. Disclaimer of Warranty.
+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.
+
+16. Limitation of Liability.
+IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR
+CONVEYS 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.
+
+17. Interpretation of Sections 15 and 16.
+If the disclaimer of warranty and limitation of liability provided above
+cannot be given local legal effect according to their terms, reviewing
+courts shall apply local law that most closely approximates an absolute
+waiver of all civil liability in connection with the Program, unless a
+warranty or assumption of liability accompanies a copy of the Program in
+return for a fee.
+
+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 state
+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 3 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, see
+ <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program does terminal interaction, make it output a short notice
+like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program 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, your
+program's commands might be different; for a GUI interface, you would
+use an “about box”.
+
+You should also get your employer (if you work as a programmer) or
+school, if any, to sign a “copyright disclaimer” for the program, if
+necessary. For more information on this, and how to apply and follow the
+GNU GPL, see <http://www.gnu.org/licenses/>.
+
+The GNU 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. But first,
+please read <http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/LICENSES/LicenseRef-DCO.txt b/LICENSES/LicenseRef-DCO.txt
new file mode 100644
index 0000000..b5b12d7
--- /dev/null
+++ b/LICENSES/LicenseRef-DCO.txt
@@ -0,0 +1,2 @@
+Everyone is permitted to copy and distribute verbatim copies of this
+license document, but changing it is not allowed.
diff --git a/LICENSES/Zlib.txt b/LICENSES/Zlib.txt
new file mode 100644
index 0000000..4dd43e5
--- /dev/null
+++ b/LICENSES/Zlib.txt
@@ -0,0 +1,19 @@
+zlib License
+
+This software is provided 'as-is', without any express or implied warranty. In
+no event will the authors be held liable for any damages arising from the use of
+this software.
+
+Permission is granted to anyone to use this software for any purpose, including
+commercial applications, and to alter it and redistribute it freely, subject to
+the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim
+ that you wrote the original software. If you use this software in a product,
+ an acknowledgment in the product documentation would be appreciated but is
+ not required.
+
+2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source distribution.
diff --git a/Makefile.am b/Makefile.am
index a2f8545..c797fb0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,4 +1,20 @@
-EXTRA_DIST =
+# SPDX-License-Identifier: GPL-2.0-only
+# Copyright 2013-2023 The DT-Utils Authors <oss-tools@pengutronix.de>
+
+MESON_FILES = \
+ check-news.sh \
+ meson.build \
+ meson_options.txt \
+ version-gen \
+ version.h.in
+
+EXTRA_DIST = \
+ $(MESON_FILES) \
+ autogen.sh \
+ DCO \
+ LICENSES/* \
+ test/*
+
CLEANFILES =
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
AM_MAKEFLAGS = --no-print-directory
@@ -27,15 +43,16 @@ AM_LDFLAGS = \
# then increment age.
# If any interfaces have been removed or changed since the last release,
# then set age to 0.
-LIBDT_CURRENT=4
-LIBDT_REVISION=0
+LIBDT_CURRENT=6
+LIBDT_REVISION=1
LIBDT_AGE=0
pkginclude_HEADERS = \
src/dt/dt.h \
src/dt/fdt.h \
src/dt/list.h \
- src/dt/common.h
+ src/dt/common.h \
+ src/linux/uuid.h
lib_LTLIBRARIES = src/libdt-utils.la
bin_PROGRAMS = barebox-state dtblint fdtdump
@@ -107,3 +124,8 @@ src_libdt_utils_la_LDFLAGS = $(AM_LDFLAGS) \
src_libdt_utils_la_DEPENDENCIES = ${top_srcdir}/src/libdt-utils.sym
EXTRA_DIST += scripts/barebox-mark-successful-boot.sh
+
+filesums: $(distdir).tar.xz
+ md5sum $(distdir).tar.xz > $(distdir).tar.xz.md5
+ sha1sum $(distdir).tar.xz > $(distdir).tar.xz.sha1
+ sha256sum $(distdir).tar.xz > $(distdir).tar.xz.sha256
diff --git a/NEWS b/NEWS
index b876f6a..fa7afca 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,273 @@
+# SPDX-License-Identifier: GPL-2.0-only
+# Copyright 2013-2023 The DT-Utils Authors <oss-tools@pengutronix.de>
+
+dt-utils 2023.11.0
+==================
+
+A small bugfix release, mainly consisting of the following commit:
+
+* commit b67e96895f52 "libdt: prefer first found disk when looking for block
+ devices"
+ When using barebox-state on boards with a barbeox-state partition on an eMMC
+ device, it could happen that barebox-state tried to find a GPT partition on
+ /dev/mmcblkXbootN instead of /dev/mmcblkX, obviously failing to find a
+ matching partition there, and quitting without any further action. This commit
+ restores the old behaviour of using the first found MMC device (/dev/mmcblkX)
+ instead of the last one. Although this is not completely future-proof, it has
+ worked for years and serves a good stop-gap solution for now.
+
+A few more housekeeping and maintenance commits:
+
+* commit feca1c1ffdaa "README: provide git format.subjectPrefix line to copy"
+* commit 1cd62596dbd7 "meson: align libdt-utils version with autotools'"
+
+This release includes contributions by Ahmad Fatoum, Enrico Jörns, Leonard
+Göhrs, and Roland Hieber. Thank you to all contributors!
+
+dt-utils 2023.08.0
+==================
+
+This release includes contributions by Ahmad Fatoum, Alexander Shiyan,
+Christian Eggers, Marco Felsch, Michael Olbrich, Roland Hieber, Sascha Hauer,
+Ulrich Ölmann, Uwe Kleine-König, and Yegor Yefremov.
+
+Possibly breaking changes
+-------------------------
+
+(none known)
+
+New features
+------------
+
+* commit f80d96b15978 "libdt: add support for barebox,storage-by-uuid" added
+ support for specifying barebox-state backend nodes in the device tree using
+ the 'barebox,storage-by-uuid' compatible. The similarly-named Barebox driver
+ looks for a storage device matching the given UUID, and when found registers a
+ new device for it. This makes it possible to use GPT and MBR partitions as
+ state backends without re-stating their respective partition tables in the
+ device tree.
+
+* commit bfa8e8eab135 "state: automatically find state.dtb in the ESP"
+ implemented auto-detection of device trees on the EFI System Partition in
+ /boot or /efi (the usual ESP mount points on most Linux distributions).
+
+* barebox-state can now auto-detect state partitions on GPT if they have the
+ Partition Type GUID 4778ed65-bf42-45fa-9c5b-287a1dc4aab1, which corresponds to
+ a feature merged in Barebox v2023.07.0 (see commits leading up to
+ <https://git.pengutronix.de/cgit/barebox/commit/?id=776714d9570253c46635>).
+ - commit 2bab30b7d653 "libdt: add of_property_write_strings support"
+ - commit c4ea02e5fb6e "libdt: generalize of_find_device_by_uuid for scoped lookup of all UUIDs"
+ - commit 7de908382bed "libdt: fix of_get_devicepath looking up sibling if device unavailable"
+ - commit 03a6d0146f5a "state: backend: direct: open block device in read-only mode if possible"
+ - commit 86233cfe9ba5 "libdt: factor out u64 sysattr parsing into helper"
+ - commit c458361777ab "libdt: drop broken if-branch"
+ - commit cff3f1c19d78 "libdt: factor out __of_cdev_find helper"
+ - commit 7a71beff497e "libdt: use block device partition instead of parent if found"
+ - commit 72970a627990 "state: align with barebox use of of_cdev_find"
+ - commit 5059165acd2b "libdt: use of_find_device_by_uuid for partuuid lookup"
+ - commit b32cb1c15c42 "state: allow lookup of barebox state partition by Type GUID"
+
+* commit 0976c48731ef "state: add option to lock device node" implemented
+ locking the device node directly via flock() in the barebox-state tool instead
+ of writing a lock file to the /run directory. This helps on systems that don't
+ have a world-writeable /run. Currently the behaviour is disabled by default
+ and can be enabled by the ./configure --enable-lock-device option and the
+ 'lock-device' option in meson.
+
+* Meson was added as a build system. The support is currently experimental, but
+ the plan is to phase out autotools in the future, but for now the old way of
+ building the project will stay in place. See the updated instruction in the
+ README for how to build dt-utils and run the new unit tests.
+ - commit bc6e5d24916f "Add meson as build system"
+ - commit 4e7ad815b856 "meson: options: use defaults of type boolean for boolean options"
+ - commit 6dc8b1a948cf "meson: set optimization level to -O2 by default"
+ - commit fc97420e830c "Makefile: include meson files in the dist tarball"
+
+* There is now an initial set of unit tests, see the README on how to run them.
+ - commit e5c524875a91 "meson: add simple integration test"
+ - commit be44af10aa91 "libdt: add CONFIG_TEST_LOOPBACK"
+ - commit 69a223619e28 "test: add barebox-state loop block device tests"
+ - commit 885bb2feac99 "test: add test case with non-existent /dev/file"
+
+* All files now have machine-readable license and copyright information, and the
+ project conforms to the REUSE specification (see <https://reuse.software/>).
+ You can build a Software Bill of Materials in SPDX format by running the
+ 'reuse spdx' command.
+ - commit 893c6c9f628f "treewide: add SPDX identifiers to files with GPL-2.0-only license"
+ - commit c1880166d1e3 "treewide: add SPDX identifiers to files with GPL-2.0-or-later license"
+ - commit af84fa465d69 "treewide: add SPDX identifiers to files with GPL-3.0-or-later license"
+ - commit fa56be74c3bd "treewide: add SPDX identifier to file with Zlib license"
+ - commit 6c7ccb22ea30 "treewide: add CC0-1.0 SPDX identifiers for trivial files"
+ - commit 75b7b2bce1d9 "treewide: add GPL-2.0-only SPDX identifiers to files without license"
+ - commit 95d6b5c4c95d "treewide: add trivial copyright headers"
+ - commit 18416bd75b83 "DCO: add SPDX license information"
+ - commit 681180373d82 "README: mention compatibility with the REUSE specification"
+
+Bug fixes
+---------
+
+* commit 81d5a909d690 "configure: pass -fno-strict-aliasing to GCC"
+* commit 10743d54b420 "libdt: fix issues of external function without prototype"
+* commit 6fd6d7ffff6d "libdt: use memcpy instead of strncpy"
+* commit f4f3b62ad229 "barebox-state: fix use after free in error path"
+
+* Bug fixes ported from Barebox:
+ - commit 624ef0ec9a83 "state: backend_raw: fix ignoring unpack failures"
+ - commit 39d574a4147e "state: backend_storage: deal gracefully with runtime bucket corruption"
+ - commit 5944ccf83477 "state: treat state with all-invalid buckets as dirty"
+ - commit 2524cbe1a879 "state: propagate failure to fixup enum32 into DT"
+ - commit 74d1803dd3b2 "common: xstrdup: don't panic on xstrdup(NULL)"
+
+Refactoring
+-----------
+
+* commit 5a9036656149 "libdt: only requires a partname for mtd"
+
+General maintenance and housekeeping
+------------------------------------
+
+* commit 1872584786ca "Makefile: add a helpful 'filesums' target"
+* commit 50f7f71f81da "treewide: remove references to CREDITS file"
+* commit b30a3162f2f9 "update README"
+* commit 181479122870 "configure: improve state-backward-compatibility help text"
+* commit 89701c0867eb "README: add link to lore mail archive"
+* commit 783a1c00de61 "configure: fix state-backward-compatibility help text"
+* commit 37a46daa6302 "sizes.h: remove unreferenced file"
+* commit db54c5f4be08 "libdt: don't use old-style function definition"
+* commit 6d60e2d68c1f "README: fix Git repository URL"
+* commit 0b194c865e3f "README: clarify the need for "real names" with the DCO process"
+* commit 3ed8bc213a82 "Makefile: include missing files in the dist tarball"
+
+* Maintenance changes ported from Barebox:
+ - commit b5ae056f25c5 "state: Remove duplicate incudes"
+ - commit 78346955f4a1 "state: remove param member from struct state_string"
+ - commit af4951b6f36a "state: remove param member from state_uint32, state_enum32, state_mac"
+ - commit a761f9ba04d9 "state: remove unused function"
+ - commit fb3452fca971 "state: add SPDX-License-Identifier for files without explicit license"
+ - commit 5fb31b446022 "state: fix typos found with codespell"
+
+
+dt-utils 2021.03.0
+==================
+
+This release includes contributions from Ahmad Fatoum, Andrey Smirnov, Enrico
+Jorns, Jan Luebbe, Jan Remmet, Jookia, Juergen Borleis, Kim Christensen, Lucas
+Stach, Roland Hieber, Sascha Hauer, Stefan Agner, Steffen Trumtrar, Ulrich
+Ölmann, Uwe Kleine-König and Xogium. Thanks to all contributors!
+
+Possibly breaking changes
+-------------------------
+
+* commit a6ca873a368d "Don't install a pkg-config file for libdt"
+ libdt isn't supposed to be installed as a system library as nobody wants to care about things like
+ a stable API. Also the generated .pc file was completely bogus as it added "-labc" to the linker
+ instead of -ldt-utils.
+
+* commit 2dbca4c3284b "state: keep backward compatibility"
+ This changes barebox-state's default behaviour.
+ Previous variants of the state variable set did not contain metadata. The read function in the
+ 'direct' storage backend honors this, but the write function doesn't, which makes an update of the
+ state variable set impossible.
+ This commit introduces the new compile time option '--enable-state-backward-compatibility' to
+ ./configure, which is disabled by default. If this compile time option is enabled, barebox-state
+ will keep the storage in a format that can be read by barebox <= v2016.08.0 when writing variables
+ into a 'direct' storage backend, or fail if this requirement cannot be guaranteed.
+
+* commit d1e4783c0051 "follow the Developer's Certificate of Origin",
+ commit 886f13aa31a6 "Makefile: add ./DCO to the dist tarball"
+ (see files README and DCO)
+
+New features
+------------
+
+* libdt:
+ - commit af85ab844b1d "libdt: support finding devices by partuuid",
+ commit 9f3915824bc7 "libdt: support upper-case hexadecimals in value of partuuid property"
+ This allows specifying partitions in devicetree that are actually not described in the
+ devicetree to allow referencing them, e.g.:
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ state_part: state {
+ partuuid = "21367da7-c51f-499f-9aad-e1f366992365";
+ };
+ };
+ - commit 4826dcbce749 "libdt: enumerate amba bus as well"
+ Make barebox-state usable on STM32MP1, which probes the SD/MMC host controller over amba, not
+ the platform bus as most other ARM systems.
+
+* barebox-state:
+ - add new options --quiet, --force, and --version
+ . commit 52221e50b0df "barebox-state: complete cmdline options"
+ . commit 15786485ab8b "barebox-state: add cmdline option "--version""
+ - commit 74cd46affa37 "barebox-state: get devicetree from file"
+ Adds an -i/--input argument to barebox-state to allow passing a devicetree as a file instead of
+ using it from the system. This can be used for example on systems that do not use device trees
+ (such as x86) but where we want to use a dtb blob for describing the state storage and format.
+ - commit 0a75604bc61f "barebox-state: have the --set option to avoid writes if possible"
+ Previously, barebox-state --set would always dirty the state when successful. Users seeking to
+ conserve write cycles thus have to --get the variable in question first to check whether to
+ write it. Make life of such users easier by having barebox-state support this out-of-the-box.
+
+* dtblint:
+ - commit 38d7af00e6cb "dtblint: check reset-gpio-active-high + reset-gpio for matching polarity"
+ - commit 8498644efe82 "dtblint: add support for fsl,imx6dl-iomuxc"
+ - commit a75ea34157c5 "dtblint: fsl,iomuxc: improve check for reserved bits"
+
+Bug Fixes
+---------
+
+* barebox-state:
+ - commit 99918b8f3ad2 "barebox-state: fix usage of multiple state instances"
+ This makes concurrent calls to barebox-state with the following syntax possible:
+ $ barebox-state --get blue.x &
+ $ barebox-state --get yellow.y &
+ - commit 634317cc9120 "state: backend_bucket_circular: fix double free()"
+ - commit ef7355cccc3a "state: Fix lseek error check in state_backend_bucket_direct_read()"
+ - commit d59af7f22ab4 "state: Fix lseek error check in state_backend_bucket_direct_write()"
+ - commit f234f3ec9498 "state: Fix lseek error check in state_mtd_peb_read()"
+ - commit b85142e1cbd4 "state: Fix lseek error check in state_mtd_peb_write()"
+ - commit a1fe3159ca2a "state: check length"
+ - commit b548f61a0460 "state: backend_bucket_circular: mark block as bad if mtd_peb_torture() failed"
+ - commit fd48fe4efb40 "state: use /run to store lockfile"
+ The old location /var/lock is considered legacy, and might no longer exist on all systems.
+
+* dtblint:
+ - commit 1ec150f6927f "dtblint-imx-pinmux: fix wrong table entry"
+ - commit 218b148b284c "dtblint-imx-pinmux: fix another set of wrong table entries"
+ - commit 186ff7702c66 "dtblint-imx-pinmux: fix swmux suggested values"
+ - commit 5b58e1fc72e9 "dtblint-imx-pinmux: fix another set of wrong table entries"
+
+Refactoring
+-----------
+
+* state: harmonise our code with barebox
+ - commit 6ae166207bc8 "common: align declarations of dev_add_param_*() functions with barebox"
+
+* several smaller bugfixes, typo fixes, and cleanup:
+ - commit 0cd8a9b06523 "of_get_devicepath: again correct comment"
+ - commit 8c3b39c89307 "barebox-state: fix error message"
+ - commit a927ee527036 "state: fix typo"
+ - commit 9106360a3c85 "barebox-state: remove declaration of __state_uint8_get()"
+ - commit e210e3b79be8 "barebox-state: remove unused variables"
+ - commit 338b9962e28a "keystore-blob: remove unused variable"
+ - commit 949bab33700e "base64: remove unused variable"
+ - commit fc86ad03b4dc "base64: remove duplicate ‘const’ declaration specifier"
+ - commit 89d033284cb6 "state: fix formatting of "off_t" variables"
+ - commit 5588a6c32d54 "state: fix formatting of "uint32_t" variables"
+ - commit 4bfd158f068d "remove leftovers from libabc skeleton"
+ - commit baee943b2c98 "state: drop unused code and declarations for non-existing functions"
+ - commit 20fb10ce5d55 "state: backend_storage: harmonize code with barebox"
+ - commit e267c877e2ee "state: harmonize code with barebox"
+ - commit 1aeb1e4fdff0 "state: harmonize code with barebox"
+ - commit 81c542966f99 "configure: remove build time option '--disable-logging'"
+ (which wasn't used anywhere)
+ - commit 8874600851ac "configure: remove build time option '--enable-debug'"
+ (which wasn't used anywhere)
+ - commit 5f1eb84d2364 "configure: update repository URL"
+
+
dt-utils 2019.01.0
==================
This release includes contributions from Andrey Smirnov, Antony Pavlov, Daniel Schultz, Enrico
diff --git a/README b/README
index 7b981d3..c6ef99c 100644
--- a/README
+++ b/README
@@ -1,15 +1,83 @@
-Questions, feedback, patches please email:
- oss-tools@pengutronix.de
+# SPDX-License-Identifier: GPL-2.0-only
-For patches, please prefix your subject with "[PATCH dt-utils]" (for example,
-see the git-config manpage for the option format.subjectPrefix).
+Utilities to work with device trees in Linux userspace
+
+The following tools are available:
+
+* barebox-state: access barebox' state storage
+* fdtdump: dump a device tree binary to stdout
+* dtblint: lint a compiled device tree
+
+For questions, feedback, patches, please send a mail to
+
+ <oss-tools@pengutronix.de>
+
+Note: you must be subscribed to post to this mailing list. You can do so by
+sending an empty mail to <oss-tools-subscribe@pengutronix.de>.
+
+Building from Sources
+---------------------
+
+Check out the latest state from Git:
+
+ git clone https://git.pengutronix.de/git/tools/dt-utils
+ cd dt-utils
+
+And then build using autotools:
+
+ ./autogen.sh
+ ./configure
+ make
+
+There's also experimental support for building with meson.
+The intention is to deprecate autotools eventually in its favor. To build:
+
+ meson setup build
+ meson compile -C build
+ meson test -C build # optional
+
+Contributing
+------------
+
+The Git web view for this software can be found at:
+
+ <https://git.pengutronix.de/cgit/tools/dt-utils>
+
+Any patches should be sent to the mailing list above. Please prefix your
+subject with "[PATCH dt-utils]". This can be configured in Git with:
+
+ git config format.subjectPrefix "PATCH dt-utils"
+
+Mails sent to this mailing list are also archived at
+
+ <https://lore.pengutronix.de/oss-tools/>
This project uses the Developer's Certificate of Origin, as stated in the file
-DCO in this repository, with the same process as used for the Linux kernel:
-<https://www.kernel.org/doc/html/latest/process/submitting-patches.html#sign-your-work-the-developer-s-certificate-of-origin>
+DCO bundled with this software, using the same process as for the Linux kernel:
+
+ <https://www.kernel.org/doc/html/latest/process/submitting-patches.html#sign-your-work-the-developer-s-certificate-of-origin>
+
By adding a Signed-off-by line (e.g. using `git commit -s`) saying
Signed-off-by: Random J Developer <random@developer.example.org>
-(using your real name and e-mail address), you state that your contributions
-are in line with the DCO.
+(using your known identity), you state that your contributions are in line with
+the DCO.
+
+License
+-------
+
+Copyright (C) 2021 Pengutronix and contributors
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License, version 2 as published by the Free
+Software Foundation.
+
+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 (the file COPYING
+bundled with this software) for more details.
+
+The dt-utils project conforms to the REUSE specification. You can use the
+'reuse' tool to get a Software Bill of Materials in SPDX format. For more
+information, see <https://reuse.software/>.
diff --git a/autogen.sh b/autogen.sh
index 0d60b0a..2a6bb35 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -1,4 +1,6 @@
#!/bin/sh -e
+# SPDX-License-Identifier: GPL-2.0-only
+# Copyright 2013-2023 The DT-Utils Authors <oss-tools@pengutronix.de>
if [ -f .git/hooks/pre-commit.sample -a ! -f .git/hooks/pre-commit ] ; then
cp -p .git/hooks/pre-commit.sample .git/hooks/pre-commit && \
diff --git a/check-news.sh b/check-news.sh
new file mode 100755
index 0000000..681a92a
--- /dev/null
+++ b/check-news.sh
@@ -0,0 +1,82 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-3.0-or-later
+# Copyright (C) 2019 Red Hat, Inc.
+# Author: Bastien Nocera <hadess@hadess.net>
+#
+# 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 3 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.
+
+
+# Add to your top-level meson.build to check for an updated NEWS file
+# when doing a "dist" release, similarly to automake's check-news:
+# https://www.gnu.org/software/automake/manual/html_node/List-of-Automake-options.html
+#
+# Checks NEWS for the version number:
+# meson.add_dist_script(
+# find_program('check-news.sh').path(),
+# '@0@'.format(meson.project_version())
+# )
+#
+# Checks NEWS and data/foo.appdata.xml for the version number:
+# meson.add_dist_script(
+# find_program('check-news.sh').path(),
+# '@0@'.format(meson.project_version()),
+# 'NEWS',
+# 'data/foo.appdata.xml'
+# )
+
+usage()
+{
+ echo "$0 VERSION [FILES...]"
+ exit 1
+}
+
+check_version()
+{
+ VERSION=$1
+ # Look in the first 15 lines for NEWS files, but look
+ # everywhere for other types of files
+ if [ "$2" = "NEWS" ]; then
+ DATA=`sed 15q $SRC_ROOT/"$2"`
+ else
+ DATA=`cat $SRC_ROOT/"$2"`
+ fi
+ case "$DATA" in
+ *"$VERSION"*)
+ :
+ ;;
+ *)
+ echo "$2 not updated; not releasing" 1>&2;
+ exit 1
+ ;;
+ esac
+}
+
+SRC_ROOT=${MESON_DIST_ROOT:-"./"}
+
+if [ $# -lt 1 ] ; then usage ; fi
+
+VERSION=$1
+shift
+
+if [ $# -eq 0 ] ; then
+ check_version $VERSION 'NEWS'
+ exit 0
+fi
+
+for i in $@ ; do
+ check_version $VERSION "$i"
+done
+
+exit 0
diff --git a/configure.ac b/configure.ac
index 777f495..b0e6129 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,9 +1,12 @@
+# SPDX-License-Identifier: GPL-2.0-only
+# Copyright 2013-2023 The DT-Utils Authors <oss-tools@pengutronix.de>
+
AC_PREREQ(2.60)
AC_INIT([dt-utils],
- [2019.01.0],
+ [2023.11.0],
[oss-tools@pengutronix.de],
[dt-utils],
- [http://git.pengutronix.de/?p=tools/dt-utils.git;a=summary])
+ [https://git.pengutronix.de/cgit/tools/dt-utils])
AC_CONFIG_SRCDIR([src/libdt.c])
AC_CONFIG_AUX_DIR([build-aux])
AM_INIT_AUTOMAKE([check-news foreign 1.11 -Wall -Wno-portability silent-rules tar-pax no-dist-gzip dist-xz subdir-objects])
@@ -18,27 +21,38 @@ AC_PREFIX_DEFAULT([/usr])
AC_PROG_SED
AC_PROG_MKDIR_P
-AC_ARG_ENABLE([logging],
- AS_HELP_STRING([--disable-logging], [disable system logging @<:@default=enabled@:>@]),
- [], enable_logging=yes)
-AS_IF([test "x$enable_logging" = "xyes"], [
- AC_DEFINE(ENABLE_LOGGING, [1], [System logging.])
+AC_ARG_ENABLE([state-backward-compatibility],
+ AS_HELP_STRING([--enable-state-backward-compatibility], [barebox-state: when using the 'direct' storage backend, keep the on-disk format readable by barebox <= v2016.08.0 @<:@default=disabled@:>@]),
+ [], [enable_state_backward_compatibility=no])
+AS_IF([test "x${enable_state_backward_compatibility}" = "xyes"], [
+ AC_DEFINE(CONFIG_STATE_BACKWARD_COMPATIBLE, [1], ['direct' storage backend backward compatibility.])
+], [
+ AC_DEFINE(CONFIG_STATE_BACKWARD_COMPATIBLE, [0])
])
-AC_ARG_ENABLE([debug],
- AS_HELP_STRING([--enable-debug], [enable debug messages @<:@default=disabled@:>@]),
- [], [enable_debug=no])
-AS_IF([test "x$enable_debug" = "xyes"], [
- AC_DEFINE(DEBUG, [1], [Debug messages.])
+AC_ARG_ENABLE([lock-device],
+ AS_HELP_STRING([--enable-lock-device], [barebox-state: lock device node instead of global lock in /run @<:@default=disabled@:>@]),
+ [], [enable_lock_device=no])
+AS_IF([test "x${enable_lock_device}" = "xyes"], [
+ AC_DEFINE(CONFIG_LOCK_DEVICE_NODE, [1], [lock device node backing state.])
+], [
+ AC_DEFINE(CONFIG_LOCK_DEVICE_NODE, [0], [use global lock in /run.])
])
+AC_DEFINE(CONFIG_MTD, [1], [Statically define to be enabled to harmonize barebox' & dt-utils' code base.])
+
+AC_DEFINE(CONFIG_STATE, [1], [Statically define to be enabled to harmonize barebox' & dt-utils' code base.])
+
+AC_DEFINE(CONFIG_TEST_LOOPBACK, [0], [Only enabled in meson for testing.])
+
AC_CHECK_FUNCS([__secure_getenv secure_getenv])
my_CFLAGS="-Wall \
-Wmissing-declarations -Wmissing-prototypes \
-Wnested-externs -Wsign-compare -Wchar-subscripts \
-Wstrict-prototypes -Wshadow \
--Wformat-security -Wtype-limits"
+-Wformat-security -Wtype-limits \
+-fno-strict-aliasing"
AC_SUBST([my_CFLAGS])
PKG_CHECK_MODULES(UDEV, [libudev])
@@ -53,15 +67,14 @@ AC_MSG_RESULT([
$PACKAGE $VERSION
=====
- prefix: ${prefix}
- sysconfdir: ${sysconfdir}
- libdir: ${libdir}
- includedir: ${includedir}
+ prefix: ${prefix}
+ sysconfdir: ${sysconfdir}
+ libdir: ${libdir}
+ includedir: ${includedir}
- compiler: ${CC}
- cflags: ${CFLAGS}
- ldflags: ${LDFLAGS}
+ compiler: ${CC}
+ cflags: ${CFLAGS}
+ ldflags: ${LDFLAGS}
- logging: ${enable_logging}
- debug: ${enable_debug}
+ state-backward-compatibility: ${enable_state_backward_compatibility}
])
diff --git a/m4/.gitignore b/m4/.gitignore
index 8bab51c..1d67dbd 100644
--- a/m4/.gitignore
+++ b/m4/.gitignore
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-only
+# Copyright 2013-2023 The DT-Utils Authors <oss-tools@pengutronix.de>
libtool.m4
ltoptions.m4
ltsugar.m4
diff --git a/meson.build b/meson.build
new file mode 100644
index 0000000..bf60171
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,178 @@
+# SPDX-License-Identifier: GPL-2.0-only
+# Copyright 2013-2023 The DT-Utils Authors <oss-tools@pengutronix.de>
+# Homepage: https://git.pengutronix.de/cgit/tools/dt-utils
+
+project(
+ 'dt-utils',
+ 'c',
+ version : '2023.11.0',
+ meson_version : '>=0.51',
+ default_options: [
+ 'c_std=gnu11',
+ 'warning_level=2',
+ 'optimization=2',
+ ],
+ license : 'GPL-2.0-only',
+)
+
+cc = meson.get_compiler('c')
+
+conf = configuration_data()
+# Statically define to be enabled to harmonize barebox' & dt-utils' code base.
+conf.set10('CONFIG_MTD', true)
+conf.set10('CONFIG_STATE', true)
+conf.set10('CONFIG_STATE_BACKWARD_COMPATIBLE', get_option('state-backward-compatibility'))
+conf.set10('CONFIG_LOCK_DEVICE_NODE', get_option('lock-device'))
+conf.set10('CONFIG_TEST_LOOPBACK', get_option('tests'))
+
+meson.add_dist_script(
+ find_program('check-news.sh').path(),
+ '@0@'.format(meson.project_version())
+)
+
+prefixdir = get_option('prefix')
+if not prefixdir.startswith('/')
+ error('Prefix is not absolute: "@0@"'.format(prefixdir))
+endif
+sysconfdir = join_paths(prefixdir, get_option('sysconfdir'))
+conf.set('SYSCONFDIR', sysconfdir)
+libexecdir = join_paths(prefixdir, get_option('libexecdir'))
+conf.set('LIBEXECDIR', libexecdir)
+
+udevdep = dependency('libudev')
+
+c_flags = '''
+ -fno-strict-aliasing
+ -ffunction-sections
+ -fdata-sections
+'''.split()
+
+c_warn_flags = '''
+ -Wmissing-declarations
+ -Wmissing-prototypes
+ -Wnested-externs
+ -Wno-sign-compare
+ -Wno-unused-parameter
+ -Wchar-subscripts
+ -Wstrict-prototypes
+ -Wshadow
+ -Wformat-security
+ -Wtype-limits
+ -Wno-pointer-sign
+ -Wno-shadow
+'''.split()
+c_flags += cc.get_supported_arguments(c_warn_flags)
+add_project_arguments(c_flags, language : 'c')
+# enable GNU extensions (required!)
+add_project_arguments('-D_GNU_SOURCE', language : 'c')
+
+ld_flags = '''
+ -Wl,--gc-sections
+ -Wl,--as-needed
+'''.split()
+
+incdir = include_directories(['src/dt', 'src'])
+
+sources_libdt = files('''
+ src/crc32.c
+ src/libdt.c
+ src/fdt.c
+'''.split())
+
+if get_option('barebox-state')
+ sources_barebox_state = files('''
+ src/crypto/digest.c
+ src/crypto/hmac.c
+ src/crypto/sha1.c
+ src/crypto/sha2.c
+ src/keystore-blob.c
+ src/base64.c
+ src/barebox-state/backend_bucket_circular.c
+ src/barebox-state/backend_bucket_direct.c
+ src/barebox-state/backend_format_dtb.c
+ src/barebox-state/backend_format_raw.c
+ src/barebox-state/backend_storage.c
+ src/barebox-state/state.c
+ src/barebox-state/state_variables.c
+ src/barebox-state.c
+ '''.split())
+endif
+
+sources_dtblint = files('''
+ src/dtblint.c
+ src/dtblint-imx-pinmux.c
+ src/dtblint.h
+'''.split())
+
+sources_fdtdump = files('''
+src/fdtdump.c
+'''.split())
+
+config_h = configure_file(
+ output : 'config.h',
+ configuration : conf
+)
+add_project_arguments('-include', meson.current_build_dir() / 'config.h', language : 'c')
+
+version_h = vcs_tag(
+ input : 'version.h.in',
+ output : 'version.h',
+)
+versiondep = declare_dependency(sources: version_h)
+
+meson.add_dist_script('version-gen', meson.project_version())
+
+# If the library source code has changed at all since the last release,
+# then increment revision (‘c:r:a’ becomes ‘c:r+1:a’).
+# If any interfaces have been added/removed/changed since the last release,
+# then increment current, and set revision to 0.
+# If any public interfaces have been added since the last public release,
+# then increment age.
+# If any interfaces have been removed or changed since the last release,
+# then set age to 0.
+lt_current = 6
+lt_revision = 1
+lt_age = 0
+
+mapfile = 'src/libdt-utils.sym'
+libdt_ld_flags = '-Wl,--version-script,@0@/@1@'.format(meson.current_source_dir(), mapfile)
+
+libdt = shared_library('dt-utils',
+ sources_libdt,
+ include_directories : incdir,
+ link_args : ld_flags + ['-Wl,--no-undefined', libdt_ld_flags],
+ link_depends : mapfile,
+ c_args : ['-include', meson.current_build_dir() / 'version.h'],
+ dependencies : [udevdep, versiondep],
+ gnu_symbol_visibility : 'default',
+ version: '@0@.@1@.@2@'.format(lt_current - lt_age, lt_age, lt_revision),
+ install : true)
+
+executable('barebox-state',
+ sources_barebox_state,
+ include_directories : incdir,
+ link_args : ld_flags,
+ c_args : ['-include', meson.current_build_dir() / 'version.h'],
+ dependencies : [versiondep],
+ link_with : libdt,
+ install : true)
+
+executable('fdtdump',
+ sources_fdtdump,
+ include_directories : incdir,
+ link_args : ld_flags,
+ c_args : ['-include', meson.current_build_dir() / 'version.h'],
+ dependencies : [versiondep],
+ link_with : libdt,
+ install : true)
+
+executable('dtblint',
+ sources_dtblint,
+ include_directories : incdir,
+ link_args : ld_flags,
+ c_args : ['-include', meson.current_build_dir() / 'version.h'],
+ dependencies : [versiondep],
+ link_with : libdt,
+ install : true)
+
+subdir('test')
diff --git a/meson_options.txt b/meson_options.txt
new file mode 100644
index 0000000..503941b
--- /dev/null
+++ b/meson_options.txt
@@ -0,0 +1,27 @@
+# SPDX-License-Identifier: GPL-2.0-only
+# Copyright 2023 The DT-Utils Authors <oss-tools@pengutronix.de>
+# feature options
+option(
+ 'state-backward-compatibility',
+ type : 'boolean',
+ value : false,
+ description : 'barebox-state: when using the "direct" storage backend, keep the on-disk format readable by barebox <= v2016.08.0')
+
+option(
+ 'lock-device',
+ type : 'boolean',
+ value : false,
+ description : 'lock device node instead of creating lockfile in /run')
+
+# build options
+option(
+ 'barebox-state',
+ type : 'boolean',
+ value : true,
+ description : 'Build barebox-state utility')
+
+option(
+ 'tests',
+ type : 'boolean',
+ value : true,
+ description : 'Enable/Disable test suite')
diff --git a/scripts/barebox-mark-successful-boot.sh b/scripts/barebox-mark-successful-boot.sh
index 3120f57..d454cc2 100644
--- a/scripts/barebox-mark-successful-boot.sh
+++ b/scripts/barebox-mark-successful-boot.sh
@@ -1,4 +1,6 @@
#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0-only
+# Copyright 2015-2023 The DT-Utils Authors <oss-tools@pengutronix.de>
DEFAULT_REMAINING_ATTEMPTS=3
DEFAULT_PRIORITY=20
diff --git a/sizes.h b/sizes.h
deleted file mode 100644
index 6f91e9b..0000000
--- a/sizes.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.
- */
-/* Size defintions
- * Copyright (C) ARM Limited 1998. All rights reserved.
- */
-
-#ifndef __sizes_h
-#define __sizes_h 1
-
-/* handy sizes */
-#define SZ_1 0x00000001
-#define SZ_2 0x00000002
-#define SZ_4 0x00000004
-#define SZ_8 0x00000008
-#define SZ_16 0x00000010
-#define SZ_32 0x00000020
-#define SZ_64 0x00000040
-#define SZ_128 0x00000080
-#define SZ_256 0x00000100
-#define SZ_512 0x00000200
-
-#define SZ_1K 0x00000400
-#define SZ_2K 0x00000800
-#define SZ_4K 0x00001000
-#define SZ_8K 0x00002000
-#define SZ_16K 0x00004000
-#define SZ_32K 0x00008000
-#define SZ_64K 0x00010000
-#define SZ_128K 0x00020000
-#define SZ_256K 0x00040000
-#define SZ_512K 0x00080000
-
-#define SZ_1M 0x00100000
-#define SZ_2M 0x00200000
-#define SZ_4M 0x00400000
-#define SZ_8M 0x00800000
-#define SZ_16M 0x01000000
-#define SZ_32M 0x02000000
-#define SZ_64M 0x04000000
-#define SZ_128M 0x08000000
-#define SZ_256M 0x10000000
-#define SZ_512M 0x20000000
-
-#define SZ_1G 0x40000000
-#define SZ_2G 0x80000000
-
-#endif /* __sizes_h */
diff --git a/src/.gitignore b/src/.gitignore
index 088ef79..9657ede 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-only
+# Copyright 2013-2023 The DT-Utils Authors <oss-tools@pengutronix.de>
.dirstamp
.deps/
.libs/
diff --git a/src/asm/unaligned.h b/src/asm/unaligned.h
index 40a8c17..52ad441 100644
--- a/src/asm/unaligned.h
+++ b/src/asm/unaligned.h
@@ -1 +1,3 @@
+/* SPDX-License-Identifier: CC0-1.0 */
+/* Copyright 2013-2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
/* empty */
diff --git a/src/barebox-state.c b/src/barebox-state.c
index 946a8db..e74ba19 100644
--- a/src/barebox-state.c
+++ b/src/barebox-state.c
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* state.c - state handling tool
*
@@ -38,6 +39,8 @@
#include <dt/dt.h>
#include <state.h>
+#define BAREBOX_STATE_LOCKFILE "/run/barebox-state.lock"
+
struct state_variable;
static int __state_uint8_set(struct state_variable *var, const char *val);
@@ -283,6 +286,7 @@ static int state_set_var(struct state *state, const char *var, const char *val)
{
struct state_variable *sv;
struct variable_str_type *vtype;
+ char *oldval;
int ret;
sv = state_find_var(state, var);
@@ -296,6 +300,14 @@ static int state_set_var(struct state *state, const char *var, const char *val)
if (!vtype->set)
return -EPERM;
+ oldval = vtype->get(sv);
+ if (!IS_ERR(oldval)) {
+ bool equal = strcmp(oldval, val) == 0;
+ free(oldval);
+ if (equal)
+ return 0;
+ }
+
ret = vtype->set(sv, val);
if (ret)
return ret;
@@ -306,17 +318,61 @@ static int state_set_var(struct state *state, const char *var, const char *val)
}
-struct state *state_get(const char *name, bool readonly, bool auth)
+struct state *state_get(const char *name, const char *filename, bool readonly, bool auth)
{
struct device_node *root, *node;
struct state *state;
int ret;
- root = of_read_proc_devicetree();
- if (IS_ERR(root)) {
- pr_err("Unable to read devicetree. %s\n",
- strerror(-PTR_ERR(root)));
- return ERR_CAST(root);
+ if (filename) {
+ void *fdt;
+
+ fdt = read_file(filename, NULL);
+ if (!fdt) {
+ pr_err("Unable to read devicetree file '%s'\n",
+ filename);
+ return ERR_PTR(-ENOENT);
+ }
+
+ root = of_unflatten_dtb(fdt);
+ free(fdt);
+ if (IS_ERR(root)) {
+ pr_err("Unable to read devicetree. %s\n",
+ strerror(-PTR_ERR(root)));
+ return ERR_CAST(root);
+ }
+ } else {
+ root = of_read_proc_devicetree();
+
+ /* No device-tree in procfs / sysfs, try dtb file in the ESP */
+ if (-PTR_ERR(root) == ENOENT) {
+ const char *paths[] = {
+ /* default mount paths used by systemd */
+ "/boot/EFI/BAREBOX/state.dtb",
+ "/boot/efi/EFI/BAREBOX/state.dtb",
+ "/efi/EFI/BAREBOX/state.dtb",
+ NULL
+ };
+ void *fdt;
+ int i;
+
+ for (i = 0; paths[i]; ++i) {
+ fdt = read_file(paths[i], NULL);
+ if (fdt)
+ break;
+ }
+ if (fdt) {
+ root = of_unflatten_dtb(fdt);
+ free(fdt);
+ }
+ else
+ root = ERR_PTR(-ENOENT);
+ }
+ if (IS_ERR(root)) {
+ pr_err("Unable to read devicetree. %s\n",
+ strerror(-PTR_ERR(root)));
+ return ERR_CAST(root);
+ }
}
of_set_root_node(root);
@@ -368,6 +424,7 @@ static struct option long_options[] = {
{"get", required_argument, 0, 'g' },
{"set", required_argument, 0, 's' },
{"name", required_argument, 0, 'n' },
+ {"input", required_argument, 0, 'i' },
{"dump", no_argument, 0, 'd' },
{"dump-shell", no_argument, 0, OPT_DUMP_SHELL },
{"force", no_argument, 0, 'f' },
@@ -386,6 +443,7 @@ static void usage(char *name)
"-g, --get <variable> get the value of a variable\n"
"-s, --set <variable>=<value> set the value of a variable\n"
"-n, --name <name> specify the state to use (default=\"state\"). Multiple states are allowed.\n"
+"-i, --input <name> load the devicetree from a file instead of using the system devicetree.\n"
"-d, --dump dump the state\n"
"--dump-shell dump the state suitable for shell sourcing\n"
"-f, --force do not check for state manipulation via the HMAC\n"
@@ -425,12 +483,13 @@ int main(int argc, char *argv[])
bool readonly = true;
int pr_level = 5;
int auth = 1;
+ const char *dtb = NULL;
INIT_LIST_HEAD(&sg_list);
INIT_LIST_HEAD(&state_list.list);
while (1) {
- c = getopt_long(argc, argv, "hg:s:dvn:qf", long_options, &option_index);
+ c = getopt_long(argc, argv, "hg:s:i:dvn:qf", long_options, &option_index);
if (c < 0)
break;
switch (c) {
@@ -439,6 +498,10 @@ int main(int argc, char *argv[])
exit(0);
case OPT_VERSION:
printf(PACKAGE_STRING "\n");
+ printf("Configured with build-time option '--%s-state-backward-compatibility'.\n",
+ (CONFIG_STATE_BACKWARD_COMPATIBLE) ? "enable" : "disable");
+ printf(" '--%s-lock-device-node'.\n",
+ (CONFIG_LOCK_DEVICE_NODE) ? "enable" : "disable");
exit(0);
case 'g':
sg = xzalloc(sizeof(*sg));
@@ -479,6 +542,9 @@ int main(int argc, char *argv[])
++nr_states;
break;
}
+ case 'i':
+ dtb = optarg;
+ break;
case ':':
case '?':
default:
@@ -505,21 +571,23 @@ int main(int argc, char *argv[])
++nr_states;
}
- lock_fd = open("/var/lock/barebox-state", O_CREAT | O_RDWR, 0600);
- if (lock_fd < 0) {
- pr_err("Failed to open lock-file /var/lock/barebox-state\n");
- exit(1);
- }
+ if (!IS_ENABLED(CONFIG_LOCK_DEVICE_NODE)) {
+ lock_fd = open(BAREBOX_STATE_LOCKFILE, O_CREAT | O_RDWR, 0600);
+ if (lock_fd < 0) {
+ pr_err("Failed to open lock-file " BAREBOX_STATE_LOCKFILE "\n");
+ exit(1);
+ }
- ret = flock(lock_fd, LOCK_EX);
- if (ret < 0) {
- pr_err("Failed to lock /var/lock/barebox-state: %m\n");
- close(lock_fd);
- exit(1);
+ ret = flock(lock_fd, LOCK_EX);
+ if (ret < 0) {
+ pr_err("Failed to lock " BAREBOX_STATE_LOCKFILE ": %m\n");
+ close(lock_fd);
+ exit(1);
+ }
}
list_for_each_entry(state, &state_list.list, list) {
- state->state = state_get(state->name, readonly, auth);
+ state->state = state_get(state->name, dtb, readonly, auth);
if (!IS_ERR(state->state) && !state->name)
state->name = state->state->name;
if (IS_ERR(state->state)) {
@@ -637,8 +705,10 @@ int main(int argc, char *argv[])
ret = 0;
out_unlock:
- flock(lock_fd, LOCK_UN);
- close(lock_fd);
+ if (!IS_ENABLED(CONFIG_LOCK_DEVICE_NODE)) {
+ flock(lock_fd, LOCK_UN);
+ close(lock_fd);
+ }
return ret;
}
diff --git a/src/barebox-state.h b/src/barebox-state.h
index bd89cf4..6c6e727 100644
--- a/src/barebox-state.h
+++ b/src/barebox-state.h
@@ -1,7 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright 2013-2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
+
#ifndef __BAREBOX_STATE__
#define __BAREBOX_STATE__
-struct state *state_get(const char *name, bool readonly, bool auth);
+struct state *state_get(const char *name, const char *file, bool readonly, bool auth);
char *state_get_var(struct state *state, const char *var);
#endif /* __BAREBOX_STATE__ */
diff --git a/src/barebox-state/backend_bucket_circular.c b/src/barebox-state/backend_bucket_circular.c
index aec17b3..0906268 100644
--- a/src/barebox-state/backend_bucket_circular.c
+++ b/src/barebox-state/backend_bucket_circular.c
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2016 Pengutronix, Markus Pargmann <mpa@pengutronix.de>
*
@@ -95,6 +96,7 @@ static int state_mtd_peb_read(struct state_backend_storage_bucket_circular *circ
if (ret == -EBADMSG) {
ret = mtd_peb_torture(circ->mtd, circ->eraseblock);
if (ret == -EIO) {
+ mtd_peb_mark_bad(circ->mtd, circ->eraseblock);
dev_err(circ->dev, "Tortured eraseblock failed and is marked bad now, PEB %u\n",
circ->eraseblock);
return -EIO;
@@ -132,6 +134,7 @@ static int state_mtd_peb_write(struct state_backend_storage_bucket_circular *cir
if (ret == -EBADMSG) {
ret = mtd_peb_torture(circ->mtd, circ->eraseblock);
if (ret == -EIO) {
+ mtd_peb_mark_bad(circ->mtd, circ->eraseblock);
dev_err(circ->dev, "Tortured eraseblock failed and is marked bad now, PEB %u\n",
circ->eraseblock);
return -EIO;
@@ -162,11 +165,10 @@ static int state_mtd_peb_read(struct state_backend_storage_bucket_circular *circ
offset += (off_t)circ->eraseblock * circ->mtd->erasesize;
- ret = lseek(circ->fd, offset, SEEK_SET);
- if (ret < 0) {
+ if (lseek(circ->fd, offset, SEEK_SET) != offset) {
dev_err(circ->dev, "Failed to set circular read position to %lld, %d\n",
- (long long) offset, ret);
- return ret;
+ (long long) offset, -errno);
+ return -errno;
}
dev_dbg(circ->dev, "Read state from %lld length %d\n", (long long) offset,
@@ -177,7 +179,6 @@ static int state_mtd_peb_read(struct state_backend_storage_bucket_circular *circ
if (ret < 0) {
dev_err(circ->dev, "Failed to read circular storage len %d, %d\n",
len, ret);
- free(buf);
return ret;
}
@@ -192,11 +193,10 @@ static int state_mtd_peb_write(struct state_backend_storage_bucket_circular *cir
offset += circ->eraseblock * circ->mtd->erasesize;
- ret = lseek(circ->fd, offset, SEEK_SET);
- if (ret < 0) {
+ if (lseek(circ->fd, offset, SEEK_SET) != offset) {
dev_err(circ->dev, "Failed to set position for circular write %lld, %d\n",
- (long long) offset, ret);
- return ret;
+ (long long) offset, -errno);
+ return -errno;
}
ret = write_full(circ->fd, buf, len);
diff --git a/src/barebox-state/backend_bucket_direct.c b/src/barebox-state/backend_bucket_direct.c
index dc00de0..1518ef6 100644
--- a/src/barebox-state/backend_bucket_direct.c
+++ b/src/barebox-state/backend_bucket_direct.c
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2016 Pengutronix, Markus Pargmann <mpa@pengutronix.de>
*
@@ -52,14 +53,13 @@ static int state_backend_bucket_direct_read(struct state_backend_storage_bucket
struct state_backend_storage_bucket_direct *direct =
get_bucket_direct(bucket);
struct state_backend_storage_bucket_direct_meta meta;
- ssize_t read_len;
+ uint32_t read_len;
void *buf;
int ret;
- ret = lseek(direct->fd, direct->offset, SEEK_SET);
- if (ret < 0) {
- dev_err(direct->dev, "Failed to seek file, %d\n", ret);
- return ret;
+ if (lseek(direct->fd, direct->offset, SEEK_SET) != direct->offset) {
+ dev_err(direct->dev, "Failed to seek file, %d\n", -errno);
+ return -errno;
}
ret = read_full(direct->fd, &meta, sizeof(meta));
if (ret < 0) {
@@ -68,14 +68,25 @@ static int state_backend_bucket_direct_read(struct state_backend_storage_bucket
}
if (meta.magic == direct_magic) {
read_len = meta.written_length;
+ if (read_len > direct->max_size) {
+ dev_err(direct->dev, "Wrong length in meta data\n");
+ return -EINVAL;
+
+ }
} else {
if (meta.magic != ~0 && !!meta.magic)
bucket->wrong_magic = 1;
+ if (!IS_ENABLED(CONFIG_STATE_BACKWARD_COMPATIBLE)) {
+ dev_err(direct->dev, "No meta data header found\n");
+ dev_dbg(direct->dev, "Enable backward compatibility or increase stride size\n");
+ return -EINVAL;
+ }
read_len = direct->max_size;
- ret = lseek(direct->fd, direct->offset, SEEK_SET);
- if (ret < 0) {
- dev_err(direct->dev, "Failed to seek file, %d\n", ret);
- return ret;
+ if (lseek(direct->fd, direct->offset, SEEK_SET) !=
+ direct->offset) {
+ dev_err(direct->dev, "Failed to seek file, %d\n",
+ -errno);
+ return -errno;
}
}
@@ -105,21 +116,25 @@ static int state_backend_bucket_direct_write(struct state_backend_storage_bucket
int ret;
struct state_backend_storage_bucket_direct_meta meta;
- if (len > direct->max_size - sizeof(meta))
- return -E2BIG;
-
- ret = lseek(direct->fd, direct->offset, SEEK_SET);
- if (ret < 0) {
- dev_err(direct->dev, "Failed to seek file, %d\n", ret);
- return ret;
+ if (lseek(direct->fd, direct->offset, SEEK_SET) != direct->offset) {
+ dev_err(direct->dev, "Failed to seek file, %d\n", -errno);
+ return -errno;
}
- meta.magic = direct_magic;
- meta.written_length = len;
- ret = write_full(direct->fd, &meta, sizeof(meta));
- if (ret < 0) {
- dev_err(direct->dev, "Failed to write metadata to file, %d\n", ret);
- return ret;
+ /* write the meta data only if there is head room */
+ if (len <= direct->max_size - sizeof(meta)) {
+ meta.magic = direct_magic;
+ meta.written_length = len;
+ ret = write_full(direct->fd, &meta, sizeof(meta));
+ if (ret < 0) {
+ dev_err(direct->dev, "Failed to write metadata to file, %d\n", ret);
+ return ret;
+ }
+ } else {
+ if (!IS_ENABLED(CONFIG_STATE_BACKWARD_COMPATIBLE)) {
+ dev_dbg(direct->dev, "Too small stride size: must skip metadata! Increase stride size\n");
+ return -EINVAL;
+ }
}
ret = write_full(direct->fd, buf, len);
@@ -150,12 +165,13 @@ static void state_backend_bucket_direct_free(struct
int state_backend_bucket_direct_create(struct device_d *dev, const char *path,
struct state_backend_storage_bucket **bucket,
- off_t offset, ssize_t max_size)
+ off_t offset, ssize_t max_size,
+ bool readonly)
{
int fd;
struct state_backend_storage_bucket_direct *direct;
- fd = open(path, O_RDWR);
+ fd = open(path, readonly ? O_RDONLY : O_RDWR);
if (fd < 0) {
dev_err(dev, "Failed to open file '%s', %d\n", path, -errno);
return -errno;
diff --git a/src/barebox-state/backend_format_dtb.c b/src/barebox-state/backend_format_dtb.c
index 48f30db..1d701ef 100644
--- a/src/barebox-state/backend_format_dtb.c
+++ b/src/barebox-state/backend_format_dtb.c
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2012-2014 Pengutronix, Jan Luebbe <j.luebbe@pengutronix.de>
* Copyright (C) 2013-2014 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
diff --git a/src/barebox-state/backend_format_raw.c b/src/barebox-state/backend_format_raw.c
index 5a71149..686eb98 100644
--- a/src/barebox-state/backend_format_raw.c
+++ b/src/barebox-state/backend_format_raw.c
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2012-2014 Pengutronix, Jan Luebbe <j.luebbe@pengutronix.de>
* Copyright (C) 2013-2014 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
@@ -16,14 +17,12 @@
*/
#include <common.h>
-#include <common.h>
#include <crypto/keystore.h>
#include <digest.h>
#include <linux/kernel.h>
#include <malloc.h>
#include <crc.h>
#include <of.h>
-#include <crc.h>
#include "state.h"
@@ -183,6 +182,7 @@ static int backend_format_raw_unpack(struct state_backend_format *format,
const struct backend_raw_header *header;
const void *data;
struct state_backend_format_raw *backend_raw = get_format_raw(format);
+ int ret = 0;
header = (const struct backend_raw_header *)buf;
data = buf + sizeof(*header);
@@ -191,12 +191,13 @@ static int backend_format_raw_unpack(struct state_backend_format *format,
if (sv->start + sv->size > header->data_len) {
dev_err(backend_raw->dev, "State variable ends behind valid data, %s\n",
sv->name);
+ ret = -ENOSPC;
continue;
}
memcpy(sv->raw, data + sv->start, sv->size);
}
- return 0;
+ return ret;
}
static int backend_format_raw_pack(struct state_backend_format *format,
diff --git a/src/barebox-state/backend_storage.c b/src/barebox-state/backend_storage.c
index 3879a8d..6d659c1 100644
--- a/src/barebox-state/backend_storage.c
+++ b/src/barebox-state/backend_storage.c
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2016 Pengutronix, Markus Pargmann <mpa@pengutronix.de>
*
@@ -192,6 +193,7 @@ int state_storage_read(struct state_backend_storage *storage,
/* Free buffer from the unused buckets */
free(bucket->buf);
bucket->buf = NULL;
+ bucket->len = 0;
}
/*
@@ -204,6 +206,7 @@ int state_storage_read(struct state_backend_storage *storage,
/* buffer from the used bucket is passed to the caller, do not free */
bucket_used->buf = NULL;
+ bucket_used->len = 0;
return 0;
}
@@ -324,7 +327,7 @@ static int state_storage_file_buckets_init(struct state_backend_storage *storage
offset = storage->offset + n * stridesize;
ret = state_backend_bucket_direct_create(storage->dev, storage->path,
&bucket, offset,
- stridesize);
+ stridesize, storage->readonly);
if (ret) {
dev_warn(storage->dev, "Failed to create direct bucket at '%s' offset %lld\n",
storage->path, (long long) offset);
@@ -369,7 +372,7 @@ int state_storage_init(struct state *state, const char *path,
const char *storagetype)
{
struct state_backend_storage *storage = &state->storage;
- int ret;
+ int ret = -ENODEV;
struct mtd_info_user meminfo;
INIT_LIST_HEAD(&storage->buckets);
@@ -380,7 +383,9 @@ int state_storage_init(struct state *state, const char *path,
storage->max_size = max_size;
storage->path = xstrdup(path);
- ret = mtd_get_meminfo(path, &meminfo);
+ if (IS_ENABLED(CONFIG_MTD))
+ ret = mtd_get_meminfo(path, &meminfo);
+
if (!ret && !(meminfo.flags & MTD_NO_ERASE)) {
bool circular;
if (!storagetype || !strcmp(storagetype, "circular")) {
diff --git a/src/barebox-state/state.c b/src/barebox-state/state.c
index e95f91e..3b02624 100644
--- a/src/barebox-state/state.c
+++ b/src/barebox-state/state.c
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (C) 2012-2014 Pengutronix, Jan Luebbe <j.luebbe@pengutronix.de>
* Copyright (C) 2013-2014 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
@@ -22,6 +23,7 @@
#include <crc.h>
#include <linux/err.h>
#include <linux/list.h>
+#include <linux/uuid.h>
#include <linux/mtd/mtd-abi.h>
#include <malloc.h>
@@ -93,7 +95,7 @@ out:
*/
static int state_do_load(struct state *state, enum state_flags flags)
{
- void *buf;
+ void *buf = NULL;
ssize_t len;
int ret;
@@ -102,7 +104,7 @@ static int state_do_load(struct state *state, enum state_flags flags)
if (ret) {
dev_err(&state->dev, "Failed to read state with format %s, %d\n",
state->format->name, ret);
- return ret;
+ goto out;
}
ret = state->format->unpack(state->format, state, buf, len);
@@ -113,9 +115,8 @@ static int state_do_load(struct state *state, enum state_flags flags)
}
state->init_from_defaults = 0;
- state->dirty = 0;
-
out:
+ state->dirty = !!ret; /* mark dirty on error */
free(buf);
return ret;
}
@@ -579,6 +580,22 @@ void state_release(struct state *state)
free(state);
}
+#ifdef __BAREBOX__
+static char *cdev_to_devpath(struct cdev *cdev, off_t *offset, size_t *size)
+{
+ /*
+ * We only accept partitions exactly mapping the barebox-state,
+ * but dt-utils may need to set non-zero values here
+ */
+ *offset = 0;
+ *size = 0;
+
+ return basprintf("/dev/%s", cdev->name);
+}
+#endif
+
+static guid_t barebox_state_partition_guid = BAREBOX_STATE_PARTITION_GUID;
+
/*
* state_new_from_node - create a new state instance from a device_node
*
@@ -595,8 +612,9 @@ struct state *state_new_from_node(struct device_node *node, bool readonly)
const char *alias;
uint32_t stridesize;
struct device_node *partition_node;
- off_t offset = 0;
- size_t size = 0;
+ struct cdev *cdev;
+ off_t offset;
+ size_t size;
alias = of_alias_get(node);
if (!alias) {
@@ -615,11 +633,8 @@ struct state *state_new_from_node(struct device_node *node, bool readonly)
goto out_release_state;
}
-#ifdef __BAREBOX__
- ret = of_find_path_by_node(partition_node, &state->backend_path, 0);
-#else
- ret = of_get_devicepath(partition_node, &state->backend_path, &offset, &size);
-#endif
+ cdev = of_cdev_find(partition_node);
+ ret = PTR_ERR_OR_ZERO(cdev);
if (ret) {
if (ret != -EPROBE_DEFER)
dev_err(&state->dev, "state failed to parse path to backend: %s\n",
@@ -627,6 +642,27 @@ struct state *state_new_from_node(struct device_node *node, bool readonly)
goto out_release_state;
}
+ /* Is the backend referencing an on-disk partitionable block device? */
+ if (cdev_is_block_disk(cdev)) {
+ cdev = cdev_find_child_by_gpt_typeuuid(cdev, &barebox_state_partition_guid);
+ if (IS_ERR(cdev)) {
+ ret = -EINVAL;
+ goto out_release_state;
+ }
+
+ pr_debug("%s: backend GPT partition looked up via PartitionTypeGUID\n",
+ node->full_name);
+ }
+
+ state->backend_path = cdev_to_devpath(cdev, &offset, &size);
+
+ pr_debug("%s: backend resolved to %s %lld %zu\n", node->full_name,
+ state->backend_path, (long long)offset, size);
+
+ /* will be released on program exit */
+ if (IS_ENABLED(CONFIG_LOCK_DEVICE_NODE))
+ (void)open_exclusive(state->backend_path, readonly ? O_RDONLY : O_RDWR);
+
state->backend_reproducible_name = of_get_reproducible_name(partition_node);
ret = of_property_read_string(node, "backend-type", &backend_type);
@@ -650,14 +686,14 @@ struct state *state_new_from_node(struct device_node *node, bool readonly)
if (ret)
goto out_release_state;
+ if (readonly)
+ state_backend_set_readonly(state);
+
ret = state_storage_init(state, state->backend_path, offset,
size, stridesize, storage_type);
if (ret)
goto out_release_state;
- if (readonly)
- state_backend_set_readonly(state);
-
ret = state_from_node(state, node, 1);
if (ret) {
goto out_release_state;
@@ -699,7 +735,7 @@ struct state *state_by_name(const char *name)
/*
* state_by_node - find a state instance by of node
*
- * @node The of node of the state intance
+ * @node The of node of the state instance
*/
struct state *state_by_node(const struct device_node *node)
{
@@ -713,13 +749,6 @@ struct state *state_by_node(const struct device_node *node)
return NULL;
}
-int state_get_name(const struct state *state, char const **name)
-{
- *name = xstrdup(state->name);
-
- return 0;
-}
-
int state_read_mac(struct state *state, const char *name, u8 *buf)
{
struct state_variable *svar;
diff --git a/src/barebox-state/state.h b/src/barebox-state/state.h
index 912d6d4..8b87554 100644
--- a/src/barebox-state/state.h
+++ b/src/barebox-state/state.h
@@ -1,6 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright 2013-2023 The DT-Utils Authors <oss-tools@pengutronix.de>
+
#include <linux/types.h>
#include <linux/list.h>
#include <driver.h>
+#include <sys/file.h>
struct state;
struct mtd_info_user;
@@ -159,7 +163,6 @@ struct state_variable {
*/
struct state_uint32 {
struct state_variable var;
- struct param_d *param;
uint32_t value;
uint32_t value_default;
};
@@ -169,7 +172,6 @@ struct state_uint32 {
*/
struct state_enum32 {
struct state_variable var;
- struct param_d *param;
uint32_t value;
uint32_t value_default;
const char **names;
@@ -181,7 +183,6 @@ struct state_enum32 {
*/
struct state_mac {
struct state_variable var;
- struct param_d *param;
uint8_t value[6];
uint8_t value_default[6];
};
@@ -191,7 +192,6 @@ struct state_mac {
*/
struct state_string {
struct state_variable var;
- struct param_d *param;
char *value;
const char *value_default;
char raw[];
@@ -227,7 +227,8 @@ void state_backend_set_readonly(struct state *state);
void state_storage_free(struct state_backend_storage *storage);
int state_backend_bucket_direct_create(struct device_d *dev, const char *path,
struct state_backend_storage_bucket **bucket,
- off_t offset, ssize_t max_size);
+ off_t offset, ssize_t max_size,
+ bool readonly);
int state_storage_write(struct state_backend_storage *storage,
const void * buf, ssize_t len);
int state_storage_read(struct state_backend_storage *storage,
@@ -270,3 +271,23 @@ static inline int state_string_copy_to_raw(struct state_string *string,
return 0;
}
+
+static inline int open_exclusive(const char *path, int flags)
+{
+ int fd;
+
+ fd = open(path, flags);
+ if (fd < 0)
+ return fd;
+
+ if (IS_ENABLED(CONFIG_LOCK_DEVICE_NODE)) {
+ int ret = flock(fd, LOCK_EX);
+ if (ret < 0) {
+ pr_err("Failed to lock %s: %d\n", path, -errno);
+ close(fd);
+ return -EWOULDBLOCK;
+ }
+ }
+
+ return fd;
+}
diff --git a/src/barebox-state/state_variables.c b/src/barebox-state/state_variables.c
index 16f630f..a94ccce 100644
--- a/src/barebox-state/state_variables.c
+++ b/src/barebox-state/state_variables.c
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (C) 2012-2014 Pengutronix, Jan Luebbe <j.luebbe@pengutronix.de>
* Copyright (C) 2013-2014 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
@@ -116,7 +117,6 @@ static struct state_variable *state_uint8_create(struct state *state,
return ERR_CAST(param);
}
- su32->param = param;
su32->var.type = vtype;
su32->var.size = sizeof(uint8_t);
#ifdef __LITTLE_ENDIAN
@@ -146,7 +146,6 @@ static struct state_variable *state_uint32_create(struct state *state,
return ERR_CAST(param);
}
- su32->param = param;
su32->var.type = vtype;
su32->var.size = sizeof(uint32_t);
su32->var.raw = &su32->value;
@@ -182,6 +181,8 @@ static int state_enum32_export(struct state_variable *var,
str += sprintf(str, "%s", enum32->names[i]) + 1;
ret = of_set_property(node, "names", prop, len, 1);
+ if (ret)
+ return ret;
free(prop);
@@ -226,6 +227,7 @@ static struct state_variable *state_enum32_create(struct state *state,
const struct variable_type *vtype)
{
struct state_enum32 *enum32;
+ struct param_d *param;
int ret, i, num_names;
enum32 = xzalloc(sizeof(*enum32));
@@ -253,11 +255,11 @@ static struct state_variable *state_enum32_create(struct state *state,
enum32->names[i] = xstrdup(name);
}
- enum32->param = dev_add_param_enum(&state->dev, name, state_set_dirty,
+ param = dev_add_param_enum(&state->dev, name, state_set_dirty,
NULL, &enum32->value, enum32->names,
num_names, &enum32->var);
- if (IS_ERR(enum32->param)) {
- ret = PTR_ERR(enum32->param);
+ if (IS_ERR(param)) {
+ ret = PTR_ERR(param);
goto out;
}
@@ -310,6 +312,7 @@ static struct state_variable *state_mac_create(struct state *state,
const struct variable_type *vtype)
{
struct state_mac *mac;
+ struct param_d *param;
int ret;
mac = xzalloc(sizeof(*mac));
@@ -319,10 +322,10 @@ static struct state_variable *state_mac_create(struct state *state,
mac->var.raw = mac->value;
mac->var.state = state;
- mac->param = dev_add_param_mac(&state->dev, name, state_set_dirty,
+ param = dev_add_param_mac(&state->dev, name, state_set_dirty,
NULL, mac->value, &mac->var);
- if (IS_ERR(mac->param)) {
- ret = PTR_ERR(mac->param);
+ if (IS_ERR(param)) {
+ ret = PTR_ERR(param);
goto out;
}
@@ -413,6 +416,7 @@ static struct state_variable *state_string_create(struct state *state,
{
struct state_string *string;
uint32_t start_size[2];
+ struct param_d *param;
int ret;
ret = of_property_read_u32_array(node, "reg", start_size,
@@ -432,11 +436,11 @@ static struct state_variable *state_string_create(struct state *state,
string->var.raw = &string->raw;
string->var.state = state;
- string->param = dev_add_param_string(&state->dev, name,
+ param = dev_add_param_string(&state->dev, name,
state_string_set, state_string_get,
&string->value, &string->var);
- if (IS_ERR(string->param)) {
- ret = PTR_ERR(string->param);
+ if (IS_ERR(param)) {
+ ret = PTR_ERR(param);
goto out;
}
@@ -492,19 +496,6 @@ struct variable_type *state_find_type_by_name(const char *name)
return NULL;
}
-struct variable_type *state_find_type(const enum state_variable_type type)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(types); i++) {
- if (type == types[i].type) {
- return &types[i];
- }
- }
-
- return NULL;
-}
-
struct state_variable *state_find_var(struct state *state, const char *name)
{
struct state_variable *sv;
diff --git a/src/base64.c b/src/base64.c
index 6c02174..5c7f9e8 100644
--- a/src/base64.c
+++ b/src/base64.c
@@ -1,11 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Code based on busybox-1.23.2
*
* Copyright 2003, Glenn McGrath
* Copyright 2006, Rob Landley <rob@landley.net>
* Copyright 2010, Denys Vlasenko
- *
- * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*/
#include <common.h>
diff --git a/src/base64.h b/src/base64.h
index 6ce0885..f9fef3b 100644
--- a/src/base64.h
+++ b/src/base64.h
@@ -1,3 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright 2013-2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
+
#ifndef __BASE64_H
#define __BASE64_H
diff --git a/src/crc.h b/src/crc.h
index 40a8c17..52ad441 100644
--- a/src/crc.h
+++ b/src/crc.h
@@ -1 +1,3 @@
+/* SPDX-License-Identifier: CC0-1.0 */
+/* Copyright 2013-2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
/* empty */
diff --git a/src/crc32.c b/src/crc32.c
index 8d4dddc..469dac3 100644
--- a/src/crc32.c
+++ b/src/crc32.c
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: Zlib */
/*
* This file is derived from crc32.c from the zlib-1.1.3 distribution
* by Jean-loup Gailly and Mark Adler.
@@ -5,9 +6,9 @@
/* crc32.c -- compute the CRC-32 of a data stream
* Copyright (C) 1995-1998 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
*/
+#include <dt/common.h>
#include <stdint.h>
/* ========================================================================
diff --git a/src/crypto/digest.c b/src/crypto/digest.c
index 8353412..66bd806 100644
--- a/src/crypto/digest.c
+++ b/src/crypto/digest.c
@@ -1,9 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* (C) Copyright 2008-2010 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
*
- * See file CREDITS for list of people who contributed to this
- * project.
- *
* 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; version 2 of
diff --git a/src/crypto/hmac.c b/src/crypto/hmac.c
index ab1b24d..c4429fb 100644
--- a/src/crypto/hmac.c
+++ b/src/crypto/hmac.c
@@ -1,7 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* (C) Copyright 2015 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
- *
- * GPL v2 only
*/
#include <common.h>
diff --git a/src/crypto/internal.h b/src/crypto/internal.h
index 06254ea..bf44146 100644
--- a/src/crypto/internal.h
+++ b/src/crypto/internal.h
@@ -1,7 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* (C) Copyright 2015 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
- *
- * GPL v2 only
*/
int digest_generic_verify(struct digest *d, const unsigned char *md);
diff --git a/src/crypto/keystore.h b/src/crypto/keystore.h
index 193a413..5997347 100644
--- a/src/crypto/keystore.h
+++ b/src/crypto/keystore.h
@@ -1,9 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* (C) Copyright 2015 Pengutronix, Marc Kleine-Budde <kernel@pengutronix.de>
*
- * See file CREDITS for list of people who contributed to this
- * project.
- *
* 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; version 2 of
diff --git a/src/crypto/sha.h b/src/crypto/sha.h
index 190f8a0..744bb2c 100644
--- a/src/crypto/sha.h
+++ b/src/crypto/sha.h
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright 2013-2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
/*
* Common values for SHA algorithms
*/
diff --git a/src/crypto/sha1.c b/src/crypto/sha1.c
index cbde4d2..018ed82 100644
--- a/src/crypto/sha1.c
+++ b/src/crypto/sha1.c
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Cryptographic API.
*
diff --git a/src/crypto/sha2.c b/src/crypto/sha2.c
index cb0f11c..bb356ca 100644
--- a/src/crypto/sha2.c
+++ b/src/crypto/sha2.c
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Cryptographic API.
*
diff --git a/src/digest.h b/src/digest.h
index efe330d..38347a3 100644
--- a/src/digest.h
+++ b/src/digest.h
@@ -1,9 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* (C) Copyright 2008-2010 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
*
- * See file CREDITS for list of people who contributed to this
- * project.
- *
* 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; version 2 of
diff --git a/src/driver.h b/src/driver.h
index 40a8c17..52ad441 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -1 +1,3 @@
+/* SPDX-License-Identifier: CC0-1.0 */
+/* Copyright 2013-2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
/* empty */
diff --git a/src/dt/common.h b/src/dt/common.h
index c3c4f53..7ba1bed 100644
--- a/src/dt/common.h
+++ b/src/dt/common.h
@@ -1,3 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright 2013-2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
+
#ifndef __DT_COMMON_H
#define __DT_COMMON_H
@@ -36,6 +39,12 @@ typedef uint64_t u64;
#undef offsetof
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#define min(x, y) ({ \
+ typeof(x) _min1 = (x); \
+ typeof(y) _min2 = (y); \
+ (void) (&_min1 == &_min2); \
+ _min1 < _min2 ? _min1 : _min2; })
+
struct device_d;
void pr_level_set(int level);
@@ -160,6 +169,14 @@ static inline void *ERR_CAST(const void *ptr)
return (void *) ptr;
}
+static inline int PTR_ERR_OR_ZERO(const void *ptr)
+{
+ if (IS_ERR(ptr))
+ return PTR_ERR(ptr);
+ else
+ return 0;
+}
+
static inline char *barebox_asprintf(const char *fmt, ...) __attribute__ ((format(__printf__, 1, 2)));
static inline char *barebox_asprintf(const char *fmt, ...)
{
@@ -199,18 +216,14 @@ static inline size_t DT_strlcpy(char *dest, const char *src, size_t size)
return ret;
}
-/* Like strncpy but make sure the resulting string is always 0 terminated. */
-static inline char * safe_strncpy(char *dst, const char *src, size_t size)
-{
- if (!size) return dst;
- dst[--size] = '\0';
- return strncpy(dst, src, size);
-}
-
static inline char *xstrdup(const char *s)
{
- char *p = strdup(s);
+ char *p;
+
+ if (!s)
+ return NULL;
+ p = strdup(s);
if (!p)
exit(EXIT_FAILURE);
@@ -415,21 +428,23 @@ static inline int dev_set_name(struct device_d *dev, const char *fmt, ...)
{
char newname[MAX_DRIVER_NAME];
va_list vargs;
- int err;
+ int ret;
va_start(vargs, fmt);
- err = vsnprintf(newname, MAX_DRIVER_NAME, fmt, vargs);
+ ret = vsnprintf(newname, MAX_DRIVER_NAME, fmt, vargs);
va_end(vargs);
+ if (WARN_ON(ret < 0))
+ return ret;
+
/*
* Copy new name into dev structure, we do this after vsnprintf call in
* case old device name was in one of vargs
*/
- safe_strncpy(dev->name, newname, MAX_DRIVER_NAME);
-
- WARN_ON(err < 0);
+ memcpy(dev->name, newname, min(MAX_DRIVER_NAME - 1, ret));
+ dev->name[MAX_DRIVER_NAME - 1] = '\0';
- return err;
+ return 0;
}
struct driver_d;
@@ -460,7 +475,7 @@ static inline int of_unregister_fixup(int (*fixup)(struct device_node *, void *)
}
#define __define_initcall(level,fn,id) \
-static void __attribute__ ((constructor)) __initcall_##id##_##fn() { \
+static void __attribute__ ((constructor)) __initcall_##id##_##fn(void) { \
fn(); \
}
@@ -577,12 +592,6 @@ static inline __u32 ror32(__u32 word, unsigned int shift)
return (word >> shift) | (word << (32 - shift));
}
-#define min(x, y) ({ \
- typeof(x) _min1 = (x); \
- typeof(y) _min2 = (y); \
- (void) (&_min1 == &_min2); \
- _min1 < _min2 ? _min1 : _min2; })
-
/*
* Helper macros to use CONFIG_ options in C expressions. Note that
* these only work with boolean and tristate options.
diff --git a/src/dt/dt.h b/src/dt/dt.h
index 4ae24ba..e473b4e 100644
--- a/src/dt/dt.h
+++ b/src/dt/dt.h
@@ -1,3 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright 2013-2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
+
#ifndef __DT_DT_H
#define __DT_DT_H
@@ -5,6 +8,7 @@
#include <dt/list.h>
#include <dt/common.h>
#include <asm/byteorder.h>
+#include <linux/uuid.h>
/* Default string compare functions */
#define of_compat_cmp(s1, s2, l) strcasecmp((s1), (s2))
@@ -121,6 +125,7 @@ extern struct device_node *of_find_node_by_type(struct device_node *from,
const char *type);
extern struct device_node *of_find_compatible_node(struct device_node *from,
const char *type, const char *compat);
+extern struct udev_device *of_find_device_by_node_path(const char *of_full_path);
extern const struct of_device_id *of_match_node(
const struct of_device_id *matches, const struct device_node *node);
extern struct device_node *of_find_matching_node_and_match(
@@ -195,6 +200,8 @@ extern int of_property_write_u64_array(struct device_node *np,
size_t sz);
extern int of_property_write_string(struct device_node *np,
const char *propname, const char *value);
+extern int of_property_write_strings(struct device_node *np,
+ const char *propname, ...) __attribute__((__sentinel__));
extern struct device_node *of_parse_phandle(const struct device_node *np,
const char *phandle_name,
@@ -216,7 +223,6 @@ extern int of_set_root_node(struct device_node *node);
extern int of_platform_populate(struct device_node *root,
const struct of_device_id *matches,
struct device_d *parent);
-extern struct device_d *of_find_device_by_node(struct device_node *np);
int of_device_is_stdout_path(struct device_d *dev);
const char *of_get_model(void);
@@ -228,6 +234,12 @@ void of_add_memory_bank(struct device_node *node, bool dump, int r,
int of_get_devicepath(struct device_node *partition_node, char **devnode, off_t *offset,
size_t *size);
+struct cdev *of_cdev_find(struct device_node *partition_node);
+char *cdev_to_devpath(struct cdev *cdev, off_t *offset, size_t *size);
+
+bool cdev_is_block_disk(struct cdev *cdev);
+struct cdev *cdev_find_child_by_gpt_typeuuid(struct cdev *cdev, guid_t *typeuuid);
+
#define for_each_node_by_name(dn, name) \
for (dn = of_find_node_by_name(NULL, name); dn; \
dn = of_find_node_by_name(dn, name))
diff --git a/src/dt/fdt.h b/src/dt/fdt.h
index 35278e3..7bdecfb 100644
--- a/src/dt/fdt.h
+++ b/src/dt/fdt.h
@@ -1,3 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright 2013-2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
+
#ifndef _FDT_H
#define _FDT_H
diff --git a/src/dt/list.h b/src/dt/list.h
index c17b5d4..f627422 100644
--- a/src/dt/list.h
+++ b/src/dt/list.h
@@ -1,3 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright 2013-2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
+
#ifndef _LINUX_LIST_H
#define _LINUX_LIST_H
diff --git a/src/dtblint-imx-pinmux.c b/src/dtblint-imx-pinmux.c
index 83bfd90..1fa2add 100644
--- a/src/dtblint-imx-pinmux.c
+++ b/src/dtblint-imx-pinmux.c
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2015 Pengutronix, Uwe Kleine-König <kernel@pengutronix.de>
*
diff --git a/src/dtblint.c b/src/dtblint.c
index ed9f0b2..21597f8 100644
--- a/src/dtblint.c
+++ b/src/dtblint.c
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2016 Pengutronix, Uwe Kleine-König <kernel@pengutronix.de>
*
diff --git a/src/dtblint.h b/src/dtblint.h
index 4efd586..3c53845 100644
--- a/src/dtblint.h
+++ b/src/dtblint.h
@@ -1 +1,3 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright 2013-2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
void dtblint_imx_pinmux(void);
diff --git a/src/fdt.c b/src/fdt.c
index 5d0831c..6907c08 100644
--- a/src/fdt.c
+++ b/src/fdt.c
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* dtb.c - flat devicetree functions
*
@@ -5,9 +6,6 @@
*
* based on Linux devicetree support
*
- * See file CREDITS for list of people who contributed to this
- * project.
- *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
diff --git a/src/fdt.h b/src/fdt.h
index 2617433..a766fbb 100644
--- a/src/fdt.h
+++ b/src/fdt.h
@@ -1,3 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright 2013-2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
+
#ifndef _FDT_H
#define _FDT_H
diff --git a/src/fdtdump.c b/src/fdtdump.c
index 1b609da..e434e32 100644
--- a/src/fdtdump.c
+++ b/src/fdtdump.c
@@ -1,3 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright 2013-2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
+
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
diff --git a/src/fs.h b/src/fs.h
index 8b05b1a..1cd28fb 100644
--- a/src/fs.h
+++ b/src/fs.h
@@ -1 +1,3 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright 2013-2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
#include <sys/mman.h>
diff --git a/src/init.h b/src/init.h
index 40a8c17..52ad441 100644
--- a/src/init.h
+++ b/src/init.h
@@ -1 +1,3 @@
+/* SPDX-License-Identifier: CC0-1.0 */
+/* Copyright 2013-2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
/* empty */
diff --git a/src/keystore-blob.c b/src/keystore-blob.c
index f71ff5d..6c00efe 100644
--- a/src/keystore-blob.c
+++ b/src/keystore-blob.c
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2015 Pengutronix, Marc Kleine-Budde <kernel@pengutronix.de>
*
@@ -30,7 +31,7 @@ int keystore_get_secret(const char *name, const unsigned char **key, int *key_le
if (!state) {
struct state *tmp;
- tmp = state_get(keystore_state_name, true, false);
+ tmp = state_get(keystore_state_name, NULL, true, false);
if (IS_ERR(tmp))
return PTR_ERR(tmp);
state = tmp;
@@ -81,10 +82,8 @@ int keystore_get_secret(const char *name, const unsigned char **key, int *key_le
/* payload */
fd = open(blob_gen_payload, O_RDONLY);
- if (fd < 0) {
- free(blob_bin);
+ if (fd < 0)
return -errno;
- }
payload = xzalloc(len);
len = read(fd, payload, len);
diff --git a/src/libbb.h b/src/libbb.h
index 9f9d32d..b4d87cd 100644
--- a/src/libbb.h
+++ b/src/libbb.h
@@ -1,3 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright 2013-2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
+
#ifndef __LIBBB_H
#define __LIBBB_H
diff --git a/src/libdt-utils.sym b/src/libdt-utils.sym
index 2c63d55..69144c4 100644
--- a/src/libdt-utils.sym
+++ b/src/libdt-utils.sym
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright 2013-2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
LIBDT_1 {
global:
crc32;
@@ -34,6 +36,10 @@ global:
of_get_child_by_name;
of_get_child_count;
of_get_devicepath;
+ of_cdev_find;
+ cdev_to_devpath;
+ cdev_is_block_disk;
+ cdev_find_child_by_gpt_typeuuid;
of_get_next_available_child;
of_get_parent;
of_get_property;
@@ -64,6 +70,7 @@ global:
of_property_read_u8_array;
of_property_write_bool;
of_property_write_string;
+ of_property_write_strings;
of_property_write_u16_array;
of_property_write_u32_array;
of_property_write_u64_array;
diff --git a/src/libdt.c b/src/libdt.c
index bdfd409..72e8ab4 100644
--- a/src/libdt.c
+++ b/src/libdt.c
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* of.c - basic devicetree functions
*
@@ -5,9 +6,6 @@
*
* based on Linux devicetree support
*
- * See file CREDITS for list of people who contributed to this
- * project.
- *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
@@ -33,8 +31,17 @@
#include <fcntl.h>
#include <unistd.h>
#include <libudev.h>
+#include <sys/sysmacros.h>
#include <dt.h>
+struct cdev {
+ char *devpath;
+ off_t offset;
+ size_t size;
+ bool is_gpt_partitioned;
+ bool is_block_disk;
+};
+
static int pr_level = 5;
void pr_level_set(int level)
@@ -1212,6 +1219,53 @@ int of_property_write_u64_array(struct device_node *np,
}
/**
+ * of_property_write_strings - Write strings to a property. If
+ * the property does not exist, it will be created and appended to the given
+ * device node.
+ *
+ * @np: device node to which the property value is to be written.
+ * @propname: name of the property to be written.
+ * @...: pointers to strings to write
+ *
+ * Search for a property in a device node and write a string to
+ * it. If the property does not exist, it will be created and appended to
+ * the device node. Returns 0 on success, -ENOMEM if the property or array
+ * of elements cannot be created, -EINVAL if no strings specified.
+ */
+int of_property_write_strings(struct device_node *np,
+ const char *propname, ...)
+{
+ const char *val;
+ char *buf = NULL, *next;
+ size_t len = 0;
+ va_list ap;
+ int ret = 0;
+
+ va_start(ap, propname);
+ for (val = va_arg(ap, char *); val; val = va_arg(ap, char *))
+ len += strlen(val) + 1;
+ va_end(ap);
+
+ if (!len)
+ return -EINVAL;
+
+ buf = malloc(len);
+ if (!buf)
+ return -ENOMEM;
+
+ next = buf;
+
+ va_start(ap, propname);
+ for (val = va_arg(ap, char *); val; val = va_arg(ap, char *))
+ next = stpcpy(next, val) + 1;
+ va_end(ap);
+
+ ret = of_set_property(np, propname, buf, len, 1);
+ free(buf);
+ return ret;
+}
+
+/**
* of_property_write_string - Write a string to a property. If
* the property does not exist, it will be created and appended to the given
* device node.
@@ -1941,7 +1995,7 @@ int of_device_disable_path(const char *path)
return of_device_disable(node);
}
-int scan_proc_dir(struct device_node *node, const char *path)
+static int scan_proc_dir(struct device_node *node, const char *path)
{
DIR *dir;
struct dirent *dirent;
@@ -2038,6 +2092,22 @@ struct udev_of_path {
static LIST_HEAD(udev_of_devices);
+static const char *udev_device_get_of_path(struct udev_device *dev)
+{
+ const char *of_path;
+
+ of_path = udev_device_get_property_value(dev, "OF_FULLNAME");
+ if (of_path)
+ return of_path;
+
+ if (IS_ENABLED(CONFIG_TEST_LOOPBACK) &&
+ !strcmp(udev_device_get_subsystem(dev), "block") &&
+ !strncmp(udev_device_get_sysname(dev), "loop", 4))
+ return udev_device_get_sysname(dev);
+
+ return NULL;
+}
+
static void of_scan_udev_devices(void)
{
struct udev *udev;
@@ -2057,6 +2127,9 @@ static void of_scan_udev_devices(void)
udev_enumerate_add_match_subsystem(enumerate, "i2c");
udev_enumerate_add_match_subsystem(enumerate, "spi");
udev_enumerate_add_match_subsystem(enumerate, "mtd");
+ udev_enumerate_add_match_subsystem(enumerate, "amba");
+ if (IS_ENABLED(CONFIG_TEST_LOOPBACK))
+ udev_enumerate_add_match_subsystem(enumerate, "block");
udev_enumerate_scan_devices(enumerate);
devices = udev_enumerate_get_list_entry(enumerate);
@@ -2070,7 +2143,7 @@ static void of_scan_udev_devices(void)
path = udev_list_entry_get_name(dev_list_entry);
dev = udev_device_new_from_syspath(udev, path);
- of_path = udev_device_get_property_value(dev, "OF_FULLNAME");
+ of_path = udev_device_get_of_path(dev);
if (!of_path)
continue;
@@ -2099,6 +2172,28 @@ struct udev_device *of_find_device_by_node_path(const char *of_full_path)
return ret;
}
+static struct udev_device *of_find_device_by_node(struct device_node *np)
+{
+ struct udev_of_path *udev_of_path;
+ struct udev_device *dev;
+ const char *filename;
+
+ dev = of_find_device_by_node_path(np->full_name);
+ if (dev)
+ return dev;
+
+ if (IS_ENABLED(CONFIG_TEST_LOOPBACK) &&
+ !of_property_read_string(np, "barebox,filename", &filename) &&
+ !strncmp(filename, "/dev/", 5)) {
+ list_for_each_entry(udev_of_path, &udev_of_devices, list) {
+ if (!strcmp(udev_of_path->of_path, filename + 5))
+ return udev_of_path->udev;
+ }
+ }
+
+ return NULL;
+}
+
static struct udev_device *device_find_mtd_partition(struct udev_device *dev,
const char *name)
{
@@ -2135,22 +2230,55 @@ static struct udev_device *device_find_mtd_partition(struct udev_device *dev,
}
/*
- * device_find_block_device - extract device path from udev block device
+ * udev_device_parse_sysattr_u64 - parse sysattr value as unsigned 64-bit integer
+ * @dev: the udev_device to extract the attribute from
+ * @attr: name of the attribute to lookup
+ * @outvalue: returns the value parsed out of the attribute
+ *
+ * returns 0 for success or negative error value on failure.
+ */
+static int udev_device_parse_sysattr_u64(struct udev_device *dev, const char *attr,
+ u64 *outvalue)
+{
+ char *endptr;
+ u64 value;
+ const char *str;
+
+ str = udev_device_get_sysattr_value(dev, attr);
+ if (!str)
+ return -EINVAL;
+
+ value = strtoull(str, &endptr, 0);
+ if (!*str || *endptr)
+ return -EINVAL;
+
+ *outvalue = value;
+ return 0;
+}
+
+/* True if A completely contains B */
+static bool region_contains(loff_t starta, loff_t enda,
+ loff_t startb, loff_t endb)
+{
+ return starta <= startb && enda >= endb;
+}
+
+/*
+ * cdev_from_block_device - Populate cdev from udev block device
*
* @dev: the udev_device to extract information from
- * @devpath: returns the devicepath under which the block device is accessible
+ * @cdev: the cdev output parameter to populate
*
* returns 0 for success or negative error value on failure.
*/
-int device_find_block_device(struct udev_device *dev,
- char **devpath)
+static int cdev_from_block_device(struct udev_device *dev,
+ struct cdev *cdev)
{
struct udev *udev;
struct udev_enumerate *enumerate;
struct udev_list_entry *devices, *dev_list_entry;
- struct udev_device *part;
- const char *outpath;
+ struct udev_device *part, *best_match = NULL;
int ret;
udev = udev_new();
@@ -2173,20 +2301,49 @@ int device_find_block_device(struct udev_device *dev,
devtype = udev_device_get_devtype(part);
if (!devtype)
continue;
- if (!strcmp(devtype, "disk")) {
- outpath = udev_device_get_devnode(part);
- *devpath = strdup(outpath);
- ret = 0;
- goto out;
+ if (!strcmp(devtype, "disk") && !best_match) {
+ best_match = part;
+
+ /* Should we try to find a matching partition first? */
+ if (!cdev->size)
+ break;
+ } else if (cdev->size && !strcmp(devtype, "partition")) {
+ u64 partstart, partsize;
+
+ ret = udev_device_parse_sysattr_u64(part, "start", &partstart);
+ if (ret)
+ continue;
+
+ ret = udev_device_parse_sysattr_u64(part, "size", &partsize);
+ if (ret)
+ continue;
+
+ /* start/size sys attributes are always in 512-byte units */
+ partstart *= 512;
+ partsize *= 512;
+
+ if (!region_contains(partstart, partstart + partsize,
+ cdev->offset, cdev->offset + cdev->size))
+ continue;
+
+ best_match = part;
+ cdev->offset -= partstart;
+ break;
}
}
- ret = -ENODEV;
-out:
+ if (best_match) {
+ const char *part_type;
+
+ cdev->devpath = strdup(udev_device_get_devnode(best_match));
+ part_type = udev_device_get_property_value(best_match, "ID_PART_TABLE_TYPE");
+ cdev->is_gpt_partitioned = part_type && !strcmp(part_type, "gpt");
+ }
+
udev_enumerate_unref(enumerate);
udev_unref(udev);
- return ret;
+ return best_match ? 0 : -ENODEV;
}
/*
@@ -2260,24 +2417,25 @@ static int udev_device_is_eeprom(struct udev_device *dev)
* udev_parse_mtd - get information from a mtd udev_device
* @dev: the udev_device to extract information from
* @devpath: returns the devicepath under which the mtd device is accessible
- * @size: returns the size of the mtd device
+ * @outsize: returns the size of the mtd device
*
* returns 0 for success or negative error value on failure. *devpath
* will be valid on success and must be freed after usage.
*/
-static int udev_parse_mtd(struct udev_device *dev, char **devpath, size_t *size)
+static int udev_parse_mtd(struct udev_device *dev, char **devpath, size_t *outsize)
{
- const char *sizestr;
const char *outpath;
+ u64 size;
+ int ret;
if (!udev_device_is_mtd(dev))
return -EINVAL;
- sizestr = udev_device_get_sysattr_value(dev, "size");
- if (!sizestr)
- return -EINVAL;
+ ret = udev_device_parse_sysattr_u64(dev, "size", &size);
+ if (ret)
+ return ret;
- *size = atol(sizestr);
+ *outsize = size;
outpath = udev_device_get_devnode(dev);
if (!outpath)
@@ -2360,34 +2518,65 @@ out:
return dev;
}
-/*
- * of_get_devicepath - get information how to access device corresponding to a device_node
- * @partition_node: The device_node which shall be accessed
- * @devpath: Returns the devicepath under which the device is accessible
- * @offset: Returns the offset in the device
- * @size: Returns the size of the device
- *
- * This function takes a device_node which represents a partition.
- * For this partition the function returns the device path and the offset
- * and size in the device. For mtd devices the path will be /dev/mtdx, for
- * EEPROMs it will be /sys/.../eeprom and for block devices it will be /dev/...
- * For mtd devices the device path returned will be the partition itself.
- * Since EEPROMs do not have partitions under Linux @offset and @size will
- * describe the offset and size inside the full device. The same applies to
- * block devices.
- *
- * returns 0 for success or negative error value on failure.
- */
-int of_get_devicepath(struct device_node *partition_node, char **devpath, off_t *offset,
- size_t *size)
+static struct udev_device *of_find_device_by_uuid(struct udev_device *parent,
+ const char *uuid,
+ bool type_uuid)
+{
+ struct udev *udev;
+ struct udev_enumerate *enumerate;
+ struct udev_list_entry *devices, *dev_list_entry;
+
+ udev = udev_new();
+ if (!udev) {
+ fprintf(stderr, "Can't create udev\n");
+ return NULL;
+ }
+
+ enumerate = udev_enumerate_new(udev);
+ if (parent)
+ udev_enumerate_add_match_parent(enumerate, parent);
+ udev_enumerate_add_match_subsystem(enumerate, "block");
+ udev_enumerate_scan_devices(enumerate);
+ devices = udev_enumerate_get_list_entry(enumerate);
+ udev_list_entry_foreach(dev_list_entry, devices) {
+ const char *path, *devtype, *dev_uuid;
+ struct udev_device *device;
+ const char *property;
+
+ path = udev_list_entry_get_name(dev_list_entry);
+ device = udev_device_new_from_syspath(udev, path);
+
+ /* distinguish device (disk) from partitions */
+ devtype = udev_device_get_devtype(device);
+ if (!devtype)
+ continue;
+
+ if (type_uuid)
+ property = "ID_PART_ENTRY_TYPE";
+ else if (!strcmp(devtype, "disk"))
+ property = "ID_PART_TABLE_UUID";
+ else if (!strcmp(devtype, "partition"))
+ property = "ID_PART_ENTRY_UUID";
+ else
+ continue;
+
+ dev_uuid = udev_device_get_property_value(device, property);
+ if (dev_uuid && !strcasecmp(dev_uuid, uuid))
+ return device;
+ }
+ return NULL;
+}
+
+static int __of_cdev_find(struct device_node *partition_node, struct cdev *cdev)
{
struct device_node *node;
struct udev_device *dev, *partdev, *mtd;
- const char *partname;
int ret;
- *offset = 0;
- *size = 0;
+ cdev->offset = 0;
+ cdev->size = 0;
+ cdev->is_gpt_partitioned = false;
+ cdev->is_block_disk = false;
/*
* simplest case: This nodepath can directly be translated into
@@ -2396,20 +2585,24 @@ int of_get_devicepath(struct device_node *partition_node, char **devpath, off_t
* 42e9401bd146 ("mtd: Add partition device node to mtd partition
* devices").
*/
- dev = of_find_device_by_node_path(partition_node->full_name);
+ dev = of_find_device_by_node(partition_node);
if (dev) {
- if (udev_device_is_eeprom(dev)) {
- return udev_parse_eeprom(dev, devpath);
- } else if (!udev_parse_mtd(dev, devpath, size)) {
+ if (udev_device_is_eeprom(dev))
+ return udev_parse_eeprom(dev, &cdev->devpath);
+ if (!udev_parse_mtd(dev, &cdev->devpath, &cdev->size))
+ return 0;
+
+ if (!cdev_from_block_device(dev, cdev)) {
+ cdev->is_block_disk = true;
return 0;
- } else if (device_find_block_device(dev, devpath)) {
- return of_parse_partition(partition_node, offset, size);
}
/*
- * If we found a device but couldn't classify it above, we fall
- * through.
+ * If we find a udev_device but couldn't classify it above,
+ * it's an error. Falling through would mean to handle it as a
+ * partition and could lead us to return an arbitrary sibling device
*/
+ return -ENODEV;
}
/*
@@ -2423,8 +2616,22 @@ int of_get_devicepath(struct device_node *partition_node, char **devpath, off_t
/* when partuuid is specified short-circuit the search for the cdev */
ret = of_property_read_string(partition_node, "partuuid", &uuid);
if (!ret) {
- *devpath = basprintf("/dev/disk/by-partuuid/%s", uuid);
+ u64 partsize;
+ int ret;
+
+ dev = of_find_device_by_uuid(NULL, uuid, false);
+ if (!dev) {
+ fprintf(stderr, "%s: cannot find device for uuid %s\n", __func__,
+ uuid);
+ return -ENODEV;
+ }
+
+ ret = udev_device_parse_sysattr_u64(dev, "size", &partsize);
+ if (ret)
+ return -EINVAL;
+ cdev->size = partsize * 512;
+ cdev->devpath = strdup(udev_device_get_devnode(dev));
return 0;
}
}
@@ -2436,44 +2643,213 @@ int of_get_devicepath(struct device_node *partition_node, char **devpath, off_t
if (!strcmp(node->name, "partitions"))
node = node->parent;
- dev = of_find_device_by_node_path(node->full_name);
- if (!dev) {
- fprintf(stderr, "%s: cannot find device from node %s\n", __func__,
- node->full_name);
- return -ENODEV;
- }
+ if (of_device_is_compatible(node, "barebox,storage-by-uuid")) {
+ const char *uuid;
- /* find the name of the partition... */
- ret = of_property_read_string(partition_node, "label", &partname);
- if (ret) {
- fprintf(stderr, "%s: no 'label' property found in %s\n", __func__,
- partition_node->full_name);
- return ret;
+ ret = of_property_read_string(node, "uuid", &uuid);
+ if (ret) {
+ fprintf(stderr, "%s: missing uuid property for %s\n", __func__,
+ node->full_name);
+ return -ENODEV;
+ }
+ dev = of_find_device_by_uuid(NULL, uuid, false);
+ if (!dev) {
+ fprintf(stderr, "%s: cannot find device for uuid %s\n", __func__,
+ uuid);
+ return -ENODEV;
+ }
+ }
+ else {
+ dev = of_find_device_by_node(node);
+ if (!dev) {
+ fprintf(stderr, "%s: cannot find device from node %s\n", __func__,
+ node->full_name);
+ return -ENODEV;
+ }
}
mtd = of_find_mtd_device(dev);
if (mtd) {
+ const char *partname;
+
+ /* find the name of the partition... */
+ ret = of_property_read_string(partition_node, "label", &partname);
+ if (ret) {
+ fprintf(stderr, "%s: no 'label' property found in %s\n", __func__,
+ partition_node->full_name);
+ return ret;
+ }
+
/* ...find the udev_device by partition name... */
partdev = device_find_mtd_partition(dev, partname);
if (!partdev)
return -ENODEV;
/* ...find the desired information by mtd udev_device */
- return udev_parse_mtd(partdev, devpath, size);
+ return udev_parse_mtd(partdev, &cdev->devpath, &cdev->size);
}
if (udev_device_is_eeprom(dev)) {
- ret = udev_parse_eeprom(dev, devpath);
+ ret = udev_parse_eeprom(dev, &cdev->devpath);
if (ret)
return ret;
- return of_parse_partition(partition_node, offset, size);
+ return of_parse_partition(partition_node, &cdev->offset, &cdev->size);
} else {
- ret = device_find_block_device(dev, devpath);
+ ret = of_parse_partition(partition_node, &cdev->offset, &cdev->size);
if (ret)
return ret;
- return of_parse_partition(partition_node, offset, size);
+ return cdev_from_block_device(dev, cdev);
}
return -EINVAL;
}
+
+/*
+ * of_get_devicepath - get information how to access device corresponding to a device_node
+ * @partition_node: The device_node which shall be accessed
+ * @devpath: Returns the devicepath under which the device is accessible
+ * @offset: Returns the offset in the device
+ * @size: Returns the size of the device
+ *
+ * This function takes a device_node which represents a partition.
+ * For this partition the function returns the device path and the offset
+ * and size in the device. For mtd devices the path will be /dev/mtdx, for
+ * EEPROMs it will be /sys/.../eeprom and for block devices it will be /dev/...
+ * For mtd devices the device path returned will be the partition itself.
+ * Since EEPROMs do not have partitions under Linux @offset and @size will
+ * describe the offset and size inside the full device. The same applies to
+ * block devices.
+ *
+ * returns 0 for success or negative error value on failure.
+ */
+int of_get_devicepath(struct device_node *partition_node, char **devpath, off_t *offset,
+ size_t *size)
+{
+ struct cdev cdev = {};
+ int ret;
+
+ ret = __of_cdev_find(partition_node, &cdev);
+ if (ret)
+ return ret;
+
+ *offset = cdev.offset;
+ *size = cdev.size;
+ *devpath = cdev.devpath;
+
+ return 0;
+}
+
+/*
+ * of_cdev_find - get information how to access device corresponding to a device_node
+ * @partition_node: The device_node which shall be accessed
+ * @devpath: Returns the devicepath under which the device is accessible
+ * @offset: Returns the offset in the device
+ * @size: Returns the size of the device
+ *
+ * This function takes a device_node which represents a partition.
+ * For this partition the function returns the device path and the offset
+ * and size in the device. For mtd devices the path will be /dev/mtdx, for
+ * EEPROMs it will be /sys/.../eeprom and for block devices it will be /dev/...
+ * For mtd devices the device path returned will be the partition itself.
+ * Since EEPROMs do not have partitions under Linux @offset and @size will
+ * describe the offset and size inside the full device. The same applies to
+ * block devices.
+ *
+ * returns 0 for success or negative error value on failure.
+ */
+struct cdev *of_cdev_find(struct device_node *partition_node)
+{
+ struct cdev cdev = {};
+ int ret;
+
+ ret = __of_cdev_find(partition_node, &cdev);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return xmemdup(&cdev, sizeof(cdev));
+}
+
+char *cdev_to_devpath(struct cdev *cdev, off_t *offset, size_t *size)
+{
+ *offset = cdev->offset;
+ *size = cdev->size;
+ return cdev->devpath;
+}
+
+static struct udev_device *udev_from_devpath(struct udev *udev,
+ const char *devpath)
+{
+ char syspath[64];
+ struct stat st;
+ const char *type;
+ int ret;
+
+ ret = stat(devpath, &st);
+ if (ret)
+ return NULL;
+
+ if (S_ISBLK(st.st_mode))
+ type = "block";
+ else if (S_ISCHR(st.st_mode))
+ type = "char";
+ else
+ return NULL;
+
+ if (major(st.st_rdev) == 0)
+ return NULL;
+
+ snprintf(syspath, sizeof(syspath), "/sys/dev/%s/%u:%u",
+ type, major(st.st_rdev), minor(st.st_rdev));
+
+ return udev_device_new_from_syspath(udev, syspath);
+}
+
+struct cdev *cdev_find_child_by_gpt_typeuuid(struct cdev *cdev, guid_t *typeuuid)
+{
+ struct cdev *new = ERR_PTR(-ENOENT);
+ struct udev_device *parent, *child;
+ struct udev *udev;
+ u64 size;
+ int ret;
+
+
+ if (!cdev->is_gpt_partitioned)
+ return ERR_PTR(-EINVAL);
+
+ udev = udev_new();
+ if (!udev)
+ return ERR_PTR(-ENOMEM);
+
+ parent = udev_from_devpath(udev, cdev->devpath);
+ if (!parent)
+ goto udev_unref;
+
+ child = of_find_device_by_uuid(parent, typeuuid->str, true);
+ if (!child)
+ goto udev_unref_parent;
+
+ ret = udev_device_parse_sysattr_u64(child, "size", &size);
+ if (ret)
+ goto udev_unref_child;
+
+ new = xzalloc(sizeof(*new));
+
+ new->offset = 0;
+ new->size = size * 512;
+ new->devpath = strdup(udev_device_get_devnode(child));
+
+udev_unref_child:
+ udev_device_unref(child);
+udev_unref_parent:
+ udev_device_unref(parent);
+udev_unref:
+ udev_unref(udev);
+
+ return new;
+}
+
+bool cdev_is_block_disk(struct cdev *cdev)
+{
+ return cdev->is_block_disk;
+}
diff --git a/src/libfile.h b/src/libfile.h
index 40a8c17..52ad441 100644
--- a/src/libfile.h
+++ b/src/libfile.h
@@ -1 +1,3 @@
+/* SPDX-License-Identifier: CC0-1.0 */
+/* Copyright 2013-2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
/* empty */
diff --git a/src/linux/err.h b/src/linux/err.h
index 40a8c17..52ad441 100644
--- a/src/linux/err.h
+++ b/src/linux/err.h
@@ -1 +1,3 @@
+/* SPDX-License-Identifier: CC0-1.0 */
+/* Copyright 2013-2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
/* empty */
diff --git a/src/linux/list.h b/src/linux/list.h
index 83c6d75..b9c30c2 100644
--- a/src/linux/list.h
+++ b/src/linux/list.h
@@ -1 +1,3 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright 2013-2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
#include <dt/list.h>
diff --git a/src/linux/mtd/mtd-abi.h b/src/linux/mtd/mtd-abi.h
index bd0de76..b678f66 100644
--- a/src/linux/mtd/mtd-abi.h
+++ b/src/linux/mtd/mtd-abi.h
@@ -1 +1,3 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright 2013-2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
#include <mtd/mtd-abi.h>
diff --git a/src/linux/uuid.h b/src/linux/uuid.h
new file mode 100644
index 0000000..6708b0e
--- /dev/null
+++ b/src/linux/uuid.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2023 Pengutronix, Ahmad Fatoum <a.fatoum@pengutronix.de>
+ *
+ * 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.
+ */
+#ifndef _LINUX_UUID_H_
+#define _LINUX_UUID_H_
+
+#define UUID_STRING_LEN 36
+
+/* We only do string comparisons anyway */
+typedef struct { const char str[UUID_STRING_LEN + 1]; } guid_t;
+
+#define GUID_INIT(str) { str }
+
+#endif
diff --git a/src/module.h b/src/module.h
index 40a8c17..52ad441 100644
--- a/src/module.h
+++ b/src/module.h
@@ -1 +1,3 @@
+/* SPDX-License-Identifier: CC0-1.0 */
+/* Copyright 2013-2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
/* empty */
diff --git a/src/mtd/mtd-peb.h b/src/mtd/mtd-peb.h
index 40a8c17..52ad441 100644
--- a/src/mtd/mtd-peb.h
+++ b/src/mtd/mtd-peb.h
@@ -1 +1,3 @@
+/* SPDX-License-Identifier: CC0-1.0 */
+/* Copyright 2013-2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
/* empty */
diff --git a/src/net.h b/src/net.h
index 40a8c17..52ad441 100644
--- a/src/net.h
+++ b/src/net.h
@@ -1 +1,3 @@
+/* SPDX-License-Identifier: CC0-1.0 */
+/* Copyright 2013-2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
/* empty */
diff --git a/src/of.h b/src/of.h
index 4cbf197..0eba9d6 100644
--- a/src/of.h
+++ b/src/of.h
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright 2013-2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
#ifndef __OF_H
#define __OF_H
diff --git a/src/printk.h b/src/printk.h
index a0adcaa..5b430d6 100644
--- a/src/printk.h
+++ b/src/printk.h
@@ -1 +1,3 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright 2013-2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
#include <dt/common.h>
diff --git a/src/state.h b/src/state.h
index 132c0c3..09c7689 100644
--- a/src/state.h
+++ b/src/state.h
@@ -1,27 +1,64 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright 2013-2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
#ifndef __STATE_H
#define __STATE_H
#include <of.h>
+#include <linux/uuid.h>
struct state;
-int state_backend_dtb_file(struct state *state, const char *of_path,
- const char *path);
-int state_backend_raw_file(struct state *state, const char *of_path,
- const char *path, off_t offset, size_t size);
+#if IS_ENABLED(CONFIG_STATE)
struct state *state_new_from_node(struct device_node *node, bool readonly);
void state_release(struct state *state);
struct state *state_by_name(const char *name);
struct state *state_by_node(const struct device_node *node);
-int state_get_name(const struct state *state, char const **name);
-int state_load(struct state *state);
int state_load_no_auth(struct state *state);
+int state_load(struct state *state);
int state_save(struct state *state);
void state_info(void);
int state_read_mac(struct state *state, const char *name, u8 *buf);
+#else /* #if IS_ENABLED(CONFIG_STATE) */
+
+static inline struct state *state_new_from_node(struct device_node *node,
+ bool readonly)
+{
+ return ERR_PTR(-ENOSYS);
+}
+
+static inline struct state *state_by_name(const char *name)
+{
+ return NULL;
+}
+
+static inline struct state *state_by_node(const struct device_node *node)
+{
+ return NULL;
+};
+
+static inline int state_load(struct state *state)
+{
+ return -ENOSYS;
+}
+
+static inline int state_save(struct state *state)
+{
+ return -ENOSYS;
+}
+
+static inline int state_read_mac(struct state *state, const char *name, u8 *buf)
+{
+ return -ENOSYS;
+}
+
+#endif /* #if IS_ENABLED(CONFIG_STATE) / #else */
+
+#define BAREBOX_STATE_PARTITION_GUID \
+ GUID_INIT("4778ed65-bf42-45fa-9c5b-287a1dc4aab1")
+
#endif /* __STATE_H */
diff --git a/test/01-fixed-partition-no-gpt.dts b/test/01-fixed-partition-no-gpt.dts
new file mode 100644
index 0000000..290731e
--- /dev/null
+++ b/test/01-fixed-partition-no-gpt.dts
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright 2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
+/dts-v1/;
+
+#include "barebox-state.dtsi"
+
+/ {
+ expected-dev = __RAW_LOOPDEV__;
+ expected-partno = <0>; /* unpartitioned space */
+ expected-offset = <0x8000>;
+ expected-size = <0x8000>;
+
+ disk: loopfile {
+ compatible = "barebox,hostfile";
+ barebox,filename = __RAW_LOOPDEV__;
+ barebox,blockdev;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ part_state: state@8000 {
+ reg = <0x8000 0x8000>;
+ label = "state";
+ };
+ };
+ };
+};
+
+&state {
+ backend = <&part_state>;
+ backend-type = "raw";
+ backend-stridesize = <0x40>;
+ backend-storage-type = "direct";
+};
diff --git a/test/02-fixed-partition-before-gpt-partition.dts b/test/02-fixed-partition-before-gpt-partition.dts
new file mode 100644
index 0000000..9493f63
--- /dev/null
+++ b/test/02-fixed-partition-before-gpt-partition.dts
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright 2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
+/dts-v1/;
+
+#include "barebox-state.dtsi"
+
+/ {
+ expected-dev = __GPT_LOOPDEV__;
+ expected-partno = <0>; /* unpartitioned space */
+ expected-offset = <0x8000>;
+ expected-size = <0x8000>;
+
+ disk: loopfile {
+ compatible = "barebox,hostfile";
+ barebox,filename = __GPT_LOOPDEV__;
+ barebox,blockdev;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ part_state: state@8000 {
+ reg = <0x8000 0x8000>;
+ label = "state";
+ };
+ };
+ };
+};
+
+&state {
+ backend = <&part_state>;
+ backend-type = "raw";
+ backend-stridesize = <0x40>;
+ backend-storage-type = "direct";
+};
diff --git a/test/03-fixed-partition-is-gpt-partition.dts b/test/03-fixed-partition-is-gpt-partition.dts
new file mode 100644
index 0000000..d4021cb
--- /dev/null
+++ b/test/03-fixed-partition-is-gpt-partition.dts
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright 2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
+/dts-v1/;
+
+#include "barebox-state.dtsi"
+
+/ {
+ expected-dev = __GPT_LOOPDEV__;
+ expected-partno = <2>;
+ expected-offset = <0x00000>;
+ expected-size = <0x8000>;
+
+ disk: loopfile {
+ compatible = "barebox,hostfile";
+ barebox,filename = __GPT_LOOPDEV__;
+ barebox,blockdev;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ part_state: state@20000 {
+ reg = <0x20000 0x8000>;
+ label = "state";
+ };
+ };
+ };
+};
+
+&state {
+ backend = <&part_state>;
+ backend-type = "raw";
+ backend-stridesize = <0x40>;
+ backend-storage-type = "direct";
+};
diff --git a/test/04-gpt-partition-by-partuuid.dts b/test/04-gpt-partition-by-partuuid.dts
new file mode 100644
index 0000000..080374d
--- /dev/null
+++ b/test/04-gpt-partition-by-partuuid.dts
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright 2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
+/dts-v1/;
+
+#include "barebox-state.dtsi"
+
+/ {
+ expected-dev = __GPT_LOOPDEV__;
+ expected-partno = <2>;
+ expected-offset = <0x00000>;
+ expected-size = <0x8000>;
+
+ disk: loopfile {
+ compatible = "barebox,hostfile";
+ barebox,filename = __GPT_LOOPDEV__;
+ barebox,blockdev;
+ };
+
+ partitions {
+ compatible = "fixed-partitions";
+
+ part_state: state {
+ partuuid = __GPT_LOOPDEV_PARTUUID__;
+ };
+ };
+};
+
+&state {
+ backend = <&part_state>;
+ backend-type = "raw";
+ backend-stridesize = <0x40>;
+ backend-storage-type = "direct";
+};
diff --git a/test/05-gpt-partition-by-typeuuid.dts b/test/05-gpt-partition-by-typeuuid.dts
new file mode 100644
index 0000000..575bd86
--- /dev/null
+++ b/test/05-gpt-partition-by-typeuuid.dts
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright 2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
+/dts-v1/;
+
+#include "barebox-state.dtsi"
+
+/ {
+ expected-dev = __GPT_LOOPDEV__;
+ expected-partno = <2>;
+ expected-offset = <0x00000>;
+ expected-size = <0x8000>;
+
+ disk: loopfile {
+ compatible = "barebox,hostfile";
+ barebox,filename = __GPT_LOOPDEV__;
+ barebox,blockdev;
+ };
+};
+
+&state {
+ backend = <&disk>;
+ backend-type = "raw";
+ backend-stridesize = <0x40>;
+ backend-storage-type = "direct";
+};
diff --git a/test/06-fixed-partition-by-diskuuid.dts b/test/06-fixed-partition-by-diskuuid.dts
new file mode 100644
index 0000000..cc7a61d
--- /dev/null
+++ b/test/06-fixed-partition-by-diskuuid.dts
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright 2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
+/dts-v1/;
+
+#include "barebox-state.dtsi"
+
+/ {
+ expected-dev = __GPT_LOOPDEV__;
+ expected-partno = <0>;
+ expected-offset = <0x28000>;
+ expected-size = <0x8000>;
+
+ disk: loopfile {
+ compatible = "barebox,storage-by-uuid";
+ uuid = __GPT_LOOPDEV_DISKUUID__;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ part_state: state@28000 {
+ reg = <0x28000 0x8000>;
+ label = "state";
+ };
+ };
+ };
+};
+
+&state {
+ backend = <&part_state>;
+ backend-type = "raw";
+ backend-stridesize = <0x40>;
+ backend-storage-type = "direct";
+};
diff --git a/test/07-raw-disk-fail.dts b/test/07-raw-disk-fail.dts
new file mode 100644
index 0000000..f5c7d22
--- /dev/null
+++ b/test/07-raw-disk-fail.dts
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright 2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
+/dts-v1/;
+
+#include "barebox-state.dtsi"
+
+/ {
+ disk: loopfile {
+ compatible = "barebox,hostfile";
+ barebox,filename = __RAW_LOOPDEV__;
+ barebox,blockdev;
+ };
+};
+
+&state {
+ backend = <&disk>;
+ backend-type = "raw";
+ backend-stridesize = <0x40>;
+ backend-storage-type = "direct";
+};
diff --git a/test/08-gpt-disk-no-typeuuid-fail.dts b/test/08-gpt-disk-no-typeuuid-fail.dts
new file mode 100644
index 0000000..2176df0
--- /dev/null
+++ b/test/08-gpt-disk-no-typeuuid-fail.dts
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright 2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
+/dts-v1/;
+
+#include "barebox-state.dtsi"
+
+/ {
+ disk: loopfile {
+ compatible = "barebox,hostfile";
+ barebox,filename = __GPT_NO_TYPEUUID_LOOPDEV__;
+ barebox,blockdev;
+ };
+};
+
+&state {
+ backend = <&disk>;
+ backend-type = "raw";
+ backend-stridesize = <0x40>;
+ backend-storage-type = "direct";
+};
diff --git a/test/09-no-disk-fail.dts b/test/09-no-disk-fail.dts
new file mode 100644
index 0000000..92f9792
--- /dev/null
+++ b/test/09-no-disk-fail.dts
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright 2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
+/dts-v1/;
+
+#include "barebox-state.dtsi"
+
+/ {
+ expected-dev = "";
+
+ disk: loopfile0 {
+ compatible = "barebox,hostfile";
+ barebox,filename = "/dev/barebox-state-dev-does-not-exist";
+ barebox,blockdev;
+ };
+
+ otherdisk: loopfile1 {
+ compatible = "barebox,hostfile";
+ barebox,filename = __GPT_LOOPDEV__;
+ barebox,blockdev;
+ };
+};
+
+&state {
+ backend = <&disk>;
+ backend-type = "raw";
+ backend-stridesize = <0x40>;
+ backend-storage-type = "direct";
+};
diff --git a/test/31-fixed-partition-overlaps-two-gpt-partitions.dts b/test/31-fixed-partition-overlaps-two-gpt-partitions.dts
new file mode 100644
index 0000000..eb6dfc3
--- /dev/null
+++ b/test/31-fixed-partition-overlaps-two-gpt-partitions.dts
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright 2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
+/dts-v1/;
+
+#include "barebox-state.dtsi"
+
+/ {
+ expected-dev = __GPT_LOOPDEV__;
+ expected-partno = <0>;
+ expected-offset = <0x10000>;
+ expected-size = <0x18000>;
+
+ disk: loopfile {
+ compatible = "barebox,hostfile";
+ barebox,filename = __GPT_LOOPDEV__;
+ barebox,blockdev;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ part_state: state@10000 {
+ reg = <0x10000 0x18000>;
+ label = "state";
+ };
+ };
+ };
+};
+
+&state {
+ backend = <&part_state>;
+ backend-type = "raw";
+ backend-stridesize = <0x40>;
+ backend-storage-type = "direct";
+};
diff --git a/test/32-fixed-partition-overlaps-two-gpt-partitions-partially.dts b/test/32-fixed-partition-overlaps-two-gpt-partitions-partially.dts
new file mode 100644
index 0000000..3cdb113
--- /dev/null
+++ b/test/32-fixed-partition-overlaps-two-gpt-partitions-partially.dts
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright 2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
+/dts-v1/;
+
+#include "barebox-state.dtsi"
+
+/ {
+ expected-dev = __GPT_LOOPDEV__;
+ expected-partno = <0>;
+ expected-offset = <0x10000>;
+ expected-size = <0x14000>;
+
+ disk: loopfile {
+ compatible = "barebox,hostfile";
+ barebox,filename = __GPT_LOOPDEV__;
+ barebox,blockdev;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ part_state: state@10000 {
+ reg = <0x10000 0x14000>;
+ label = "state";
+ };
+ };
+ };
+};
+
+&state {
+ backend = <&part_state>;
+ backend-type = "raw";
+ backend-stridesize = <0x40>;
+ backend-storage-type = "direct";
+};
diff --git a/test/33-fixed-partition-part-of-gpt-partition.dts b/test/33-fixed-partition-part-of-gpt-partition.dts
new file mode 100644
index 0000000..771b7be
--- /dev/null
+++ b/test/33-fixed-partition-part-of-gpt-partition.dts
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright 2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
+/dts-v1/;
+
+#include "barebox-state.dtsi"
+
+/ {
+ expected-dev = __GPT_LOOPDEV__;
+ expected-partno = <2>;
+ expected-offset = <0x00000>;
+ expected-size = <0x2000>;
+
+ disk: loopfile {
+ compatible = "barebox,hostfile";
+ barebox,filename = __GPT_LOOPDEV__;
+ barebox,blockdev;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ part_state: state@20000 {
+ reg = <0x20000 0x2000>;
+ label = "state";
+ };
+ };
+ };
+};
+
+&state {
+ backend = <&part_state>;
+ backend-type = "raw";
+ backend-stridesize = <0x40>;
+ backend-storage-type = "direct";
+};
diff --git a/test/barebox-state.dtsi b/test/barebox-state.dtsi
new file mode 100644
index 0000000..204f1b3
--- /dev/null
+++ b/test/barebox-state.dtsi
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright 2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
+/ {
+ aliases {
+ state = &state;
+ };
+
+ /* State: mutable part */
+ state: state {
+ magic = <0x4d433230>;
+ compatible = "barebox,state";
+
+ bootstate {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ system0 { /* the node's name here must match the subnode's name in the 'bootstate' node */
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ remaining_attempts@0 {
+ reg = <0x0 0x4>;
+ type = "uint32";
+ default = <3>;
+ };
+ priority@4 {
+ reg = <0x4 0x4>;
+ type = "uint32";
+ default = <20>;
+ };
+ };
+
+ system1 { /* the node's name here must match the subnode's name in the 'bootstate' node */
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ remaining_attempts@8 {
+ reg = <0x8 0x4>;
+ type = "uint32";
+ default = <3>;
+ };
+ priority@c {
+ reg = <0xC 0x4>;
+ type = "uint32";
+ default = <20>;
+ };
+ };
+
+ last_chosen@10 {
+ reg = <0x10 0x4>;
+ type = "uint32";
+ };
+ };
+ };
+};
diff --git a/test/barebox-state.t b/test/barebox-state.t
new file mode 100755
index 0000000..24b3415
--- /dev/null
+++ b/test/barebox-state.t
@@ -0,0 +1,231 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0-only
+# Copyright 2023 The DT-Utils Authors <oss-tools@pengutronix.de>
+
+set -e
+
+test_description="barebox-state binary tests"
+
+. ./sharness.sh
+
+# Prerequisite: device tree compiler available [DTC]
+dtc --version &&
+ test_set_prereq DTC
+
+# Prerequisite: fdtget available [FDTGET]
+fdtget --version &&
+ test_set_prereq FDTGET
+
+# Prerequisite: C preprocessor available [CPP]
+cpp --version &&
+ test_set_prereq CPP
+
+# Prerequisite: UUID generator available [UUIDGEN]
+uuidgen --version &&
+ test_set_prereq UUIDGEN
+
+# Prerequisite: genimage available [GENIMAGE]
+genimage --version &&
+ test_set_prereq GENIMAGE
+
+# Prerequisite: root available [ROOT]
+whoami | grep -q root &&
+ test_set_prereq ROOT
+
+# Prerequisite: root available [LOSETUP]
+losetup --version &&
+ test_set_prereq LOSETUP
+
+# Prerequisite: udisksctl available [UDISKSCTL]
+udisksctl help &&
+ test_set_prereq UDISKSCTL
+
+if ! test_have_prereq DTC; then
+ skip_all='skipping all tests, dtc not available'
+ test_done
+fi
+
+if ! test_have_prereq CPP; then
+ skip_all='skipping all tests, cpp not available'
+ test_done
+fi
+
+if ! test_have_prereq GENIMAGE; then
+ skip_all='skipping all tests, genimage not available'
+ test_done
+fi
+
+test_expect_success "barebox-state invalid arg" "
+ test_must_fail barebox-state --foobar baz
+"
+
+test_expect_success "barebox-state missing arg" "
+ test_expect_code 1 barebox-state --get &&
+ test_expect_code 1 barebox-state --set &&
+ test_expect_code 1 barebox-state --name &&
+ test_expect_code 1 barebox-state --input &&
+ test_expect_code 1 barebox-state info
+"
+
+test_expect_success "barebox-state version" "
+ barebox-state --version
+"
+
+test_expect_success "barebox-state help" "
+ barebox-state --help
+"
+
+if test_have_prereq ROOT && test_have_prereq LOSETUP; then
+ loopsetup () { losetup -P --find --show "$1"; }
+ loopdetach () { losetup --detach "$1"; }
+ losetup=losetup
+elif test_have_prereq UDISKSCTL; then
+ loopsetup () {
+ output=$(udisksctl loop-setup --file "$1")
+ echo $output | sed -n 's/^Mapped file .* as \(.*\)\.$/\1/p'
+ }
+ loopdetach () { udisksctl loop-delete -b "$1"; }
+ losetup=udiskctl
+else
+ loopsetup () { :; }
+ loopdetach () { :; }
+fi
+
+# Prerequisite: loop mount possible [LOOP]
+[ -n "$losetup" ] &&
+ test_set_prereq LOOP
+
+TEST_TMPDIR=$(mktemp -d)
+
+if test_have_prereq UUIDGEN; then
+ partuuid="$(uuidgen)"
+ diskuuid="$(uuidgen)"
+else
+ partuuid="1da8efb0-4932-4786-b1fc-50dd3cff212f"
+ diskuuid="30b8d4b2-ec91-4288-9233-cdb643cb5486"
+fi
+
+for config in ${SHARNESS_TEST_DIRECTORY}/*.config; do
+ basename=$(basename $config .config)
+ config_pp=${TEST_TMPDIR}/${basename}.pp.config
+ cpp -o${config_pp} -nostdinc -undef -x assembler-with-cpp \
+ -D__IMAGE__='"'$basename'.hdimg"' \
+ -D__GPT_LOOPDEV_PARTUUID__='"'$partuuid'"' \
+ -D__GPT_LOOPDEV_DISKUUID__='"'$diskuuid'"' $config
+
+ genimage --config=${config_pp} --tmppath="${TEST_TMPDIR}/genimage" \
+ --inputpath="${TEST_TMPDIR}" --outputpath="${TEST_TMPDIR}" \
+ --rootpath="${SHARNESS_TEST_DIRECTORY}"
+done
+
+gptloop=$(loopsetup ${TEST_TMPDIR}/gpt.hdimg)
+gptnouuidloop=$(loopsetup ${TEST_TMPDIR}/gpt-no-typeuuid.hdimg)
+rawloop=$(loopsetup ${TEST_TMPDIR}/raw.hdimg)
+
+for dts in ${SHARNESS_TEST_DIRECTORY}/*.dts; do
+ dtb=$(basename ${dts} .dts).dtb
+ cpp -nostdinc -undef -D__DTS__ -x assembler-with-cpp \
+ -D__GPT_LOOPDEV__='"'$gptloop'"' -D__RAW_LOOPDEV__='"'$rawloop'"' \
+ -D__GPT_NO_TYPEUUID_LOOPDEV__='"'$gptnouuidloop'"' \
+ -D__GPT_LOOPDEV_PARTUUID__='"'$partuuid'"' \
+ -D__GPT_LOOPDEV_DISKUUID__='"'$diskuuid'"' $dts | \
+ dtc -O dtb -o "${TEST_TMPDIR}/${dtb}" -b 0
+
+ if [ "${dtb#*-fail.dtb}" != "$dtb" ]; then
+ test_expect_success LOOP "barebox-state -i ${dtb} --dump" "
+ test_must_fail barebox-state --input ${TEST_TMPDIR}/$dtb --dump
+ "
+ continue
+ fi
+
+ test_expect_success LOOP "barebox-state -i ${dtb} --dump" "
+ barebox-state --input ${TEST_TMPDIR}/$dtb --dump
+ "
+
+ if test_have_prereq FDTGET && test_have_prereq LOOP; then
+ resolution=$(barebox-state --input ${TEST_TMPDIR}/$dtb -vv --dump 2>&1 | \
+ grep 'state: backend resolved to ')
+ partinfo=$(echo $resolution | sed 's/\/state: backend resolved to //gp')
+
+ set $partinfo
+ actual_dev=$1
+ actual_off=$2
+ actual_siz=$3
+
+ expected_fail=$(fdtget -t s ${TEST_TMPDIR}/${dtb} / expected-dev)
+ expected_disk=$(fdtget -t s ${TEST_TMPDIR}/${dtb} / expected-dev)
+ expected_partno=$(fdtget -t u ${TEST_TMPDIR}/${dtb} / expected-partno)
+ if [ "$expected_partno" != "0" ]; then
+ expected_dev="${expected_disk}p${expected_partno}"
+ else
+ expected_dev="${expected_disk}"
+ fi
+ expected_off=$(fdtget -t u ${TEST_TMPDIR}/${dtb} / expected-offset)
+ expected_siz=$(fdtget -t u ${TEST_TMPDIR}/${dtb} / expected-size)
+
+ test_expect_success LOOP "check backend partition device for ${dtb}" "
+ [ "$actual_dev" = "$expected_dev" ]
+ "
+
+ test_expect_success LOOP "check backend partition offset for ${dtb}" "
+ [ "$actual_off" = "$expected_off" ]
+ "
+
+ test_expect_success LOOP "check backend partition size for ${dtb}" "
+ [ "$actual_siz" = "$expected_siz" ]
+ "
+ fi
+
+ test_expect_success LOOP "barebox-state -i ${dtb} --dump-shell" "
+ eval $(barebox-state --input ${TEST_TMPDIR}/$dtb --dump-shell)
+ [ $? -eq 0 ] || return 1
+ "
+
+ test_expect_success LOOP "verify shell dump for ${dtb}" "
+ [ $state_bootstate_system0_remaining_attempts = 3 ] || return 2
+ [ $state_bootstate_system0_priority = 20 ] || return 2
+ [ $state_bootstate_system1_remaining_attempts = 3 ] || return 2
+ [ $state_bootstate_system1_priority = 20 ] || return 2
+ "
+
+ test_expect_success LOOP "barebox-state -i ${dtb} --set bootstate.last_chosen=0" "
+ barebox-state --input ${TEST_TMPDIR}/$dtb --set bootstate.last_chosen=0
+ "
+
+ test_expect_success LOOP "barebox-state -i ${dtb} --dump-shell #2" "
+ eval $(barebox-state --input ${TEST_TMPDIR}/$dtb --dump-shell)
+ [ $? -eq 0 ] || return 1
+ "
+
+ test_expect_success LOOP "verify set for ${dtb} #1" "
+ [ $state_bootstate_last_chosen = 0 ] || return 2
+ "
+
+ test_expect_success LOOP "barebox-state -i ${dtb} --set bootstate.last_chosen=1337" "
+ barebox-state --input ${TEST_TMPDIR}/$dtb --set bootstate.last_chosen=1337
+ "
+
+ test_expect_success LOOP "barebox-state -i ${dtb} --dump-shell #2" "
+ eval $(barebox-state --input ${TEST_TMPDIR}/$dtb --dump-shell)
+ [ $? -eq 0 ] || return 1
+ "
+
+ test_expect_success LOOP "verify set for ${dtb} #2" "
+ #test_when_finished rm -f ${TEST_TMPDIR}/${dtb}
+ [ $state_bootstate_system0_remaining_attempts = 3 ] || return 2
+ [ $state_bootstate_system0_priority = 20 ] || return 2
+ [ $state_bootstate_system1_remaining_attempts = 3 ] || return 2
+ [ $state_bootstate_system1_priority = 20 ] || return 2
+ [ $state_bootstate_last_chosen = 1337 ] || return 2
+ "
+done
+
+loopdetach $rawloop
+loopdetach $gptnouuidloop
+loopdetach $gptloop
+
+rm -rf $TEST_TMPDIR
+
+test_done
+
+# vi: ft=sh
diff --git a/test/crc32.c b/test/crc32.c
new file mode 100644
index 0000000..f4cad5b
--- /dev/null
+++ b/test/crc32.c
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright 2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
+#include <stdint.h>
+#include <assert.h>
+
+#include <dt/common.h>
+
+int main(void)
+{
+ const char *str = "Hello, World!";
+ uint32_t checksum;
+
+ checksum = crc32(0, str, strlen(str));
+ assert(checksum == 0xec4ac3d0);
+
+ checksum = crc32_no_comp(0, str, strlen(str));
+ assert(checksum == 0xe33e8552);
+
+ return 0;
+}
diff --git a/test/gpt-no-typeuuid.config b/test/gpt-no-typeuuid.config
new file mode 100644
index 0000000..a03aaea
--- /dev/null
+++ b/test/gpt-no-typeuuid.config
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright 2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
+image __IMAGE__ {
+ hdimage {
+ align = 32K
+ partition-table-type = gpt
+ }
+
+ partition oldstate {
+ image = /dev/zero
+ in-partition-table = false
+ offset = 32K
+ size = 32K
+ }
+
+ partition part1 {
+ image = /dev/zero
+ size = 64K
+ }
+
+ partition part2 {
+ image = /dev/zero
+ size = 32K
+ partition-uuid = __GPT_LOOPDEV_PARTUUID__
+ }
+
+ partition oldstate2 {
+ image = /dev/zero
+ in-partition-table = false
+ offset = 160K
+ size = 32K
+ }
+}
+
+/* vim: set tabstop=8 noexpandtab : */
diff --git a/test/gpt.config b/test/gpt.config
new file mode 100644
index 0000000..f0fe87e
--- /dev/null
+++ b/test/gpt.config
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright 2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
+image __IMAGE__ {
+ hdimage {
+ align = 32K
+ partition-table-type = gpt
+ disk-uuid = __GPT_LOOPDEV_DISKUUID__
+ }
+
+ partition oldstate {
+ image = /dev/zero
+ in-partition-table = false
+ offset = 32K
+ size = 32K
+ }
+
+ partition part1 {
+ image = /dev/zero
+ size = 64K
+ }
+
+ partition part2 {
+ image = /dev/zero
+ size = 32K
+ partition-type-uuid = 4778ed65-bf42-45fa-9c5b-287a1dc4aab1
+ partition-uuid = __GPT_LOOPDEV_PARTUUID__
+ }
+
+ partition oldstate2 {
+ image = /dev/zero
+ in-partition-table = false
+ offset = 160K
+ size = 32K
+ }
+}
+
+/* vim: set tabstop=8 noexpandtab : */
diff --git a/test/meson.build b/test/meson.build
new file mode 100644
index 0000000..df6bc01
--- /dev/null
+++ b/test/meson.build
@@ -0,0 +1,38 @@
+# SPDX-License-Identifier: GPL-2.0-only
+# Copyright 2023 The DT-Utils Authors <oss-tools@pengutronix.de>
+if not get_option('tests')
+ subdir_done()
+endif
+
+tests = [
+ 'crc32',
+]
+
+extra_test_sources = files([
+])
+
+foreach test_name : tests
+ exe = executable(
+ test_name + '-test',
+ test_name + '.c',
+ extra_test_sources,
+ link_with : [libdt],
+ include_directories : incdir)
+
+ test(
+ test_name,
+ exe,
+ is_parallel : false,
+ timeout : 240,
+ workdir : meson.source_root())
+endforeach
+
+test(
+ 'barebox-state.t',
+ find_program('barebox-state.t'),
+ args : '-v',
+ is_parallel : false,
+ timeout : 300,
+ env : ['SHARNESS_BUILD_DIRECTORY=' + meson.build_root()],
+ workdir : meson.current_source_dir(),
+)
diff --git a/test/raw.config b/test/raw.config
new file mode 100644
index 0000000..71918a5
--- /dev/null
+++ b/test/raw.config
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright 2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
+image __IMAGE__ {
+ hdimage {
+ align = 32K
+ partition-table-type = none
+ }
+
+ partition oldstate {
+ image = /dev/zero
+ offset = 32K
+ size = 32K
+ }
+
+ partition part1 {
+ image = /dev/zero
+ size = 64K
+ }
+
+ partition part2 {
+ image = /dev/zero
+ size = 32K
+ }
+}
+
+/* vim: set tabstop=8 noexpandtab : */
diff --git a/test/sharness.sh b/test/sharness.sh
new file mode 100755
index 0000000..63e25a6
--- /dev/null
+++ b/test/sharness.sh
@@ -0,0 +1,858 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright (c) 2011-2012 Mathias Lafeldt
+# Copyright (c) 2005-2012 Git project
+# Copyright (c) 2005-2012 Junio C Hamano
+#
+# 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, see http://www.gnu.org/licenses/ .
+
+# Public: Current version of Sharness.
+SHARNESS_VERSION="1.0.0"
+export SHARNESS_VERSION
+
+# Public: The file extension for tests. By default, it is set to "t".
+: ${SHARNESS_TEST_EXTENSION:=t}
+export SHARNESS_TEST_EXTENSION
+
+# Reset TERM to original terminal if found, otherwise save original TERM
+[ "x" = "x$SHARNESS_ORIG_TERM" ] &&
+ SHARNESS_ORIG_TERM="$TERM" ||
+ TERM="$SHARNESS_ORIG_TERM"
+# Public: The unsanitized TERM under which sharness is originally run
+export SHARNESS_ORIG_TERM
+
+# Export SHELL_PATH
+: ${SHELL_PATH:=$SHELL}
+export SHELL_PATH
+
+# For repeatability, reset the environment to a known state.
+# TERM is sanitized below, after saving color control sequences.
+LANG=C
+LC_ALL=C
+PAGER=cat
+TZ=UTC
+EDITOR=:
+export LANG LC_ALL PAGER TZ EDITOR
+unset VISUAL CDPATH GREP_OPTIONS
+
+# Line feed
+LF='
+'
+
+[ "x$TERM" != "xdumb" ] && (
+ [ -t 1 ] &&
+ tput bold >/dev/null 2>&1 &&
+ tput setaf 1 >/dev/null 2>&1 &&
+ tput sgr0 >/dev/null 2>&1
+ ) &&
+ color=t
+
+while test "$#" -ne 0; do
+ case "$1" in
+ -d|--d|--de|--deb|--debu|--debug)
+ debug=t; shift ;;
+ -i|--i|--im|--imm|--imme|--immed|--immedi|--immedia|--immediat|--immediate)
+ immediate=t; shift ;;
+ -l|--l|--lo|--lon|--long|--long-|--long-t|--long-te|--long-tes|--long-test|--long-tests)
+ TEST_LONG=t; export TEST_LONG; shift ;;
+ --in|--int|--inte|--inter|--intera|--interac|--interact|--interacti|--interactiv|--interactive|--interactive-|--interactive-t|--interactive-te|--interactive-tes|--interactive-test|--interactive-tests):
+ TEST_INTERACTIVE=t; export TEST_INTERACTIVE; verbose=t; shift ;;
+ -h|--h|--he|--hel|--help)
+ help=t; shift ;;
+ -v|--v|--ve|--ver|--verb|--verbo|--verbos|--verbose)
+ verbose=t; shift ;;
+ -q|--q|--qu|--qui|--quie|--quiet)
+ # Ignore --quiet under a TAP::Harness. Saying how many tests
+ # passed without the ok/not ok details is always an error.
+ test -z "$HARNESS_ACTIVE" && quiet=t; shift ;;
+ --chain-lint)
+ chain_lint=t; shift ;;
+ --no-chain-lint)
+ chain_lint=; shift ;;
+ --no-color)
+ color=; shift ;;
+ --root=*)
+ root=$(expr "z$1" : 'z[^=]*=\(.*\)')
+ shift ;;
+ *)
+ echo "error: unknown test option '$1'" >&2; exit 1 ;;
+ esac
+done
+
+if test -n "$color"; then
+ # Save the color control sequences now rather than run tput
+ # each time say_color() is called. This is done for two
+ # reasons:
+ # * TERM will be changed to dumb
+ # * HOME will be changed to a temporary directory and tput
+ # might need to read ~/.terminfo from the original HOME
+ # directory to get the control sequences
+ # Note: This approach assumes the control sequences don't end
+ # in a newline for any terminal of interest (command
+ # substitutions strip trailing newlines). Given that most
+ # (all?) terminals in common use are related to ECMA-48, this
+ # shouldn't be a problem.
+ say_color_error=$(tput bold; tput setaf 1) # bold red
+ say_color_skip=$(tput setaf 4) # blue
+ say_color_warn=$(tput setaf 3) # brown/yellow
+ say_color_pass=$(tput setaf 2) # green
+ say_color_info=$(tput setaf 6) # cyan
+ say_color_reset=$(tput sgr0)
+ say_color_="" # no formatting for normal text
+ say_color() {
+ test -z "$1" && test -n "$quiet" && return
+ eval "say_color_color=\$say_color_$1"
+ shift
+ printf "%s\\n" "$say_color_color$*$say_color_reset"
+ }
+else
+ say_color() {
+ test -z "$1" && test -n "$quiet" && return
+ shift
+ printf "%s\n" "$*"
+ }
+fi
+
+TERM=dumb
+export TERM
+
+error() {
+ say_color error "error: $*"
+ EXIT_OK=t
+ exit 1
+}
+
+say() {
+ say_color info "$*"
+}
+
+test -n "$test_description" || error "Test script did not set test_description."
+
+if test "$help" = "t"; then
+ echo "$test_description"
+ exit 0
+fi
+
+exec 5>&1
+exec 6<&0
+if test "$verbose" = "t"; then
+ exec 4>&2 3>&1
+else
+ exec 4>/dev/null 3>/dev/null
+fi
+
+test_failure=0
+test_count=0
+test_fixed=0
+test_broken=0
+test_success=0
+
+die() {
+ code=$?
+ if test -n "$EXIT_OK"; then
+ exit $code
+ else
+ echo >&5 "FATAL: Unexpected exit with code $code"
+ exit 1
+ fi
+}
+
+EXIT_OK=
+trap 'die' EXIT
+
+# Public: Define that a test prerequisite is available.
+#
+# The prerequisite can later be checked explicitly using test_have_prereq or
+# implicitly by specifying the prerequisite name in calls to test_expect_success
+# or test_expect_failure.
+#
+# $1 - Name of prerequisite (a simple word, in all capital letters by convention)
+#
+# Examples
+#
+# # Set PYTHON prerequisite if interpreter is available.
+# command -v python >/dev/null && test_set_prereq PYTHON
+#
+# # Set prerequisite depending on some variable.
+# test -z "$NO_GETTEXT" && test_set_prereq GETTEXT
+#
+# Returns nothing.
+test_set_prereq() {
+ satisfied_prereq="$satisfied_prereq$1 "
+}
+satisfied_prereq=" "
+
+# Public: Check if one or more test prerequisites are defined.
+#
+# The prerequisites must have previously been set with test_set_prereq.
+# The most common use of this is to skip all the tests if some essential
+# prerequisite is missing.
+#
+# $1 - Comma-separated list of test prerequisites.
+#
+# Examples
+#
+# # Skip all remaining tests if prerequisite is not set.
+# if ! test_have_prereq PERL; then
+# skip_all='skipping perl interface tests, perl not available'
+# test_done
+# fi
+#
+# Returns 0 if all prerequisites are defined or 1 otherwise.
+test_have_prereq() {
+ # prerequisites can be concatenated with ','
+ save_IFS=$IFS
+ IFS=,
+ set -- $*
+ IFS=$save_IFS
+
+ total_prereq=0
+ ok_prereq=0
+ missing_prereq=
+
+ for prerequisite; do
+ case "$prerequisite" in
+ !*)
+ negative_prereq=t
+ prerequisite=${prerequisite#!}
+ ;;
+ *)
+ negative_prereq=
+ esac
+
+ total_prereq=$(($total_prereq + 1))
+ case "$satisfied_prereq" in
+ *" $prerequisite "*)
+ satisfied_this_prereq=t
+ ;;
+ *)
+ satisfied_this_prereq=
+ esac
+
+ case "$satisfied_this_prereq,$negative_prereq" in
+ t,|,t)
+ ok_prereq=$(($ok_prereq + 1))
+ ;;
+ *)
+ # Keep a list of missing prerequisites; restore
+ # the negative marker if necessary.
+ prerequisite=${negative_prereq:+!}$prerequisite
+ if test -z "$missing_prereq"; then
+ missing_prereq=$prerequisite
+ else
+ missing_prereq="$prerequisite,$missing_prereq"
+ fi
+ esac
+ done
+
+ test $total_prereq = $ok_prereq
+}
+
+# You are not expected to call test_ok_ and test_failure_ directly, use
+# the text_expect_* functions instead.
+
+test_ok_() {
+ test_success=$(($test_success + 1))
+ say_color "" "ok $test_count - $@"
+}
+
+test_failure_() {
+ test_failure=$(($test_failure + 1))
+ say_color error "not ok $test_count - $1"
+ shift
+ echo "$@" | sed -e 's/^/# /'
+ test "$immediate" = "" || { EXIT_OK=t; exit 1; }
+}
+
+test_known_broken_ok_() {
+ test_fixed=$(($test_fixed + 1))
+ say_color error "ok $test_count - $@ # TODO known breakage vanished"
+}
+
+test_known_broken_failure_() {
+ test_broken=$(($test_broken + 1))
+ say_color warn "not ok $test_count - $@ # TODO known breakage"
+}
+
+# Public: Execute commands in debug mode.
+#
+# Takes a single argument and evaluates it only when the test script is started
+# with --debug. This is primarily meant for use during the development of test
+# scripts.
+#
+# $1 - Commands to be executed.
+#
+# Examples
+#
+# test_debug "cat some_log_file"
+#
+# Returns the exit code of the last command executed in debug mode or 0
+# otherwise.
+test_debug() {
+ test "$debug" = "" || eval "$1"
+}
+
+# Public: Stop execution and start a shell.
+#
+# This is useful for debugging tests and only makes sense together with "-v".
+# Be sure to remove all invocations of this command before submitting.
+test_pause() {
+ if test "$verbose" = t; then
+ "$SHELL_PATH" <&6 >&3 2>&4
+ else
+ error >&5 "test_pause requires --verbose"
+ fi
+}
+
+test_eval_() {
+ # This is a separate function because some tests use
+ # "return" to end a test_expect_success block early.
+ case ",$test_prereq," in
+ *,INTERACTIVE,*)
+ eval "$*"
+ ;;
+ *)
+ eval </dev/null >&3 2>&4 "$*"
+ ;;
+ esac
+}
+
+test_run_() {
+ test_cleanup=:
+ expecting_failure=$2
+ test_eval_ "$1"
+ eval_ret=$?
+
+ if test "$chain_lint" = "t"; then
+ test_eval_ "(exit 117) && $1"
+ if test "$?" != 117; then
+ error "bug in the test script: broken &&-chain: $1"
+ fi
+ fi
+
+ if test -z "$immediate" || test $eval_ret = 0 || test -n "$expecting_failure"; then
+ test_eval_ "$test_cleanup"
+ fi
+ if test "$verbose" = "t" && test -n "$HARNESS_ACTIVE"; then
+ echo ""
+ fi
+ return "$eval_ret"
+}
+
+test_skip_() {
+ test_count=$(($test_count + 1))
+ to_skip=
+ for skp in $SKIP_TESTS; do
+ case $this_test.$test_count in
+ $skp)
+ to_skip=t
+ break
+ esac
+ done
+ if test -z "$to_skip" && test -n "$test_prereq" && ! test_have_prereq "$test_prereq"; then
+ to_skip=t
+ fi
+ case "$to_skip" in
+ t)
+ of_prereq=
+ if test "$missing_prereq" != "$test_prereq"; then
+ of_prereq=" of $test_prereq"
+ fi
+
+ say_color skip >&3 "skipping test: $@"
+ say_color skip "ok $test_count # skip $1 (missing $missing_prereq${of_prereq})"
+ : true
+ ;;
+ *)
+ false
+ ;;
+ esac
+}
+
+# Public: Run test commands and expect them to succeed.
+#
+# When the test passed, an "ok" message is printed and the number of successful
+# tests is incremented. When it failed, a "not ok" message is printed and the
+# number of failed tests is incremented.
+#
+# With --immediate, exit test immediately upon the first failed test.
+#
+# Usually takes two arguments:
+# $1 - Test description
+# $2 - Commands to be executed.
+#
+# With three arguments, the first will be taken to be a prerequisite:
+# $1 - Comma-separated list of test prerequisites. The test will be skipped if
+# not all of the given prerequisites are set. To negate a prerequisite,
+# put a "!" in front of it.
+# $2 - Test description
+# $3 - Commands to be executed.
+#
+# Examples
+#
+# test_expect_success \
+# 'git-write-tree should be able to write an empty tree.' \
+# 'tree=$(git-write-tree)'
+#
+# # Test depending on one prerequisite.
+# test_expect_success TTY 'git --paginate rev-list uses a pager' \
+# ' ... '
+#
+# # Multiple prerequisites are separated by a comma.
+# test_expect_success PERL,PYTHON 'yo dawg' \
+# ' test $(perl -E 'print eval "1 +" . qx[python -c "print 2"]') == "4" '
+#
+# Returns nothing.
+test_expect_success() {
+ test "$#" = 3 && { test_prereq=$1; shift; } || test_prereq=
+ test "$#" = 2 || error "bug in the test script: not 2 or 3 parameters to test_expect_success"
+ export test_prereq
+ if ! test_skip_ "$@"; then
+ say >&3 "expecting success: $2"
+ if test_run_ "$2"; then
+ test_ok_ "$1"
+ else
+ test_failure_ "$@"
+ fi
+ fi
+ echo >&3 ""
+}
+
+# Public: Run test commands and expect them to fail. Used to demonstrate a known
+# breakage.
+#
+# This is NOT the opposite of test_expect_success, but rather used to mark a
+# test that demonstrates a known breakage.
+#
+# When the test passed, an "ok" message is printed and the number of fixed tests
+# is incremented. When it failed, a "not ok" message is printed and the number
+# of tests still broken is incremented.
+#
+# Failures from these tests won't cause --immediate to stop.
+#
+# Usually takes two arguments:
+# $1 - Test description
+# $2 - Commands to be executed.
+#
+# With three arguments, the first will be taken to be a prerequisite:
+# $1 - Comma-separated list of test prerequisites. The test will be skipped if
+# not all of the given prerequisites are set. To negate a prerequisite,
+# put a "!" in front of it.
+# $2 - Test description
+# $3 - Commands to be executed.
+#
+# Returns nothing.
+test_expect_failure() {
+ test "$#" = 3 && { test_prereq=$1; shift; } || test_prereq=
+ test "$#" = 2 || error "bug in the test script: not 2 or 3 parameters to test_expect_failure"
+ export test_prereq
+ if ! test_skip_ "$@"; then
+ say >&3 "checking known breakage: $2"
+ if test_run_ "$2" expecting_failure; then
+ test_known_broken_ok_ "$1"
+ else
+ test_known_broken_failure_ "$1"
+ fi
+ fi
+ echo >&3 ""
+}
+
+# Public: Run command and ensure that it fails in a controlled way.
+#
+# Use it instead of "! <command>". For example, when <command> dies due to a
+# segfault, test_must_fail diagnoses it as an error, while "! <command>" would
+# mistakenly be treated as just another expected failure.
+#
+# This is one of the prefix functions to be used inside test_expect_success or
+# test_expect_failure.
+#
+# $1.. - Command to be executed.
+#
+# Examples
+#
+# test_expect_success 'complain and die' '
+# do something &&
+# do something else &&
+# test_must_fail git checkout ../outerspace
+# '
+#
+# Returns 1 if the command succeeded (exit code 0).
+# Returns 1 if the command died by signal (exit codes 130-192)
+# Returns 1 if the command could not be found (exit code 127).
+# Returns 0 otherwise.
+test_must_fail() {
+ "$@"
+ exit_code=$?
+ if test $exit_code = 0; then
+ echo >&2 "test_must_fail: command succeeded: $*"
+ return 1
+ elif test $exit_code -gt 129 -a $exit_code -le 192; then
+ echo >&2 "test_must_fail: died by signal: $*"
+ return 1
+ elif test $exit_code = 127; then
+ echo >&2 "test_must_fail: command not found: $*"
+ return 1
+ fi
+ return 0
+}
+
+# Public: Run command and ensure that it succeeds or fails in a controlled way.
+#
+# Similar to test_must_fail, but tolerates success too. Use it instead of
+# "<command> || :" to catch failures caused by a segfault, for instance.
+#
+# This is one of the prefix functions to be used inside test_expect_success or
+# test_expect_failure.
+#
+# $1.. - Command to be executed.
+#
+# Examples
+#
+# test_expect_success 'some command works without configuration' '
+# test_might_fail git config --unset all.configuration &&
+# do something
+# '
+#
+# Returns 1 if the command died by signal (exit codes 130-192)
+# Returns 1 if the command could not be found (exit code 127).
+# Returns 0 otherwise.
+test_might_fail() {
+ "$@"
+ exit_code=$?
+ if test $exit_code -gt 129 -a $exit_code -le 192; then
+ echo >&2 "test_might_fail: died by signal: $*"
+ return 1
+ elif test $exit_code = 127; then
+ echo >&2 "test_might_fail: command not found: $*"
+ return 1
+ fi
+ return 0
+}
+
+# Public: Run command and ensure it exits with a given exit code.
+#
+# This is one of the prefix functions to be used inside test_expect_success or
+# test_expect_failure.
+#
+# $1 - Expected exit code.
+# $2.. - Command to be executed.
+#
+# Examples
+#
+# test_expect_success 'Merge with d/f conflicts' '
+# test_expect_code 1 git merge "merge msg" B master
+# '
+#
+# Returns 0 if the expected exit code is returned or 1 otherwise.
+test_expect_code() {
+ want_code=$1
+ shift
+ "$@"
+ exit_code=$?
+ if test $exit_code = $want_code; then
+ return 0
+ fi
+
+ echo >&2 "test_expect_code: command exited with $exit_code, we wanted $want_code $*"
+ return 1
+}
+
+# Public: Compare two files to see if expected output matches actual output.
+#
+# The TEST_CMP variable defines the command used for the comparison; it
+# defaults to "diff -u". Only when the test script was started with --verbose,
+# will the command's output, the diff, be printed to the standard output.
+#
+# This is one of the prefix functions to be used inside test_expect_success or
+# test_expect_failure.
+#
+# $1 - Path to file with expected output.
+# $2 - Path to file with actual output.
+#
+# Examples
+#
+# test_expect_success 'foo works' '
+# echo expected >expected &&
+# foo >actual &&
+# test_cmp expected actual
+# '
+#
+# Returns the exit code of the command set by TEST_CMP.
+test_cmp() {
+ ${TEST_CMP:-diff -u} "$@"
+}
+
+# Public: portably print a sequence of numbers.
+#
+# seq is not in POSIX and GNU seq might not be available everywhere,
+# so it is nice to have a seq implementation, even a very simple one.
+#
+# $1 - Starting number.
+# $2 - Ending number.
+#
+# Examples
+#
+# test_expect_success 'foo works 10 times' '
+# for i in $(test_seq 1 10)
+# do
+# foo || return
+# done
+# '
+#
+# Returns 0 if all the specified numbers can be displayed.
+test_seq() {
+ i="$1"
+ j="$2"
+ while test "$i" -le "$j"
+ do
+ echo "$i" || return
+ i=$(expr "$i" + 1)
+ done
+}
+
+# Public: Check if the file expected to be empty is indeed empty, and barfs
+# otherwise.
+#
+# $1 - File to check for emptyness.
+#
+# Returns 0 if file is empty, 1 otherwise.
+test_must_be_empty() {
+ if test -s "$1"
+ then
+ echo "'$1' is not empty, it contains:"
+ cat "$1"
+ return 1
+ fi
+}
+
+# Public: Schedule cleanup commands to be run unconditionally at the end of a
+# test.
+#
+# If some cleanup command fails, the test will not pass. With --immediate, no
+# cleanup is done to help diagnose what went wrong.
+#
+# This is one of the prefix functions to be used inside test_expect_success or
+# test_expect_failure.
+#
+# $1.. - Commands to prepend to the list of cleanup commands.
+#
+# Examples
+#
+# test_expect_success 'test core.capslock' '
+# git config core.capslock true &&
+# test_when_finished "git config --unset core.capslock" &&
+# do_something
+# '
+#
+# Returns the exit code of the last cleanup command executed.
+test_when_finished() {
+ test_cleanup="{ $*
+ } && (exit \"\$eval_ret\"); eval_ret=\$?; $test_cleanup"
+}
+
+# Public: Schedule cleanup commands to be run unconditionally when all tests
+# have run.
+#
+# This can be used to clean up things like test databases. It is not needed to
+# clean up temporary files, as test_done already does that.
+#
+# Examples:
+#
+# cleanup mysql -e "DROP DATABASE mytest"
+#
+# Returns the exit code of the last cleanup command executed.
+final_cleanup=
+cleanup() {
+ final_cleanup="{ $*
+ } && (exit \"\$eval_ret\"); eval_ret=\$?; $final_cleanup"
+}
+
+# Public: Summarize test results and exit with an appropriate error code.
+#
+# Must be called at the end of each test script.
+#
+# Can also be used to stop tests early and skip all remaining tests. For this,
+# set skip_all to a string explaining why the tests were skipped before calling
+# test_done.
+#
+# Examples
+#
+# # Each test script must call test_done at the end.
+# test_done
+#
+# # Skip all remaining tests if prerequisite is not set.
+# if ! test_have_prereq PERL; then
+# skip_all='skipping perl interface tests, perl not available'
+# test_done
+# fi
+#
+# Returns 0 if all tests passed or 1 if there was a failure.
+test_done() {
+ EXIT_OK=t
+
+ if test -z "$HARNESS_ACTIVE"; then
+ test_results_dir="$SHARNESS_TEST_DIRECTORY/test-results"
+ mkdir -p "$test_results_dir"
+ test_results_path="$test_results_dir/$this_test.$$.counts"
+
+ cat >>"$test_results_path" <<-EOF
+ total $test_count
+ success $test_success
+ fixed $test_fixed
+ broken $test_broken
+ failed $test_failure
+
+ EOF
+ fi
+
+ if test "$test_fixed" != 0; then
+ say_color error "# $test_fixed known breakage(s) vanished; please update test(s)"
+ fi
+ if test "$test_broken" != 0; then
+ say_color warn "# still have $test_broken known breakage(s)"
+ fi
+ if test "$test_broken" != 0 || test "$test_fixed" != 0; then
+ test_remaining=$(( $test_count - $test_broken - $test_fixed ))
+ msg="remaining $test_remaining test(s)"
+ else
+ test_remaining=$test_count
+ msg="$test_count test(s)"
+ fi
+
+ case "$test_failure" in
+ 0)
+ # Maybe print SKIP message
+ if test -n "$skip_all" && test $test_count -gt 0; then
+ error "Can't use skip_all after running some tests"
+ fi
+ [ -z "$skip_all" ] || skip_all=" # SKIP $skip_all"
+
+ if test $test_remaining -gt 0; then
+ say_color pass "# passed all $msg"
+ fi
+ say "1..$test_count$skip_all"
+
+ test_eval_ "$final_cleanup"
+
+ test -d "$remove_trash" &&
+ cd "$(dirname "$remove_trash")" &&
+ rm -rf "$(basename "$remove_trash")"
+
+ exit 0 ;;
+
+ *)
+ say_color error "# failed $test_failure among $msg"
+ say "1..$test_count"
+
+ test_eval_ "$final_cleanup"
+
+ test -d "$remove_trash" &&
+ cd "$(dirname "$remove_trash")" &&
+ rm -rf "$(basename "$remove_trash")"
+
+ exit 1 ;;
+
+ esac
+}
+
+# Public: Root directory containing tests. Tests can override this variable,
+# e.g. for testing Sharness itself.
+: ${SHARNESS_TEST_DIRECTORY:=$(pwd)}
+export SHARNESS_TEST_DIRECTORY
+
+# Public: Source directory of test code and sharness library.
+# This directory may be different from the directory in which tests are
+# being run.
+: ${SHARNESS_TEST_SRCDIR:=$(cd $(dirname $0) && pwd)}
+export SHARNESS_TEST_SRCDIR
+
+# Public: Build directory that will be added to PATH. By default, it is set to
+# the parent directory of SHARNESS_TEST_DIRECTORY.
+: ${SHARNESS_BUILD_DIRECTORY:="$SHARNESS_TEST_DIRECTORY/.."}
+PATH="$SHARNESS_BUILD_DIRECTORY:$PATH"
+export PATH SHARNESS_BUILD_DIRECTORY
+
+# Public: Path to test script currently executed.
+SHARNESS_TEST_FILE="$0"
+export SHARNESS_TEST_FILE
+
+# Prepare test area.
+SHARNESS_TRASH_DIRECTORY="trash directory.$(basename "$SHARNESS_TEST_FILE" ".$SHARNESS_TEST_EXTENSION")"
+test -n "$root" && SHARNESS_TRASH_DIRECTORY="$root/$SHARNESS_TRASH_DIRECTORY"
+case "$SHARNESS_TRASH_DIRECTORY" in
+/*) ;; # absolute path is good
+ *) SHARNESS_TRASH_DIRECTORY="$SHARNESS_TEST_DIRECTORY/$SHARNESS_TRASH_DIRECTORY" ;;
+esac
+test "$debug" = "t" || remove_trash="$SHARNESS_TRASH_DIRECTORY"
+rm -rf "$SHARNESS_TRASH_DIRECTORY" || {
+ EXIT_OK=t
+ echo >&5 "FATAL: Cannot prepare test area"
+ exit 1
+}
+
+
+#
+# Load any extensions in $srcdir/sharness.d/*.sh
+#
+if test -d "${SHARNESS_TEST_SRCDIR}/sharness.d"
+then
+ for file in "${SHARNESS_TEST_SRCDIR}"/sharness.d/*.sh
+ do
+ # Ensure glob was not an empty match:
+ test -e "${file}" || break
+
+ if test -n "$debug"
+ then
+ echo >&5 "sharness: loading extensions from ${file}"
+ fi
+ . "${file}"
+ if test $? != 0
+ then
+ echo >&5 "sharness: Error loading ${file}. Aborting."
+ exit 1
+ fi
+ done
+fi
+
+# Public: Empty trash directory, the test area, provided for each test. The HOME
+# variable is set to that directory too.
+export SHARNESS_TRASH_DIRECTORY
+
+HOME="$SHARNESS_TRASH_DIRECTORY"
+export HOME
+
+mkdir -p "$SHARNESS_TRASH_DIRECTORY" || exit 1
+# Use -P to resolve symlinks in our working directory so that the cwd
+# in subprocesses like git equals our $PWD (for pathname comparisons).
+cd -P "$SHARNESS_TRASH_DIRECTORY" || exit 1
+
+this_test=${SHARNESS_TEST_FILE##*/}
+this_test=${this_test%.$SHARNESS_TEST_EXTENSION}
+for skp in $SKIP_TESTS; do
+ case "$this_test" in
+ $skp)
+ say_color info >&3 "skipping test $this_test altogether"
+ skip_all="skip all tests in $this_test"
+ test_done
+ esac
+done
+
+test -n "$TEST_LONG" && test_set_prereq EXPENSIVE
+test -n "$TEST_INTERACTIVE" && test_set_prereq INTERACTIVE
+
+# Make sure this script ends with code 0
+:
+
+# vi: set ts=4 sw=4 noet :
diff --git a/version-gen b/version-gen
new file mode 100755
index 0000000..19ce8cc
--- /dev/null
+++ b/version-gen
@@ -0,0 +1,5 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0-only
+# Copyright 2023 The DT-Utils Authors <oss-tools@pengutronix.de>
+
+echo "$1" > "$MESON_DIST_ROOT/.tarball-version"
diff --git a/version.h.in b/version.h.in
new file mode 100644
index 0000000..9286a75
--- /dev/null
+++ b/version.h.in
@@ -0,0 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright 2013-2023 The DT-Utils Authors <oss-tools@pengutronix.de> */
+#define PACKAGE_STRING "dt-utils @VCS_TAG@"
+
+#define PACKAGE_VERSION "@VCS_TAG@"