diff options
94 files changed, 4795 insertions, 608 deletions
@@ -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 @@ -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 @@ -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 @@ -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 @@ -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/>. @@ -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 @@ -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); @@ -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. @@ -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> @@ -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> @@ -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 */ @@ -1 +1,3 @@ +/* SPDX-License-Identifier: CC0-1.0 */ +/* Copyright 2013-2023 The DT-Utils Authors <oss-tools@pengutronix.de> */ /* empty */ @@ -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@" |