pax_global_header00006660000000000000000000000064143647145600014524gustar00rootroot0000000000000052 comment=eb79ba8d3c35549f023a9d5fd2fe4c1c70c084d2 fwupd-efi-1.4/000077500000000000000000000000001436471456000132565ustar00rootroot00000000000000fwupd-efi-1.4/.clang-format000066400000000000000000000025641436471456000156400ustar00rootroot00000000000000--- AlignAfterOpenBracket: 'Align' AlignConsecutiveAssignments: 'false' AlignConsecutiveDeclarations: 'false' AlignConsecutiveMacros: 'true' AlignOperands: 'true' AlignTrailingComments: 'true' AllowAllArgumentsOnNextLine: 'false' AllowAllParametersOfDeclarationOnNextLine: 'false' AllowShortBlocksOnASingleLine: 'false' AllowShortCaseLabelsOnASingleLine: 'false' AllowShortFunctionsOnASingleLine: 'Inline' AllowShortIfStatementsOnASingleLine: 'false' AlwaysBreakAfterReturnType: 'All' BinPackParameters: 'false' BinPackArguments: 'false' BreakBeforeBraces: 'Linux' ColumnLimit: '100' DerivePointerAlignment: 'false' IndentCaseLabels: 'false' IndentWidth: '8' IncludeBlocks: 'Regroup' KeepEmptyLinesAtTheStartOfBlocks: 'false' Language: 'Cpp' MaxEmptyLinesToKeep: '1' PointerAlignment: 'Right' SortIncludes: 'true' SpaceAfterCStyleCast: 'false' SpaceBeforeAssignmentOperators : 'true' SpaceBeforeParens: 'ControlStatements' SpaceInEmptyParentheses: 'false' SpacesInSquareBrackets: 'false' TabWidth: '8' UseTab: 'Always' PenaltyBreakAssignment: '3' PenaltyBreakBeforeFirstCallParameter: '15' IncludeCategories: - Regex: '^"config.h"$' Priority: '0' - Regex: '' Priority: '1' - Regex: '^<' Priority: '2' - Regex: 'fwupd' Priority: '3' - Regex: '.*' Priority: '4' ... fwupd-efi-1.4/.github/000077500000000000000000000000001436471456000146165ustar00rootroot00000000000000fwupd-efi-1.4/.github/workflows/000077500000000000000000000000001436471456000166535ustar00rootroot00000000000000fwupd-efi-1.4/.github/workflows/main.yml000066400000000000000000000022551436471456000203260ustar00rootroot00000000000000name: Continuous Integration on: push: branches: [ main ] pull_request: branches: [ main ] jobs: pre-commit: runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v2 - name: Refresh dependencies run: sudo apt update - name: Install dependencies run: sudo apt install shellcheck -y - name: Run pre-commit hooks run: | ./contrib/setup source venv/bin/activate sed -i "/no-commit-to-branch/,+1d" .pre-commit-config.yaml pre-commit run --all-files build: runs-on: ubuntu-latest strategy: matrix: os: [fedora, debian-x86_64, arch, debian-i386] steps: - uses: actions/checkout@v2 - name: Docker login run: docker login docker.pkg.github.com -u $GITHUB_ACTOR -p $GITHUB_TOKEN env: GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} - name: Build in container env: CI_NETWORK: true CI: true run: | echo $GITHUB_WORKSPACE docker run --privileged -e CI=true -t -v $GITHUB_WORKSPACE:/github/workspace docker.pkg.github.com/fwupd/fwupd/fwupd-${{matrix.os}}:latest ./contrib/ci.sh fwupd-efi-1.4/.gitignore000066400000000000000000000001161436471456000152440ustar00rootroot00000000000000build/ venv/ .vscode fwupd*.build *.gz *.changes *.deb *.xz *.dsc *.buildinfo fwupd-efi-1.4/.markdownlint.json000066400000000000000000000001251436471456000167360ustar00rootroot00000000000000{ "default": true, "MD013": { "tables": false, "line_length": 1000 } } fwupd-efi-1.4/.pre-commit-config.yaml000066400000000000000000000025511436471456000175420ustar00rootroot00000000000000repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.1.0 hooks: - id: no-commit-to-branch args: [--branch, main] - id: check-added-large-files - id: check-byte-order-marker - id: check-executables-have-shebangs - id: forbid-new-submodules - id: check-yaml - id: check-json - id: check-symlinks - id: check-xml - id: end-of-file-fixer types_or: [c, shell, python] - id: trailing-whitespace types_or: [c, shell, python, xml] - id: check-docstring-first - id: check-merge-conflict - id: mixed-line-ending args: [--fix=lf] - repo: https://github.com/codespell-project/codespell rev: v2.1.0 hooks: - id: codespell args: ['--config', './contrib/codespell.cfg', --write-changes] - repo: https://github.com/ambv/black rev: 22.3.0 hooks: - id: black - repo: local hooks: - id: shellcheck name: check shellscript style language: system entry: shellcheck --severity=error -e SC2068 types: [shell] - id: clang-format name: clang-format language: script entry: ./contrib/reformat-code.py types: [c] - repo: https://github.com/igorshubovych/markdownlint-cli rev: v0.31.1 hooks: - id: markdownlint args: ['--fix', '--ignore', '.github'] fwupd-efi-1.4/AUTHORS000066400000000000000000000000451436471456000143250ustar00rootroot00000000000000Richard Hughes fwupd-efi-1.4/CODE_OF_CONDUCT.md000066400000000000000000000062231436471456000160600ustar00rootroot00000000000000# Contributor Covenant Code of Conduct ## Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards Examples of behavior that contributes to creating a positive environment include: * Using welcoming and inclusive language * Being respectful of differing viewpoints and experiences * Gracefully accepting constructive criticism * Focusing on what is best for the community * Showing empathy towards other community members Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or advances * Trolling, insulting/derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or electronic address, without explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at fwupd@googlegroups.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] [homepage]: http://contributor-covenant.org [version]: http://contributor-covenant.org/version/1/4/ fwupd-efi-1.4/COMMITMENT000066400000000000000000000037761436471456000146720ustar00rootroot00000000000000Common Cure Rights Commitment, version 1.0 Before filing or continuing to prosecute any legal proceeding or claim (other than a Defensive Action) arising from termination of a Covered License, we commit to extend to the person or entity ('you') accused of violating the Covered License the following provisions regarding cure and reinstatement, taken from GPL version 3. As used here, the term 'this License' refers to the specific Covered License being enforced. 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. We intend this Commitment to be irrevocable, and binding and enforceable against us and assignees of or successors to our copyrights. Definitions 'Covered License' means the GNU General Public License, version 2 (GPLv2), the GNU Lesser General Public License, version 2.1 (LGPLv2.1), or the GNU Library General Public License, version 2 (LGPLv2), all as published by the Free Software Foundation. 'Defensive Action' means a legal proceeding or claim that We bring against you in response to a prior proceeding or claim initiated by you or your affiliate. 'We' means each contributor to this repository as of the date of inclusion of this file, including subsidiaries of a corporate contributor. This work is available under a Creative Commons Attribution-ShareAlike 4.0 International license. fwupd-efi-1.4/CONTRIBUTING.md000066400000000000000000000031661436471456000155150ustar00rootroot00000000000000# Getting started To set up your local environment, from the top level of the checkout run ```shell ./contrib/setup ``` This will create pre-commit hooks to fixup many code style issues before your code is submitted. On some Linux distributions this will install all build dependencies needed to compile fwupd as well. ## Coding Style The coding style to respect in this project is very similar to most GLib projects. In particular, the following rules are largely adapted from the PackageKit Coding Style. * 8-space tabs for indentation * Prefer lines of less than <= 80 columns * 1-space between function name and braces (both calls and macro declarations) * If function signature/call fits in a single line, do not break it into multiple lines * Prefer descriptive names over abbreviations (unless well-known) and shortening of names. e.g `device` not `dev` * Single statements inside if/else should not be enclosed by '{}' * Use comments to explain why something is being done, but also avoid over-documenting the obvious. Here is an example of useless comment: // Fetch the document fetch_the_document (); * Comments should not start with a capital letter or end with a full stop and should be C-style, not C++-style, e.g. `/* this */` not `// this` * Each object should go in a separate .c file and be named according to the class * Use g_autoptr() and g_autofree whenever possible, and avoid `goto out` error handling * Failing methods should return FALSE with a suitable `GError` set * Trailing whitespace is forbidden * Pointers should be checked for NULL explicitly, e.g. `foo != NULL` not `!foo` fwupd-efi-1.4/COPYING000066400000000000000000000636421436471456000143240ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! fwupd-efi-1.4/MAINTAINERS000066400000000000000000000001131436471456000147460ustar00rootroot00000000000000Richard Hughes Mario Limonciello fwupd-efi-1.4/README.md000066400000000000000000000036321436471456000145410ustar00rootroot00000000000000# EFI executable for fwupd This repository contains the source used for the fwupd project to generate a UEFI binary for installing updates using the `UpdateCapsule` runtime service. It was originally imported from the combined fwupd project, and is now maintained separately to allow fwupd userspace releases and fwupd-efi UEFI executable releases to follow a different cadence. ## Compatibility ### 1.1.x through 1.5.x This UEFI executable is compatible will all fwupd releases from `1_1_X` and newer. In these fwupd sustaining releases, the EFI source continues to be distributed, but a new *fwupd* meson build option `-Defi_binary=false` is introduced which will allow disabling the compilation of built-in fwupd EFI binary. ### 1.6.x and newer The fwupd EFI source has been removed from the releases and is now distributed by this repository. Hand-building fwupd will perform a subproject checkout of *fwupd-efi* and build the binary at the same time. All packagers should generate separate source packages for *fwupd* and *fwupd-efi*. In the *fwupd* package, the subproject behavior should be explicitly disabled using `-Defi_binary=false`. ## Standalone compilation `fwupd-efi` uses the `meson` system to build EFI executables. Install `gnu-efi` and then follow these instructions to build and install locally: ```bash meson build ninja -C build ninja -C build install ``` ## UEFI SBAT Support The packager should also specify the SBAT metadata required for the secure boot revocation support. See the [specification](https://github.com/rhboot/shim/blob/main/SBAT.md) for more information. Typically, this will be set as part of the packager build script, e.g. ```meson -Defi_sbat_distro_id="fedora" \ -Defi_sbat_distro_summary="The Fedora Project" \ -Defi_sbat_distro_pkgname="%{name}" \ -Defi_sbat_distro_version="%{version}" \ -Defi_sbat_distro_url="https://src.fedoraproject.org/rpms/%{name}" \ ``` fwupd-efi-1.4/RELEASE000066400000000000000000000017311436471456000142630ustar00rootroot00000000000000fwupd-efi Release Notes Write release entries: git log --format="%s" --cherry-pick --right-only 1.3... | grep -i -v trivial | grep -v Merge | sort | uniq Add any user visible changes into ../contrib/org.freedesktop.fwupd.efi.metainfo.xml appstream-util appdata-to-news ../contrib/org.freedesktop.fwupd.efi.metainfo.xml > NEWS 2. Commit changes to git: # MAKE SURE THIS IS CORRECT export release_ver="1.4" git commit -a -m "Release fwupd-efi ${release_ver}" --no-verify git tag -s -f -m "Release fwupd-efi ${release_ver}" "${release_ver}" git push --tags git push 3. Generate the tarball: ninja dist 3a. Generate the additional verification metadata gpg -b -a meson-dist/fwupd-efi-${release_ver}.tar.xz 4. Upload tarball: scp meson-dist/fwupd-efi-${release_ver}.tar.* hughsient@people.freedesktop.org:~/public_html/releases 5. Do post release version bump in meson.build 6. Commit changes: git commit -a -m "trivial: post release version bump" --no-verify git push fwupd-efi-1.4/SECURITY.md000066400000000000000000000026321436471456000150520ustar00rootroot00000000000000# Security Policy Due to the nature of what we are doing, fwupd takes security very seriously. If you have any concerns please let us know. ## Supported Versions The `1.3.x`, `1.2.x` and `1.1.x` branches are fully supported by the upstream authors. Additionally, the `1.0.x` branch is supported for security and bug fixes. Older releases than this are unsupported by upstream but may be supported by your distributor or distribution. If you open an issue with one of these older releases the very first question from us is going to be asking if it's fixed on a supported branch. You can use the flatpak or snap packages if your distributor is unwilling to update to a supported version. | Version | Supported | | ------- | ------------------ | | 1.3.x | :heavy_check_mark: | | 1.2.x | :heavy_check_mark: | | 1.1.x | :heavy_check_mark: | | 1.0.x | :white_check_mark: | | 0.9.x | :x: | | 0.8.x | :x: | ## Reporting a Vulnerability If you find a vulnerability in fwupd your first thing you should do is email all the maintainers, which are currently listed in the `MAINTAINERS` file in this repository. Failing that, please report the issue against the `fwupd` component in Red Hat bugzilla, with the security checkbox set. You should get a response within 3 days. We have no bug bounty program, but we're happy to credit you in updates if this is what you would like us to do. fwupd-efi-1.4/contrib/000077500000000000000000000000001436471456000147165ustar00rootroot00000000000000fwupd-efi-1.4/contrib/ci.sh000077500000000000000000000026731436471456000156600ustar00rootroot00000000000000#!/bin/bash set -e set -x shopt -s extglob rm -rf build/ # disable the safe directory feature git config --global safe.directory "*" if [ "$OS" = "fedora" ]; then meson build VERSION=`meson introspect build --projectinfo | jq -r .version` RPMVERSION=${VERSION//-/.} sed "s,#VERSION#,$RPMVERSION,; s,#BUILD#,1,; s,#LONGDATE#,`date '+%a %b %d %Y'`,; s,#ALPHATAG#,alpha,; s,Source0.*,Source0:\tfwupd-efi-$VERSION.tar.xz," \ contrib/fwupd-efi.spec.in > build/fwupd-efi.spec if [ -n "$CI" ]; then sed -i "s,enable_ci 0,enable_ci 1,;" build/fwupd-efi.spec fi ninja -C build dist mkdir -p $HOME/rpmbuild/SOURCES/ mv build/meson-dist/fwupd-efi-$VERSION.tar.xz $HOME/rpmbuild/SOURCES/ rpmbuild -ba build/fwupd-efi.spec mkdir -p dist cp $HOME/rpmbuild/RPMS/*/*.rpm dist elif [ "$OS" = "debian-x86_64" ] || [ "$OS" = "debian-i386" ]; then export DEBFULLNAME="CI Builder" export DEBEMAIL="ci@travis-ci.org" VERSION=`head meson.build | grep ' version :' | cut -d \' -f2` mkdir -p build cp -lR !(build|dist|venv) build/ pushd build mv contrib/debian . sed s/quilt/native/ debian/source/format -i #build the package EDITOR=/bin/true dch --create --package fwupd-efi -v $VERSION "CI Build" debuild --no-lintian --preserve-envvar CI --preserve-envvar CC \ --preserve-envvar QUBES_OPTION else meson build ninja -C build fi fwupd-efi-1.4/contrib/codespell.cfg000066400000000000000000000003171436471456000173520ustar00rootroot00000000000000[codespell] builtin = clear,informal,en-GB_to_en-US skip = *.po,*.csv,*.svg,*.p7c,subprojects,.git,pcrs,build*,.ossfuzz,*/tests/* ignore-words-list = conexant,Conexant,gir,GIR,hsi,HSI,cancelled,Cancelled,te fwupd-efi-1.4/contrib/debian/000077500000000000000000000000001436471456000161405ustar00rootroot00000000000000fwupd-efi-1.4/contrib/debian/compat000066400000000000000000000000031436471456000173370ustar00rootroot0000000000000012 fwupd-efi-1.4/contrib/debian/control000066400000000000000000000053631436471456000175520ustar00rootroot00000000000000Source: fwupd-efi Priority: optional Maintainer: Debian EFI Uploaders: Steve McIntyre <93sam@debian.org>, Matthias Klumpp , Mario Limonciello Build-Depends: gnu-efi [amd64 arm64 armhf i386], meson, mingw-w64-tools [amd64 arm64 armhf i386], Standards-Version: 4.5.0 Section: admin Homepage: https://github.com/fwupd/fwupd-efi Vcs-Git: https://salsa.debian.org/efi-team/fwupd-efi.git Vcs-Browser: https://salsa.debian.org/efi-team/fwupd-efi Package: fwupd-unsigned Architecture: amd64 arm64 armhf i386 Depends: ${misc:Depends}, ${shlibs:Depends}, Recommends: fwupd-signed Multi-Arch: foreign Description: Firmware update daemon (Unsigned EFI binaries) fwupd is a daemon to allow session software to update device firmware. You can either use a GUI software manager like GNOME Software to view and apply updates, the command-line tool or the system D-Bus interface directly. Firmware updates are supported for a variety of technologies. See for details . This package provides the EFI binaries used for UEFI capsule updates Package: fwupd-unsigned-dev Architecture: all Depends: fwupd-unsigned (= ${binary:Version}) Description: Firmware update daemon (Development information) fwupd is a daemon to allow session software to update device firmware. You can either use a GUI software manager like GNOME Software to view and apply updates, the command-line tool or the system D-Bus interface directly. Firmware updates are supported for a variety of technologies. See for details . This package provides the dependencies for the fwupd daemon to resolve Package: fwupd-amd64-signed-template Architecture: amd64 Depends: ${shlibs:Depends}, ${misc:Depends}, make | build-essential | dpkg-dev Description: Template for signed fwupd package This package is used to control code signing by the Debian signing service. Package: fwupd-i386-signed-template Architecture: i386 Depends: ${shlibs:Depends}, ${misc:Depends}, make | build-essential | dpkg-dev Description: Template for signed fwupd package This package is used to control code signing by the Debian signing service. Package: fwupd-armhf-signed-template Architecture: armhf Depends: ${shlibs:Depends}, ${misc:Depends}, make | build-essential | dpkg-dev Description: Template for signed fwupd package This package is used to control code signing by the Debian signing service. Package: fwupd-arm64-signed-template Architecture: arm64 Depends: ${shlibs:Depends}, ${misc:Depends}, make | build-essential | dpkg-dev Description: Template for signed fwupd package This package is used to control code signing by the Debian signing service. fwupd-efi-1.4/contrib/debian/copyright000066400000000000000000000020241436471456000200710ustar00rootroot00000000000000Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: fwupd-efi Source: https://github.com/fwupd/fwupd-efi Files: debian/* Copyright: 2021 Mario Limonciello License: LGPL-2.1+ License: LGPL-2.1+ This package is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. . This package 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 Lesser General Public License along with this program. If not, see . On Debian systems, the complete text of the GNU Lesser General Public License version 2.1 can be found in "/usr/share/common-licenses/LGPL-2.1". fwupd-efi-1.4/contrib/debian/fwupd-unsigned-dev.install000066400000000000000000000000251436471456000232400ustar00rootroot00000000000000usr/lib/*/pkgconfig/ fwupd-efi-1.4/contrib/debian/fwupd-unsigned.install000066400000000000000000000000241436471456000224630ustar00rootroot00000000000000usr/libexec/fwupd/* fwupd-efi-1.4/contrib/debian/gbp.conf000066400000000000000000000001611436471456000175550ustar00rootroot00000000000000[DEFAULT] debian-branch = debian upstream-tag = %(version)s [buildpackage] sign-tags = True dist = experimental fwupd-efi-1.4/contrib/debian/gen_signing_changelog000077500000000000000000000023131436471456000223630ustar00rootroot00000000000000#!/bin/sh # # Generate a changelog file for the signed fwupdate package, based on # a changelog.in file and other state DIR=$1 SOURCE=$2 ARCH=$3 IN="${DIR}/changelog.in" OUT="${DIR}/changelog" # Parse out fields from our changelg entry - want the signing-template # one to match all the important details where we can DISTRIBUTION="$(dpkg-parsechangelog | sed -ne 's/^Distribution: \(.*\)/\1/p')" URGENCY="$(dpkg-parsechangelog | sed -ne 's/^Urgency: \(.*\)/\1/p')" MAINT="$(dpkg-parsechangelog | sed -ne 's/^Maintainer: \(.*\)/\1/p')" DATE="$(dpkg-parsechangelog | sed -ne 's/^Date: \(.*\)/\1/p')" # If the version ends in "+bXXX", this is a binNMU. We don't want a new # source package to look like that, so change it to ".bXXX" instead VERSION="$(dpkg-parsechangelog | sed -ne 's/^Version: \(.*\)/\1/p')" MANGLED_VERSION="$(echo $VERSION | sed -r 's/-/\+/;s/\+(b[[:digit:]]+)$/.\1/')" printf "%s-%s-signed (%s) %s; urgency=%s\n" "${SOURCE}" "${ARCH}" "${MANGLED_VERSION}" "${DISTRIBUTION}" "${URGENCY}" > $OUT printf "\n" >> $OUT printf " * Update to %s version %s\n" "${SOURCE}" "${VERSION}" >> $OUT printf "\n" >> $OUT printf " -- %s %s\n" "${MAINT}" "${DATE}" >> $OUT printf "\n" >> $OUT cat $IN >> $OUT rm -f $IN fwupd-efi-1.4/contrib/debian/gen_signing_json000077500000000000000000000013421436471456000214060ustar00rootroot00000000000000#!/bin/sh # # Generate a json file to go in the the fwupd-signed template # package. Describes exactly what needs to be signed, and how. DIR=$1 SOURCE=$2 ARCH=$3 OUT="$DIR/files.json" # What file are we looking to sign? BINARY=$(find debian/tmp -name '*.efi' | xargs basename) # Actually needs full path within the binary deb BINARY="usr/libexec/${SOURCE}/efi/${BINARY}" rm -f $OUT printf '{\n' >> $OUT printf ' "packages": {\n' >> $OUT printf ' "%s": {\n' "${SOURCE}" >> $OUT printf ' "trusted_certs": [],\n' >> $OUT printf ' "files": [ \n' >> $OUT printf ' {"sig_type": "efi", "file": "%s"}\n' "${BINARY}" >> $OUT printf ' ]\n' >> $OUT printf ' }\n' >> $OUT printf ' }\n' >> $OUT printf '}\n' >> $OUT fwupd-efi-1.4/contrib/debian/rules000077500000000000000000000047661436471456000172350ustar00rootroot00000000000000#!/usr/bin/make -f # -*- makefile -*- export LC_ALL := C.UTF-8 export DEB_BUILD_MAINT_OPTIONS = hardening=+all export DEB_LDFLAGS_MAINT_STRIP=-Wl,-Bsymbolic-functions CONFARGS = ifneq ($(CI),) CONFARGS += --werror --wrap-mode=default endif SB_STYLE := debian deb_version := $(shell dpkg-parsechangelog --show-field Version) ifeq (yes,$(shell dpkg-vendor --derives-from Ubuntu && echo yes)) SB_STYLE := ubuntu tar_name := fwupd_$(deb_version)_$(DEB_HOST_ARCH).tar.gz CONFARGS += -Defi_sbat_distro_id=ubuntu CONFARGS += -Defi_sbat_distro_summary=Ubuntu CONFARGS += -Defi_sbat_distro_pkgname=fwupd CONFARGS += -Defi_sbat_distro_version=$(deb_version) CONFARGS += -Defi_sbat_distro_url="https://launchpad.net/ubuntu/+source/fwupd" else TMPLDIR := debian/fwupd-$(DEB_HOST_ARCH)-signed-template/usr/share/code-signing/fwupd-$(DEB_HOST_ARCH)-signed-template CONFARGS += -Defi_sbat_distro_id=debian CONFARGS += -Defi_sbat_distro_summary=Debian CONFARGS += -Defi_sbat_distro_pkgname=fwupd CONFARGS += -Defi_sbat_distro_version=$(deb_version) CONFARGS += -Defi_sbat_distro_url="https://tracker.debian.org/pkg/fwupd" endif %: dh $@ --with gir override_dh_auto_clean: rm -fr obj-* rm -fr debian/build ifeq (ubuntu,$(SB_STYLE)) rm -rf debian/fwupd-images endif override_dh_auto_configure: dh_auto_configure -- $(CONFARGS) override_dh_install: dh_install ifeq (debian,$(SB_STYLE)) # Generate the template source for the Debian signing service to use mkdir -p $(TMPLDIR)/source-template/debian cp -a debian/signing-template/* $(TMPLDIR)/source-template/debian find $(TMPLDIR)/source-template/debian -type f | xargs sed -i "s,SIGNARCH,$(DEB_HOST_ARCH)," find $(TMPLDIR)/source-template/debian -type f | xargs sed -i "s,SIGNVERSION,$(deb_version)," set -e; for file in $$(find $(TMPLDIR)/source-template/debian -type f -name '*SIGNARCH*'); do \ file1=$$(echo $$file | sed "s,SIGNARCH,$(DEB_HOST_ARCH),"); \ mv -v $$file $$file1; \ done debian/gen_signing_changelog $(TMPLDIR)/source-template/debian fwupd $(DEB_HOST_ARCH) debian/gen_signing_json $(TMPLDIR) fwupd ${DEB_HOST_ARCH} endif override_dh_builddeb: dh_builddeb ifeq (ubuntu,$(SB_STYLE)) set -e; if [ -d debian/tmp/usr/libexec/fwupd/efi/ ]; then \ mkdir -p debian/fwupd-images/$(deb_version); \ cp debian/tmp/usr/libexec/fwupd/efi/fwupd*.efi debian/fwupd-images/$(deb_version); \ echo $(deb_version) > debian/fwupd-images/$(deb_version)/version; \ tar -C debian/fwupd-images -czvf ../$(tar_name) .; \ dpkg-distaddfile $(tar_name) raw-uefi -; \ fi endif fwupd-efi-1.4/contrib/debian/signing-template/000077500000000000000000000000001436471456000214075ustar00rootroot00000000000000fwupd-efi-1.4/contrib/debian/signing-template/README.source000066400000000000000000000003311436471456000235630ustar00rootroot00000000000000This source package is generated by the Debian signing service from a template built by the fwupd package. It should never be updated directly. -- Steve McIntyre <93sam@debian.org> Sat, 07 Apr 2018 12:44:55 +0100 fwupd-efi-1.4/contrib/debian/signing-template/changelog.in000066400000000000000000000002501436471456000236630ustar00rootroot00000000000000fwupd-SIGNARCH-signed (1) unstable; urgency=medium * Add template source package for signing -- Steve McIntyre <93sam@debian.org> Sat, 07 Apr 2018 12:44:55 +0100 fwupd-efi-1.4/contrib/debian/signing-template/compat000066400000000000000000000000021436471456000226050ustar00rootroot000000000000009 fwupd-efi-1.4/contrib/debian/signing-template/control000066400000000000000000000022511436471456000230120ustar00rootroot00000000000000Source: fwupd-SIGNARCH-signed Priority: optional Maintainer: Debian EFI Uploaders: Steve McIntyre <93sam@debian.org>, Matthias Klumpp , Mario Limonciello Build-Depends: debhelper (>= 9.0.0), sbsigntool [amd64 arm64 armhf i386], fwupd-unsigned (= SIGNVERSION) [SIGNARCH] Standards-Version: 4.5.0 Section: libs Homepage: https://github.com/fwupd/fwupd Vcs-Git: https://salsa.debian.org/efi-team/fwupd.git Vcs-Browser: https://salsa.debian.org/efi-team/fwupd Package: fwupd-SIGNARCH-signed Section: admin Architecture: SIGNARCH Provides: fwupd-signed Depends: ${shlibs:Depends}, ${misc:Depends}, fwupd (= SIGNVERSION) Built-Using: fwupd (= SIGNVERSION) Description: Tools to manage UEFI firmware updates (signed) fwupd provides functionality to update system firmware. It has been initially designed to update firmware using UEFI capsule updates, but it is designed to be extensible to other firmware update standards. . This package contains just the signed version of the fwupd binary, needed if your system has UEFI Secure Boot enabled. It depends on the normal fwupd package for everything else. fwupd-efi-1.4/contrib/debian/signing-template/copyright000066400000000000000000000024401436471456000233420ustar00rootroot00000000000000Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: fwupd Source: https://github.com/fwupd/fwupd Files: * Copyright: 2015 Richard Hughes License: LGPL-2.1+ Files: data/tests/colorhug/firmware.metainfo.xml Copyright: 2015 Richard Hughes License: CC0-1.0 Files: debian/* Copyright: 2015 Daniel Jared Dominguez 2015 Mario Limonciello License: LGPL-2.1+ License: LGPL-2.1+ This package is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. . This package 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 Lesser General Public License along with this program. If not, see . On Debian systems, the complete text of the GNU Lesser General Public License version 2.1 can be found in "/usr/share/common-licenses/LGPL-2.1". fwupd-efi-1.4/contrib/debian/signing-template/fwupd-SIGNARCH-signed.install000066400000000000000000000000441436471456000265650ustar00rootroot00000000000000*.efi.signed /usr/libexec/fwupd/efi fwupd-efi-1.4/contrib/debian/signing-template/rules000077500000000000000000000006511436471456000224710ustar00rootroot00000000000000#!/usr/bin/make -f # -*- makefile -*- PACKAGE_NAME := fwupd SIG_PKG_NAME := fwupd-SIGNARCH-signed SIGNATURE_DIR := debian/signatures/$(PACKAGE_NAME) BINARY := $(shell find /usr/libexec/fwupd/efi -name '*.efi' | xargs basename) %: dh $@ override_dh_auto_build: cp /usr/libexec/fwupd/efi/$(BINARY) . sbattach --attach $(SIGNATURE_DIR)/usr/libexec/fwupd/efi/$(BINARY).sig $(BINARY) mv $(BINARY) $(BINARY).signed fwupd-efi-1.4/contrib/debian/signing-template/source/000077500000000000000000000000001436471456000227075ustar00rootroot00000000000000fwupd-efi-1.4/contrib/debian/signing-template/source/format000066400000000000000000000000151436471456000241160ustar00rootroot000000000000003.0 (native) fwupd-efi-1.4/contrib/debian/source/000077500000000000000000000000001436471456000174405ustar00rootroot00000000000000fwupd-efi-1.4/contrib/debian/source/format000066400000000000000000000000141436471456000206460ustar00rootroot000000000000003.0 (quilt) fwupd-efi-1.4/contrib/debian/source/lintian-overrides000066400000000000000000000001271436471456000230210ustar00rootroot00000000000000#github doesn't have these fwupd-efi source: debian-watch-does-not-check-gpg-signature fwupd-efi-1.4/contrib/debian/source/options000066400000000000000000000000351436471456000210540ustar00rootroot00000000000000extend-diff-ignore=".vscode" fwupd-efi-1.4/contrib/debian/watch000066400000000000000000000003631436471456000171730ustar00rootroot00000000000000# You can run the "uscan" command to check for upstream updates and more. # See uscan(1) for format version=3 opts=filenamemangle=s/.+\/v?(\d\S*)\.tar\.gz/fwupd-efi-$1\.tar\.gz/ \ https://github.com/fwupd/fwupd-efi/tags .*/v?(\d\S*)\.tar\.gz fwupd-efi-1.4/contrib/fwupd-efi.spec.in000066400000000000000000000032031436471456000200630ustar00rootroot00000000000000%define alphatag #ALPHATAG# %global enable_ci 0 %global debug_package %{nil} Summary: Firmware update daemon EFI binaries Name: fwupd-efi Version: #VERSION# Release: 0.#BUILD#%{?alphatag}%{?dist} License: LGPLv2+ URL: https://github.com/fwupd/fwupd-efi Source0: http://people.freedesktop.org/~hughsient/releases/%{name}-%{version}.tar.xz # these are the only architectures supporting UEFI SecureBoot ExclusiveArch: x86_64 aarch64 BuildRequires: gcc BuildRequires: meson BuildRequires: gnu-efi-devel BuildRequires: pesign BuildRequires: python3-pefile %description fwupd is a daemon to allow session software to update device firmware, and this project provides the EFI binary that is used for updating capsules. %prep %autosetup -p1 %build %meson \ %if 0%{?enable_ci} --werror \ %endif -Defi_sbat_distro_id="fedora" \ -Defi_sbat_distro_summary="The Fedora Project" \ -Defi_sbat_distro_pkgname="%{name}" \ -Defi_sbat_distro_version="%{version}" \ -Defi_sbat_distro_url="https://src.fedoraproject.org/rpms/%{name}" %meson_build %install %meson_install # sign fwupd.efi loader %ifarch x86_64 %global efiarch x64 %endif %ifarch aarch64 %global efiarch aa64 %endif %global fwup_efi_fn $RPM_BUILD_ROOT%{_libexecdir}/fwupd/efi/fwupd%{efiarch}.efi %pesign -s -i %{fwup_efi_fn} -o %{fwup_efi_fn}.tmp %define __pesign_client_cert fwupd-signer %pesign -s -i %{fwup_efi_fn}.tmp -o %{fwup_efi_fn}.signed rm -vf %{fwup_efi_fn}.tmp %files %doc README.md AUTHORS %license COPYING %{_libexecdir}/fwupd/efi/*.efi %{_libexecdir}/fwupd/efi/*.efi.signed %{_libdir}/pkgconfig/fwupd-efi.pc %changelog %autochangelog fwupd-efi-1.4/contrib/org.freedesktop.fwupd.efi.metainfo.xml000066400000000000000000000054131436471456000242330ustar00rootroot00000000000000 org.freedesktop.fwupd.efi org.freedesktop.fwupd CC0-1.0 LGPL-2.0+ fwupd-efi EFI helpers to install system firmware

This project builds a UEFI binary for installing updates using the UpdateCapsule runtime service.

The source was imported from the combined fwupd project, and is now maintained separately to allow fwupd userspace releases and fwupd-efi UEFI executable releases to follow a different candence.

https://github.com/fwupd/fwupd-efi/issues https://fwupd.org/ richard_at_hughsie.com

This release fixes the following bugs:

  • Add additional checks for incompatible CRT0
  • Align sections to 512 bytes
  • Generate images that are NX compatible
  • Use manual symbols mode on ARM32
  • Use objcopy to build arm/aarch64 binaries for new binutils

This release fixes the following bugs:

  • Fix a regression when applying updates on an HP M60
  • Fix the ARM system crt0 name
  • Show the version when starting fwupd-efi

This release fixes the following bugs:

  • Sleep longer when no updates to process or event of error
  • Use the correct ldscript when the local crt0 is used for SBAT
  • Use the standard objcopy binary

This release fixes the following bugs:

  • Abort if the host architecture isn't known
  • Account for objdump missing --target option on FreeBSD
  • Pass the found genpeimg to generate_binary

This is the first release split from the fwupd parent project.

fwupd-efi-1.4/contrib/reformat-code.py000077500000000000000000000046621436471456000200320ustar00rootroot00000000000000#!/usr/bin/python3 # # Copyright (C) 2017 Dell Inc. # # SPDX-License-Identifier: LGPL-2.1+ # import os import sys import subprocess import argparse CLANG_DIFF_FORMATTERS = [ "clang-format-diff-11", "clang-format-diff-13", "clang-format-diff", ] def parse_args(): parser = argparse.ArgumentParser( description="Reformat C code to match project style", epilog="Call with no argument to reformat uncommitted code.", ) parser.add_argument( "commit", nargs="*", default="", help="Reformat all changes since this commit" ) parser.add_argument( "--debug", action="store_true", help="Display all launched commands" ) return parser.parse_args() def select_clang_version(formatters): for formatter in formatters: try: ret = subprocess.check_call( [formatter, "--help"], stdout=subprocess.PIPE, stderr=subprocess.PIPE ) if ret == 0: return formatter except FileNotFoundError: continue print("No clang formatter installed") sys.exit(1) ## Entry Point ## if __name__ == "__main__": args = parse_args() base = os.getenv("GITHUB_BASE_REF") if base: base = "origin/%s" % base else: if args.commit: base = args.commit[0] else: base = "HEAD" cmd = ["git", "describe", base] if args.debug: print(cmd) ret = subprocess.run(cmd, capture_output=True) if ret.returncode: if args.debug: print(ret.stderr) base = "HEAD" print("Reformatting code against %s" % base) formatter = select_clang_version(CLANG_DIFF_FORMATTERS) cmd = ["git", "diff", "-U0", base] if args.debug: print(cmd) ret = subprocess.run(cmd, capture_output=True, text=True) if ret.returncode: print("Failed to run %s\n%s" % (cmd, ret.stderr.strip())) sys.exit(1) cmd = [formatter, "-p1"] if args.debug: print(cmd) ret = subprocess.run(cmd, input=ret.stdout, capture_output=True, text=True) if ret.returncode: print("Failed to run %s\n%s" % (cmd, ret.stderr.strip())) sys.exit(1) cmd = ["patch", "-p0"] if args.debug: print(cmd) ret = subprocess.run(cmd, input=ret.stdout, capture_output=True, text=True) if ret.returncode: print("Failed to run %s\n%s" % (cmd, ret.stderr.strip())) sys.exit(1) sys.exit(0) fwupd-efi-1.4/contrib/setup000077500000000000000000000007271436471456000160120ustar00rootroot00000000000000#!/bin/bash -e # Setup the repository. cd "$(dirname "$0")/.." # Add default vscode settings if not existing SETTINGS_FILE=./.vscode/settings.json SETTINGS_TEMPLATE_FILE=./contrib/vscode/settings.json if [ ! -f "$SETTINGS_FILE" ]; then mkdir ./.vscode echo "Copy $SETTINGS_TEMPLATE_FILE to $SETTINGS_FILE." cp "$SETTINGS_TEMPLATE_FILE" "$SETTINGS_FILE" fi python3 -m venv venv source venv/bin/activate python3 -m pip install pre-commit pre-commit install fwupd-efi-1.4/contrib/vscode/000077500000000000000000000000001436471456000162015ustar00rootroot00000000000000fwupd-efi-1.4/contrib/vscode/settings.json000066400000000000000000000001131436471456000207270ustar00rootroot00000000000000{ "editor.tabSize": 8, "mesonbuild.buildFolder": "build" } fwupd-efi-1.4/efi/000077500000000000000000000000001436471456000140215ustar00rootroot00000000000000fwupd-efi-1.4/efi/crt0/000077500000000000000000000000001436471456000146715ustar00rootroot00000000000000fwupd-efi-1.4/efi/crt0/crt0-efi-aarch64.S000066400000000000000000000123311436471456000176540ustar00rootroot00000000000000/* * crt0-efi-aarch64.S - PE/COFF header for AArch64 EFI applications * * Copyright (C) 2014 Linaro Ltd. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice and this list of conditions, without modification. * 2. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * Alternatively, this software may be distributed 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. */ .section .text.head /* * Magic "MZ" signature for PE/COFF */ .globl ImageBase ImageBase: .ascii "MZ" .skip 58 // 'MZ' + pad + offset == 64 .long pe_header - ImageBase // Offset to the PE header. pe_header: .ascii "PE" .short 0 coff_header: .short 0xaa64 // AArch64 .short 4 // nr_sections .long 0 // TimeDateStamp .long 0 // PointerToSymbolTable .long 1 // NumberOfSymbols .short section_table - optional_header // SizeOfOptionalHeader .short 0x206 // Characteristics. // IMAGE_FILE_DEBUG_STRIPPED | // IMAGE_FILE_EXECUTABLE_IMAGE | // IMAGE_FILE_LINE_NUMS_STRIPPED optional_header: .short 0x20b // PE32+ format .byte 0x02 // MajorLinkerVersion .byte 0x14 // MinorLinkerVersion .long _text_size // SizeOfCode .long _alldata_size // SizeOfInitializedData .long 0 // SizeOfUninitializedData .long _start - ImageBase // AddressOfEntryPoint .long _start - ImageBase // BaseOfCode extra_header_fields: .quad 0 // ImageBase .long 0x1000 // SectionAlignment .long 0x200 // FileAlignment .short 0 // MajorOperatingSystemVersion .short 0 // MinorOperatingSystemVersion .short 0 // MajorImageVersion .short 0 // MinorImageVersion .short 0 // MajorSubsystemVersion .short 0 // MinorSubsystemVersion .long 0 // Win32VersionValue .long _erodata - ImageBase // SizeOfImage // Everything before the kernel image is considered part of the header .long _start - ImageBase // SizeOfHeaders .long 0 // CheckSum .short EFI_SUBSYSTEM // Subsystem .short 0 // DllCharacteristics .quad 0 // SizeOfStackReserve .quad 0 // SizeOfStackCommit .quad 0 // SizeOfHeapReserve .quad 0 // SizeOfHeapCommit .long 0 // LoaderFlags .long 0x6 // NumberOfRvaAndSizes .quad 0 // ExportTable .quad 0 // ImportTable .quad 0 // ResourceTable .quad 0 // ExceptionTable .quad 0 // CertificationTable .quad 0 // BaseRelocationTable // Section table section_table: .ascii ".text\0\0\0" .long _evtext - _start // VirtualSize .long _start - ImageBase // VirtualAddress .long _etext - _start // SizeOfRawData .long _start - ImageBase // PointerToRawData .long 0 // PointerToRelocations (0 for executables) .long 0 // PointerToLineNumbers (0 for executables) .short 0 // NumberOfRelocations (0 for executables) .short 0 // NumberOfLineNumbers (0 for executables) /* * EFI_IMAGE_SCN_MEM_READ | EFI_IMAGE_SCN_MEM_EXECUTE | EFI_IMAGE_SCN_CNT_CODE */ .long 0x60000020 // Characteristics (section flags) .ascii ".data\0\0\0" .long _data_vsize // VirtualSize .long _data - ImageBase // VirtualAddress .long _data_size // SizeOfRawData .long _data - ImageBase // PointerToRawData .long 0 // PointerToRelocations (0 for executables) .long 0 // PointerToLineNumbers (0 for executables) .short 0 // NumberOfRelocations (0 for executables) .short 0 // NumberOfLineNumbers (0 for executables) /* * EFI_IMAGE_SCN_MEM_WRITE | EFI_IMAGE_SCN_MEM_READ | EFI_IMAGE_SCN_CNT_INITIALIZED_DATA */ .long 0xc0000040 // Characteristics (section flags) .ascii ".sbat\0\0\0" .long _sbat_vsize // VirtualSize .long _sbat - ImageBase // VirtualAddress .long _sbat_size // SizeOfRawData .long _sbat - ImageBase // PointerToRawData .long 0 // PointerToRelocations (0 for executables) .long 0 // PointerToLineNumbers (0 for executables) .short 0 // NumberOfRelocations (0 for executables) .short 0 // NumberOfLineNumbers (0 for executables) /* * EFI_IMAGE_SCN_MEM_READ | EFI_IMAGE_SCN_ALIGN_8BYTES | EFI_IMAGE_SCN_CNT_INITIALIZED_DATA */ .long 0x40400040 // Characteristics (section flags) .ascii ".rodata\0" .long _rodata_vsize // VirtualSize .long _rodata - ImageBase // VirtualAddress .long _rodata_size // SizeOfRawData .long _rodata - ImageBase // PointerToRawData .long 0 // PointerToRelocations (0 for executables) .long 0 // PointerToLineNumbers (0 for executables) .short 0 // NumberOfRelocations (0 for executables) .short 0 // NumberOfLineNumbers (0 for executables) /* * EFI_IMAGE_SCN_MEM_READ | EFI_IMAGE_SCN_ALIGN_8BYTES | EFI_IMAGE_SCN_CNT_INITIALIZED_DATA */ .long 0x40400040 // Characteristics (section flags) .align 12 _start: stp x29, x30, [sp, #-32]! mov x29, sp stp x0, x1, [sp, #16] mov x2, x0 mov x3, x1 adr x0, ImageBase adrp x1, _DYNAMIC add x1, x1, #:lo12:_DYNAMIC bl _relocate cbnz x0, 0f ldp x0, x1, [sp, #16] bl efi_main 0: ldp x29, x30, [sp], #32 ret fwupd-efi-1.4/efi/crt0/crt0-efi-arm.S000066400000000000000000000135011436471456000172030ustar00rootroot00000000000000/* * crt0-efi-arm.S - PE/COFF header for ARM EFI applications * * Copyright (C) 2014 Linaro Ltd. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice and this list of conditions, without modification. * 2. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * Alternatively, this software may be distributed 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. */ .section .text.head /* * Magic "MZ" signature for PE/COFF */ .globl ImageBase ImageBase: .ascii "MZ" .skip 58 // 'MZ' + pad + offset == 64 .long pe_header - ImageBase // Offset to the PE header. pe_header: .ascii "PE" .short 0 coff_header: .short 0x1c2 // Mixed ARM/Thumb .short 4 // nr_sections .long 0 // TimeDateStamp .long 0 // PointerToSymbolTable .long 1 // NumberOfSymbols .short section_table - optional_header // SizeOfOptionalHeader .short 0x306 // Characteristics. // IMAGE_FILE_32BIT_MACHINE | // IMAGE_FILE_DEBUG_STRIPPED | // IMAGE_FILE_EXECUTABLE_IMAGE | // IMAGE_FILE_LINE_NUMS_STRIPPED optional_header: .short 0x10b // PE32+ format .byte 0x02 // MajorLinkerVersion .byte 0x14 // MinorLinkerVersion .long _text_size // SizeOfCode .long _alldata_size // SizeOfInitializedData .long 0 // SizeOfUninitializedData .long _start - ImageBase // AddressOfEntryPoint .long _start - ImageBase // BaseOfCode .long _data - ImageBase // BaseOfData extra_header_fields: .long 0 // ImageBase .long 0x800 // SectionAlignment .long 0x200 // FileAlignment .short 0 // MajorOperatingSystemVersion .short 0 // MinorOperatingSystemVersion .short 0 // MajorImageVersion .short 0 // MinorImageVersion .short 0 // MajorSubsystemVersion .short 0 // MinorSubsystemVersion .long 0 // Win32VersionValue .long _erodata - ImageBase // SizeOfImage // Everything before the kernel image is considered part of the header .long _start - ImageBase // SizeOfHeaders .long 0 // CheckSum .short EFI_SUBSYSTEM // Subsystem .short 0 // DllCharacteristics .long 0 // SizeOfStackReserve .long 0 // SizeOfStackCommit .long 0 // SizeOfHeapReserve .long 0 // SizeOfHeapCommit .long 0 // LoaderFlags .long 0x6 // NumberOfRvaAndSizes .quad 0 // ExportTable .quad 0 // ImportTable .quad 0 // ResourceTable .quad 0 // ExceptionTable .quad 0 // CertificationTable .quad 0 // BaseRelocationTable // Section table section_table: #if 0 /* * The EFI application loader requires a relocation section * because EFI applications must be relocatable. This is a * dummy section as far as we are concerned. */ .ascii ".reloc" .byte 0 .byte 0 // end of 0 padding of section name .long 0 .long 0 .long 0 // SizeOfRawData .long 0 // PointerToRawData .long 0 // PointerToRelocations .long 0 // PointerToLineNumbers .short 0 // NumberOfRelocations .short 0 // NumberOfLineNumbers .long 0x42100040 // Characteristics (section flags) #endif .ascii ".text\0\0\0" .long _evtext - _start // VirtualSize .long _start - ImageBase // VirtualAddress .long _etext - _start // SizeOfRawData .long _start - ImageBase // PointerToRawData .long 0 // PointerToRelocations (0 for executables) .long 0 // PointerToLineNumbers (0 for executables) .short 0 // NumberOfRelocations (0 for executables) .short 0 // NumberOfLineNumbers (0 for executables) /* * EFI_IMAGE_SCN_MEM_READ | EFI_IMAGE_SCN_MEM_EXECUTE | EFI_IMAGE_SCN_CNT_CODE */ .long 0x60000020 // Characteristics (section flags) .ascii ".data\0\0\0" .long _data_vsize // VirtualSize .long _data - ImageBase // VirtualAddress .long _data_size // SizeOfRawData .long _data - ImageBase // PointerToRawData .long 0 // PointerToRelocations (0 for executables) .long 0 // PointerToLineNumbers (0 for executables) .short 0 // NumberOfRelocations (0 for executables) .short 0 // NumberOfLineNumbers (0 for executables) /* * EFI_IMAGE_SCN_MEM_WRITE | EFI_IMAGE_SCN_MEM_READ | EFI_IMAGE_SCN_CNT_INITIALIZED_DATA */ .long 0xc0000040 // Characteristics (section flags) .ascii ".sbat\0\0\0" .long _sbat_vsize // VirtualSize .long _sbat - ImageBase // VirtualAddress .long _sbat_size // SizeOfRawData .long _sbat - ImageBase // PointerToRawData .long 0 // PointerToRelocations (0 for executables) .long 0 // PointerToLineNumbers (0 for executables) .short 0 // NumberOfRelocations (0 for executables) .short 0 // NumberOfLineNumbers (0 for executables) /* * EFI_IMAGE_SCN_MEM_READ | EFI_IMAGE_SCN_ALIGN_8BYTES | EFI_IMAGE_SCN_CNT_INITIALIZED_DATA */ .long 0x40400040 // Characteristics (section flags) .ascii ".rodata\0" .long _rodata_vsize // VirtualSize .long _rodata - ImageBase // VirtualAddress .long _rodata_size // SizeOfRawData .long _rodata - ImageBase // PointerToRawData .long 0 // PointerToRelocations (0 for executables) .long 0 // PointerToLineNumbers (0 for executables) .short 0 // NumberOfRelocations (0 for executables) .short 0 // NumberOfLineNumbers (0 for executables) /* * EFI_IMAGE_SCN_MEM_READ | EFI_IMAGE_SCN_ALIGN_8BYTES | EFI_IMAGE_SCN_CNT_INITIALIZED_DATA */ .long 0x40400040 // Characteristics (section flags) .align 11 _start: stmfd sp!, {r0-r2, lr} mov r2, r0 mov r3, r1 adr r1, .L_DYNAMIC ldr r0, [r1] add r1, r0, r1 adr r0, ImageBase bl _relocate teq r0, #0 bne 0f ldmfd sp, {r0-r1} bl efi_main 0: add sp, sp, #12 ldr pc, [sp], #4 .L_DYNAMIC: .word _DYNAMIC - . fwupd-efi-1.4/efi/crt0/meson.build000066400000000000000000000003711436471456000170340ustar00rootroot00000000000000o_crt0 = custom_target('efi_crt0', input : arch_crt_source, output : arch_crt, command : [cc.cmd_array(), '-c', '@INPUT@', '-o', '@OUTPUT@'] + compile_args) fwupd-efi-1.4/efi/fwup-cleanups.h000066400000000000000000000010011436471456000167530ustar00rootroot00000000000000/* * Copyright (C) 2019 Richard Hughes * * SPDX-License-Identifier: LGPL-2.1+ */ #pragma once #define _DEFINE_CLEANUP_FUNCTION0(Type, name, func) \ static inline VOID name(VOID *v) \ { \ if (*(Type*)v) \ func (*(Type*)v); \ } _DEFINE_CLEANUP_FUNCTION0(VOID *, _FreePool_p, FreePool) #define _cleanup_free __attribute__ ((cleanup(_FreePool_p))) static inline VOID * _steal_pointer(VOID *pp) { VOID **ptr = (VOID **) pp; VOID *ref = *ptr; *ptr = NULL; return ref; } fwupd-efi-1.4/efi/fwup-common.c000066400000000000000000000050751436471456000164430ustar00rootroot00000000000000/* * Copyright (C) 2019 Richard Hughes * * SPDX-License-Identifier: LGPL-2.1+ */ #include #include #include "fwup-debug.h" #include "fwup-common.h" VOID fwup_msleep(unsigned long msecs) { BS->Stall(msecs); } /* * Allocate some raw pages that aren't part of the pool allocator. */ VOID * fwup_malloc_raw(UINTN size) { UINTN pages = size / 4096 + ((size % 4096) ? 1 : 0); /* page size is always 4096 */ EFI_STATUS rc; EFI_PHYSICAL_ADDRESS pageaddr = 0; EFI_ALLOCATE_TYPE type = AllocateAnyPages; if (sizeof(VOID *) == 4) { pageaddr = 0xffffffffULL - 8192; type = AllocateMaxAddress; } rc = uefi_call_wrapper(BS->AllocatePages, 4, type, EfiLoaderData, pages, &pageaddr); if (EFI_ERROR(rc)) { fwup_warning(L"Could not allocate %d", size); return NULL; } if (sizeof(VOID *) == 4 && pageaddr > 0xffffffffULL) { uefi_call_wrapper(BS->FreePages, 2, pageaddr, pages); fwup_warning(L"Got bad allocation at 0x%016x", (UINT64)pageaddr); return NULL; } return (VOID *)(UINTN)pageaddr; } /* * Free our raw page allocations. */ static EFI_STATUS fwup_free_raw(VOID *addr, UINTN size) { UINTN pages = size / 4096 + ((size % 4096) ? 1 : 0); return uefi_call_wrapper(BS->FreePages, 2, (EFI_PHYSICAL_ADDRESS)(UINTN)addr, pages); } VOID * fwup_malloc (UINTN size) { VOID *addr = AllocatePool(size); if (addr == NULL) fwup_warning(L"Could not allocate %d", size); return addr; } VOID * fwup_malloc0 (UINTN size) { VOID *addr = AllocateZeroPool(size); if (addr == NULL) fwup_warning(L"Could not allocate %d", size); return addr; } EFI_STATUS fwup_time(EFI_TIME *ts) { EFI_TIME_CAPABILITIES timecaps = { 0, }; return uefi_call_wrapper(RT->GetTime, 2, ts, &timecaps); } EFI_STATUS fwup_read_file(EFI_FILE_HANDLE fh, UINT8 **buf_out, UINTN *buf_size_out) { const UINTN bs = 512; UINTN i = 0; UINTN n_blocks = 4096; UINT8 *buf = NULL; while (1) { VOID *newb = NULL; UINTN news = n_blocks * bs * 2; newb = fwup_malloc_raw(news); if (newb == NULL) return EFI_OUT_OF_RESOURCES; if (buf != NULL) { CopyMem(newb, buf, bs * n_blocks); fwup_free_raw(buf, bs * n_blocks); } buf = newb; n_blocks *= 2; for (; i < n_blocks; i++) { EFI_STATUS rc; UINTN sz = bs; rc = uefi_call_wrapper(fh->Read, 3, fh, &sz, &buf[i * bs]); if (EFI_ERROR(rc)) { fwup_free_raw(buf, bs * n_blocks); fwup_warning(L"Could not read file: %r", rc); return rc; } if (sz != bs) { *buf_size_out = bs * i + sz; *buf_out = buf; return EFI_SUCCESS; } } } return EFI_SUCCESS; } fwupd-efi-1.4/efi/fwup-common.h000066400000000000000000000012551436471456000164440ustar00rootroot00000000000000/* * Copyright (C) 2015-2016 Peter Jones * Copyright (C) 2019 Richard Hughes * * SPDX-License-Identifier: LGPL-2.1+ */ #pragma once #include "fwup-efi.h" VOID fwup_msleep (unsigned long msecs); EFI_STATUS fwup_time (EFI_TIME *ts); EFI_STATUS fwup_read_file (EFI_FILE_HANDLE fh, UINT8 **buf_out, UINTN *buf_size_out); VOID *fwup_malloc_raw (UINTN size); VOID *fwup_malloc (UINTN size); VOID *fwup_malloc0 (UINTN size); #define fwup_new(struct_type, n) ((struct_type*)fwup_malloc((n)*sizeof(struct_type))) #define fwup_new0(struct_type, n) ((struct_type*)fwup_malloc0((n)*sizeof(struct_type))) fwupd-efi-1.4/efi/fwup-debug.c000066400000000000000000000031251436471456000162330ustar00rootroot00000000000000/* * Copyright (C) 2019 Richard Hughes * * SPDX-License-Identifier: LGPL-2.1+ */ #include #include #include "fwup-cleanups.h" #include "fwup-debug.h" #include "fwup-efi.h" static BOOLEAN debugging = FALSE; BOOLEAN fwup_debug_get_enabled(VOID) { return debugging; } VOID fwup_debug_set_enabled(BOOLEAN val) { debugging = val; } static VOID fwupd_debug_efivar_append(CHAR16 *out1) { CHAR16 *name = L"FWUPDATE_DEBUG_LOG"; UINT32 attrs = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS; static BOOLEAN once = TRUE; if (once) { once = FALSE; fwup_delete_variable(name, &fwupdate_guid); } else { attrs |= EFI_VARIABLE_APPEND_WRITE; } fwup_set_variable(name, &fwupdate_guid, out1, StrSize(out1) - sizeof(CHAR16), attrs); } VOID fwup_log(FwupLogLevel level, const char *func, const char *file, const int line, CHAR16 *fmt, ...) { va_list args; _cleanup_free CHAR16 *tmp = NULL; va_start(args, fmt); tmp = VPoolPrint(fmt, args); va_end(args); if (tmp == NULL) { Print(L"fwupdate: Allocation for debug log failed!\n"); return; } if (debugging) { _cleanup_free CHAR16 *out1 = NULL; out1 = PoolPrint(L"%a:%d:%a(): %s\n", file, line, func, tmp); if (out1 == NULL) { Print(L"fwupdate: Allocation for debug log failed!\n"); return; } Print(L"%s", out1); fwupd_debug_efivar_append(out1); } else { switch (level) { case FWUP_DEBUG_LEVEL_DEBUG: break; case FWUP_DEBUG_LEVEL_WARNING: Print(L"WARNING: %s\n", tmp); break; default: Print(L"%s\n", tmp); break; } } } fwupd-efi-1.4/efi/fwup-debug.h000066400000000000000000000015561436471456000162460ustar00rootroot00000000000000/* * Copyright (C) 2015-2016 Peter Jones * Copyright (C) 2019 Richard Hughes * * SPDX-License-Identifier: LGPL-2.1+ */ #pragma once typedef enum { FWUP_DEBUG_LEVEL_DEBUG, FWUP_DEBUG_LEVEL_INFO, FWUP_DEBUG_LEVEL_WARNING, FWUP_DEBUG_LEVEL_LAST } FwupLogLevel; VOID fwup_log (FwupLogLevel level, const char *func, const char *file, const int line, CHAR16 *fmt, ...); BOOLEAN fwup_debug_get_enabled (VOID); VOID fwup_debug_set_enabled (BOOLEAN val); #define fwup_debug(fmt, args...) fwup_log(FWUP_DEBUG_LEVEL_DEBUG, __func__, __FILE__, __LINE__, fmt, ## args ) #define fwup_info(fmt, args...) fwup_log(FWUP_DEBUG_LEVEL_INFO, __func__, __FILE__, __LINE__, fmt, ## args ) #define fwup_warning(fmt, args...) fwup_log(FWUP_DEBUG_LEVEL_WARNING, __func__, __FILE__, __LINE__, fmt, ## args ) fwupd-efi-1.4/efi/fwup-efi.c000066400000000000000000000035131436471456000157110ustar00rootroot00000000000000/* * Copyright (C) 2019 Richard Hughes * * SPDX-License-Identifier: LGPL-2.1+ */ #include #include #include "fwup-cleanups.h" #include "fwup-common.h" #include "fwup-debug.h" #include "fwup-efi.h" EFI_STATUS fwup_delete_variable(CHAR16 *name, EFI_GUID *guid) { EFI_STATUS rc; UINT32 attrs = 0; /* get the attrs so we can delete it */ rc = uefi_call_wrapper(RT->GetVariable, 5, name, guid, &attrs, NULL, NULL); if (EFI_ERROR(rc)) { if (rc == EFI_NOT_FOUND) { fwup_debug(L"Not deleting variable '%s' as not found", name); return EFI_SUCCESS; } fwup_debug(L"Could not get variable '%s' for delete: %r", name, rc); return rc; } return uefi_call_wrapper(RT->SetVariable, 5, name, guid, attrs, 0, NULL); } EFI_STATUS fwup_set_variable(CHAR16 *name, EFI_GUID *guid, VOID *data, UINTN size, UINT32 attrs) { return uefi_call_wrapper(RT->SetVariable, 5, name, guid, attrs, size, data); } EFI_STATUS fwup_get_variable(CHAR16 *name, EFI_GUID *guid, VOID **buf_out, UINTN *buf_size_out, UINT32 *attrs_out) { EFI_STATUS rc; UINTN size = 0; UINT32 attrs; _cleanup_free VOID *buf = NULL; rc = uefi_call_wrapper(RT->GetVariable, 5, name, guid, &attrs, &size, NULL); if (EFI_ERROR(rc)) { if (rc == EFI_BUFFER_TOO_SMALL) { buf = fwup_malloc(size); if (buf == NULL) return EFI_OUT_OF_RESOURCES; } else if (rc != EFI_NOT_FOUND) { fwup_debug(L"Could not get variable '%s': %r", name, rc); return rc; } } else { fwup_debug(L"GetVariable(%s) succeeded with size=0", name); return EFI_INVALID_PARAMETER; } rc = uefi_call_wrapper(RT->GetVariable, 5, name, guid, &attrs, &size, buf); if (EFI_ERROR(rc)) { fwup_warning(L"Could not get variable '%s': %r", name, rc); return rc; } *buf_out = _steal_pointer(&buf); *buf_size_out = size; *attrs_out = attrs; return EFI_SUCCESS; } fwupd-efi-1.4/efi/fwup-efi.h000066400000000000000000000033051436471456000157150ustar00rootroot00000000000000/* * Copyright (C) 2015 Peter Jones * * SPDX-License-Identifier: LGPL-2.1+ */ #pragma once #define FWUPDATE_ATTEMPT_UPDATE 0x00000001 #define FWUPDATE_ATTEMPTED 0x00000002 #define UPDATE_INFO_VERSION 7 static __attribute__((__unused__)) EFI_GUID empty_guid = {0x0,0x0,0x0,{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}}; static __attribute__((__unused__))EFI_GUID fwupdate_guid = {0x0abba7dc,0xe516,0x4167,{0xbb,0xf5,0x4d,0x9d,0x1c,0x73,0x94,0x16}}; static __attribute__((__unused__))EFI_GUID ux_capsule_guid = {0x3b8c8162,0x188c,0x46a4,{0xae,0xc9,0xbe,0x43,0xf1,0xd6,0x56,0x97}}; static __attribute__((__unused__))EFI_GUID global_variable_guid = EFI_GLOBAL_VARIABLE; typedef struct { UINT8 version; UINT8 checksum; UINT8 image_type; UINT8 reserved; UINT32 mode; UINT32 x_offset; UINT32 y_offset; } __attribute__((__packed__)) UX_CAPSULE_HEADER; typedef struct { UINT32 update_info_version; /* stuff we need to apply an update */ EFI_GUID guid; UINT32 capsule_flags; UINT64 hw_inst; EFI_TIME time_attempted; /* our metadata */ UINT32 status; /* variadic device path */ union { EFI_DEVICE_PATH dp; UINT8 dp_buf[0]; }; } __attribute__((__packed__)) FWUP_UPDATE_INFO; typedef struct { UINT32 attributes; UINT16 file_path_list_length; CHAR16 *description; } __attribute__((__packed__)) EFI_LOAD_OPTION; EFI_STATUS fwup_delete_variable (CHAR16 *name, EFI_GUID *guid); EFI_STATUS fwup_set_variable (CHAR16 *name, EFI_GUID *guid, VOID *data, UINTN size, UINT32 attrs); EFI_STATUS fwup_get_variable (CHAR16 *name, EFI_GUID *guid, VOID **buf_out, UINTN *buf_size_out, UINT32 *attrs_out); fwupd-efi-1.4/efi/fwupdate.c000066400000000000000000000402501436471456000160050ustar00rootroot00000000000000/* * Copyright (C) 2014 Red Hat, Inc. * * SPDX-License-Identifier: LGPL-2.1+ */ #include "config.h" #include #include #include "fwup-cleanups.h" #include "fwup-common.h" #include "fwup-debug.h" #include "fwup-efi.h" #define UNUSED __attribute__((__unused__)) #define GNVN_BUF_SIZE 1024 #define FWUP_NUM_CAPSULE_UPDATES_MAX 128 typedef struct { CHAR16 *name; UINT32 attrs; UINTN size; FWUP_UPDATE_INFO *info; } FWUP_UPDATE_TABLE; static VOID fwup_update_table_free(FWUP_UPDATE_TABLE *update) { FreePool(update->info); FreePool(update->name); FreePool(update); } _DEFINE_CLEANUP_FUNCTION0(FWUP_UPDATE_TABLE *, _fwup_update_table_free_p, fwup_update_table_free) #define _cleanup_update_table __attribute__ ((cleanup(_fwup_update_table_free_p))) #define SECONDS 1000000 static INTN fwup_dp_size(EFI_DEVICE_PATH *dp, INTN limit) { INTN ret = 0; while (1) { if (limit < 4) break; INTN nodelen = DevicePathNodeLength(dp); if (nodelen > limit) break; limit -= nodelen; ret += nodelen; if (IsDevicePathEnd(dp)) return ret; dp = NextDevicePathNode(dp); } return -1; } static EFI_STATUS fwup_populate_update_info(CHAR16 *name, FWUP_UPDATE_TABLE *info_out) { EFI_STATUS rc; FWUP_UPDATE_INFO *info = NULL; UINTN info_size = 0; UINT32 attrs = 0; VOID *info_ptr = NULL; rc = fwup_get_variable(name, &fwupdate_guid, &info_ptr, &info_size, &attrs); if (EFI_ERROR(rc)) return rc; info = (FWUP_UPDATE_INFO *)info_ptr; if (info_size < sizeof(*info)) { fwup_warning(L"Update '%s' is is too small", name); return EFI_INVALID_PARAMETER; } if (info_size - sizeof(EFI_DEVICE_PATH) <= sizeof(*info)) { fwup_warning(L"Update '%s' is malformed, " L"and cannot hold a file path", name); return EFI_INVALID_PARAMETER; } EFI_DEVICE_PATH *hdr = (EFI_DEVICE_PATH *)&info->dp; INTN is = EFI_FIELD_OFFSET(FWUP_UPDATE_INFO, dp); if (is > (INTN)info_size) { fwup_warning(L"Update '%s' has an invalid file path, " L"device path offset is %d, but total size is %d", name, is, info_size); return EFI_INVALID_PARAMETER; } is = info_size - is; INTN sz = fwup_dp_size(hdr, info_size); if (sz < 0 || is > (INTN)info_size || is != sz) { fwup_warning(L"Update '%s' has an invalid file path, " L"update info size: %d dp size: %d size for dp: %d", name, info_size, sz, is); return EFI_INVALID_PARAMETER; } info_out->info = info; info_out->size = info_size; info_out->attrs = attrs; info_out->name = StrDuplicate(name); if (info_out->name == NULL) { fwup_warning(L"Could not allocate %d", StrSize(name)); return EFI_OUT_OF_RESOURCES; } return EFI_SUCCESS; } static EFI_STATUS fwup_populate_update_table(FWUP_UPDATE_TABLE **updates, UINTN *n_updates_out) { EFI_GUID vendor_guid = empty_guid; EFI_STATUS rc; UINTN n_updates = 0; _cleanup_free CHAR16 *variable_name = NULL; /* How much do we trust "size of the VariableName buffer" to mean * sizeof(vn) and not sizeof(vn)/sizeof(vn[0]) ? */ variable_name = fwup_malloc0(GNVN_BUF_SIZE * 2); if (variable_name == NULL) return EFI_OUT_OF_RESOURCES; while (1) { UINTN variable_name_size = GNVN_BUF_SIZE; rc = uefi_call_wrapper(RT->GetNextVariableName, 3, &variable_name_size, variable_name, &vendor_guid); if (rc == EFI_NOT_FOUND) break; /* ignore any huge names */ if (rc == EFI_BUFFER_TOO_SMALL) continue; if (EFI_ERROR(rc)) { fwup_warning(L"Could not get variable name: %r", rc); return rc; } /* not one of our state variables */ if (CompareGuid(&vendor_guid, &fwupdate_guid)) continue; /* ignore debugging settings */ if (StrCmp(variable_name, L"FWUPDATE_VERBOSE") == 0 || StrCmp(variable_name, L"FWUPDATE_DEBUG_LOG") == 0) continue; if (n_updates > FWUP_NUM_CAPSULE_UPDATES_MAX) { fwup_warning(L"Ignoring update %s", variable_name); continue; } fwup_debug(L"Found update %s", variable_name); _cleanup_update_table FWUP_UPDATE_TABLE *update = fwup_malloc0(sizeof(FWUP_UPDATE_TABLE)); if (update == NULL) return EFI_OUT_OF_RESOURCES; rc = fwup_populate_update_info(variable_name, update); if (EFI_ERROR(rc)) { fwup_delete_variable(variable_name, &fwupdate_guid); fwup_warning(L"Could not populate update info for '%s'", variable_name); return rc; } if (update->info->status & FWUPDATE_ATTEMPT_UPDATE) { fwup_time(&update->info->time_attempted); update->info->status = FWUPDATE_ATTEMPTED; updates[n_updates++] = _steal_pointer(&update); } } *n_updates_out = n_updates; return EFI_SUCCESS; } static EFI_STATUS fwup_search_file(EFI_DEVICE_PATH **file_dp, EFI_FILE_HANDLE *fh) { EFI_DEVICE_PATH *dp, *parent_dp; EFI_GUID sfsp = SIMPLE_FILE_SYSTEM_PROTOCOL; EFI_GUID dpp = DEVICE_PATH_PROTOCOL; UINTN n_handles, count; EFI_STATUS rc; _cleanup_free EFI_FILE_HANDLE *devices = NULL; rc = uefi_call_wrapper(BS->LocateHandleBuffer, 5, ByProtocol, &sfsp, NULL, &n_handles, (EFI_HANDLE **)&devices); if (EFI_ERROR(rc)) { fwup_warning(L"Could not find handles"); return rc; } dp = *file_dp; fwup_debug(L"Searching Device Path: %s...", DevicePathToStr(dp)); parent_dp = DuplicateDevicePath(dp); if (parent_dp == NULL) return EFI_INVALID_PARAMETER; dp = parent_dp; count = 0; while (1) { if (IsDevicePathEnd(dp)) return EFI_INVALID_PARAMETER; if (DevicePathType(dp) == MEDIA_DEVICE_PATH && DevicePathSubType(dp) == MEDIA_FILEPATH_DP) break; dp = NextDevicePathNode(dp); ++count; } SetDevicePathEndNode(dp); fwup_debug(L"Device Path prepared: %s", DevicePathToStr(parent_dp)); for (UINTN i = 0; i < n_handles; i++) { EFI_DEVICE_PATH *path; rc = uefi_call_wrapper(BS->HandleProtocol, 3, devices[i], &dpp, (VOID **)&path); if (EFI_ERROR(rc)) continue; fwup_debug(L"Device supporting SFSP: %s", DevicePathToStr(path)); while (!IsDevicePathEnd(path)) { fwup_debug(L"Comparing: %s and %s", DevicePathToStr(parent_dp), DevicePathToStr(path)); if (LibMatchDevicePaths(path, parent_dp) == TRUE) { *fh = devices[i]; for (UINTN j = 0; j < count; j++) *file_dp = NextDevicePathNode(*file_dp); fwup_debug(L"Match up! Returning %s", DevicePathToStr(*file_dp)); return EFI_SUCCESS; } path = NextDevicePathNode(path); } } fwup_warning(L"Failed to find '%s' DevicePath", DevicePathToStr(*file_dp)); return EFI_UNSUPPORTED; } static EFI_STATUS fwup_open_file(EFI_DEVICE_PATH *dp, EFI_FILE_HANDLE *fh) { CONST UINTN devpath_max_size = 1024; /* arbitrary limit */ EFI_DEVICE_PATH *file_dp = dp; EFI_GUID sfsp = SIMPLE_FILE_SYSTEM_PROTOCOL; EFI_FILE_HANDLE device; EFI_FILE_IO_INTERFACE *drive; EFI_FILE_HANDLE root; EFI_STATUS rc; rc = uefi_call_wrapper(BS->LocateDevicePath, 3, &sfsp, &file_dp, (EFI_HANDLE *)&device); if (EFI_ERROR(rc)) { rc = fwup_search_file(&file_dp, &device); if (EFI_ERROR(rc)) { fwup_warning(L"Could not locate device handle: %r", rc); return rc; } } if (DevicePathType(file_dp) != MEDIA_DEVICE_PATH || DevicePathSubType(file_dp) != MEDIA_FILEPATH_DP) { fwup_warning(L"Could not find appropriate device"); return EFI_UNSUPPORTED; } UINT16 sz16; UINTN sz; CopyMem(&sz16, &file_dp->Length[0], sizeof(sz16)); sz = sz16; sz -= 4; if (sz <= 6 || sz % 2 != 0 || sz > devpath_max_size * sizeof(CHAR16)) { fwup_warning(L"Invalid file device path of size %d", sz); return EFI_INVALID_PARAMETER; } _cleanup_free CHAR16 *filename = fwup_malloc0(sz + sizeof(CHAR16)); CopyMem(filename, (UINT8 *)file_dp + 4, sz); rc = uefi_call_wrapper(BS->HandleProtocol, 3, device, &sfsp, (VOID **)&drive); if (EFI_ERROR(rc)) { fwup_warning(L"Could not open device interface: %r", rc); return rc; } fwup_debug(L"Found device"); rc = uefi_call_wrapper(drive->OpenVolume, 2, drive, &root); if (EFI_ERROR(rc)) { fwup_warning(L"Could not open volume: %r", rc); return rc; } fwup_debug(L"Found volume"); rc = uefi_call_wrapper(root->Open, 5, root, fh, filename, EFI_FILE_MODE_READ, 0); if (EFI_ERROR(rc)) { fwup_warning(L"Could not open file '%s': %r", filename, rc); return rc; } fwup_debug(L"Found file"); return EFI_SUCCESS; } static EFI_STATUS fwup_get_gop_mode(UINT32 *mode, EFI_HANDLE loaded_image) { EFI_HANDLE *handles, gop_handle; UINTN num_handles; EFI_STATUS status; EFI_GUID gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; EFI_GRAPHICS_OUTPUT_PROTOCOL *gop; VOID *iface; status = LibLocateHandle(ByProtocol, &gop_guid, NULL, &num_handles, &handles); if (EFI_ERROR(status)) return status; if (handles == NULL || num_handles == 0) return EFI_UNSUPPORTED; for (UINTN i = 0; i < num_handles; i++) { gop_handle = handles[i]; status = uefi_call_wrapper(BS->OpenProtocol, 6, gop_handle, &gop_guid, &iface, loaded_image, 0, EFI_OPEN_PROTOCOL_GET_PROTOCOL); if (EFI_ERROR(status)) continue; gop = (EFI_GRAPHICS_OUTPUT_PROTOCOL *)iface; *mode = gop->Mode->Mode; return EFI_SUCCESS; } return EFI_UNSUPPORTED; } static inline void fwup_update_ux_capsule_checksum(UX_CAPSULE_HEADER *payload_hdr) { UINT8 *buf = (UINT8 *)payload_hdr; UINT8 sum = 0; payload_hdr->checksum = 0; for (UINTN i = 0; i < sizeof(*payload_hdr); i++) sum = (UINT8) (sum + buf[i]); payload_hdr->checksum = sum; } static EFI_STATUS fwup_check_gop_for_ux_capsule(EFI_HANDLE loaded_image, EFI_CAPSULE_HEADER *capsule) { UX_CAPSULE_HEADER *payload_hdr; EFI_STATUS rc; payload_hdr = (UX_CAPSULE_HEADER *) (((UINT8 *) capsule) + capsule->HeaderSize); rc = fwup_get_gop_mode(&payload_hdr->mode, loaded_image); if (EFI_ERROR(rc)) return EFI_UNSUPPORTED; fwup_update_ux_capsule_checksum(payload_hdr); return EFI_SUCCESS; } static EFI_STATUS fwup_add_update_capsule(FWUP_UPDATE_TABLE *update, EFI_CAPSULE_HEADER **capsule_out, EFI_CAPSULE_BLOCK_DESCRIPTOR *cbd_out, EFI_HANDLE loaded_image) { EFI_STATUS rc; EFI_FILE_HANDLE fh = NULL; UINT8 *fbuf = NULL; UINTN fsize = 0; EFI_CAPSULE_HEADER *capsule; UINTN cbd_len; EFI_PHYSICAL_ADDRESS cbd_data; EFI_CAPSULE_HEADER *cap_out; rc = fwup_open_file((EFI_DEVICE_PATH *)update->info->dp_buf, &fh); if (EFI_ERROR(rc)) return rc; rc = fwup_read_file(fh, &fbuf, &fsize); if (EFI_ERROR(rc)) return rc; uefi_call_wrapper(fh->Close, 1, fh); if (fsize < sizeof(EFI_CAPSULE_HEADER)) { fwup_warning(L"Invalid capsule size %d", fsize); return EFI_INVALID_PARAMETER; } fwup_debug(L"Read file; %d bytes", fsize); fwup_debug(L"updates guid: %g", &update->info->guid); fwup_debug(L"File guid: %g", fbuf); cbd_len = fsize; cbd_data = (EFI_PHYSICAL_ADDRESS)(UINTN)fbuf; capsule = cap_out = (EFI_CAPSULE_HEADER *)fbuf; if (cap_out->Flags == 0 && CompareGuid(&update->info->guid, &ux_capsule_guid) != 0) { #if defined(__aarch64__) cap_out->Flags |= update->info->capsule_flags; #else cap_out->Flags |= update->info->capsule_flags | CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_INITIATE_RESET; #endif } if (CompareGuid(&update->info->guid, &ux_capsule_guid) == 0) { fwup_debug(L"Checking GOP for ux capsule"); rc = fwup_check_gop_for_ux_capsule(loaded_image, capsule); if (EFI_ERROR(rc)) return EFI_UNSUPPORTED; } cbd_out->Length = cbd_len; cbd_out->Union.DataBlock = cbd_data; *capsule_out = cap_out; return EFI_SUCCESS; } static EFI_STATUS fwup_apply_capsules(EFI_CAPSULE_HEADER **capsules, EFI_CAPSULE_BLOCK_DESCRIPTOR *cbd, UINTN num_updates, EFI_RESET_TYPE *reset) { UINT64 max_capsule_size; EFI_STATUS rc; rc = uefi_call_wrapper(RT->QueryCapsuleCapabilities, 4, capsules, num_updates, &max_capsule_size, reset); if (rc == EFI_SUCCESS) { fwup_debug(L"QueryCapsuleCapabilities: %r max: %ld reset:%d", rc, max_capsule_size, *reset); } else { fwup_warning(L"QueryCapsuleCapabilities failed, assuming EfiResetWarm: %r", rc); *reset = EfiResetWarm; } fwup_debug(L"Capsules: %d", num_updates); fwup_msleep(1 * SECONDS); rc = uefi_call_wrapper(RT->UpdateCapsule, 3, capsules, num_updates, (EFI_PHYSICAL_ADDRESS)(UINTN)cbd); if (EFI_ERROR(rc)) { fwup_warning(L"Could not apply capsule update: %r", rc); return rc; } return EFI_SUCCESS; } static EFI_STATUS fwup_set_update_statuses(FWUP_UPDATE_TABLE **updates) { EFI_STATUS rc; for (UINTN i = 0; i < FWUP_NUM_CAPSULE_UPDATES_MAX; i++) { if (updates[i] == NULL || updates[i]->name == NULL) break; rc = fwup_set_variable(updates[i]->name, &fwupdate_guid, updates[i]->info, updates[i]->size, updates[i]->attrs); if (EFI_ERROR(rc)) { fwup_warning(L"Could not update variable status for '%s': %r", updates[i]->name, rc); return rc; } } return EFI_SUCCESS; } EFI_GUID SHIM_LOCK_GUID = {0x605dab50,0xe046,0x4300,{0xab,0xb6,0x3d,0xd8,0x10,0xdd,0x8b,0x23}}; static VOID __attribute__((__optimize__("0"))) fwup_debug_hook(VOID) { EFI_GUID guid = SHIM_LOCK_GUID; UINTN data = 0; UINTN data_size = 1; EFI_STATUS efi_status; UINT32 attrs; register volatile int x = 0; extern char _text UNUSED, _data UNUSED; /* shim has done whatever is needed to get a debugger attached */ efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"SHIM_DEBUG", &guid, &attrs, &data_size, &data); if (EFI_ERROR(efi_status) || data != 1) { efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"FWUPDATE_VERBOSE", &fwupdate_guid, &attrs, &data_size, &data); if (EFI_ERROR(efi_status) || data != 1) return; fwup_debug_set_enabled(TRUE); return; } fwup_debug_set_enabled(TRUE); if (x) return; x = 1; fwup_info(L"add-symbol-file "DEBUGDIR L"fwupdate.efi.debug %p -s .data %p", &_text, &_data); } EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) { EFI_STATUS rc; UINTN i, n_updates = 0; EFI_RESET_TYPE reset_type = EfiResetWarm; _cleanup_free FWUP_UPDATE_TABLE **updates = NULL; InitializeLib(image, systab); /* if SHIM_DEBUG is set, fwup_info info for our attached debugger */ fwup_debug_hook(); /* show the version to screen */ fwup_info(L"fwupd-efi version " PACKAGE_VERSION); /* step 1: find and validate update state variables */ /* XXX TODO: * 1) survey the reset types first, and separate into groups * according to them * 2) if there's more than one, mirror BootCurrent back into BootNext * so we can do multiple runs * 3) only select the ones from one type for the first go */ updates = fwup_new0(FWUP_UPDATE_TABLE *, FWUP_NUM_CAPSULE_UPDATES_MAX); if (updates == NULL) return EFI_OUT_OF_RESOURCES; rc = fwup_populate_update_table(updates, &n_updates); if (EFI_ERROR(rc)) { fwup_warning(L"Could not find updates: %r", rc); return rc; } if (n_updates == 0) { fwup_warning(L"No updates to process, exiting in 10 seconds."); fwup_msleep(10 * SECONDS); return EFI_INVALID_PARAMETER; } /* step 2: Build our data structure and add the capsules to it */ _cleanup_free EFI_CAPSULE_HEADER **capsules = NULL; capsules = fwup_new0(EFI_CAPSULE_HEADER *, n_updates + 1); EFI_CAPSULE_BLOCK_DESCRIPTOR *cbd_data; UINTN j = 0; cbd_data = fwup_malloc_raw(sizeof(EFI_CAPSULE_BLOCK_DESCRIPTOR)*(n_updates+1)); if (cbd_data == NULL) return EFI_OUT_OF_RESOURCES; for (i = 0; i < n_updates; i++) { fwup_debug(L"Adding new capsule"); rc = fwup_add_update_capsule(updates[i], &capsules[j], &cbd_data[j], image); if (EFI_ERROR(rc)) { /* ignore a failing capsule */ fwup_warning(L"Could not add capsule with guid %g for update: %r", updates[i]->info->guid, rc); continue; } j++; } if (j == 0) { fwup_warning(L"Could not build update list: %r\n", rc); return rc; } n_updates = j; fwup_debug(L"n_updates: %d", n_updates); cbd_data[i].Length = 0; cbd_data[i].Union.ContinuationPointer = 0; /* step 3: update the state variables */ rc = fwup_set_update_statuses(updates); if (EFI_ERROR(rc)) { fwup_warning(L"Could not set update status: %r", rc); return rc; } /* step 4: apply the capsules */ rc = fwup_apply_capsules(capsules, cbd_data, n_updates, &reset_type); if (EFI_ERROR(rc)) fwup_warning(L"Could not apply capsules: %r", rc); /* step 5: if #4 didn't reboot us, do it manually */ fwup_info(L"Reset System"); fwup_msleep(5 * SECONDS); if (fwup_debug_get_enabled()) fwup_msleep(30 * SECONDS); uefi_call_wrapper(RT->ResetSystem, 4, reset_type, EFI_SUCCESS, 0, NULL); return rc; } fwupd-efi-1.4/efi/generate_binary.py000077500000000000000000000053061436471456000175400ustar00rootroot00000000000000#!/usr/bin/python3 # # Copyright (C) 2021 Javier Martinez Canillas # Copyright (C) 2021 Richard Hughes # # SPDX-License-Identifier: LGPL-2.1+ # # pylint: disable=missing-docstring, invalid-name import subprocess import sys import argparse def _run_objcopy(args): argv = [ args.objcopy, "-j", ".text", "-j", ".sbat", "-j", ".sdata", "-j", ".data", "-j", ".dynamic", "-j", ".rodata", "-j", ".rel*", "--section-alignment", "512", args.infile, args.outfile, ] # older objcopy for Aarch64 and ARM32 are not EFI capable. # Use "binary" instead, and add required symbols manually. if args.objcopy_manualsymbols: argv.extend(["-O", "binary"]) elif args.os == "freebsd": # `--target` option is missing and --input-target doesn't recognize # "efi-app-*" argv.extend(["--output-target", "efi-app-{}".format(args.arch)]) else: argv.extend(["--target", "efi-app-{}".format(args.arch)]) try: subprocess.run(argv, check=True) except FileNotFoundError as e: print(str(e)) sys.exit(1) def _run_genpeimg(args): if not args.genpeimg: return argv = [args.genpeimg, "-d", "+d", "-d", "+n", "-d", "+s", args.outfile] try: subprocess.run(argv, check=True) except FileNotFoundError as e: print(str(e)) sys.exit(1) def _add_nx_pefile(args): # unnecessary if we have genpeimg if args.genpeimg: return try: import pefile except ImportError: print("Unable to add NX support to binaries without genpeimg or python3-pefile") sys.exit(1) pe = pefile.PE(args.outfile) pe.OPTIONAL_HEADER.DllCharacteristics |= pefile.DLL_CHARACTERISTICS[ "IMAGE_DLLCHARACTERISTICS_NX_COMPAT" ] pe.write(args.outfile) if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument( "--objcopy", default="objcopy", help="Binary file to use for objcopy" ) parser.add_argument("--genpeimg", help="Binary file to use for genpeimg") parser.add_argument("--arch", default="x86_64", help="EFI architecture") parser.add_argument("--os", help="OS type") parser.add_argument( "--objcopy-manualsymbols", action="store_true", help="whether adding symbols direct to binary", ) parser.add_argument("infile", help="Input file") parser.add_argument("outfile", help="Output file") _args = parser.parse_args() _run_objcopy(_args) _run_genpeimg(_args) _add_nx_pefile(_args) sys.exit(0) fwupd-efi-1.4/efi/generate_sbat.py000077500000000000000000000072301436471456000172030ustar00rootroot00000000000000#!/usr/bin/python3 # # Copyright (C) 2021 Javier Martinez Canillas # Copyright (C) 2021 Richard Hughes # # SPDX-License-Identifier: LGPL-2.1+ # # pylint: disable=missing-docstring, invalid-name import subprocess import sys import argparse import tempfile def _generate_sbat(args): """append SBAT metadata""" FWUPD_SUMMARY = "Firmware update daemon" FWUPD_URL = "https://github.com/fwupd/fwupd-efi" cmd = ( args.cc.split() + ["-x", "c", "-c", "-o", args.outfile, "/dev/null"] + args.cflags.split(" ") ) subprocess.run(cmd, check=True) # not specified if not args.sbat_distro_id: return with tempfile.NamedTemporaryFile() as sfd: # spec sfd.write( "{0},{1},{2},{0},{1},{3}\n".format( "sbat", args.sbat_version, "UEFI shim", "https://github.com/rhboot/shim/blob/main/SBAT.md", ).encode() ) # fwupd sfd.write( "{0},{1},{2},{0},{3},{4}\n".format( args.project_name, args.sbat_generation, "Firmware update daemon", args.project_version, FWUPD_URL, ).encode() ) # distro specifics, falling back to the project defaults sfd.write( "{0}.{1},{2},{3},{4},{5},{6}\n".format( args.project_name, args.sbat_distro_id, args.sbat_distro_generation or args.sbat_generation, args.sbat_distro_summary or FWUPD_SUMMARY, args.sbat_distro_pkgname, args.sbat_distro_version or args.project_version, args.sbat_distro_url or FWUPD_URL, ).encode() ) # all written sfd.seek(0) # add a section to the object; use `objdump -s -j .sbat` to verify argv = [ args.objcopy, "--add-section", ".sbat={}".format(sfd.name), "--set-section-flags", ".sbat=contents,alloc,load,readonly,data", args.outfile, ] subprocess.run(argv, check=True) if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument( "--cc", default="gcc", help="Compiler to use for generating sbat object" ) parser.add_argument("--cflags", help="C compiler flags to be used by CC") parser.add_argument( "--objcopy", default="objcopy", help="Binary file to use for objcopy" ) parser.add_argument("--project-name", help="SBAT project name") parser.add_argument("--project-version", help="SBAT project version") parser.add_argument("--sbat-version", default=1, type=int, help="SBAT version") parser.add_argument( "--sbat-generation", default=1, type=int, help="SBAT generation" ) parser.add_argument("--sbat-distro-id", default=None, help="SBAT distribution ID") parser.add_argument( "--sbat-distro-generation", default=None, type=int, help="SBAT distribution generation", ) parser.add_argument( "--sbat-distro-summary", default=None, help="SBAT distribution summary" ) parser.add_argument( "--sbat-distro-pkgname", default=None, help="SBAT distribution package name" ) parser.add_argument( "--sbat-distro-version", default=None, help="SBAT distribution version" ) parser.add_argument("--sbat-distro-url", default=None, help="SBAT distribution URL") parser.add_argument("outfile", help="Output file") _args = parser.parse_args() _generate_sbat(_args) sys.exit(0) fwupd-efi-1.4/efi/lds/000077500000000000000000000000001436471456000146035ustar00rootroot00000000000000fwupd-efi-1.4/efi/lds/elf_aarch64_efi.lds000066400000000000000000000036251436471456000202160ustar00rootroot00000000000000OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64") OUTPUT_ARCH(aarch64) ENTRY(_start) SECTIONS { .text 0x0 : { _text = .; *(.text.head) *(.text) *(.text.*) *(.gnu.linkonce.t.*) _evtext = .; . = ALIGN(4096); } _etext = .; _text_size = . - _text; _text_vsize = _evtext - _text; . = ALIGN(4096); .data : { _data = .; *(.sdata) *(.data) *(.data1) *(.data.*) *(.got.plt) *(.got) *(.dynamic) /* the EFI loader doesn't seem to like a .bss section, so we stick it all into .data: */ . = ALIGN(16); _bss = .; *(.sbss) *(.scommon) *(.dynbss) *(.bss) *(COMMON) _evdata = .; . = ALIGN(4096); _bss_end = .; } _edata = .; _data_vsize = _evdata - _data; _data_size = . - _data; /* * Note that _sbat must be the beginning of the data, and _esbat must be the * end and must be before any section padding. The sbat self-check uses * _esbat to find the bounds of the data, and if the padding is included, the * CSV parser (correctly) rejects the data as having NUL values in one of the * required columns. */ . = ALIGN(4096); .sbat : { _sbat = .; *(.sbat) *(.sbat.*) _esbat = .; . = ALIGN(4096); _epsbat = .; } _sbat_size = _epsbat - _sbat; _sbat_vsize = _esbat - _sbat; . = ALIGN(4096); .rodata : { _rodata = .; *(.rela.dyn) *(.rela.plt) *(.rela.got) *(.rela.data) *(.rela.data*) *(.rodata*) *(.srodata) *(.dynsym) *(.dynstr) . = ALIGN(16); *(.note.gnu.build-id) . = ALIGN(4096); *(.vendor_cert) *(.data.ident) _evrodata = .; . = ALIGN(4096); } _erodata = .; _rodata_size = . - _rodata; _rodata_vsize = _evrodata - _rodata; _alldata_size = . - _data; /DISCARD/ : { *(.rel.reloc) *(.eh_frame) *(.note.GNU-stack) } .comment 0 : { *(.comment) } } fwupd-efi-1.4/efi/lds/elf_arm_efi.lds000066400000000000000000000036001436471456000175360ustar00rootroot00000000000000OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") OUTPUT_ARCH(arm) ENTRY(_start) SECTIONS { .text 0x0 : { _text = .; *(.text.head) *(.text) *(.text.*) *(.gnu.linkonce.t.*) _evtext = .; . = ALIGN(4096); } _etext = .; _text_size = . - _text; _text_vsize = _evtext - _text; . = ALIGN(4096); .data : { _data = .; *(.sdata) *(.data) *(.data1) *(.data.*) *(.got.plt) *(.got) *(.dynamic) /* the EFI loader doesn't seem to like a .bss section, so we stick it all into .data: */ . = ALIGN(16); _bss = .; *(.sbss) *(.scommon) *(.dynbss) *(.bss) *(COMMON) _evdata = .; . = ALIGN(4096); _bss_end = .; } _edata = .; _data_vsize = _evdata - _data; _data_size = . - _data; /* * Note that _sbat must be the beginning of the data, and _esbat must be the * end and must be before any section padding. The sbat self-check uses * _esbat to find the bounds of the data, and if the padding is included, the * CSV parser (correctly) rejects the data as having NUL values in one of the * required columns. */ . = ALIGN(4096); .sbat : { _sbat = .; *(.sbat) *(.sbat.*) _esbat = .; . = ALIGN(4096); _epsbat = .; } _sbat_size = _epsbat - _sbat; _sbat_vsize = _esbat - _sbat; . = ALIGN(4096); .rodata : { _rodata = .; *(.rel.dyn) *(.rel.plt) *(.rel.got) *(.rel.data) *(.rel.data*) *(.rodata*) *(.srodata) *(.dynsym) *(.dynstr) . = ALIGN(16); *(.note.gnu.build-id) . = ALIGN(4096); *(.vendor_cert) *(.data.ident) _evrodata = .; . = ALIGN(4096); } _erodata = .; _rodata_size = . - _rodata; _rodata_vsize = _evrodata - _rodata; _alldata_size = . - _data; /DISCARD/ : { *(.rel.reloc) *(.eh_frame) *(.note.GNU-stack) } .comment 0 : { *(.comment) } } fwupd-efi-1.4/efi/lds/elf_ia32_efi.lds000066400000000000000000000026641436471456000175260ustar00rootroot00000000000000OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") OUTPUT_ARCH(i386) ENTRY(_start) SECTIONS { . = 0; ImageBase = .; .hash : { *(.hash) } /* this MUST come first! */ . = ALIGN(4096); .text : { _text = .; *(.text) *(.text.*) *(.gnu.linkonce.t.*) _etext = .; } .reloc : { *(.reloc) } . = ALIGN(4096); .note.gnu.build-id : { *(.note.gnu.build-id) } . = ALIGN(4096); .data.ident : { *(.data.ident) } . = ALIGN(4096); .data : { _data = .; *(.rodata*) *(.data) *(.data1) *(.data.*) *(.sdata) *(.got.plt) *(.got) /* the EFI loader doesn't seem to like a .bss section, so we stick it all into .data: */ *(.sbss) *(.scommon) *(.dynbss) *(.bss) *(COMMON) } . = ALIGN(4096); .vendor_cert : { *(.vendor_cert) } . = ALIGN(4096); .dynamic : { *(.dynamic) } . = ALIGN(4096); .rel : { *(.rel.data) *(.rel.data.*) *(.rel.got) *(.rel.stab) *(.data.rel.ro.local) *(.data.rel.local) *(.data.rel.ro) *(.data.rel*) } _edata = .; _data_size = . - _data; . = ALIGN(4096); .sbat : { _sbat = .; *(.sbat) *(.sbat.*) } _esbat = .; _sbat_size = . - _sbat; . = ALIGN(4096); .dynsym : { *(.dynsym) } . = ALIGN(4096); .dynstr : { *(.dynstr) } . = ALIGN(4096); /DISCARD/ : { *(.rel.reloc) *(.eh_frame) *(.note.GNU-stack) } .comment 0 : { *(.comment) } } fwupd-efi-1.4/efi/lds/elf_x86_64_efi.lds000066400000000000000000000030571436471456000177230ustar00rootroot00000000000000/* Same as elf_x86_64_fbsd_efi.lds, except for OUTPUT_FORMAT below - KEEP IN SYNC */ OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64") OUTPUT_ARCH(i386:x86-64) ENTRY(_start) SECTIONS { . = 0; ImageBase = .; .hash : { *(.hash) } /* this MUST come first! */ . = ALIGN(4096); .eh_frame : { *(.eh_frame) } . = ALIGN(4096); .text : { _text = .; *(.text) *(.text.*) *(.gnu.linkonce.t.*) _etext = .; } . = ALIGN(4096); .reloc : { *(.reloc) } . = ALIGN(4096); .note.gnu.build-id : { *(.note.gnu.build-id) } . = ALIGN(4096); .data.ident : { *(.data.ident) } . = ALIGN(4096); .data : { _data = .; *(.rodata*) *(.got.plt) *(.got) *(.data*) *(.sdata) /* the EFI loader doesn't seem to like a .bss section, so we stick it all into .data: */ *(.sbss) *(.scommon) *(.dynbss) *(.bss) *(COMMON) *(.rel.local) } . = ALIGN(4096); .vendor_cert : { *(.vendor_cert) } . = ALIGN(4096); .dynamic : { *(.dynamic) } . = ALIGN(4096); .rela : { *(.rela.data*) *(.rela.got*) *(.rela.stab*) } _edata = .; _data_size = . - _data; . = ALIGN(4096); .sbat : { _sbat = .; *(.sbat) *(.sbat.*) } _esbat = .; _sbat_size = . - _sbat; . = ALIGN(4096); .dynsym : { *(.dynsym) } . = ALIGN(4096); .dynstr : { *(.dynstr) } . = ALIGN(4096); .ignored.reloc : { *(.rela.reloc) *(.eh_frame) *(.note.GNU-stack) } .comment 0 : { *(.comment) } .note.gnu.build-id : { *(.note.gnu.build-id) } } fwupd-efi-1.4/efi/meson.build000066400000000000000000000244571436471456000161770ustar00rootroot00000000000000generate_sbat = find_program('generate_sbat.py', native: true) generate_binary = find_program('generate_binary.py', native: true) efi_ldsdir = get_option('efi-ldsdir') efi_incdir = get_option('efi-includedir') gnu_efi_path_arch = '' foreach name : [gnu_efi_arch, EFI_MACHINE_TYPE_NAME] if (gnu_efi_path_arch == '' and name != '' and cc.has_header('@0@/@1@/efibind.h'.format(efi_incdir, name))) gnu_efi_path_arch = name endif endforeach if gnu_efi_path_arch != '' and EFI_MACHINE_TYPE_NAME == '' error('gnu-efi is available, but EFI_MACHINE_TYPE_NAME is unknown') endif efi_libdir = get_option('efi-libdir') if efi_libdir == '' multi = run_command(cc.cmd_array(), '-print-multi-os-directory').stdout().strip() efi_libdir = join_paths('/usr/lib/', multi) endif have_gnu_efi = gnu_efi_path_arch != '' and efi_libdir != '' if not have_gnu_efi error('gnu-efi support requested, but headers were not found') endif # The name we need to look for on this arch and OS: elf_x86_64_fbsd_efi.lds lds_os = '' if host_cpu == 'x86_64' and host_machine.system() == 'freebsd' lds_os = '_fbsd' endif arch_lds = 'efi.lds' arch_crt = 'crt0.o' if efi_ldsdir == '' efi_ldsdir = join_paths(efi_libdir, 'gnuefi', gnu_efi_path_arch) cmd = run_command('test', '-f', join_paths(efi_ldsdir, arch_lds)) if cmd.returncode() != 0 arch_lds = 'elf_@0@@1@_efi.lds'.format(gnu_efi_path_arch, lds_os) arch_crt = 'crt0-efi-@0@.o'.format(gnu_efi_path_arch) efi_ldsdir = join_paths(efi_libdir, 'gnuefi') cmd = run_command('test', '-f', join_paths(efi_ldsdir, arch_lds)) endif if cmd.returncode() != 0 efi_ldsdir = efi_libdir cmd = run_command('test', '-f', join_paths(efi_ldsdir, arch_lds)) if cmd.returncode() != 0 error('Cannot find @0@'.format(arch_lds)) endif endif else cmd = run_command('test', '-f', join_paths(efi_ldsdir, arch_lds)) if cmd.returncode() != 0 arch_lds = 'elf_@0@@1@_efi.lds'.format(gnu_efi_path_arch, lds_os) arch_crt = 'crt0-efi-@0@.o'.format(gnu_efi_path_arch) cmd = run_command('test', '-f', join_paths(efi_ldsdir, arch_lds)) endif if cmd.returncode() != 0 error('Cannot find @0@'.format(arch_lds)) endif endif efi_crtdir = efi_ldsdir # If using objcopy, crt0 must not include the PE/COFF header if run_command('grep', '-q', 'coff_header', join_paths(efi_crtdir, arch_crt), check: false).returncode() == 0 coff_header_in_crt0 = true else coff_header_in_crt0 = false endif # older objcopy for Aarch64 and ARM32 are not EFI capable. # Use 'binary' instead, and add required symbols manually. if host_cpu == 'arm' or (host_cpu == 'aarch64' and (objcopy_version.version_compare ('< 2.38') or coff_header_in_crt0)) objcopy_manualsymbols = true generate_binary_extra = ['--objcopy-manualsymbols'] else objcopy_manualsymbols = false generate_binary_extra = [] endif # is the system linker script new enough to know about SBAT? # i.e. gnu-efi with https://github.com/vathpela/gnu-efi/pull/14 has been installed if get_option('efi_sbat_distro_id') != '' cmd = run_command('grep', '-q', 'sbat', join_paths(efi_ldsdir, arch_lds)) if cmd.returncode() != 0 warning('Cannot find SBAT section in @0@, using local copy'.format(join_paths(efi_ldsdir, arch_lds))) efi_ldsdir = join_paths(meson.current_source_dir(), 'lds') endif endif # is the system crt0 for arm and aarch64 new enough to know about SBAT? if objcopy_manualsymbols if get_option('efi_sbat_distro_id') != '' arch_crt_source = 'crt0-efi-@0@.S'.format(gnu_efi_path_arch) cmd = run_command('grep', '-q', 'sbat', join_paths(efi_crtdir, arch_crt)) if cmd.returncode() != 0 warning('Cannot find SBAT section in @0@, using local copy'.format(join_paths(efi_crtdir, arch_crt))) # The gnuefi libraries are still needed efi_libdir = efi_crtdir efi_crtdir = join_paths(meson.current_build_dir(), 'crt0') efi_ldsdir = join_paths(meson.current_source_dir(), 'lds') endif endif endif message('efi-libdir: "@0@"'.format(efi_libdir)) message('efi-ldsdir: "@0@"'.format(efi_ldsdir)) message('efi-crtdir: "@0@"'.format(efi_crtdir)) message('efi-includedir: "@0@"'.format(efi_incdir)) debugdir = join_paths (libdir, 'debug') compile_args = ['-Og', '-g3', '--param=ssp-buffer-size=4', '-fexceptions', '-Wall', '-Wextra', '-Wvla', '-std=gnu11', '-fpic', '-fshort-wchar', '-ffreestanding', '-fno-strict-aliasing', '-fno-stack-protector', '-fno-stack-check', '-fno-merge-constants', '-Wsign-compare', '-Wno-missing-field-initializers', '-Wno-address-of-packed-member', '-grecord-gcc-switches', '-DDEBUGDIR="@0@"'.format(debugdir), '-I.', '-isystem', efi_incdir, '-isystem', join_paths(efi_incdir, gnu_efi_path_arch)] if get_option('werror') compile_args += '-Werror' endif if host_cpu == 'x86_64' compile_args += ['-mno-red-zone', '-mno-sse', '-mno-mmx', '-DEFI_FUNCTION_WRAPPER', '-DGNU_EFI_USE_MS_ABI'] elif host_cpu == 'x86' compile_args += ['-mno-sse', '-mno-mmx', '-mno-red-zone', '-m32'] # no special cases for aarch64 or arm endif efi_ldflags = ['-T', join_paths(efi_ldsdir, arch_lds), '-shared', '-Bsymbolic', '-nostdlib', '-znocombreloc', '-L', efi_crtdir, '-L', efi_libdir, join_paths(efi_crtdir, arch_crt)] if objcopy_manualsymbols # older objcopy for Aarch64 and ARM32 are not EFI capable. # Use 'binary' instead, and add required symbols manually. efi_ldflags += ['--defsym=EFI_SUBSYSTEM=0xa'] efi_format = ['-O', 'binary'] else efi_format = ['--target=efi-app-@0@'.format(gnu_efi_arch)] endif libgcc_file_name = run_command(cc.cmd_array(), '-print-libgcc-file-name').stdout().strip() efi_name = 'fwupd@0@.efi'.format(EFI_MACHINE_TYPE_NAME) o_file1 = custom_target('fwupdate.o', input : 'fwupdate.c', output : 'fwupdate.o', command : [cc.cmd_array(), '-c', '@INPUT@', '-o', '@OUTPUT@'] + compile_args) o_file2 = custom_target('fwup-debug.o', input : 'fwup-debug.c', output : 'fwup-debug.o', command : [cc.cmd_array(), '-c', '@INPUT@', '-o', '@OUTPUT@'] + compile_args) o_file3 = custom_target('fwup-efi.o', input : 'fwup-efi.c', output : 'fwup-efi.o', command : [cc.cmd_array(), '-c', '@INPUT@', '-o', '@OUTPUT@'] + compile_args) o_file4 = custom_target('fwup-common.o', input : 'fwup-common.c', output : 'fwup-common.o', command : [cc.cmd_array(), '-c', '@INPUT@', '-o', '@OUTPUT@'] + compile_args) o_file5 = custom_target('fwup-sbat.o', output : 'fwup-sbat.o', command : [ generate_sbat, '@OUTPUT@', '--cc', ' '.join(cc.cmd_array()), '--cflags', ' '.join(compile_args), '--objcopy', objcopy, '--project-name', meson.project_name(), '--project-version', meson.project_version(), '--sbat-version', '1', '--sbat-generation', '@0@'.format(get_option('efi_sbat_fwupd_generation')), '--sbat-distro-id', get_option('efi_sbat_distro_id'), '--sbat-distro-generation', '0', '--sbat-distro-summary', get_option('efi_sbat_distro_summary'), '--sbat-distro-pkgname', get_option('efi_sbat_distro_pkgname'), '--sbat-distro-version', get_option('efi_sbat_distro_version'), '--sbat-distro-url', get_option('efi_sbat_distro_url'), ]) fwupd_so_deps = [] if efi_crtdir == join_paths(meson.current_build_dir(), 'crt0') # A custom crt0 is needed subdir('crt0') fwupd_so_deps += [o_crt0] endif so = custom_target('fwup.so', input : [o_file1, o_file2, o_file3, o_file4, o_file5], output : 'fwup.so', command : [ld, '-o', '@OUTPUT@'] + efi_ldflags + ['@INPUT@'] + ['-lefi', '-lgnuefi', libgcc_file_name], depends: fwupd_so_deps) app = custom_target(efi_name, input : so, output : efi_name, command : [ generate_binary, '@INPUT@', '@OUTPUT@', '--arch', gnu_efi_arch, '--os', host_machine.system(), '--objcopy', objcopy, '--genpeimg', genpeimg.found() ? genpeimg : '' ] + generate_binary_extra, install : true, install_dir : efi_app_location) dbg = custom_target('efi_debug', input : so, output : efi_name + '.debug', command : [objcopy, '-j', '.text', '-j', '.sdata', '-j', '.data', '-j', '.dynamic', '-j', '.rodata', '-j', '.rel*', '-j', '.rela*', '-j', '.reloc', '-j', '.eh_frame', '-j', '.debug*', '-j', '.note.gnu.build-id'] + efi_format + ['@INPUT@', '@OUTPUT@'], install : false, install_dir : debugdir) fwupd-efi-1.4/meson.build000066400000000000000000000032011436471456000154140ustar00rootroot00000000000000project('fwupd-efi', 'c', version : '1.4', license : 'LGPL-2.1+', meson_version : '>=0.53.0', default_options : ['warning_level=2', 'c_std=c99'], ) conf = configuration_data() conf.set_quoted('PACKAGE_VERSION', meson.project_version()) cc = meson.get_compiler('c') ld = cc.get_linker_id() objcopy = find_program('objcopy') objcopy_version = run_command(objcopy, '--version').stdout().split('\n')[0].split(' ')[-1] prefix = get_option('prefix') libdir = join_paths(prefix, get_option('libdir')) libexecdir = join_paths(prefix, get_option('libexecdir')) genpeimg = find_program ('genpeimg', required: false) efi_app_location = join_paths(libexecdir, 'fwupd', 'efi') host_cpu = host_machine.cpu_family() if host_cpu == 'x86' EFI_MACHINE_TYPE_NAME = 'ia32' gnu_efi_arch = 'ia32' elif host_cpu == 'x86_64' EFI_MACHINE_TYPE_NAME = 'x64' gnu_efi_arch = 'x86_64' elif host_cpu == 'arm' EFI_MACHINE_TYPE_NAME = 'arm' gnu_efi_arch = 'arm' elif host_cpu == 'aarch64' EFI_MACHINE_TYPE_NAME = 'aa64' gnu_efi_arch = 'aarch64' else error('Unknown host_cpu ' + host_cpu) endif # sanity check the packager set this to *SOMETHING* if get_option('efi_sbat_distro_id') == '' warning('-Defi_sbat_distro_id is unset, see README.md') endif configure_file( output : 'config.h', configuration : conf ) pkgg = import('pkgconfig') pkgg.generate( version : meson.project_version(), name : meson.project_name(), filebase : 'fwupd-efi', description : 'fwupd-efi is the UEFI binary used with fwupd for installing UEFI firmware updates', ) fwupd_efi_dep = declare_dependency() subdir('efi') fwupd-efi-1.4/meson_options.txt000066400000000000000000000017731436471456000167230ustar00rootroot00000000000000option('efi-libdir', type : 'string', description : 'path to the EFI lib directory') option('efi-ldsdir', type : 'string', description : 'path to the EFI lds directory') option('efi-includedir', type : 'string', value : '/usr/include/efi', description : 'path to the EFI header directory') option('efi_sbat_fwupd_generation', type : 'integer', value : 1, description : 'SBAT fwupd generation') option('efi_sbat_distro_id', type : 'string', value : '', description : 'SBAT distribution ID, e.g. fedora') option('efi_sbat_distro_summary', type : 'string', value : '', description : 'SBAT distribution summary, e.g. Fedora') option('efi_sbat_distro_pkgname', type : 'string', value : '', description : 'SBAT distribution package name, e.g. fwupd') option('efi_sbat_distro_version', type : 'string', value : '', description : 'SBAT distribution version, e.g. fwupd-1.5.6.fc33') option('efi_sbat_distro_url', type : 'string', value : '', description : 'SBAT distribution URL, e.g. https://src.fedoraproject.org/rpms/fwupd')