pax_global_header 0000666 0000000 0000000 00000000064 14556524316 0014525 g ustar 00root root 0000000 0000000 52 comment=c47820c37ac26286559ec004de07d48d05f3308c
efivar-39/ 0000775 0000000 0000000 00000000000 14556524316 0012576 5 ustar 00root root 0000000 0000000 efivar-39/.github/ 0000775 0000000 0000000 00000000000 14556524316 0014136 5 ustar 00root root 0000000 0000000 efivar-39/.github/workflows/ 0000775 0000000 0000000 00000000000 14556524316 0016173 5 ustar 00root root 0000000 0000000 efivar-39/.github/workflows/ci.yml 0000664 0000000 0000000 00000001337 14556524316 0017315 0 ustar 00root root 0000000 0000000 {
"name": "pull-request",
"on": {
"push": { "branches": "main" },
"pull_request": { "branches": "main" },
},
"jobs": {
"linux": {
"runs-on": "ubuntu-latest",
"strategy": {
"fail-fast": false,
"matrix": {
"container": [
"f33", "f34", "f35", "f36", "centos8", "centos9",
],
},
},
"container": "vathpela/efi-ci:${{ matrix.container }}-x64",
"steps": [
{ "uses": "actions/checkout@v2" },
{ "run": "make all test" },
{ "run": "make abicheck" },
],
},
},
}
efivar-39/.gitignore 0000664 0000000 0000000 00000000320 14556524316 0014561 0 ustar 00root root 0000000 0000000 .*.c.P
.*.h.P
.*.d
.*.sw?
.gdb_history
*~
*.a
*.bin
*.C
/.cache/
*.cer
*.E
*.env
*.esl
*.o
*.map
*.pc
*.S
*.so
*.so.*
*.spec
*.strace
*.tar.*
*.var
compile_commands.json
core.*
cov-int
vgcore.*
scan-results/
efivar-39/CODE_OF_CONDUCT.md 0000664 0000000 0000000 00000012566 14556524316 0015407 0 ustar 00root root 0000000 0000000
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, caste, color, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders 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, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
rharwood AT redhat DOT com.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.1, available at
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
Community Impact Guidelines were inspired by
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
For answers to common questions about this code of conduct, see the FAQ at
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available
at [https://www.contributor-covenant.org/translations][translations].
[homepage]: https://www.contributor-covenant.org
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
[Mozilla CoC]: https://github.com/mozilla/diversity
[FAQ]: https://www.contributor-covenant.org/faq
[translations]: https://www.contributor-covenant.org/translations
efivar-39/COPYING 0000664 0000000 0000000 00000063316 14556524316 0013642 0 ustar 00root root 0000000 0000000 GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
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, see .
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!
efivar-39/Makefile 0000664 0000000 0000000 00000005153 14556524316 0014242 0 ustar 00root root 0000000 0000000 export TOPDIR = $(realpath $(dir $(firstword $(MAKEFILE_LIST))))
include $(TOPDIR)/src/include/deprecated.mk
include $(TOPDIR)/src/include/version.mk
include $(TOPDIR)/src/include/rules.mk
include $(TOPDIR)/src/include/defaults.mk
include $(TOPDIR)/src/include/coverity.mk
include $(TOPDIR)/src/include/scan-build.mk
SUBDIRS := src
ifeq ($(ENABLE_DOCS), 1)
SUBDIRS += docs
endif
all : | efivar.spec src/include/version.mk prep
all clean install prep :
@set -e ; for x in $(SUBDIRS) ; do \
$(MAKE) -C $$x $@ ; \
done
abicheck abidw efisecdb efisecdb-static efivar efivar-static static : | all
$(MAKE) -C src $@
abiupdate :
$(MAKE) clean all
$(MAKE) -C src abiclean abixml
$(SUBDIRS) :
$(MAKE) -C $@ all
brick : all
@echo -n $(info this is the rule for brick PWD:$(PWD) MAKECMDGOALS:$(MAKECMDGOALS))
@set -e ; for x in $(SUBDIRS) ; do \
$(MAKE) -C $${x} test ; \
done
a :
@if [ $${EUID} != 0 ]; then \
echo no 1>&2 ; \
exit 1 ; \
fi
GITTAG = $(shell bash -c "echo $$(($(VERSION) + 1))")
efivar.spec : | Makefile src/include/version.mk
clean : clean-toplevel
clean-toplevel:
@rm -vf efivar.spec vgcore.* core.*
@$(MAKE) -C tests clean
test : all
@$(MAKE) -C tests
test-archive: abicheck efivar.spec
@rm -rf /tmp/efivar-$(GITTAG) /tmp/efivar-$(GITTAG)-tmp
@mkdir -p /tmp/efivar-$(GITTAG)-tmp
@git archive --format=tar $(shell git branch | awk '/^*/ { print $$2 }') | ( cd /tmp/efivar-$(GITTAG)-tmp/ ; tar x )
@git diff | ( cd /tmp/efivar-$(GITTAG)-tmp/ ; patch -s -p1 -b -z .gitdiff )
@mv /tmp/efivar-$(GITTAG)-tmp/ /tmp/efivar-$(GITTAG)/
@cp efivar.spec /tmp/efivar-$(GITTAG)/
@dir=$$PWD; cd /tmp; tar -c --bzip2 -f $$dir/efivar-$(GITTAG).tar.bz2 efivar-$(GITTAG)
@rm -rf /tmp/efivar-$(GITTAG)
@echo "The archive is in efivar-$(GITTAG).tar.bz2"
bumpver :
@echo VERSION=$(GITTAG) > src/include/version.mk
@git add src/include/version.mk
git commit -m "Bump version to $(GITTAG)" -s
tag:
git tag -s $(GITTAG) refs/heads/master
archive: abicheck bumpver abidw tag efivar.spec
@rm -rf /tmp/efivar-$(GITTAG) /tmp/efivar-$(GITTAG)-tmp
@mkdir -p /tmp/efivar-$(GITTAG)-tmp
@git archive --format=tar $(GITTAG) | ( cd /tmp/efivar-$(GITTAG)-tmp/ ; tar x )
@mv /tmp/efivar-$(GITTAG)-tmp/ /tmp/efivar-$(GITTAG)/
@cp efivar.spec /tmp/efivar-$(GITTAG)/
@dir=$$PWD; cd /tmp; tar -c --bzip2 -f $$dir/efivar-$(GITTAG).tar.bz2 efivar-$(GITTAG)
@rm -rf /tmp/efivar-$(GITTAG)
@echo "The archive is in efivar-$(GITTAG).tar.bz2"
.PHONY: $(SUBDIRS)
.PHONY: a abiclean abicheck abidw abiupdate all archive
.PHONY: brick bumpver clean clean-toplevel
.PHONY: efivar efivar-static
.PHONY: install prep tag test test-archive
.NOTPARALLEL:
efivar-39/README.md 0000664 0000000 0000000 00000002127 14556524316 0014057 0 ustar 00root root 0000000 0000000 efivar
======
Tools and libraries to manipulate EFI variables
---------------------------------------------
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, see [http://www.gnu.org/licenses/].
There is an ABI tracker for this project at [ABI Laboratory].
[http://www.gnu.org/licenses/]: http://www.gnu.org/licenses/
[ABI Laboratory]: https://abi-laboratory.pro/tracker/timeline/efivar/
WARNING
=======
You should probably not run "make a brick" *ever*, unless you're already
reasonably sure it won't permanently corrupt your firmware. This is not a
joke.
efivar-39/TODO 0000664 0000000 0000000 00000001526 14556524316 0013272 0 ustar 00root root 0000000 0000000 - lots of work still on device path generation and parsing in -lefiboot:
- network paths of all kinds
- fcoe - no idea
- fc - no idea
- iscsi - right now we write out HD paths that don't work because edk2 and
similar don't put an HD() below iSCSI(), and there's no such thing as an
"abbreviated iscsi device path"
- but 9.3.5.21.2 actually /shows/ it having an HD() path.
- so we need to write out:
PciRoot(0x0)/Pci(0x3,0x0)/MAC(c0ffeec0ffee,1)/IPv4(192.168.100.182:0<->10.0.0.29:3260,6,0)/iSCSI(iqn.2012-07.lenovoemc:storage.pjones-iscsi.vol0,1,0x0,None,None,None,TCP) or something like that.
- this is ugly :/
- not sure how to tell from the OS side what parts should be DHCP based
- pretty ugly when ens3 changes addresses every time
- would IPv4(0.0.0.0:0<->10.0.0.29:3260,6,0) be valid?
- lots of man pages
efivar-39/docs/ 0000775 0000000 0000000 00000000000 14556524316 0013526 5 ustar 00root root 0000000 0000000 efivar-39/docs/.gitignore 0000664 0000000 0000000 00000000013 14556524316 0015510 0 ustar 00root root 0000000 0000000 efisecdb.1
efivar-39/docs/Makefile 0000664 0000000 0000000 00000003047 14556524316 0015172 0 ustar 00root root 0000000 0000000 SRCDIR = $(realpath .)
include $(TOPDIR)/src/include/deprecated.mk
include $(TOPDIR)/src/include/version.mk
include $(TOPDIR)/src/include/rules.mk
include $(TOPDIR)/src/include/defaults.mk
MAN1TARGETS = efisecdb.1 \
efivar.1
MAN3TARGETS = efi_append_variable.3 \
efi_del_variable.3 \
efi_get_next_variable_name.3 \
efi_get_variable.3 \
efi_get_variable_attributes.3 \
efi_get_variable_size.3 \
efi_guid_to_id_guid.3 \
efi_guid_to_name.3 \
efi_guid_to_str.3 \
efi_guid_to_symbol.3 \
efi_name_to_guid.3 \
efi_set_variable.3 \
efi_str_to_guid.3 \
efi_symbol_to_guid.3 \
efi_variables_supported.3 \
efi_variable_t.3 \
efi_variable_import.3 \
efi_variable_export.3 \
efi_variable_alloc.3 \
efi_variable_free.3 \
efi_variable_set_name.3 \
efi_variable_get_name.3 \
efi_variable_set_guid.3 \
efi_variable_get_guid.3 \
efi_variable_set_data.3 \
efi_variable_get_data.3 \
efi_variable_get_attributes.3 \
efi_variable_set_attributes.3 \
efi_variable_realize.3
all : $(MAN1TARGETS) $(MAN3TARGETS)
clean :
@rm -f efisecdb.1
prep :
test :
install : $(MAN1TARGETS) $(MAN3TARGETS)
$(INSTALL) -d -m 755 $(DESTDIR)$(MANDIR)/man1
$(foreach x, $(MAN1TARGETS), $(INSTALL) -m 644 $(x) $(DESTDIR)/$(MANDIR)/man1/;)
$(INSTALL) -d -m 755 $(DESTDIR)$(MANDIR)/man3
$(foreach x, $(MAN3TARGETS), $(INSTALL) -m 644 $(x) $(DESTDIR)/$(MANDIR)/man3/;)
.PHONY: all clean install
include $(TOPDIR)/src/include/rules.mk
efivar-39/docs/efi_append_variable.3 0000664 0000000 0000000 00000000034 14556524316 0017546 0 ustar 00root root 0000000 0000000 .so man3/efi_get_variable.3
efivar-39/docs/efi_del_variable.3 0000664 0000000 0000000 00000000034 14556524316 0017043 0 ustar 00root root 0000000 0000000 .so man3/efi_get_variable.3
efivar-39/docs/efi_get_next_variable_name.3 0000664 0000000 0000000 00000000034 14556524316 0021114 0 ustar 00root root 0000000 0000000 .so man3/efi_get_variable.3
efivar-39/docs/efi_get_variable.3 0000664 0000000 0000000 00000013010 14556524316 0017054 0 ustar 00root root 0000000 0000000 .TH EFI_GET_VARIABLE 3 "Thu Aug 20 2012"
.SH NAME
efi_variables_supported, efi_del_variable, efi_get_variable,
efi_get_variable_attributes, efi_get_variable_size, efi_set_variable \-
manipulate UEFI variables
.SH SYNOPSIS
.nf
.B #include
.sp
\fBint efi_variables_supported(void);\fR
\fBint efi_del_variable(efi_guid_t\fR \fIguid\fR\fB, const char\fR \fI*name\fR\fB);\fR
\fBint efi_get_variable(efi_guid_t\fR \fIguid\fR\fB, const char *\fR\fIname\fR\fB,
void **\fR\fIdata\fR\fB, ssize_t *\fR\fIdata_size\fR\fB,
uint32_t *\fR\fIattributes\fR\fB);\fR
\fBint efi_get_variable_attributes(efi_guid_t \fR\fIguid\fR\fB, const char *\fR\fIname\fR\fB,
uint32_t *\fR\fIattributes\fR\fB);\fR
\fBint efi_get_variable_exists(efi_guid_t\fR \fIguid\fR\fB, const char\fR \fI*name\fR\fB);\fR
\fBint efi_get_variable_size(efi_guid_t \fR\fIguid\fR\fB, const char *\fR\fIname\fR\fB,
size_t *\fR\fIsize\fR\fB);\fR
\fBint efi_append_variable(efi_guid_t \fR\fIguid\fR\fB, const char *\fR\fIname\fR\fB,
void *\fR\fIdata\fR\fB, size_t \fR\fIdata_size\fR\fB,
uint32_t \fR\fIattributes\fR\fB);\fR
\fBint efi_set_variable(efi_guid_t \fR\fIguid\fR\fB, const char *\fR\fIname\fR\fB,
void *\fR\fIdata\fR\fB, size_t \fR\fIdata_size\fR\fB,
uint32_t \fR\fIattributes\fR\fB, mode_t \fR\fImode\fR\fB);\fR
\fBint efi_get_next_variable_name(efi_guid_t **\fR\fIguid\fR\fB, char **\fR\fIname\fR\fB);\fR
\fBint efi_str_to_guid(const char *\fR\fIs\fR\fB, efi_guid_t *\fR\fIguid\fR\fB);\fR
\fBint efi_guid_to_str(const efi_guid_t *\fR\fIguid\fR\fB, char **\fR\fIsp\fR\fB);\fR
\fBint efi_name_to_guid(const char *\fR\fIname\fR\fB, efi_guid_t *\fR\fIguid\fR\fB);\fR
\fBint efi_id_guid_to_guid(const char *\fR\fIid_guid\fR\fB, efi_guid_t *\fR\fIguid\fR\fB);\fR
\fBint efi_guid_to_name(efi_guid_t *\fR\fIguid\fR\fB, char **\fR\fIname\fR\fB);\fR
\fBint efi_guid_to_id_guid(efi_guid_t *\fR\fIguid\fR\fB, char **\fR\fIid_guid\fR\fB);\fR
\fBint efi_guid_to_symbol(efi_guid_t *\fR\fIguid\fR\fB, char **\fR\fIsymbol\fR\fB);\fR
\fBint efi_symbol_to_guid(const char *\fR\fIsymbol\fR\fB, efi_guid_t *\fR\fIguid\fR\fB);\fR
.fi
.SH DESCRIPTION
.BR efi_variables_supported ()
tests if the UEFI variable facility is supported on the current machine.
.PP
.BR efi_del_variable ()
deletes the variable specified by \fIguid\fR and \fIname\fR.
.PP
.BR efi_get_variable ()
gets the variable specified by \fIguid\fR and \fIname\fR. The value is stored in \fIdata\fR, its size in \fIdata_size\fR, and its attributes are stored in \fIattributes\fR.
.PP
.BR efi_get_variable_attributes ()
gets attributes for the variable specified by \fIguid\fR and \fIname\fR.
.PP
.BR efi_get_variable_exists ()
gets if the variable specified by \fIguid\fR and \fIname\fR exists.
.PP
.BR efi_get_variable_size ()
gets the size of the data for the variable specified by \fIguid\fR and \fIname\fR.
.PP
.BR efi_append_variable ()
appends \fIdata\fR of size \fIsize\fR to the variable specified by \fIguid\fR and \fIname\fR.
.PP
.BR efi_set_variable ()
sets the variable specified by \fIguid\fR and \fIname\fR, and sets the file mode to \fImode\fR, subject to umask. Note that the mode will not persist across a reboot, and that the permissions only apply if on systems using efivarfs.
.PP
.BR efi_get_next_variable_name ()
iterates across the currently extant variables, passing back a guid and name.
.PP
.BR efi_str_to_guid ()
parses a UEFI GUID from string form to an efi_guid_t the caller provides
.PP
.BR efi_guid_to_str ()
Creates a string representation of a UEFI GUID. If sp is NULL, it returns how big the string would be. If sp is not NULL but *sp is NULL, it allocates a string and returns it with. It is the caller's responsibility to free this string. If sp is not NULL and *sp is not NULL, \fBefi_guid_to_str\fR() assumes there is an allocation of suitable size and uses it.
.PP
.BR efi_name_to_guid ()
translates from a well known name to an efi_guid_t the caller provides.
.PP
.BR efi_guid_to_name ()
translates from an efi_guid_t to a well known name. If the supplied GUID does not have a well known name, this function is equivalent to \fBefi_guid_to_str\fR().
.PP
.BR efi_guid_to_id_guid ()
translates from an efi_guid_t to an {ID GUID}. If the supplied GUID has a well known name, the {ID GUID} will be of the form "{name_here}". If not, it will be of the form "{66b2af1c-6211-4082-95cb-9f73a4795a7e}".
.PP
.BR efi_id_guid_to_guid ()
translates from an {ID GUID} to an efi_guid_t the caller provides.
.PP
.BR efi_guid_to_symbol ()
translates from an efi_guid_t to a unique (within libefivar) C-style symbol name. These symbol names are useful for printing as a unique, easily parsed identifier, and are also provide by the library and its header files.
.PP
.BR efi_symbol_to_guid ()
translates from a libefivar efi_guid_$FOO symbol name to an efi_guid_t the caller provides.
.PP
.SH "RETURN VALUE"
\fBefi_variables_supported\fR() returns true if variables are supported on the running hardware, and false if they are not.
.PP
\fBefi_get_next_variable_name\fR() returns 0 when iteration has completed, 1 when iteration has not completed, and -1 on error. In the event of an error,
.IR errno (3)
is set appropriately.
.PP
\fBefi_del_variable\fR(), \fBefi_get_variable\fR(), \fBefi_get_variable_attributes\fR(), \fBefi_get_variable_exists\fR(), \fBefi_get_variable_size\fR(), \fBefi_append_variable\fR(), \fBefi_set_variable\fR(), \fBefi_str_to_guid\fR(), \fBefi_guid_to_str\fR(), \fBefi_name_to_guid\fR(), and \fBefi_guid_to_name\fR() return negative on error and zero on success.
.SH AUTHORS
.nf
Peter Jones
.fi
efivar-39/docs/efi_get_variable_attributes.3 0000664 0000000 0000000 00000000034 14556524316 0021324 0 ustar 00root root 0000000 0000000 .so man3/efi_get_variable.3
efivar-39/docs/efi_get_variable_size.3 0000664 0000000 0000000 00000000034 14556524316 0020110 0 ustar 00root root 0000000 0000000 .so man3/efi_get_variable.3
efivar-39/docs/efi_guid_to_id_guid.3 0000664 0000000 0000000 00000000034 14556524316 0017550 0 ustar 00root root 0000000 0000000 .so man3/efi_get_variable.3
efivar-39/docs/efi_guid_to_name.3 0000664 0000000 0000000 00000000034 14556524316 0017064 0 ustar 00root root 0000000 0000000 .so man3/efi_get_variable.3
efivar-39/docs/efi_guid_to_str.3 0000664 0000000 0000000 00000000034 14556524316 0016754 0 ustar 00root root 0000000 0000000 .so man3/efi_get_variable.3
efivar-39/docs/efi_guid_to_symbol.3 0000664 0000000 0000000 00000000034 14556524316 0017451 0 ustar 00root root 0000000 0000000 .so man3/efi_get_variable.3
efivar-39/docs/efi_id_guid_to_guid.3 0000664 0000000 0000000 00000000034 14556524316 0017550 0 ustar 00root root 0000000 0000000 .so man3/efi_get_variable.3
efivar-39/docs/efi_name_to_guid.3 0000664 0000000 0000000 00000000034 14556524316 0017064 0 ustar 00root root 0000000 0000000 .so man3/efi_get_variable.3
efivar-39/docs/efi_set_variable.3 0000664 0000000 0000000 00000000034 14556524316 0017072 0 ustar 00root root 0000000 0000000 .so man3/efi_get_variable.3
efivar-39/docs/efi_str_to_guid.3 0000664 0000000 0000000 00000000034 14556524316 0016754 0 ustar 00root root 0000000 0000000 .so man3/efi_get_variable.3
efivar-39/docs/efi_symbol_to_guid.3 0000664 0000000 0000000 00000000034 14556524316 0017451 0 ustar 00root root 0000000 0000000 .so man3/efi_get_variable.3
efivar-39/docs/efi_variable_alloc.3 0000664 0000000 0000000 00000000032 14556524316 0017367 0 ustar 00root root 0000000 0000000 .so man3/efi_variable_t.3
efivar-39/docs/efi_variable_export.3 0000664 0000000 0000000 00000000032 14556524316 0017616 0 ustar 00root root 0000000 0000000 .so man3/efi_variable_t.3
efivar-39/docs/efi_variable_free.3 0000664 0000000 0000000 00000000032 14556524316 0017216 0 ustar 00root root 0000000 0000000 .so man3/efi_variable_t.3
efivar-39/docs/efi_variable_get_attributes.3 0000664 0000000 0000000 00000000032 14556524316 0021322 0 ustar 00root root 0000000 0000000 .so man3/efi_variable_t.3
efivar-39/docs/efi_variable_get_data.3 0000664 0000000 0000000 00000000032 14556524316 0020045 0 ustar 00root root 0000000 0000000 .so man3/efi_variable_t.3
efivar-39/docs/efi_variable_get_guid.3 0000664 0000000 0000000 00000000032 14556524316 0020064 0 ustar 00root root 0000000 0000000 .so man3/efi_variable_t.3
efivar-39/docs/efi_variable_get_name.3 0000664 0000000 0000000 00000000032 14556524316 0020054 0 ustar 00root root 0000000 0000000 .so man3/efi_variable_t.3
efivar-39/docs/efi_variable_import.3 0000664 0000000 0000000 00000000032 14556524316 0017607 0 ustar 00root root 0000000 0000000 .so man3/efi_variable_t.3
efivar-39/docs/efi_variable_realize.3 0000664 0000000 0000000 00000000032 14556524316 0017730 0 ustar 00root root 0000000 0000000 .so man3/efi_variable_t.3
efivar-39/docs/efi_variable_set_attributes.3 0000664 0000000 0000000 00000000032 14556524316 0021336 0 ustar 00root root 0000000 0000000 .so man3/efi_variable_t.3
efivar-39/docs/efi_variable_set_data.3 0000664 0000000 0000000 00000000032 14556524316 0020061 0 ustar 00root root 0000000 0000000 .so man3/efi_variable_t.3
efivar-39/docs/efi_variable_set_guid.3 0000664 0000000 0000000 00000000032 14556524316 0020100 0 ustar 00root root 0000000 0000000 .so man3/efi_variable_t.3
efivar-39/docs/efi_variable_set_name.3 0000664 0000000 0000000 00000000032 14556524316 0020070 0 ustar 00root root 0000000 0000000 .so man3/efi_variable_t.3
efivar-39/docs/efi_variable_t.3 0000664 0000000 0000000 00000017465 14556524316 0016562 0 ustar 00root root 0000000 0000000 .TH EFI_VARIABLE_T 3 "Thu Nov 11 2014"
.SH NAME
efi_variable_import, efi_variable_export, efi_variable_alloc,
efi_variable_free, efi_variable_set_name, efi_variable_get_name,
efi_variable_set_guid, efi_variable_get_guid,
efi_variable_set_data, efi_variable_get_data,
efi_variable_set_attributes, efi_variable_get_attributes,
efi_variable_realize \-
utility functions to import and export UEFI variables to files.
.SH SYNOPSIS
.nf
.B #include
.sp
\fItypedef struct efi_variable \fR\fBefi_variable_t\fR\fI;\fR
\fIssize_t \fR\fBefi_variable_import\fR(\fIuint8_t *\fR\fBdata\fR, \fIsize_t\fR \fBsize\fR, \fIefi_variable_t **\fR\fBvar\fR);
\fIssize_t \fR\fBefi_variable_export\fR(\fIefi_variable_t *\fR\fBvar\fR, \fIuint8_t **\fR\fBdata\fR, \fIsize_t *\fR\fBsize\fR);
\fIefi_variable_t *\fR\fBefi_variable_alloc\fR(\fIvoid\fR);
\fIvoid \fR\fBefi_variable_free\fR(\fIefi_variable_t *\fR\fBvar\fR, \fIint \fR\fBfree_data\fR);
\fIint \fR\fBefi_variable_set_name\fR(\fIefi_variable_t *\fR\fBvar\fR, \fIchar *\fR\fBname\fR);
\fIchar *\fR\fBefi_variable_get_name\fR(\fIefi_variable_t *\fR\fBvar\fR);
\fIint \fR\fBefi_variable_set_guid\fR(\fIefi_variable_t *\fR\fBvar\fR, \fIefi_guid_t *\fR\fBguid\fR);
\fIint \fR\fBefi_variable_get_guid\fR(\fIefi_variable_t *\fR\fBvar\fR, \fIefi_guid_t **\fR\fBguid\fR);
\fIint \fR\fBefi_variable_set_data\fR(\fIefi_variable_t *\fR\fBvar\fR, \fIuint8_t *\fR\fBdata\fR, \fIsize_t \fR\fBsize\fR);
\fIint \fR\fBefi_variable_get_data\fR(\fIefi_variable_t *\fR\fBvar\fR, \fIuint8_t **\fR\fBdata\fR, \fIsize_t *\fR\fBsize\fR);
\fI#define\fR \fBEFI_VARIABLE_NON_VOLATILE\fR \fI0x0000000000000001\fR
\fI#define\fR \fBEFI_VARIABLE_BOOTSERVICE_ACCESS\fR \fI0x0000000000000002\fR
\fI#define\fR \fBEFI_VARIABLE_RUNTIME_ACCESS\fR \fI0x0000000000000004\fR
\fI#define\fR \fBEFI_VARIABLE_HARDWARE_ERROR_RECORD\fR \fI0x0000000000000008\fR
\fI#define\fR \fBEFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS\fR \fI0x0000000000000010\fR
\fI#define\fR \fBEFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS\fR \fI0x0000000000000020\fR
\fI#define\fR \fBEFI_VARIABLE_APPEND_WRITE\fR \fI0x0000000000000040\fR
\fI#define\fR \fBEFI_VARIABLE_HAS_AUTH_HEADER\fR \fI0x0000000100000000\fR
\fI#define\fR \fBEFI_VARIABLE_HAS_SIGNATURE\fR \fI0x0000000200000000\fR
\fIint \fR\fBefi_variable_set_attributes\fR(\fIefi_variable_t *\fR\fBvar\fR, \fIuint64_t \fR\fBattrs\fR);
\fIint \fR\fBefi_variable_get_attributes\fR(\fIefi_variable_t *\fR\fBvar\fR, \fIuint64_t *\fR\fBattrs\fR);
\fIint \fR\fBefi_variable_realize\fR(\fIefi_variable_t *\fR\fBvar\fR);
.fi
.SH DESCRIPTION
\fBefi_variable_t\fR is an opaque data type used to store variables in-memory for use with this API.
.PP
\fBefi_variable_import\fR() is used to import raw data read from a file. This function returns the amount of data consumed with this variable, and may be used successively, using its return code as an offset, to parse a list of variables. Note that the internal guid, name, and data values are allocated separately, and must be freed either individually or using the \fBfree_data\fR parameter of \fBefi_variable_free\fR(). \fB_get\fR() accessors for those values return data suitable for freeing individually, except in such cases where a \fB_set\fR() accessor has been passed an object already unsuitable for that.
.PP
\fBefi_variable_export\fR() is used to marshall \fBefi_variable_t\fR objects into linear data which can be written to a file. If \fBdata\fR or \fBsize\fR parameters are not provided, this function will return how much storage a caller must allocate. Otherwise, \fBefi_variable_export\fR() will use the storage referred to as its buffer; if \fBsize\fR is smaller than the amount of needed storage , the buffer will not be modified, and the difference between the needed space and \fBsize\fR will be returned.
.PP
\fBefi_variable_alloc\fR() is used to allocate an unpopulated \fBefi_variable_t\fR object suitable to be used throughout this API.
\fBefi_variable_free\fR() is used to free an \fBefi_variable_t\fR object, and if \fBfree_data\fR is nonzero, to free its constituent data.
.PP
Each pair of \fB_set\fR() and \fB_get\fR() accessors have essentially the same semantics. Neither operation performs any memory management, including freeing of previously set values or values set by \fBefi_variable_import\fR(), and so in some cases it may be necessary to use a \fB_get\fR() accessor to retrieve an object to be freed. In cases where no value has been set, \fB_get\fR() accessors will set \fBerrno\fR to \fBENOENT\fR and return a negative value or NULL.
.PP
\fBefi_variable_set_name\fR() and \fBefi_variable_get_name\fR() are used to set and retrieve the name of the variable referred to by the \fBefi_variable_t\fR object.
.PP
\fBefi_variable_set_guid\fR() and \fBefi_variable_get_guid\fR() are used to set and retrieve the Vendor GUID value of the variable referred to by the \fBefi_variable_t\fR object.
.PP
\fBefi_variable_set_data\fR() and \fBefi_variable_get_data\fR() are used to set and retrieve an \fBefi_variable_t\fR object's variable data.
.PP
\fBefi_variable_set_attributes\fR() and \fBefi_variable_get_attributes\fR are used to set and retrieve an \fBefi_variable_t\fR object's attributes. All bits except \fBEFI_VARIABLE_HAS_AUTH_HEADER\fR and \fBEFI_VARIABLE_HAS_SIGNATURE\fR are defined in the UEFI specification and should be used accordingly. \fBEFI_VARIABLE_HAS_AUTH_HEADER\fR should be used by applications to track whether the variable data contents include an authentication header. \fBEFI_VARIABLE_HAS_SIGNATURE\fR should be used by applications to track if the variable's data contents include a signature, and should not be set unless \fBEFI_VARIABLE_HAS_AUTH_HEADER\fR is also set. These attributes are used to track if an exported variable is in a state of partial construction, for example if an authenticated variable has been created but is intended to be signed at a later date.
.PP
\fBefi_variable_realize\fR() is a convenience function to set or append a UEFI variable on the running system from an \fBefi_variable_t\fR object. its return codes are the same as \fBefi_append_variable\fR(3) if EFI_VARIABLE_APPEND_WRITE is set, and \fBefi_set_variable\fR() if that bit is not set. Additionally, in the case that any of the authentication bits are set, \fBefi_variable_realize\fR() will return error and set \fBerrno\fR to \fBEPERM\fR unless both \fBEFI_VARIABLE_HAS_AUTH_HEADER\fR and \fBEFI_VARIABLE_HAS_SIGNATURE\fR attribute bits are been set.
.PP
.SH "RETURN VALUE"
\fBefi_variable_import\fR() returns 0 on success, and -1 on failure. In cases where it cannot parse the data, \fBerrno\fR will be set to \fBEINVAL\fR. In cases where memory has been exhausted, \fBerrno\fR will be set to \fBENOMEM\fR.
.PP
\fBefi_variable_export\fR() returns the size of the buffer data on success, or a negative value in the case of an error. If \fBdata\fR or \fBsize\fR parameters are not provided, this function will return how much storage a caller must allocate. Otherwise, this function will use the storage provided in \fBdata\fR; if \fBsize\fR is less than the needed space, the buffer will not be modified, and the return value will be the difficiency in size.
.PP
\fBefi_variable_alloc\fR() returns a newly allocated \fBefi_variable_t\fR object, but does not peform any allocation for that object's \fBname\fR, \fBguid\fR, or \fBdata\fR. In the case that memory is exhausted, \fBNULL\fR will be returned, and \fBerrno\fR will be set to \fBENOMEM\fR.
.PP
\fBefi_variable_get_name\fR() returns a pointer the NUL-terminated string containing the \fBefi_variable_t\fR object's name information.
.PP
\fBefi_variable_set_name\fR(), \fBefi_variable_set_guid\fR(), \fBefi_variable_get_guid\fR(), \fBefi_variable_set_data\fR(), \fBefi_variable_get_data\fR(), \fBefi_variable_set_attributes\fR(), \fBefi_variable_get_attributes\fR(), and \fBefi_variable_realize\fR() return 0 on success and -1 on error.
.SH AUTHORS
.nf
Peter Jones
.fi
efivar-39/docs/efi_variables_supported.3 0000664 0000000 0000000 00000000034 14556524316 0020507 0 ustar 00root root 0000000 0000000 .so man3/efi_get_variable.3
efivar-39/docs/efidp_make_generic.3 0000664 0000000 0000000 00000013103 14556524316 0017370 0 ustar 00root root 0000000 0000000 .TH EFIDP_MAKE_GENERIC 3 "Mon 11 May 2015"
.SH NAME
efidp_make_generic, efidp_make_end_instance, efidp_make_end_entire,
efidp_make_vendor, efidp_make_file, efidp_make_hd, efidp_make_nvme,
efidp_make_sas, efidp_make_ipv4, efidp_make_mac_addr, efidp_make_sata,
efidp_make_scsi, efidp_make_acpi_hid, efidp_make_acpi_hid_ex, efidp_make_edd10,
efidp_make_pci, efidp_make_hw_vendor, efidp_make_msg_vendor, efidp_make_media_vendor \-
Create EFI Device Path node data structures for specific device types
efidp_set_node_data, efidp_duplicate_path, efidp_append_path, efidp_append_node,
efidp_append_instance \-
Manipulate EFI Device Path and node relationships.
efidp_is_valid, efidp_instance_size, efidp_size, efidp_get_next_end,
efidp_is_multiinstance, efidp_next_instance, efidp_next_node, efidp_node_size,
efidp_type, efidp_subtype \-
Inspect EFI Device Path data structures
efidp_parse_device_node, efidp_parse_device_path \-
Create EFI Device Path structures from printable strings.
efidp_format_device_path \-
Format EFI Device Path structures as printable strings.
.SH SYNOPSIS
.nf
.B #include
.sp
\fBssize_t \fRefidp_make_generic\fB(\kZuint8_t *\fIbuf\fP, ssize_t \fIsize\fB,
.ta \nZu
uint8_t \fItype\fB, uint8_t \fIsubtype\fB,
ssize_t \fItotal_size\fB);\fR
\fBssize_t \fRefidp_make_end_instance\fB(uint8_t *\fIbuf\fB, ssize_t \fIsize\fB);\fR
\fBssize_t \fRefidp_make_end_entire\fB(uint8_t *\fIbuf\fB, ssize_t \fIsize\fR\fB);\fR
\fBssize_t \fRefidp_make_vendor\fB(\kZuint8_t *\fIbuf\fB, ssize_t \fIsize\fB, uint8_t \fItype\fB,
.ta \nZu
uint8_t \fIsubtype\fB, efi_guid_t \fIvendor_guid\fB,
void *\fIdata\fB, size_t \fIdata_size\fB);\fR
\fBssize_t \fRefidp_make_file\fB(uint8_t *\fIbuf\fB, ssize_t \fIsize\fB, char *\fIfilename\fB);\fR
.ta
\fBssize_t \fRefidp_make_hd\fB(\kZuint8_t *\fIbuf\fB, ssize_t \fIsize\fB, uint32_t \fInum\fB,
.ta \nZu
uint64_t \fIpart_start\fB, uint64_t \fIpart_size\fB,
uint8_t *\fIsignature\fB, uint8_t \fIformat\fB,
uint8_t \fIsignature_type\fB);\fR
\fBssize_t \fRefidp_make_nvme\fB(\kZuint8_t *\fIbuf\fB, ssize_t \fIsize\fB,
.ta \nZu
uint32_t \fInamespace_id\fB, uint8_t *\fIieee_eui_64\fB);\fR
\fBssize_t \fRefidp_make_sas\fB(uint8_t *\fIbuf\fB, ssize_t \fIsize\fB, uint64_t \fIsas_address\fB);\fR
\fBssize_t \fRefidp_make_ipv4\fB(\kZuint8_t *\fIbuf\fB, ssize_t \fIsize\fB,
.ta \nZu
uint32_t \fIlocal\fB, uint32_t \fIremote\fB,
uint32_t \fIgateway\fB, uint32_t \fInetmask\fB,
uint16_t \fIlocal_port\fB, uint16_t \fIremote_port\fB,
uint16_t \fIprotocol\fB, int \fIis_static\fB);\fR
\fBssize_t \fRefidp_make_mac_addr\fB(\kZuint8_t *\fIbuf\fB, ssize_t \fIsize\fB,
.ta \nZu
uint8_t \fIif_type\fB,
const uint8_t const *\fImac_addr\fB,
ssize_t \fImac_addr_size\fB);\fR
\fBssize_t \fRefidp_make_sata\fB(\kZuint8_t *\fIbuf\fB, ssize_t \fIsize\fB, uint16_t \fIhba_port\fB,
.ta \nZu
uint16_t \fIport_multiplier_port\fB, uint16_t \fIlun\fB);\fR
\fBssize_t \fRefidp_make_scsi\fB(\kZuint8_t *\fIbuf\fB, ssize_t \fIsize\fB, uint16_t \fItarget\fB,
.ta \nZu
uint16_t \fIlun\fB);\fR
\fBssize_t \fRefidp_make_acpi_hid\fB(\kZuint8_t *\fIbuf\fB, ssize_t \fIsize\fB, uint32_t \fIhid\fB,
.ta \nZu
uint32_t \fIuid\fB);\fR
\fBssize_t \fRefidp_make_acpi_hid_ex\fB(\kZuint8_t *\fIbuf\fB, ssize_t \fIsize\fB, uint32_t \fIhid\fB,
.ta \nZu
uint32_t \fIuid\fB, uint32_t \fIcid\fB, char *\fIhidstr\fB,
char *\fIuidstr\fB, char *\fIcidstr\fB);\fR
\fBssize_t \fRefidp_make_edd10\fB(\kZuint8_t *\fIbuf\fB, ssize_t \fIsize\fB,
.ta \nZu
uint32_t \fIhardware_device\fB);\fR
\fBssize_t \fRefidp_make_pci\fB(\kZuint8_t *\fIbuf\fB, ssize_t \fIsize\fB, uint8_t \fIdevice\fB,
.ta \nZu
uint8_t \fIfunction\fR);
\fBssize_t \fRefidp_make_hw_vendor\fB(\kZuint8_t *\fIbuf\fB, ssize_t \fIsize\fB,
.ta \nZu
efi_guid_t \fIguid\fB, void *\fIdata\fB,
size_t \fIdata_size\fB);\fR
\fBssize_t \fRefidp_make_msg_vendor\fB(\kZuint8_t *\fIbuf\fB, ssize_t \fIsize\fB,
.ta \nZu
efi_guid_t \fIguid\fB, void *\fIdata\fB,
size_t \fIdata_size\fB);\fR
\fBssize_t \fRefidp_make_media_vendor\fB(\kZuint8_t *\fIbuf\fB, ssize_t \fIsize\fB,
.ta \nZu
efi_guid_t \fIguid\fB, void *\fIdata\fB,
size_t \fIdata_size\fB);\fR
\fBint \fRefidp_set_node_data\fB(\kZconst_efidp \fIdn\fB, void *\fIbuf\fB, size_t \fIbufsize\fB);
\fBint \fRefidp_duplicate_path\fB(\kZconst_efidp \fIdp\fB, efidp *\fIout\fB);\fR
\fBint \fRefidp_append_path\fB(\kZconst_efidp \fIdp0\fB, const_efidp \fIdp1\fB, efidp *\fIout\fB);
\fBint \fRefidp_append_node\fB(\kZconst_efidp \fIdp\fB, const_efidp \fIdn\fB, efidp *\fIout\fB);\fR
\fBint \fRefidp_append_instance\fB(\kZconst_efidp \fIdp\fB, const_efidp \fIdpi\fB, efidp *\fIout\fB);
\fBint16_t \fRefidp_type\fB(const_efidp \fIdp\fB);\fR
\fBint16_t \fRefidp_subtype\fB(const_efidp \fIdp\fB);\fR
\fBssize_t \fRefidp_node_size\fB(const_efidp \fIdn\fB);\fR
\fBint \fRefidp_next_node\fB(const_efidp \fIin\fB, const_efidp *\fIout\fB);\fR
\fBint \fRefidp_next_instance\fB(const_efidp \fIin\fB, const_efidp *\fIout\fB);\fR
\fBint \fRefidp_is_multiinstance\fB(const_efidp \fIdn\fB);\fR
\fBint \fRefidp_get_next_end\fB(const_efidp \fIin\fB, const_efidp *\fIout\fB);\fR
\fBssize_t \fRefidp_size\fB(const_efidp \fIdp\fB);\fR
\fBssize_t \fRefidp_instance_size\fB(const_efidp \fIdpi\fB);\fR
\fBint \fRefidp_is_valid\fB(const_efidp \fIdp\fB, ssize_t \fIlimit\fB);\fR
\fBssize_t \fRefidp_parse_device_node\fB(char *\fIpath\fB, efidp \fIout\fB, size_t \fIsize\fB);\fR
\fBssize_t \fRefidp_parse_device_path\fB(char *\fIpath\fB, efidp \fIout\fB, size_t \fIsize\fB);\fR
\fBssize_t \fRefidp_format_device_path\fB(\kZchar *\fIbuf\fB, size_t \fIsize\fB,
.ta \nZu
const_efidp \fIdp\fB, ssize_t \fIlimit\fB);\fR
.fi
.SH AUTHORS
.nf
Peter Jones
.fi
efivar-39/docs/efisecdb.1.mdoc 0000664 0000000 0000000 00000015415 14556524316 0016303 0 ustar 00root root 0000000 0000000 .Dd $Mdocdate: Jan 7 2021$
.Dt EFISECDB 1
.Sh NAME
.Nm efisecdb
.Nd utility for managing UEFI signature lists
.Sh SYNOPSIS
.Nm
.Bk -words
.Oo Fl s Ar SORT Oc
.Oo Fl i Ar file Oo Fl i Ar file
.Oc ... Oc
\ \p
.Oo
.Cm Fl g Ar guid
.Ao Cm Fl a | Fl r Ac
.Ao
.Cm Oo Fl t Ar hash-type Oc Cm Fl h Ar hash |
.Cm Fl c Ar file
.Ac
\ \p
.Oo
.Cm Fl g Ar guid
.Ao Cm Fl a | Fl r Ac
.Ao
.Cm Oo Fl t Ar hash-type Oc Cm Fl h Ar hash |
.Cm Fl c Ar file
.Ac
.Oc ... Oc
.Ao
.Cm Fl d Op Fl A
|
.Cm Fl o Ar file
|
.Cm Fl L
.Ac
.Ek
.Sh DESCRIPTION
.Nm
is a command line utility for management of UEFI signature lists in detached
files. That is, it's for command line generation and management of files in the
format of KEK, DB, and DBX.
Operation occurs in three phases:
.Bl -enum -compact
.It
Loading of security databases specified with
.Fl Fl input
.It
Left-to-right processing of other options, using
.Fl Fl hash-type, Fl Fl owner-guid, Fl Fl add,
and
.Fl Fl remove
as state to build selectors to add or remove hashes and certificates specified by
.Fl Fl hash
and
.Fl Fl certificate\fR.
.It
Generation of output
.El
The accumulated state is persistent; once an Owner GUID, Add or Delete
operation, or hash type are specified, they need only be present again to
change the operations that follow. Operations are added to the list to process
when
.Fl h Ar hash
or
.Fl c Ar cert
are specified, and are processed in the order they appear. Additionally,
at least one
.Fl g
argument and either
.Fl Fl add
or
.Fl Fl remove
must appear before the first use of
.Fl h Ar hash
or
.Fl c Ar cert\fR.
.Sh OPTIONS
.Bl -tag
.It Ao Fl s | Fl Fl sort Ac Ao Ar all | Ar data | Ar none | Ar type Ac
Sort by data after sorting and grouping entry types, entry data, no sorting, or by entry type
.It Ao Fl s | Fl Fl sort Ac Ao Ar ascending | Ar descending Ac
Sort in ascending or descending order
.It Fl i Ar file | Fl Fl infile Ar file
Read EFI Security Database from
.Ar file
.It Fl g Ar guid | Fl Fl owner-guid Ar guid
Use the specified GUID or symbolic refrence (i.e. {empty}) for forthcoming
addition and removal operations
.It Fl a | Fl Fl add | Fl r | Fl Fl remove
Select
.Ar add
or
.Ar remove
for forthcoming operations
.It Fl t Ar hash-type | Fl Fl hash-type Ar hash-type
Select
.Ar hash-type
for forthcoming addition and removal operations
.Po
default \fIsha256\fR
.Pc
Use hash-type \fIhelp\fR to list supported hash types.
.It Fl h Ar hash | Fl Fl hash Ar hash
Add or remove the specified hash
.It Fl c Ar file | Fl Fl certificate Ar file
Add or remove the specified certificate
.It Fl d | Fl Fl dump
Produce a hex dump of the output
.It Fl A | Fl Fl annotate
Annotate the hex dump produced by
.Fl Fl dump
.It Fl o Ar file | Fl Fl outfile Ar file
Write EFI Security Database to
.Ar file
.It Fl L | Fl Fl list-guids
List the well known guids
The output is tab delimited: GUID short_name desription
.Sh EXAMPLES
.Ss Dumping the current system's \fIDBX\fP database with annotations
.Bd -literal -compact
host:~$ \fBefisecdb -d -A -i /sys/firmware/efi/efivars/dbx-d719b2cb-3d3a-4596-a3bc-dad00e67656f\fR
00000000 26 16 c4 c1 4c 50 92 40 ac a9 41 f9 36 93 43 28 |&...LP.@..A.6.C(| esl[0].signature_type = {sha256}
00000010 60 00 00 00 |....| esl[0].signature_list_size = 96
00000014 00 00 00 00 |....| esl[0].signature_header_size = 0
00000018 30 00 00 00 |0...| esl[0].signature_size = 48
0000001c esl[0].signature_header (end:0x0000001c)
0000001c bd 9a fa 77 |...w| esl[0].signature[0].owner = {microsoft}
00000020 59 03 32 4d bd 60 28 f4 e7 8f 78 4b |Y.2M.`(...xK|
0000002c fe cf b2 32 |...2| esl[0].signature[0].data (end:0x0000004c)
00000030 d1 2e 99 4b 6d 48 5d 2c 71 67 72 8a a5 52 59 84 |...KmH],qgr..RY.|
00000040 ad 5c a6 1e 75 16 22 1f 07 9a 14 36 |.\..u."....6|
0000004c bd 9a fa 77 |...w| esl[0].signature[1].owner = {microsoft}
00000050 59 03 32 4d bd 60 28 f4 e7 8f 78 4b |Y.2M.`(...xK|
0000005c fe 63 a8 4f |.c.O| esl[0].signature[1].data (end:0x0000007c)
00000060 78 2c c9 d3 fc f2 cc f9 fc 11 fb d0 37 60 87 87 |x,..........7`..|
00000070 58 d2 62 85 ed 12 66 9b dc 6e 6d 01 |X.b...f..nm.|
0000007c
.Ed
.Ss Building a new EFI Security Database for use as \fIKEK\fP, replacing one certificate.
.Bd -literal -compact
# Figure out the original cert... the easy way
host:~$ \fBstrings KEK-* | grep microsoft.*crt\fR\p
Dhttp://www.microsoft.com/pki/certs/MicCorThiParMarRoo_2010-10-05.crt0
# Find it, because --export isn't implemented yet
host:~$ \fBwget \e\p
--user-agent='Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko' \e\p
http://www.microsoft.com/pki/certs/MicCorThiParMarRoo_2010-10-05.crt\fR\p
--2020-06-04 20:41:27-- http://www.microsoft.com/pki/certs/MicCorThiParMarRoo_2010-10-05.crt
Resolving www.microsoft.com (www.microsoft.com)... 2600:141b:800:287::356e, 2600:141b:800:2a0::356e, 23.43.254.254
Connecting to www.microsoft.com (www.microsoft.com)|2600:141b:800:287::356e|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1539 (1.5K) [application/octet-stream]
Saving to: ‘MicCorThiParMarRoo_2010-10-05.crt’
MicCorThiParMarRoo_ 100%[===================>] 1.50K --.-KB/s in 0s
2020-06-04 20:41:27 (177 MB/s) - ‘MicCorThiParMarRoo_2010-10-05.crt’ saved [1539/1539]
# Pick a GUID-like object, any GUID-like object...
host:~$ \fBuuidgen\fR
aab3960c-501e-485e-ac59-62805970a3dd
# Remove the old KEK entry and add a different one
host:~$ \fBefisecdb -i KEK-8be4df61-93ca-11d2-aa0d-00e098032b8c \e\p
-g {microsoft} -r -c MicCorThiParMarRoo_2010-10-05.crt \e\p
-g aab3960c-501e-485e-ac59-62805970a3dd -a -c pjkek.cer \e\p
-o newkek.bin\fR\p
.Ed
.Ss Searching the list of well-known GUIDs
.Bd -literal -compact
host:~$ \fBefisecdb -L | grep shim\fR\p
{605dab50-e046-4300-abb6-3dd810dd8b23} {shim} shim
.Ed
.Sh STANDARDS
.Rs
.%A UEFI Specification Working Group
.%B Unified Extensible Firmware Interface (UEFI) Specification Version 2.8
.%I Unified Extensible Firmware Interface Forum
.%D March 2019
.%U https://uefi.org/specifications\ \&
.Re
.Sh SEE ALSO
.Xr authvar 1 ,
.Xr efikeygen 1 ,
.Xr pesign 1
.Sh AUTHORS
.An Peter Jones
.Sh BUGS
.Nm
is currently lacking several useful features:
.Bl -bullet -compact
.It
positional exporting of certificates
.It
.Fl Fl dump
and
.Fl Fl annotate
do not adjust the output width for the terminal
.It
certificates can't be specified for removal by their \fIToBeSigned\fR hash
.El
efivar-39/docs/efivar.1 0000664 0000000 0000000 00000002321 14556524316 0015062 0 ustar 00root root 0000000 0000000 .TH EFIVAR "1" "September 2019" "efivar 37" "User Commands"
.SH NAME
efivar \- Tool to manipulate UEFI variables
.SH SYNOPSIS
.B efivar
[\fI\,OPTION\/\fR...]
.SH DESCRIPTION
.TP
\fB\-A\fR, \fB\-\-attributes=\fR
attributes to use on append
.TP
\fB\-l\fR, \fB\-\-list\fR
list current variables
.TP
\fB\-p\fR, \fB\-\-print\fR
print variable specified by \fB\-\-name\fR
.TP
\fB\-D\fR, \fB\-\-dmpstore\fR
use DMPSTORE format when exporting
.TP
\fB\-d\fR, \fB\-\-print\-decimal\fR
print variable in decimal format values specified by \fB\-\-name\fR
.TP
\fB\-n\fR, \fB\-\-name=\fR
variable to manipulate, in the form
8be4df61\-93ca\-11d2\-aa0d\-00e098032b8c\-Boot0000
.TP
\fB\-a\fR, \fB\-\-append\fR
append to variable specified by \fB\-\-name\fR
.TP
\fB\-f\fR, \fB\-\-datafile=\fR
load or save variable contents from
.TP
\fB\-e\fR, \fB\-\-export=\fR
export variable to
.TP
\fB\-i\fR, \fB\-\-import=\fR
import variable from
.TP
\fB\-L\fR, \fB\-\-list\-guids\fR
show internal guid list
.TP
\fB\-w\fR, \fB\-\-write\fR
write to variable specified by \fB\-\-name\fR
.SS "Help options:"
.TP
\-?, \fB\-\-help\fR
Show this help message
.TP
\fB\-\-usage\fR
Display brief usage message
efivar-39/efivar.spec.in 0000664 0000000 0000000 00000016350 14556524316 0015340 0 ustar 00root root 0000000 0000000 Name: efivar
Version: @@VERSION@@
Release: 1%{?dist}
Summary: Tools to manage UEFI variables
License: LGPL-2.1-only
URL: https://github.com/rhboot/efivar
Requires: %{name}-libs = %{version}-%{release}
ExclusiveArch: %{efi}
BuildRequires: efi-srpm-macros
BuildRequires: gcc
BuildRequires: git
BuildRequires: glibc-static
BuildRequires: libabigail
BuildRequires: mandoc
BuildRequires: make
# please don't fix this to reflect github's incomprehensible url that goes
# to a different tarball.
Source0: https://github.com/rhboot/efivar/releases/download/%{version}/efivar-%{version}.tar.bz2
%description
efivar provides a simple command line interface to the UEFI variable facility.
%package libs
Summary: Library to manage UEFI variables
%description libs
Library to allow for the simple manipulation of UEFI variables.
%package devel
Summary: Development headers for libefivar
Requires: %{name}-libs = %{version}-%{release}
%description devel
development headers required to use libefivar.
%prep
%setup -q -n %{name}-%{version}
git init
git config user.email "%{name}-owner@fedoraproject.org"
git config user.name "Fedora Ninjas"
git add .
git commit -a -q -m "%{version} baseline."
git am %{patches} - 32-1
- efivar 32
- lots of coverity fixes; mostly leaked memory and fds and the like
- fix sysfs pci path formats
- handle device paths for dns, nfit, bluetooth, wifi, emmc, btle.
- improved abi checking on releases
- Fix failures on EDIT_WRITE in edit_variable() when the variable doesn't exist
- Add efi_guid_ux_capsule_guid to our guids
- Now with %%check
* Wed Aug 02 2017 Fedora Release Engineering - 31-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild
* Wed Jul 26 2017 Fedora Release Engineering - 31-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild
* Mon Mar 06 2017 Peter Jones - 31-1
- Update to efivar 31
- Work around NVMe EUI sysfs change
- Provide some oldish version strings we should have kept.
- lots of overflow checking on our pointer math in dp parsing
- fix major/minor device number handling in the linux code
- Do better formatting checks for MBR partitions
- Fixes for gcc 7
* Fri Feb 10 2017 Fedora Release Engineering - 30-5
- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild
* Mon Oct 17 2016 Peter Jones - 30-4
- Handle NVMe device attributes paths moving around in sysfs.
* Wed Sep 28 2016 Peter Jones - 30-3
- Maybe even provide the *right* old linker deps.
* Tue Sep 27 2016 Peter Jones - 30-2
- Try not to screw up SONAME stuff quite so badly.
* Tue Sep 27 2016 Peter Jones - 30-1
- Fix efidp_*() functions with __pure__ that break with some optimizations
- Fix NVMe EUI parsing.
* Tue Sep 27 2016 Peter Jones - 29-1
- Use -pie not -PIE in our linker config
- Fix some overflow checks for gcc < 5.x
- Make variable class probes other than the first one actually work
- Move -flto to CFLAGS
- Pack all of the efi device path headers
- Fix redundant decl of efi_guid_zero()
* Wed Aug 17 2016 Peter Jones - 28-1
- Make our sonames always lib$FOO.1 , not lib$FOO.$VERSION .
* Tue Aug 16 2016 Peter Jones - 27-1
- Bug fix for 086eeb17 in efivar 26.
* Thu Aug 11 2016 Peter Jones - 26-1
- Use symmacros.h to make newer compilers happy
- Fix a bug in efidp_size() double-counting End nodes sometimes.
- Handle nonnull comparisons in the headers more gracefully.
* Wed Aug 10 2016 Peter Jones - 25-1
- Rework version numbers.
- Add error tracking API.
- Remove use of deprecated readdir_r
- SATA device path fixes.
* Mon Jul 13 2015 Peter Jones - 0.21-1
- Rename "make test" so packagers don't think it's a good idea to run it
during builds.
- Error check sizes in vars_get_variable()
- Fix some file size comparisons
- make SONAME reflect the correct values.
- Fix some uses of "const"
- Compile with -O2 by default
- Fix some strict-aliasing violations
- Fix some of the .pc files and how we do linking to work better.
* Tue Jun 02 2015 Peter Jones - 0.20-1
- Update to 0.20
- Make sure tester is build with the right link order for libraries.
- Adjust linker order for pkg-config
- Work around LocateDevicePath() not grokking PcieRoot() devices properly.
- Rectify some missing changelog entries
* Thu May 28 2015 Peter Jones - 0.19-1
- Update to 0.19
- add API from efibootmgr so fwupdate and other tools can use it.
* Wed Oct 15 2014 Peter Jones - 0.15-1
- Update to 0.15
- Make 32-bit builds set variables' DataSize correctly.
* Wed Oct 08 2014 Peter Jones - 0.14-1
- Update to 0.14
- add efi_id_guid_to_guid() and efi_guid_to_id_guid(), which support {ID GUID}
as a concept.
- Add some vendor specific guids to our guid list.
- Call "empty" "zero" now, as many other places do. References to
efi_guid_is_empty() and efi_guid_empty still exist for ABI compatibility.
- add "efivar -L" to the man page.
* Tue Oct 07 2014 Peter Jones - 0.13-1
- Update to 0.13:
- add efi_symbol_to_guid()
- efi_name_to_guid() will now fall back on efi_symbol_to_guid() as a last
resort
- "efivar -L" to list all the guids we know about
- better namespacing on libefivar.so (rename well_known_* -> efi_well_known_*)
* Thu Sep 25 2014 Peter Jones - 0.12-1
- Update to 0.12
* Wed Aug 20 2014 Peter Jones - 0.11-1
- Update to 0.11
* Fri May 02 2014 Peter Jones - 0.10-1
- Update package to 0.10.
- Fixes a build error due to different cflags in the builders vs updstream
makefile.
* Fri May 02 2014 Peter Jones - 0.9-0.1
- Update package to 0.9.
* Tue Apr 01 2014 Peter Jones - 0.8-0.1
- Update package to 0.8 as well.
* Fri Oct 25 2013 Peter Jones - 0.7-1
- Update package to 0.7
- adds --append support to the binary.
* Fri Sep 06 2013 Peter Jones - 0.6-1
- Update package to 0.6
- fixes to documentation from lersek
- more validation of uefi guids
- use .xz for archives
* Thu Sep 05 2013 Peter Jones - 0.5-0.1
- Update to 0.5
* Mon Jun 17 2013 Peter Jones - 0.4-0.2
- Fix ldconfig invocation
* Mon Jun 17 2013 Peter Jones - 0.4-0.1
- Initial spec file
efivar-39/src/ 0000775 0000000 0000000 00000000000 14556524316 0013365 5 ustar 00root root 0000000 0000000 efivar-39/src/.gitignore 0000664 0000000 0000000 00000000215 14556524316 0015353 0 ustar 00root root 0000000 0000000 !guids.S
*.bin
/efivar
efivar-guids.h
efivar-static
efisecdb
efisecdb-static
makeguids
guid-symbols.c
guids.lds
thread-test
util-makeguids.c
efivar-39/src/Android.mk 0000664 0000000 0000000 00000003532 14556524316 0015301 0 ustar 00root root 0000000 0000000 #
# Copyright (C) 2019 The Android-x86 Open Source Project
#
# Licensed under the GNU Lesser General Public License Version 2.1.
# You may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.gnu.org/licenses/lgpl-2.1.html
#
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := makeguids
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_CFLAGS := -DEFIVAR_BUILD_ENVIRONMENT
LOCAL_SRC_FILES := guid.c makeguids.c
LOCAL_LDLIBS := -ldl
include $(BUILD_HOST_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_MODULE := libefivar
LOCAL_MODULE_CLASS := STATIC_LIBRARIES
LIBEFIBOOT_SOURCES := \
crc32.c \
creator.c \
disk.c \
gpt.c \
loadopt.c \
path-helpers.c \
$(notdir $(wildcard $(LOCAL_PATH)/linux*.c))
LIBEFIVAR_SOURCES := \
dp.c \
dp-acpi.c \
dp-hw.c \
dp-media.c \
dp-message.c \
efivarfs.c \
error.c \
export.c \
guid.c \
guids.S \
lib.c \
vars.c
LIBEFISEC_SOURCES := \
sec.c
include $(LOCAL_PATH)/include/version.mk
LOCAL_SRC_FILES := $(LIBEFIBOOT_SOURCES) $(LIBEFIVAR_SOURCES) $(LIBEFISEC_SOURCES)
LOCAL_CFLAGS := -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -std=gnu11 -DLIBEFIVAR_VERSION=$(VERSION) -Wno-missing-field-initializers
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_C_INCLUDES) $(LOCAL_C_INCLUDES)/efivar $(local-generated-sources-dir)
LIBEFIVAR_GUIDS_H := $(local-generated-sources-dir)/efivar/efivar-guids.h
LOCAL_GENERATED_SOURCES := $(LIBEFIVAR_GUIDS_H) $(local-generated-sources-dir)/guid-symbols.c
$(LIBEFIVAR_GUIDS_H): PRIVATE_CUSTOM_TOOL = $^ $(addprefix $(dir $(@D)),guids.bin names.bin guid-symbols.c efivar/efivar-guids.h)
$(LIBEFIVAR_GUIDS_H): $(BUILD_OUT_EXECUTABLES)/makeguids $(LOCAL_PATH)/guids.txt
$(transform-generated-source)
$(lastword $(LOCAL_GENERATED_SOURCES)): $(LIBEFIVAR_GUIDS_H)
include $(BUILD_STATIC_LIBRARY)
efivar-39/src/Makefile 0000664 0000000 0000000 00000013523 14556524316 0015031 0 ustar 00root root 0000000 0000000 SRCDIR = $(realpath .)
include $(TOPDIR)/src/include/deprecated.mk
include $(TOPDIR)/src/include/version.mk
include $(TOPDIR)/src/include/rules.mk
include $(TOPDIR)/src/include/defaults.mk
LIBTARGETS=libefivar.so libefiboot.so libefisec.so
STATICLIBTARGETS=libefivar.a libefiboot.a libefisec.a
BINTARGETS=efivar efisecdb thread-test
STATICBINTARGETS=efivar-static efisecdb-static
PCTARGETS=efivar.pc efiboot.pc efisec.pc
TARGETS=$(LIBTARGETS) $(BINTARGETS) $(PCTARGETS)
STATICTARGETS=$(STATICLIBTARGETS) $(STATICBINTARGETS)
LIBEFISEC_SOURCES = sec.c secdb.c esl-iter.c util.c
LIBEFISEC_OBJECTS = $(patsubst %.c,%.o,$(LIBEFISEC_SOURCES))
LIBEFIBOOT_SOURCES = crc32.c creator.c disk.c gpt.c loadopt.c path-helpers.c \
linux.c $(sort $(wildcard linux-*.c))
LIBEFIBOOT_OBJECTS = $(patsubst %.c,%.o,$(LIBEFIBOOT_SOURCES))
LIBEFIVAR_SOURCES = crc32.c dp.c dp-acpi.c dp-hw.c dp-media.c dp-message.c \
efivarfs.c error.c export.c guid.c guid-symbols.c \
lib.c vars.c time.c
LIBEFIVAR_OBJECTS = $(patsubst %.S,%.o,$(patsubst %.c,%.o,$(LIBEFIVAR_SOURCES)))
EFIVAR_SOURCES = efivar.c guid.c util.c
EFIVAR_OBJECTS = $(patsubst %.S,%.o,$(patsubst %.c,%.o,$(EFIVAR_SOURCES)))
EFISECDB_SOURCES = efisecdb.c guid-symbols.c secdb-dump.c util.c
EFISECDB_OBJECTS = $(patsubst %.S,%.o,$(patsubst %.c,%.o,$(EFISECDB_SOURCES)))
GENERATED_SOURCES = include/efivar/efivar-guids.h guid-symbols.c
MAKEGUIDS_SOURCES = makeguids.c util-makeguids.c
MAKEGUIDS_OBJECTS = $(patsubst %.S,%.o,$(patsubst %.c,%.o,$(MAKEGUIDS_SOURCES)))
MAKEGUIDS_OUTPUT = $(GENERATED_SOURCES)
util-makeguids.c : util.c
cp util.c util-makeguids.c
ALL_SOURCES=$(LIBEFISEC_SOURCES) $(LIBEFIBOOT_SOURCES) $(LIBEFIVAR_SOURCES) \
$(MAKEGUIDS_SOURCES) $(GENERATED_SOURCES) $(EFIVAR_SOURCES) \
$(sort $(wildcard include/efivar/*.h))
ifneq ($(MAKECMDGOALS),clean)
$(call deps-of,$(ALL_SOURCES)) : | deps
-include $(call deps-of,$(ALL_SOURCES))
endif
all : $(TARGETS)
static : $(STATICTARGETS)
$(BINTARGETS) : | $(LIBTARGETS) $(PCTARGETS)
$(STATICTARGETS) : | $(STATICLIBTARGETS) $(PCTARGETS)
abiclean :
@rm -vf $(patsubst %.so,%.abixml,$@)
abixml : | $(LIBTARGETS)
abixml : $(patsubst %.so,%.abixml,$(LIBTARGETS))
abidw : $(patsubst %.so,%.abixml,$(LIBTARGETS))
git commit -s --amend $^
abicheck : $(patsubst %.so,%.abicheck,$(LIBTARGETS))
makeguids : CPPFLAGS=$(HOST_CPPFLAGS)
makeguids : LIBS=dl
makeguids : CC=$(HOSTCC)
makeguids : CCLD=$(HOSTCCLD)
makeguids : CFLAGS=$(HOST_CFLAGS)
makeguids : LDFLAGS=$(HOST_LDFLAGS)
makeguids : CCLDFLAGS=$(HOST_CCLDFLAGS)
makeguids : $(MAKEGUIDS_OBJECTS)
$(MAKEGUIDS_OUTPUT) : makeguids
$(MAKEGUIDS_OUTPUT) : guids.txt
@set -e ; \
missing=no ; \
for x in $$(cat guids.txt | awk '{ print $$2 }' | grep -v ^zz) ; do \
if ! grep -q "efi_guid_$${x}" libefivar.map.in ; then \
echo missing symbol "efi_guid_$${x}" ; \
missing=yes ; \
fi ; \
done ; \
if [ "$${missing}" != "no" ]; then \
exit 1 ; \
fi
./makeguids guids.txt guid-symbols.c include/efivar/efivar-guids.h
prep : makeguids $(GENERATED_SOURCES)
$(LIBEFIVAR_OBJECTS) $(LIBEFIBOOT_OBJECTS) : include/efivar/efivar-guids.h
libefivar.a : | $(GENERATED_SOURCES)
libefivar.a : $(patsubst %.o,%.static.o,$(LIBEFIVAR_OBJECTS))
libefivar.so : $(LIBEFIVAR_OBJECTS)
libefivar.so : | $(GENERATED_SOURCES) libefivar.map
libefivar.so : private LIBS=dl
libefivar.so : private MAP=libefivar.map
efivar : $(EFIVAR_OBJECTS) | libefivar.so
efivar : private LIBS=efivar dl
efivar-static : $(EFIVAR_OBJECTS) $(patsubst %.o,%.static.o,$(LIBEFIVAR_OBJECTS))
efivar-static : | $(GENERATED_SOURCES)
efivar-static : private LIBS=dl
libefiboot.a : $(patsubst %.o,%.static.o,$(LIBEFIBOOT_OBJECTS))
libefiboot.so : $(LIBEFIBOOT_OBJECTS)
libefiboot.so : | libefiboot.map libefivar.so
libefiboot.so : private LIBS=efivar
libefiboot.so : private MAP=libefiboot.map
libefisec.a : $(patsubst %.o,%.static.o,$(LIBEFISEC_OBJECTS))
libefisec.so : $(LIBEFISEC_OBJECTS)
libefisec.so : | libefisec.map
libefisec.so : private MAP=libefisec.map
efisecdb : $(EFISECDB_OBJECTS) | libefisec.so
efisecdb : private LIBS=efivar efisec dl
efisecdb-static : $(EFISECDB_OBJECTS)
efisecdb-static : $(patsubst %.o,%.static.o,$(LIBEFISEC_OBJECTS) $(LIBEFIVAR_OBJECTS))
efisecdb-static : | $(GENERATED_SOURCES)
efisecdb-static : private LIBS=dl
thread-test : libefivar.so
# make sure we don't propagate CFLAGS to object files used by 'libefivar.so'
thread-test.o : private CFLAGS=$(HOST_CFLAGS) -I$(TOPDIR)/src/include/efivar
thread-test : private LIBS=pthread efivar
deps : $(ALL_SOURCES)
@$(MAKE) -f $(SRCDIR)/include/deps.mk deps SOURCES="$(ALL_SOURCES)"
clean :
@rm -rfv *~ *.o *.a *.E *.so *.so.* *.pc *.bin .*.d *.map \
makeguids guid-symbols.c util-makeguids.c \
include/efivar/efivar-guids.h $(TARGETS) \
$(STATICTARGETS)
@# remove the deps files we used to create, as well.
@rm -rfv .*.P .*.h.P *.S.P include/efivar/.*.h.P
install : all
$(INSTALL) -d -m 755 $(DESTDIR)$(LIBDIR)
$(foreach x,$(LIBTARGETS), \
$(INSTALL) -m 755 $(x) $(DESTDIR)$(LIBDIR)/$(x).1.$(VERSION) ;\
ln -fs $(x).1.$(VERSION) $(DESTDIR)$(LIBDIR)/$(x).1 ;\
ln -fs $(x).1.$(VERSION) $(DESTDIR)$(LIBDIR)/$(x) ;\
)
$(INSTALL) -d -m 755 $(DESTDIR)$(PCDIR)
$(foreach x, $(PCTARGETS), $(INSTALL) -m 644 $(x) $(DESTDIR)$(PCDIR) ;)
$(INSTALL) -d -m 755 $(DESTDIR)$(INCLUDEDIR)/efivar
$(foreach x, $(sort $(wildcard $(TOPDIR)/src/include/efivar/*.h)), $(INSTALL) -m 644 $(x) $(DESTDIR)$(INCLUDEDIR)/efivar/$(notdir $(x));)
$(INSTALL) -d -m 755 $(DESTDIR)$(BINDIR)
$(foreach x, $(filter-out %-test,$(BINTARGETS)), $(INSTALL) -m 755 $(x) $(DESTDIR)$(BINDIR);)
test : all
$(MAKE) -C test $@
.PHONY: abiclean abicheck abidw abixml all
.PHONY: clean deps install test
.SECONDARY : libefivar.so.1.$(VERSION) libefivar.so.1
.SECONDARY : libefiboot.so.1.$(VERSION) libefiboot.so.1
.SECONDARY : libefisec.so.1.$(VERSION) libefisec.so.1
.SECONDARY : $(GENERATED_SOURCES)
.INTERMEDIATE : guids.bin names.bin
.PRECIOUS : makeguids
efivar-39/src/abignore 0000664 0000000 0000000 00000004430 14556524316 0015077 0 ustar 00root root 0000000 0000000 # 1 function with some indirect sub-type change:
#
# [C]'function int efidp_append_instance(const_efidp, const_efidp, efidp*)' at dp.c:259:1 has some indirect sub-type changes:
# parameter 1 of type 'typedef const_efidp' has sub-type changes:
# underlying type 'const efidp_data*' changed:
# in pointed to type 'const efidp_data':
# in unqualified underlying type 'typedef efidp_data' at efivar-dp.h:882:1:
# underlying type 'union __anonymous_union__' at efivar-dp.h:825:1 changed:
# 5 data member insertions:
# 'efidp_bt __anonymous_union__::bt' at efivar-dp.h:867:1
# 'efidp_btle __anonymous_union__::btle' at efivar-dp.h:870:1
# 'efidp_dns __anonymous_union__::dns' at efivar-dp.h:871:1
# 'efidp_emmc __anonymous_union__::emmc' at efivar-dp.h:869:1
# 'efidp_wifi __anonymous_union__::wifi' at efivar-dp.h:868:1
#
[suppress_type]
name = efidp_data
type_kind = typedef
has_data_member_inserted_at = end
soname_regexp = libefi(var|boot|sec)\\.so\\..*
# https://bugzilla.redhat.com/show_bug.cgi?id=2030482 (el9 only)
# 1 function with some indirect sub-type change:
# [C] 'function int _efi_set_variable(efi_guid_t, const char*, uint8_t*, size_t, uint32_t)' at lib.c:33:1 has some indirect sub-type changes:
# parameter 1 of type 'typedef efi_guid_t' changed:
# underlying type 'struct efi_guid_t' at efivar-types.h:13:1 changed:
# type name changed from 'efi_guid_t' to '__anonymous_struct__6'
# type size hasn't changed
# no data member changes (5 filtered);
[suppress_type]
name = efi_guid_t
type_kind = struct
# 1 Added variable:
#
# 'const __anonymous_struct__ efi_guid_ux_capsule' {efi_guid_ux_capsule@@LIBEFIVAR_1.33}
#
[suppress_variable]
change_kind = added-variable
soname_regexp = libefivar\\.so\\..*
symbol_name_regexp = ^efi_guid_[[:alnum:]_]+$
# allow new functions that are prefixed correctly
[suppress_function]
change_kind = added-function
soname_regexp = ^libefi(var|boot|sec)\\.so\\..*
name_regexp = ^(efidp_|efi_)[[:alnum:]_]+
# allow new variables that are prefixed correctly
[suppress_variable]
change_kind = added-variable
soname_regexp = libefi(var|boot|sec)\\.so\\..*
symbol_name_regexp = ^(efidp_|efi_)[[:alnum:]_]+
efivar-39/src/compiler.h 0000664 0000000 0000000 00000005171 14556524316 0015354 0 ustar 00root root 0000000 0000000 // SPDX-License-Identifier: LGPL-2.1-or-later
/*
* compiler.h - compiler related macros
* Copyright Peter Jones
*/
#ifndef COMPILER_H_
#define COMPILER_H_
/* GCC version checking borrowed from glibc. */
#if defined(__GNUC__) && defined(__GNUC_MINOR__)
# define GNUC_PREREQ(maj,min) \
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
#else
# define GNUC_PREREQ(maj,min) 0
#endif
/* Does this compiler support compile-time error attributes? */
#if GNUC_PREREQ(4,3)
# define ATTRIBUTE_ERROR(msg) \
__attribute__ ((__error__ (msg)))
#else
# define ATTRIBUTE_ERROR(msg) __attribute__ ((noreturn))
#endif
#if GNUC_PREREQ(4,4)
# define GNU_PRINTF gnu_printf
#else
# define GNU_PRINTF printf
#endif
#if GNUC_PREREQ(3,4)
# define WARN_UNUSED_RESULT __attribute__ ((warn_unused_result))
#else
# define WARN_UNUSED_RESULT
#endif
#if defined(__clang__) && defined(__clang_major__) && defined(__clang_minor__)
# define CLANG_PREREQ(maj,min) \
((__clang_major__ > (maj)) || \
(__clang_major__ == (maj) && __clang_minor__ >= (min)))
#else
# define CLANG_PREREQ(maj,min) 0
#endif
#define UNUSED __attribute__((__unused__))
#define HIDDEN __attribute__((__visibility__ ("hidden")))
#define PUBLIC __attribute__((__visibility__ ("default")))
#define DESTRUCTOR __attribute__((__destructor__))
#define CONSTRUCTOR __attribute__((__constructor__))
#define ALIAS(x) __attribute__((weak, alias (#x)))
#define NONNULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
#define PRINTF(...) __attribute__((__format__(printf, __VA_ARGS__)))
#define FLATTEN __attribute__((__flatten__))
#define PACKED __attribute__((__packed__))
#if defined(__clang__)
# define VERSION(sym, ver)
#else
# if GNUC_PREREQ(10,0)
# define VERSION(sym, ver) __attribute__ ((symver (# ver)))
# else
# define VERSION(sym, ver) __asm__(".symver " # sym "," # ver);
# endif
#endif
#define NORETURN __attribute__((__noreturn__))
#define ALIGNED(n) __attribute__((__aligned__(n)))
#define CLEANUP_FUNC(x) __attribute__((__cleanup__(x)))
#define __CONCAT3(a, b, c) a ## b ## c
#define CONCATENATE(a, b) __CONCAT(a, b)
#define CAT(a, b) __CONCAT(a, b)
#define CAT3(a, b, c) __CONCAT3(a, b, c)
#define STRING(x) __STRING(x)
#define __ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))
#define __ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a) - 1)
#define ALIGN(x, a) __ALIGN((x), (a))
#define ALIGN_DOWN(x, a) __ALIGN((x) - ((a) - 1), (a))
#define ALIGNMENT_PADDING(value, align) ((align - (value % align)) % align)
#define ALIGN_UP(value, align) ((value) + ALIGNMENT_PADDING(value, align))
#endif /* !COMPILER_H_ */
// vim:fenc=utf-8:tw=75:noet
efivar-39/src/crc32.c 0000664 0000000 0000000 00000015704 14556524316 0014454 0 ustar 00root root 0000000 0000000 // SPDX-License-Identifier: LGPL-2.1-or-later
/*
* Dec 5, 2000 Matt Domsch
* - Copied crc32.c from the linux/drivers/net/cipe directory.
* - Now pass seed as an arg
* - changed len to be an unsigned long
* - changed crc32val to be a register
* - License remains unchanged! It's still GPL-compatable!
*/
/* ============================================================= */
/* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or */
/* code or tables extracted from it, as desired without restriction. */
/* */
/* First, the polynomial itself and its table of feedback terms. The */
/* polynomial is */
/* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */
/* */
/* Note that we take it "backwards" and put the highest-order term in */
/* the lowest-order bit. The X^32 term is "implied"; the LSB is the */
/* X^31 term, etc. The X^0 term (usually shown as "+1") results in */
/* the MSB being 1. */
/* */
/* Note that the usual hardware shift register implementation, which */
/* is what we're using (we're merely optimizing it by doing eight-bit */
/* chunks at a time) shifts bits into the lowest-order term. In our */
/* implementation, that means shifting towards the right. Why do we */
/* do it this way? Because the calculated CRC must be transmitted in */
/* order from highest-order term to lowest-order term. UARTs transmit */
/* characters in order from LSB to MSB. By storing the CRC this way, */
/* we hand it to the UART in the order low-byte to high-byte; the UART */
/* sends each low-bit to hight-bit; and the result is transmission bit */
/* by bit from highest- to lowest-order term without requiring any bit */
/* shuffling on our part. Reception works similarly. */
/* */
/* The feedback terms table consists of 256, 32-bit entries. Notes: */
/* */
/* The table can be generated at runtime if desired; code to do so */
/* is shown later. It might not be obvious, but the feedback */
/* terms simply represent the results of eight shift/xor opera- */
/* tions for all combinations of data and CRC register values. */
/* */
/* The values must be right-shifted by eight bits by the "updcrc" */
/* logic; the shift must be unsigned (bring in zeroes). On some */
/* hardware you could probably optimize the shift in assembler by */
/* using byte-swap instructions. */
/* polynomial $edb88320 */
/* */
/* -------------------------------------------------------------------- */
#include
static uint32_t crc32_tab[] = {
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
0x2d02ef8dL
};
/* Return a 32-bit CRC of the contents of the buffer. */
uint32_t
crc32(const void *buf, unsigned long len, uint32_t seed)
{
unsigned long i;
register uint32_t val;
const unsigned char *s = buf;
val = seed;
for (i = 0; i < len; i ++)
val = crc32_tab[(val ^ s[i]) & 0xff] ^ (val >> 8);
return val;
}
// vim:fenc=utf-8:tw=75:noet
efivar-39/src/crc32.h 0000664 0000000 0000000 00000001642 14556524316 0014455 0 ustar 00root root 0000000 0000000 // SPDX-License-Identifier: LGPL-2.1-or-later
/*
* crc32.h - headers for crc32
*
*/
#ifndef _CRC32_H
#define _CRC32_H
#include
/*
* This computes a 32 bit CRC of the data in the buffer, and returns the CRC.
* The polynomial used is 0xedb88320.
*/
extern uint32_t crc32 (const void *buf, unsigned long len, uint32_t seed);
/**
* efi_crc32() - EFI version of crc32 function
* @buf: buffer to calculate crc32 of
* @len - length of buf
*
* Description: Returns EFI-style CRC32 value for @buf
*
* This function uses the little endian Ethernet polynomial
* but seeds the function with ~0, and xor's with ~0 at the end.
* Note, the EFI Specification, v1.02, has a reference to
* Dr. Dobbs Journal, May 1994 (actually it's in May 1992).
*/
static inline uint32_t
efi_crc32(const void *buf, unsigned long len)
{
return (crc32(buf, len, ~0L) ^ ~0L);
}
#endif /* _CRC32_H */
// vim:fenc=utf-8:tw=75:noet
efivar-39/src/creator.c 0000664 0000000 0000000 00000024624 14556524316 0015200 0 ustar 00root root 0000000 0000000 // SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libefiboot - library for the manipulation of EFI boot variables
* Copyright 2012-2015 Red Hat, Inc.
*/
#include "fix_coverity.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "efiboot.h"
static int NONNULL(1, 2, 3)
find_file(const char * const filepath, char **devicep, char **relpathp)
{
struct stat fsb = { 0, };
int rc;
int ret = -1;
FILE *mounts = NULL;
char linkbuf[PATH_MAX+1] = "";
ssize_t linklen = 0;
linklen = strlen(filepath);
if (linklen > PATH_MAX) {
errno = ENAMETOOLONG;
efi_error("filepath length exceeds PATH_MAX");
return -1;
}
strcpy(linkbuf, filepath);
do {
rc = stat(linkbuf, &fsb);
if (rc < 0)
return rc;
if (S_ISLNK(fsb.st_mode)) {
char tmp[PATH_MAX+1] = "";
ssize_t l;
l = readlink(linkbuf, tmp, PATH_MAX);
if (l < 0) {
efi_error("readlink failed");
return -1;
}
tmp[l] = '\0';
linklen = l;
strcpy(linkbuf, tmp);
} else {
break;
}
} while (1);
mounts = setmntent("/proc/self/mounts", "r");
if (mounts == NULL) {
efi_error("couldn not open /proc/self/mounts");
return -1;
}
struct mntent *me;
while (1) {
struct stat dsb = { 0, };
errno = 0;
me = getmntent(mounts);
if (!me) {
if (feof(mounts)) {
errno = ENOENT;
efi_error("could not find mountpoint");
}
goto err;
}
if (me->mnt_fsname[0] != '/')
continue;
rc = stat(me->mnt_fsname, &dsb);
if (rc < 0) {
if (errno == ENOENT)
continue;
efi_error("could not stat mountpoint");
goto err;
}
if (!S_ISBLK(dsb.st_mode))
continue;
if (dsb.st_rdev == fsb.st_dev) {
ssize_t mntlen = strlen(me->mnt_dir);
if (mntlen >= linklen)
continue;
if (strncmp(linkbuf, me->mnt_dir, mntlen))
continue;
*devicep = strdup(me->mnt_fsname);
if (!*devicep) {
errno = ENOMEM;
efi_error("strdup failed");
goto err;
}
*relpathp = strdup(linkbuf + mntlen);
if (!*relpathp) {
free(*devicep);
*devicep = NULL;
errno = ENOMEM;
efi_error("strdup failed");
goto err;
}
ret = 0;
break;
}
}
err:
if (mounts)
endmntent(mounts);
return ret;
}
static int
open_disk(struct device *dev, int flags)
{
char *diskpath = NULL;
int rc;
rc = asprintfa(&diskpath, "/dev/%s", dev->disk_name);
if (rc < 0) {
efi_error("could not allocate buffer");
return -1;
}
rc = open(diskpath, flags);
if (rc < 0)
efi_error("could not open disk");
return rc;
}
static char *
tilt_slashes(char *s)
{
char *p;
for (p = s; *p; p++)
if (*p == '/')
*p = '\\';
return s;
}
ssize_t
efi_va_generate_file_device_path_from_esp(uint8_t *buf, ssize_t size,
const char *devpath, int partition,
const char *relpath,
uint32_t options, va_list ap)
{
ssize_t ret = -1, off = 0, sz;
struct device *dev = NULL;
int fd = -1;
int saved_errno;
debug("partition:%d", partition);
if (buf && size)
memset(buf, '\0', size);
fd = open(devpath, O_RDONLY);
if (fd < 0) {
efi_error("could not open device for ESP");
goto err;
}
dev = device_get(fd, partition);
if (dev == NULL) {
efi_error("could not get ESP disk info");
goto err;
}
if (partition < 0) {
int disk_fd;
debug("partition: %d", partition);
disk_fd = open_disk(dev,
(options & EFIBOOT_OPTIONS_WRITE_SIGNATURE)
? O_RDWR : O_RDONLY);
if (disk_fd < 0) {
efi_error("could not open disk");
goto err;
}
if (is_partitioned(disk_fd))
partition = 1;
else
partition = 0;
debug("is_partitioned(): partition -> %d", partition);
close(disk_fd);
}
set_part(dev, partition);
if (partition == 0) {
options |= EFIBOOT_ABBREV_NONE;
options &= ~(EFIBOOT_ABBREV_HD|
EFIBOOT_ABBREV_FILE|
EFIBOOT_ABBREV_EDD10);
}
if (options & EFIBOOT_ABBREV_NONE)
debug("EFIBOOT_ABBREV_NONE");
if (options & EFIBOOT_ABBREV_HD)
debug("EFIBOOT_ABBREV_HD");
if (options & EFIBOOT_ABBREV_FILE)
debug("EFIBOOT_ABBREV_FILE");
if (options & EFIBOOT_ABBREV_EDD10)
debug("EFIBOOT_ABBREV_EDD10");
if (options & EFIBOOT_ABBREV_EDD10) {
va_list aq;
va_copy(aq, ap);
dev->edd10_devicenum = va_arg(aq, uint32_t);
va_end(aq);
}
if (!(options & (EFIBOOT_ABBREV_FILE|EFIBOOT_ABBREV_HD))
&& (dev->flags & DEV_ABBREV_ONLY)) {
efi_error_clear();
errno = EINVAL;
efi_error("Device must use File() or HD() device path");
goto err;
}
if ((options & EFIBOOT_ABBREV_EDD10)
&& (!(options & EFIBOOT_ABBREV_FILE)
&& !(options & EFIBOOT_ABBREV_HD))) {
sz = efidp_make_edd10(buf, size, dev->edd10_devicenum);
if (sz < 0) {
efi_error("could not make EDD 1.0 device path");
goto err;
}
off = sz;
} else if (!(options & EFIBOOT_ABBREV_FILE)
&& !(options & EFIBOOT_ABBREV_HD)) {
/*
* We're probably on a modern kernel, so just parse the
* symlink from /sys/dev/block/$major:$minor and get it
* from there.
*/
sz = make_blockdev_path(buf, size, dev);
if (sz < 0) {
efi_error("could not create device path");
goto err;
}
off += sz;
}
if ((!(options & EFIBOOT_ABBREV_FILE) && dev->part_name) ||
((options & EFIBOOT_ABBREV_HD) && ! dev->part_name)) {
int disk_fd;
int saved_errno;
disk_fd = open_disk(dev,
(options & EFIBOOT_OPTIONS_WRITE_SIGNATURE)
? O_RDWR : O_RDONLY);
if (disk_fd < 0) {
efi_error("could not open disk");
goto err;
}
sz = make_hd_dn(buf+off, size?size-off:0,
disk_fd, dev->part, options);
saved_errno = errno;
close(disk_fd);
errno = saved_errno;
if (sz < 0) {
efi_error("could not make HD() DP node");
goto err;
}
off += sz;
}
char *filepath = strdupa(relpath);
tilt_slashes(filepath);
sz = efidp_make_file(buf+off, size?size-off:0, filepath);
if (sz < 0) {
efi_error("could not make File() DP node");
goto err;
}
off += sz;
sz = efidp_make_end_entire(buf+off, size?size-off:0);
if (sz < 0) {
efi_error("could not make EndEntire DP node");
goto err;
}
off += sz;
ret = off;
err:
saved_errno = errno;
if (dev)
device_free(dev);
if (fd >= 0)
close(fd);
errno = saved_errno;
debug("= %zd", ret);
return ret;
}
ssize_t NONNULL(3, 5) PUBLIC
efi_generate_file_device_path_from_esp(uint8_t *buf, ssize_t size,
const char *devpath, int partition,
const char *relpath,
uint32_t options, ...)
{
ssize_t ret;
int saved_errno;
va_list ap;
va_start(ap, options);
ret = efi_va_generate_file_device_path_from_esp(buf, size, devpath,
partition, relpath,
options, ap);
saved_errno = errno;
va_end(ap);
errno = saved_errno;
if (ret < 0)
efi_error("could not generate File DP from ESP");
return ret;
}
static int
get_part(char *devpath)
{
int fd;
int partition = -1;
struct device *dev = NULL;
fd = open(devpath, O_RDONLY);
if (fd < 0) {
efi_error("could not open device for ESP");
goto err;
}
dev = device_get(fd, -1);
if (dev == NULL) {
efi_error("could not get ESP disk info");
goto err;
}
partition = dev->part;
if (partition < 0)
partition = 0;
err:
if (dev)
device_free(dev);
if (fd >= 0)
close(fd);
return partition;
}
ssize_t NONNULL(3) PUBLIC
efi_generate_file_device_path(uint8_t *buf, ssize_t size,
const char * const filepath,
uint32_t options, ...)
{
int rc;
ssize_t ret = -1;
char *child_devpath = NULL;
char *parent_devpath = NULL;
char *relpath = NULL;
va_list ap;
int saved_errno;
rc = find_file(filepath, &child_devpath, &relpath);
if (rc < 0) {
efi_error("could not canonicalize fs path");
goto err;
}
rc = find_parent_devpath(child_devpath, &parent_devpath);
if (rc < 0) {
efi_error("could not find parent device for file");
goto err;
}
debug("child_devpath:%s", child_devpath);
debug("parent_devpath:%s", parent_devpath);
debug("child_devpath:%s", child_devpath);
debug("rc:%d", rc);
rc = get_part(child_devpath);
if (rc < 0) {
efi_error("Couldn't get partition number for %s",
child_devpath);
goto err;
}
debug("detected partition:%d", rc);
va_start(ap, options);
if (!strcmp(parent_devpath, "/dev/block"))
ret = efi_va_generate_file_device_path_from_esp(buf, size,
child_devpath, rc,
relpath, options, ap);
else
ret = efi_va_generate_file_device_path_from_esp(buf, size,
parent_devpath, rc,
relpath, options, ap);
saved_errno = errno;
va_end(ap);
errno = saved_errno;
if (ret < 0)
efi_error("could not generate File DP from ESP");
err:
saved_errno = errno;
if (child_devpath)
free(child_devpath);
if (parent_devpath)
free(parent_devpath);
if (relpath)
free(relpath);
errno = saved_errno;
return ret;
}
static ssize_t NONNULL(3, 4, 5, 6)
make_ipv4_path(uint8_t *buf, ssize_t size,
const char * const local_addr UNUSED,
const char * const remote_addr UNUSED,
const char * const gateway_addr UNUSED,
const char * const netmask UNUSED,
uint16_t local_port UNUSED,
uint16_t remote_port UNUSED,
uint16_t protocol UNUSED,
uint8_t addr_origin UNUSED)
{
ssize_t ret;
#if 0
if (local_addr == NULL || remote_addr == NULL ||
gateway_addr == NULL || netmask == NULL) {
errno = EINVAL;
return -1;
}
#endif
ret = efidp_make_ipv4(buf, size, 0, 0, 0, 0, 0, 0, 0, 0);
if (ret < 0)
efi_error("could not make ipv4 DP node");
return ret;
}
ssize_t NONNULL(3, 4, 5, 6, 7) PUBLIC
efi_generate_ipv4_device_path(uint8_t *buf, ssize_t size,
const char * const ifname,
const char * const local_addr,
const char * const remote_addr,
const char * const gateway_addr,
const char * const netmask,
uint16_t local_port,
uint16_t remote_port,
uint16_t protocol,
uint8_t addr_origin)
{
ssize_t off = 0;
ssize_t sz;
sz = make_mac_path(buf, size, ifname);
if (sz < 0) {
efi_error("could not make MAC DP node");
return -1;
}
off += sz;
sz = make_ipv4_path(buf+off, size?size-off:0, local_addr, remote_addr,
gateway_addr, netmask, local_port, remote_port,
protocol, addr_origin);
if (sz < 0) {
efi_error("could not make IPV4 DP node");
return -1;
}
off += sz;
sz = efidp_make_end_entire(buf+off, size?size-off:0);
if (sz < 0) {
efi_error("could not make EndEntire DP node");
return -1;
}
off += sz;
return off;
}
uint32_t PUBLIC
efi_get_libefiboot_version(void)
{
return LIBEFIVAR_VERSION;
}
// vim:fenc=utf-8:tw=75:noet
efivar-39/src/diag.h 0000664 0000000 0000000 00000004504 14556524316 0014445 0 ustar 00root root 0000000 0000000 // SPDX-License-Identifier: LGPL-2.1-or-later
/*
* diag.h - Set up appropriate -W flags based on which compiler is in use
* Copyright Peter Jones
*/
#ifndef PRIVATE_DIAG_H_
#define PRIVATE_DIAG_H_
#if defined(__clang__)
#pragma clang diagnostic ignored "-Wpointer-bool-conversion"
/*
* -Wmissing-field-initializers just encourages you to write worse code,
* and that's all it's ever done. It vaguely made sense pre-C99, before
* named initializers, but at this point it's just completely nonsense.
*/
#pragma clang diagnostic ignored "-Wmissing-field-initializers"
#pragma clang diagnostic warning "-Wcpp"
#endif
#if defined(__GNUC__) && !defined(__clang__)
/*
* nonnull compare is more or less completetly defective; rather than
* warning that you're *calling* something without ensuring an argument
* can't be NULL, it complains in the implementation of the callee that
* you're *checking* for NULL. Useful behavior would be to complain in the
* caller if an argument hasn't been properly constrained, and to complain
* in the callee if either the visibility is public and the variable
* /isn't/ checked, or the visibility is hidden and it is - i.e. only
* complain about checking if you can verify every caller.
*/
#if __GNUC__ > 6
#pragma GCC diagnostic ignored "-Wnonnull-compare"
#endif
/*
* -Wmissing-field-initializers just encourages you to write worse code,
* and that's all it's ever done. It vaguely made sense pre-C99, before
* named initializers, but at this point it's just completely nonsense.
*/
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#if defined(EFIVAR_SYNTAX_CHECKING)
#pragma GCC diagnostic ignored "-Wcpp"
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-result"
#pragma GCC diagnostic ignored "-Wunused-variable"
#else
#pragma GCC diagnostic warning "-Wcpp"
#pragma GCC diagnostic error "-Wunused-but-set-variable"
#pragma GCC diagnostic error "-Wunused-function"
#pragma GCC diagnostic error "-Wunused-parameter"
#pragma GCC diagnostic error "-Wunused-result"
#pragma GCC diagnostic error "-Wunused-variable"
#endif /* !defined(EFIVAR_SYNTAX_CHECKING) */
#endif
#endif /* !PRIVATE_DIAG_H_ */
// vim:fenc=utf-8:tw=75:noet
efivar-39/src/disk.c 0000664 0000000 0000000 00000015554 14556524316 0014475 0 ustar 00root root 0000000 0000000 // SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libefiboot - library for the manipulation of EFI boot variables
* Copyright 2012-2015 Red Hat, Inc.
* Copyright (C) 2000-2001 Dell Computer Corporation
*/
#include "fix_coverity.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "efiboot.h"
/**
* is_mbr_valid(): test MBR for validity
* @mbr: pointer to a legacy mbr structure
*
* Description: Returns 1 if MBR is valid, 0 otherwise.
* Validity depends on one thing:
* 1) MSDOS signature is in the last two bytes of the MBR
*/
static inline int
is_mbr_valid(legacy_mbr *mbr)
{
int ret;
if (!mbr)
return 0;
ret = (mbr->magic == MSDOS_MBR_MAGIC);
if (!ret) {
errno = ENOTTY;
efi_error("mbr magic is 0x%04hx not MSDOS_MBR_MAGIC (0x%04hx)",
mbr->magic, MSDOS_MBR_MAGIC);
}
return ret;
}
/************************************************************
* msdos_disk_get_extended partition_info()
* Requires:
* - open file descriptor fd
* - start, size
* Modifies: all these
* Returns:
* 0 on success
* non-zero on failure
*
************************************************************/
static int
msdos_disk_get_extended_partition_info (int fd UNUSED,
legacy_mbr *mbr UNUSED,
uint32_t num UNUSED,
uint64_t *start UNUSED,
uint64_t *size UNUSED)
{
/* Until I can handle these... */
//fprintf(stderr, "Extended partition info not supported.\n");
errno = ENOSYS;
efi_error("extended partition info is not supported");
return -1;
}
/************************************************************
* msdos_disk_get_partition_info()
* Requires:
* - mbr
* - open file descriptor fd (for extended partitions)
* - start, size, signature, mbr_type, signature_type
* Modifies: all these
* Returns:
* 0 on success
* non-zero on failure
*
************************************************************/
static int
msdos_disk_get_partition_info (int fd, int write_signature,
legacy_mbr *mbr, uint32_t num, uint64_t *start,
uint64_t *size, uint32_t *signature,
uint8_t *mbr_type, uint8_t *signature_type)
{
int rc;
long disk_size=0;
struct stat stat;
struct timeval tv;
if (!mbr) {
errno = EINVAL;
efi_error("mbr argument must not be NULL");
return -1;
}
if (!is_mbr_valid(mbr)) {
errno = ENOENT;
efi_error("mbr is not valid");
return -1;
}
*mbr_type = 0x01;
*signature_type = 0x01;
if (!mbr->unique_mbr_signature && !write_signature) {
efi_error("\n******************************************************\n"
"Warning! This MBR disk does not have a unique signature.\n"
"If this is not the first disk found by EFI, you may not be able\n"
"to boot from it without a unique signature.\n"
"Run efibootmgr with the -w flag to write a unique signature\n"
"to the disk.\n"
"******************************************************");
} else if (!mbr->unique_mbr_signature && write_signature) {
/* MBR Signatures must be unique for the
EFI Boot Manager
to find the right disk to boot from */
rc = fstat(fd, &stat);
if (rc < 0) {
efi_error("could not fstat disk");
return rc;
}
rc = gettimeofday(&tv, NULL);
if (rc < 0) {
efi_error("gettimeofday failed");
return rc;
}
/* Write the device type to the signature.
This should be unique per disk per system */
mbr->unique_mbr_signature = tv.tv_usec << 16;
mbr->unique_mbr_signature |= stat.st_rdev & 0xFFFF;
/* Write it to the disk */
lseek(fd, 0, SEEK_SET);
rc = write(fd, mbr, sizeof(*mbr));
if (rc < 0) {
efi_error("could not write MBR signature");
return rc;
}
}
*signature = mbr->unique_mbr_signature;
if (num > 4) {
/* Extended partition */
rc = msdos_disk_get_extended_partition_info(fd, mbr, num,
start, size);
if (rc < 0) {
efi_error("could not get extended partition info");
return rc;
}
} else if (num == 0) {
/* Whole disk */
*start = 0;
ioctl(fd, BLKGETSIZE, &disk_size);
*size = disk_size;
} else if (num >= 1 && num <= 4) {
/* Primary partition */
*start = mbr->partition[num-1].starting_lba;
*size = mbr->partition[num-1].size_in_lba;
}
return 0;
}
static int
get_partition_info(int fd, uint32_t options,
uint32_t part, uint64_t *start, uint64_t *size,
partition_signature_t *signature, uint8_t *mbr_type,
uint8_t *signature_type)
{
legacy_mbr *mbr;
void *mbr_sector;
size_t mbr_size;
off_t offset UNUSED;
int this_bytes_read = 0;
int gpt_invalid=0, mbr_invalid=0;
int rc=0;
int sector_size = get_sector_size(fd);
mbr_size = lcm(sizeof(*mbr), sector_size);
if ((rc = posix_memalign(&mbr_sector, sector_size, mbr_size)) != 0) {
efi_error("posix_memalign failed");
goto error;
}
memset(mbr_sector, '\0', mbr_size);
offset = lseek(fd, 0, SEEK_SET);
this_bytes_read = read(fd, mbr_sector, mbr_size);
if (this_bytes_read < (ssize_t)sizeof(*mbr)) {
efi_error("short read trying to read mbr data");
rc = -1;
goto error_free_mbr;
}
mbr = (legacy_mbr *)mbr_sector;
gpt_invalid = gpt_disk_get_partition_info(
fd, part, start, size, &signature->gpt_signature, mbr_type,
signature_type, (options & EFIBOOT_OPTIONS_IGNORE_PMBR_ERR) ? 1 : 0,
sector_size);
if (gpt_invalid < 0) {
mbr_invalid = msdos_disk_get_partition_info(
fd, (options & EFIBOOT_OPTIONS_WRITE_SIGNATURE) ? 1 : 0,
mbr, part, start, size, &signature->mbr_signature, mbr_type,
signature_type);
if (mbr_invalid < 0) {
efi_error("neither MBR nor GPT is valid");
rc = -1;
goto error_free_mbr;
}
efi_error_clear();
}
error_free_mbr:
free(mbr_sector);
error:
return rc;
}
bool HIDDEN
is_partitioned(int fd)
{
int rc;
uint32_t options = 0;
uint32_t part = 1;
uint64_t start = 0, size = 0;
uint8_t mbr_type = 0, signature_type = 0;
partition_signature_t signature;
memset(&signature, 0, sizeof(signature));
rc = get_partition_info(fd, options, part, &start, &size,
&signature, &mbr_type, &signature_type);
if (rc < 0)
return false;
return true;
}
ssize_t HIDDEN
make_hd_dn(uint8_t *buf, ssize_t size, int fd, int32_t partition,
uint32_t options)
{
uint64_t part_start=0, part_size = 0;
partition_signature_t signature;
uint8_t format=0, signature_type=0;
int rc;
errno = 0;
if (partition <= 0)
return 0;
memset(&signature, 0, sizeof(signature));
rc = get_partition_info(fd, options, partition, &part_start,
&part_size, &signature, &format,
&signature_type);
if (rc < 0) {
efi_error("could not get partition info");
return rc;
}
rc = efidp_make_hd(buf, size, partition, part_start, part_size,
(uint8_t *)&signature, format, signature_type);
if (rc < 0)
efi_error("could not make HD DP node");
return rc;
}
// vim:fenc=utf-8:tw=75:noet
efivar-39/src/disk.h 0000664 0000000 0000000 00000000755 14556524316 0014477 0 ustar 00root root 0000000 0000000 // SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libefiboot - library for the manipulation of EFI boot variables
* Copyright 2012-2015 Red Hat, Inc.
* Copyright (C) 2001 Dell Computer Corporation
*/
#ifndef _EFIBOOT_DISK_H
#define _EFIBOOT_DISK_H
extern bool HIDDEN is_partitioned(int fd);
extern HIDDEN ssize_t make_hd_dn(uint8_t *buf, ssize_t size, int fd,
int32_t partition, uint32_t options);
#endif /* _EFIBOOT_DISK_H */
// vim:fenc=utf-8:tw=75:noet
efivar-39/src/dp-acpi.c 0000664 0000000 0000000 00000020646 14556524316 0015056 0 ustar 00root root 0000000 0000000 // SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libefivar - library for the manipulation of EFI variables
* Copyright 2012-2019 Red Hat, Inc.
*/
#include "fix_coverity.h"
#include
#include
#include
#include
#include "efivar.h"
static ssize_t
_format_acpi_adr(unsigned char *buf, size_t size,
const char *dp_type UNUSED,
const_efidp dp)
{
ssize_t off = 0;
format(buf, size, off, "AcpiAdr", "AcpiAdr(");
format_array(buf, size, off, "AcpiAdr", "0x%"PRIx32,
__typeof__(dp->acpi_adr.adr[0]), dp->acpi_adr.adr,
(efidp_node_size(dp)-4) / sizeof (dp->acpi_adr.adr[0]));
format(buf, size, off, "AcpiAdr", ")");
return off;
}
#define format_acpi_adr(buf, size, off, dp) \
format_helper(_format_acpi_adr, buf, size, off, "AcpiAdr", dp)
static ssize_t
_format_acpi_hid_ex(unsigned char *buf, size_t size,
const char *dp_type UNUSED, const_efidp dp,
const char *hidstr, const char *cidstr,
const char *uidstr)
{
ssize_t off = 0;
debug("hid:0x%08x hidstr:'%s'", dp->acpi_hid_ex.hid, hidstr);
debug("cid:0x%08x cidstr:'%s'", dp->acpi_hid_ex.cid, cidstr);
debug("uid:0x%08x uidstr:'%s'", dp->acpi_hid_ex.uid, uidstr);
if (!hidstr && !cidstr && (uidstr || dp->acpi_hid_ex.uid)) {
format(buf, size, off, "AcpiExp",
"AcpiExp(0x%"PRIx32",0x%"PRIx32",",
dp->acpi_hid_ex.hid, dp->acpi_hid_ex.cid);
if (uidstr) {
format(buf, size, off, "AcpiExp", "%s)", uidstr);
} else {
format(buf, size, off, "AcpiExp", "0x%"PRIx32")",
dp->acpi_hid_ex.uid);
}
return off;
}
format(buf, size, off, "AcpiEx", "AcpiEx(");
if (hidstr) {
format(buf, size, off, "AcpiEx", "%s,", hidstr);
} else {
format(buf, size, off, "AcpiEx", "0x%"PRIx32",",
dp->acpi_hid_ex.hid);
}
if (cidstr) {
format(buf, size, off, "AcpiEx", "%s,", cidstr);
} else {
format(buf, size, off, "AcpiEx", "0x%"PRIx32",",
dp->acpi_hid_ex.cid);
}
if (uidstr) {
format(buf, size, off, "AcpiEx", "%s)", uidstr);
} else {
format(buf, size, off, "AcpiEx", "0x%"PRIx32")",
dp->acpi_hid_ex.uid);
}
return off;
}
#define format_acpi_hid_ex(buf, size, off, dp, hidstr, cidstr, uidstr) \
format_helper(_format_acpi_hid_ex, buf, size, off, "AcpiEx", dp,\
hidstr, cidstr, uidstr)
ssize_t
_format_acpi_dn(unsigned char *buf, size_t size, const_efidp dp)
{
ssize_t off = 0;
const char *hidstr = NULL;
size_t hidlen = 0;
const char *uidstr = NULL;
size_t uidlen = 0;
const char *cidstr = NULL;
// size_t cidlen = 0;
if (dp->subtype == EFIDP_ACPI_ADR) {
debug("formatting ACPI _ADR");
format_acpi_adr(buf, size, off, dp);
return off;
} else if (dp->subtype != EFIDP_ACPI_HID_EX &&
dp->subtype != EFIDP_ACPI_HID) {
debug("DP subtype %d, formatting as ACPI Path", dp->subtype);
format(buf, size, off, "AcpiPath", "AcpiPath(%d,", dp->subtype);
format_hex(buf, size, off, "AcpiPath", (uint8_t *)dp+4,
(efidp_node_size(dp)-4) / 2);
format(buf, size, off, "AcpiPath", ")");
return off;
} else if (dp->subtype == EFIDP_ACPI_HID_EX) {
ssize_t limit = efidp_node_size(dp)
- offsetof(efidp_acpi_hid_ex, hidstr);
debug("formatting ACPI HID EX");
hidstr = dp->acpi_hid_ex.hidstr;
hidlen = strnlen(hidstr, limit);
limit -= hidlen + 1;
if (limit) {
uidstr = hidstr + hidlen + 1;
uidlen = strnlen(uidstr, limit);
limit -= uidlen + 1;
}
if (limit) {
cidstr = uidstr + uidlen + 1;
// cidlen = strnlen(cidstr, limit);
// limit -= cidlen + 1;
}
if (uidstr) {
switch (dp->acpi_hid.hid) {
case EFIDP_ACPI_PCI_ROOT_HID:
format(buf, size, off, "PciRoot",
"PciRoot(%s)", uidstr);
return off;
case EFIDP_ACPI_CONTAINER_0A05_HID:
case EFIDP_ACPI_CONTAINER_0A06_HID:
format(buf, size, off, "AcpiContainer",
"AcpiContainer(%s)", uidstr);
break;
case EFIDP_ACPI_PCIE_ROOT_HID:
format(buf, size, off, "PcieRoot",
"PcieRoot(%s)", uidstr);
return off;
case EFIDP_ACPI_EC_HID:
format(buf, size, off, "EmbeddedController",
"EmbeddedController()");
return off;
default:
format_acpi_hid_ex(buf, size, off, dp,
hidstr, cidstr, uidstr);
return off;
}
}
} else if (dp->subtype == EFIDP_ACPI_HID) {
debug("formatting ACPI HID 0x%08x", dp->acpi_hid.hid);
switch (dp->acpi_hid.hid) {
case EFIDP_ACPI_PCI_ROOT_HID:
format(buf, size, off, "PciRoot",
"PciRoot(0x%"PRIx32")",
dp->acpi_hid.uid);
break;
case EFIDP_ACPI_CONTAINER_0A05_HID:
case EFIDP_ACPI_CONTAINER_0A06_HID:
format(buf, size, off, "AcpiContainer",
"AcpiContainer()");
break;
case EFIDP_ACPI_PCIE_ROOT_HID:
format(buf, size, off, "PcieRoot",
"PcieRoot(0x%"PRIx32")",
dp->acpi_hid.uid);
break;
case EFIDP_ACPI_EC_HID:
format(buf, size, off, "EmbeddedController",
"EmbeddedController()");
break;
case EFIDP_ACPI_FLOPPY_HID:
format(buf, size, off, "Floppy",
"Floppy(0x%"PRIx32")",
dp->acpi_hid.uid);
break;
case EFIDP_ACPI_KEYBOARD_HID:
format(buf, size, off, "Keyboard",
"Keyboard(0x%"PRIx32")",
dp->acpi_hid.uid);
break;
case EFIDP_ACPI_SERIAL_HID:
format(buf, size, off, "Serial",
"Serial(0x%"PRIx32")",
dp->acpi_hid.uid);
break;
case EFIDP_ACPI_NVDIMM_HID: {
int rc;
const_efidp next = NULL;
efidp_acpi_adr *adrdp;
int end;
format(buf, size, off, "NvRoot()", "NvRoot()");
rc = efidp_next_node(dp, &next);
if (rc < 0 || !next) {
efi_error("could not format DP");
return rc;
}
if (efidp_type(next) != EFIDP_ACPI_TYPE ||
efidp_subtype(next) != EFIDP_ACPI_ADR) {
efi_error("Invalid child node type (0x%02x,0x%02x)",
efidp_type(next), efidp_subtype(next));
return -EINVAL;
}
adrdp = (efidp_acpi_adr *)next;
end = efidp_size_after(adrdp, header)
/ sizeof(adrdp->adr[0]);
for (int i = 0; i < end; i++) {
uint32_t node_controller, socket, memory_controller;
uint32_t memory_channel, dimm;
uint32_t adr = adrdp->adr[i];
efidp_decode_acpi_nvdimm_adr(adr,
&node_controller, &socket,
&memory_controller, &memory_channel,
&dimm);
if (i != 0)
format(buf, size, off, "NvDimm", ",");
format(buf, size, off, "NvDimm",
"NvDimm(0x%03x,0x%01x,0x%01x,0x%01x,0x%01x)",
node_controller, socket, memory_controller,
memory_channel, dimm);
}
break;
}
default:
debug("Decoding non-well-known HID");
switch (dp->subtype) {
case EFIDP_ACPI_HID_EX:
format_acpi_hid_ex(buf, size, off, dp,
hidstr, cidstr, uidstr);
break;
case EFIDP_ACPI_HID:
debug("Decoding ACPI HID");
format(buf, size, off, "Acpi",
"Acpi(0x%08x,0x%"PRIx32")",
dp->acpi_hid.hid, dp->acpi_hid.uid);
break;
default:
debug("ACPI subtype %d???",
dp->subtype);
errno = EINVAL;
return -1;
}
}
} else {
debug("Unknown ACPI device path type {0x%04hhx,0x%04hhx}",
dp->type, dp->subtype);
}
return off;
}
ssize_t PUBLIC
efidp_make_acpi_hid(uint8_t *buf, ssize_t size, uint32_t hid, uint32_t uid)
{
efidp_acpi_hid *acpi_hid = (efidp_acpi_hid *)buf;
ssize_t req = sizeof (*acpi_hid);
ssize_t sz;
sz = efidp_make_generic(buf, size, EFIDP_ACPI_TYPE, EFIDP_ACPI_HID,
sizeof (*acpi_hid));
if (size && sz == req) {
acpi_hid->uid = uid;
acpi_hid->hid = hid;
}
if (sz < 0)
efi_error("efidp_make_generic failed");
return sz;
}
ssize_t PUBLIC
efidp_make_acpi_hid_ex(uint8_t *buf, ssize_t size,
uint32_t hid, uint32_t uid, uint32_t cid,
const char *hidstr, const char *uidstr,
const char *cidstr)
{
efidp_acpi_hid_ex *acpi_hid = (efidp_acpi_hid_ex *)buf;
ssize_t req;
ssize_t sz;
size_t hidlen = hidstr ? strlen(hidstr) : 0;
size_t uidlen = uidstr ? strlen(uidstr) : 0;
size_t cidlen = cidstr ? strlen(cidstr) : 0;
req = sizeof (*acpi_hid) + 3 + hidlen + uidlen + cidlen;
sz = efidp_make_generic(buf, size, EFIDP_ACPI_TYPE, EFIDP_ACPI_HID_EX,
req);
if (size && sz == req) {
acpi_hid->hid = hidlen ? 0 : hid;
acpi_hid->uid = uidlen ? 0 : uid;
acpi_hid->cid = cidlen ? 0 : cid;
char *next = (char *)buf+offsetof(efidp_acpi_hid_ex, hidstr);
if (hidlen)
strcpy(next, hidstr);
next += hidlen + 1;
if (uidlen)
strcpy(next, uidstr);
next += uidlen + 1;
if (cidlen)
strcpy(next, cidstr);
}
if (sz < 0)
efi_error("efidp_make_generic failed");
return sz;
}
// vim:fenc=utf-8:tw=75:noet
efivar-39/src/dp-hw.c 0000664 0000000 0000000 00000005504 14556524316 0014554 0 ustar 00root root 0000000 0000000 // SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libefivar - library for the manipulation of EFI variables
* Copyright 2012-2015 Red Hat, Inc.
*/
#include "fix_coverity.h"
#include
#include
#include "efivar.h"
ssize_t
format_edd10_guid(unsigned char *buf, size_t size,
const char *dp_type, const_efidp dp)
{
ssize_t off = 0;
efidp_edd10 const *edd_dp = (efidp_edd10 *)dp;
format(buf, size, off, dp_type, "EDD10(0x%"PRIx32")",
edd_dp->hardware_device);
return off;
}
ssize_t
_format_hw_dn(unsigned char *buf, size_t size, const_efidp dp)
{
efi_guid_t edd10_guid = EDD10_HARDWARE_VENDOR_PATH_GUID;
ssize_t off = 0;
switch (dp->subtype) {
case EFIDP_HW_PCI:
format(buf, size, off, "Pci", "Pci(0x%"PRIx32",0x%"PRIx32")",
dp->pci.device, dp->pci.function);
break;
case EFIDP_HW_PCCARD:
format(buf, size, off, "PcCard", "PcCard(0x%"PRIx32")",
dp->pccard.function);
break;
case EFIDP_HW_MMIO:
format(buf, size, off, "MemoryMapped",
"MemoryMapped(%"PRIu32",0x%"PRIx64",0x%"PRIx64")",
dp->mmio.memory_type, dp->mmio.starting_address,
dp->mmio.ending_address);
break;
case EFIDP_HW_VENDOR:
if (!efi_guid_cmp(&dp->hw_vendor.vendor_guid, &edd10_guid)) {
format_helper(format_edd10_guid, buf, size, off,
"EDD 1.0", dp);
} else {
format_vendor(buf, size, off, "VenHw", dp);
}
break;
case EFIDP_HW_CONTROLLER:
format(buf, size, off, "Ctrl", "Ctrl(0x%"PRIx32")",
dp->controller.controller);
break;
case EFIDP_HW_BMC:
format(buf, size, off, "BMC", "BMC(%d,0x%"PRIx64")",
dp->bmc.interface_type, dp->bmc.base_addr);
break;
default:
format(buf, size, off, "Hardware",
"HardwarePath(%d,", dp->subtype);
format_hex(buf, size, off, "Hardware", (uint8_t *)dp+4,
efidp_node_size(dp)-4);
format(buf, size, off, "Hardware", ")");
break;
}
return off;
}
ssize_t PUBLIC
efidp_make_pci(uint8_t *buf, ssize_t size, uint8_t device, uint8_t function)
{
efidp_pci *pci = (efidp_pci *)buf;
ssize_t sz;
ssize_t req = sizeof (*pci);
sz = efidp_make_generic(buf, size, EFIDP_HARDWARE_TYPE, EFIDP_HW_PCI,
req);
if (size && sz == req) {
pci->device = device;
pci->function = function;
}
if (sz < 0)
efi_error("efidp_make_generic failed");
return sz;
}
ssize_t PUBLIC
efidp_make_edd10(uint8_t *buf, ssize_t size, uint32_t hardware_device)
{
efi_guid_t edd10_guid = EDD10_HARDWARE_VENDOR_PATH_GUID;
efidp_edd10 *edd_dp = (efidp_edd10 *)buf;
ssize_t sz;
ssize_t req = sizeof (*edd_dp);
sz = efidp_make_generic(buf, size, EFIDP_HARDWARE_TYPE, EFIDP_HW_VENDOR,
req);
if (size && sz == req) {
memcpy(&edd_dp->vendor_guid, &edd10_guid, sizeof (edd10_guid));
edd_dp->hardware_device = hardware_device;
}
if (sz < 0)
efi_error("efidp_make_generic failed");
return sz;
}
// vim:fenc=utf-8:tw=75:noet
efivar-39/src/dp-media.c 0000664 0000000 0000000 00000012474 14556524316 0015221 0 ustar 00root root 0000000 0000000 // SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libefivar - library for the manipulation of EFI variables
* Copyright 2012-2015 Red Hat, Inc.
*/
#include "fix_coverity.h"
#include
#include
#include
#include
#include "efivar.h"
ssize_t
_format_media_dn(unsigned char *buf, size_t size, const_efidp dp)
{
ssize_t off = 0;
switch (dp->subtype) {
case EFIDP_MEDIA_HD:
format(buf, size, off, "HD", "HD(%d,", dp->hd.partition_number);
switch (dp->hd.signature_type) {
case EFIDP_HD_SIGNATURE_MBR:
format(buf, size, off, "HD",
"MBR,0x%"PRIx32",0x%"PRIx64",0x%"PRIx64")",
(uint32_t)dp->hd.signature[0] |
((uint32_t)dp->hd.signature[1] << 8) |
((uint32_t)dp->hd.signature[2] << 16) |
((uint32_t)dp->hd.signature[3] << 24),
dp->hd.start, dp->hd.size);
break;
case EFIDP_HD_SIGNATURE_GUID:
format(buf, size, off, "HD", "GPT,");
format_guid(buf, size, off, "HD", dp->hd.signature);
format(buf, size, off, "HD",
",0x%"PRIx64",0x%"PRIx64")",
dp->hd.start, dp->hd.size);
break;
default:
format(buf, size, off, "HD", "%d,",
dp->hd.signature_type);
format_hex(buf, size, off, "HD", dp->hd.signature,
sizeof(dp->hd.signature));
format(buf, size, off, "HD",
",0x%"PRIx64",0x%"PRIx64")",
dp->hd.start, dp->hd.size);
break;
}
break;
case EFIDP_MEDIA_CDROM:
format(buf, size, off, "CDROM",
"CDROM(%d,0x%"PRIx64",0x%"PRIx64")",
dp->cdrom.boot_catalog_entry,
dp->cdrom.partition_rba, dp->cdrom.sectors);
break;
case EFIDP_MEDIA_VENDOR:
format_vendor(buf, size, off, "VenMedia", dp);
break;
case EFIDP_MEDIA_FILE: {
size_t limit = (efidp_node_size(dp)
- offsetof(efidp_file, name)) / 2;
format_ucs2(buf, size, off, "File", dp->file.name, limit);
break;
}
case EFIDP_MEDIA_PROTOCOL:
format(buf, size, off, "Media", "Media(");
format_guid(buf, size, off, "Media",
&dp->protocol.protocol_guid);
format(buf, size, off, "Media", ")");
break;
case EFIDP_MEDIA_FIRMWARE_FILE:
format(buf, size, off, "FvFile", "FvFile(");
format_guid(buf, size, off, "FvFile",
&dp->protocol.protocol_guid);
format(buf, size, off, "FvFile", ")");
break;
case EFIDP_MEDIA_FIRMWARE_VOLUME:
format(buf, size, off, "FvVol", "FvVol(");
format_guid(buf, size, off, "FvVol",
&dp->protocol.protocol_guid);
format(buf, size, off, "FvVol", ")");
break;
case EFIDP_MEDIA_RELATIVE_OFFSET:
format(buf, size, off, "Offset",
"Offset(0x%"PRIx64",0x%"PRIx64")",
dp->relative_offset.first_byte,
dp->relative_offset.last_byte);
break;
case EFIDP_MEDIA_RAMDISK: {
struct {
efi_guid_t guid;
char label[40];
} subtypes[] = {
{ EFIDP_VIRTUAL_DISK_GUID, "VirtualDisk" },
{ EFIDP_VIRTUAL_CD_GUID, "VirtualCD" },
{ EFIDP_PERSISTENT_VIRTUAL_DISK_GUID, "PersistentVirtualDisk" },
{ EFIDP_PERSISTENT_VIRTUAL_CD_GUID, "PersistentVirtualCD" },
{ efi_guid_empty, "" }
};
char *label = NULL;
for (int i = 0; !efi_guid_is_zero(&subtypes[i].guid); i++) {
if (efi_guid_cmp(&subtypes[i].guid,
&dp->ramdisk.disk_type_guid))
continue;
label = subtypes[i].label;
break;
}
if (label) {
format(buf, size, off, label,
"%s(0x%"PRIx64",0x%"PRIx64",%d)", label,
dp->ramdisk.start_addr,
dp->ramdisk.end_addr,
dp->ramdisk.instance_number);
break;
}
format(buf, size, off, "Ramdisk",
"Ramdisk(0x%"PRIx64",0x%"PRIx64",%d,",
dp->ramdisk.start_addr, dp->ramdisk.end_addr,
dp->ramdisk.instance_number);
format_guid(buf, size, off, "Ramdisk",
&dp->ramdisk.disk_type_guid);
format(buf, size, off, "Ramdisk", ")");
break;
}
default:
format(buf, size, off, "Media", "MediaPath(%d,", dp->subtype);
format_hex(buf, size, off, "Media", (uint8_t *)dp+4,
(efidp_node_size(dp)-4) / 2);
format(buf,size,off, "Media",")");
break;
}
return off;
}
ssize_t PUBLIC
efidp_make_file(uint8_t *buf, ssize_t size, char *filepath)
{
efidp_file *file = (efidp_file *)buf;
unsigned char *lf = (unsigned char *)filepath;
ssize_t sz;
ssize_t len = utf8len(lf, -1) + 1;
ssize_t req = sizeof (*file) + len * sizeof (uint16_t);
if (len == 0) {
errno = EINVAL;
efi_error("%s() called with %s file path", __func__,
filepath == NULL ? "NULL" : "empty");
return -1;
}
sz = efidp_make_generic(buf, size, EFIDP_MEDIA_TYPE, EFIDP_MEDIA_FILE,
req);
if (size && sz == req) {
memset(buf+4, 0, req-4);
utf8_to_ucs2(file->name, req-4, 1, lf);
}
if (sz < 0)
efi_error("efidp_make_generic failed");
return sz;
}
ssize_t PUBLIC
efidp_make_hd(uint8_t *buf, ssize_t size, uint32_t num, uint64_t part_start,
uint64_t part_size, uint8_t *signature, uint8_t format,
uint8_t signature_type)
{
efidp_hd *hd = (efidp_hd *)buf;
ssize_t sz;
ssize_t req = sizeof (*hd);
sz = efidp_make_generic(buf, size, EFIDP_MEDIA_TYPE, EFIDP_MEDIA_HD,
req);
if (size && sz == req) {
hd->partition_number = num;
hd->start = part_start;
hd->size = part_size;
if (signature)
memcpy(hd->signature, signature,
sizeof (hd->signature));
hd->format = format;
hd->signature_type = signature_type;
}
if (sz < 0)
efi_error("efidp_make_generic failed");
return sz;
}
// vim:fenc=utf-8:tw=75:noet
efivar-39/src/dp-message.c 0000664 0000000 0000000 00000056344 14556524316 0015572 0 ustar 00root root 0000000 0000000 // SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libefivar - library for the manipulation of EFI variables
* Copyright 2012-2015 Red Hat, Inc.
*/
#include "fix_coverity.h"
#include
#include
#include
#include
#include "efivar.h"
static ssize_t
format_ipv4_addr_helper(unsigned char *buf, size_t size, const char *dp_type,
const uint8_t *ipaddr, int32_t port)
{
ssize_t off = 0;
format(buf, size, off, dp_type, "%hhu.%hhu.%hhu.%hhu",
ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]);
if (port > 0)
format(buf, size, off, dp_type, ":%hu", (uint16_t)port);
return off;
}
static ssize_t
format_ipv6_addr_helper(unsigned char *buf, size_t size, const char *dp_type,
const uint8_t *ipaddr, int32_t port)
{
uint16_t *ip = (uint16_t *)ipaddr;
ssize_t off = 0;
format(buf, size, off, dp_type, "[");
// deciding how to print an ipv6 ip requires 2 passes, because
// RFC5952 says we have to use :: a) only once and b) to maximum effect.
int largest_zero_block_size = 0;
int largest_zero_block_offset = -1;
int this_zero_block_size = 0;
int this_zero_block_offset = -1;
int in_zero_block = 0;
int i;
for (i = 0; i < 8; i++) {
if (ip[i] != 0 && in_zero_block) {
if (this_zero_block_size > largest_zero_block_size) {
largest_zero_block_size = this_zero_block_size;
largest_zero_block_offset =
this_zero_block_offset;
this_zero_block_size = 0;
this_zero_block_offset = -1;
in_zero_block = 0;
}
}
if (ip[i] == 0) {
if (in_zero_block == 0) {
in_zero_block = 1;
this_zero_block_offset = i;
}
this_zero_block_size++;
}
}
if (this_zero_block_size > largest_zero_block_size) {
largest_zero_block_size = this_zero_block_size;
largest_zero_block_offset = this_zero_block_offset;
/*
* clang-analyzer hates these because they're the last use,
* and they don't believe in writing code so that bugs won't
* be introduced later...
*/
#if 0
this_zero_block_size = 0;
this_zero_block_offset = -1;
in_zero_block = 0;
#endif
}
if (largest_zero_block_size == 1)
largest_zero_block_offset = -1;
for (i = 0; i < 8; i++) {
if (largest_zero_block_offset == i) {
format(buf, size, off, dp_type, "::");
i += largest_zero_block_size -1;
continue;
} else if (i > 0) {
format(buf, size, off, dp_type, ":");
}
format(buf, size, off, dp_type, "%x", ip[i]);
}
format(buf, size, off, dp_type, "]");
if (port > 0)
format(buf, size, off, dp_type, ":%hu", (uint16_t)port);
return off;
}
#define format_ip_protocol(buf, size, off, dp_type, proto) \
({ \
switch(proto) { \
case 6: \
format(buf, size, off, dp_type, "TCP"); \
break; \
case 17: \
format(buf, size, off, dp_type, "UDP"); \
break; \
default: \
format(buf, size, off, dp_type, "%u", proto); \
break; \
} \
})
#define format_ipv4_addr(buf, size, off, addr, port) \
format_helper(format_ipv4_addr_helper, buf, size, off, \
"IPv4", addr, port)
#define format_ipv6_addr(buf, size, off, addr, port) \
format_helper(format_ipv6_addr_helper, buf, size, off, \
"IPv6", addr, port)
static ssize_t
format_ip_addr_helper(unsigned char *buf, size_t size,
const char *dp_type UNUSED,
int is_ipv6, const efi_ip_addr_t *addr)
{
ssize_t off = 0;
if (is_ipv6)
format_helper(format_ipv6_addr_helper, buf, size, off, "IPv6",
(const uint8_t *)&addr->v6, -1);
else
format_helper(format_ipv4_addr_helper, buf, size, off, "IPv4",
(const uint8_t *)&addr->v4, -1);
return off;
}
#define format_ip_addr(buf, size, off, dp_type, is_ipv6, addr) \
format_helper(format_ip_addr_helper, buf, size, off, \
dp_type, is_ipv6, addr)
static ssize_t
format_uart(unsigned char *buf, size_t size,
const char *dp_type UNUSED,
const_efidp dp)
{
uint32_t value;
ssize_t off = 0;
char *labels[] = {"None", "Hardware", "XonXoff", ""};
value = dp->uart_flow_control.flow_control_map;
if (value > 2) {
format(buf, size, off, "UartFlowControl",
"UartFlowControl(%d)", value);
return off;
}
format(buf, size, off, "UartFlowControl", "UartFlowControl(%s)",
labels[value]);
return off;
}
static ssize_t
format_sas(unsigned char *buf, size_t size,
const char *dp_type UNUSED,
const_efidp dp)
{
ssize_t off = 0;
const efidp_sas * const s = &dp->sas;
int more_info = 0;
int sassata = 0;
int location = 0;
int connect = 0;
int drive_bay = -1;
const char * const sassata_label[] = {"NoTopology", "SAS", "SATA"};
const char * const location_label[] = {"Internal", "External" };
const char * const connect_label[] = {"Direct", "Expanded" };
more_info = s->device_topology_info & EFIDP_SAS_TOPOLOGY_MASK;
if (more_info) {
sassata = (s->device_topology_info & EFIDP_SAS_DEVICE_MASK)
>> EFIDP_SAS_DEVICE_SHIFT;
if (sassata == EFIDP_SAS_DEVICE_SATA_EXTERNAL
|| sassata == EFIDP_SAS_DEVICE_SAS_EXTERNAL)
location = 1;
if (sassata == EFIDP_SAS_DEVICE_SAS_INTERNAL
|| sassata == EFIDP_SAS_DEVICE_SATA_INTERNAL)
sassata = 1;
else
sassata = 2;
connect = (s->device_topology_info & EFIDP_SAS_CONNECT_MASK)
>> EFIDP_SAS_CONNECT_SHIFT;
if (more_info == EFIDP_SAS_TOPOLOGY_NEXTBYTE)
drive_bay = s->drive_bay_id + 1;
}
format(buf, size, off, "SAS", "SAS(%"PRIx64",%"PRIx64",%"PRIx16",%s",
dp->subtype == EFIDP_MSG_SAS_EX ?
be64_to_cpu(s->sas_address) :
le64_to_cpu(s->sas_address),
dp->subtype == EFIDP_MSG_SAS_EX ?
be64_to_cpu(s->lun) :
le64_to_cpu(s->lun),
s->rtp, sassata_label[sassata]);
if (more_info) {
format(buf, size, off, "SAS", ",%s,%s",
location_label[location], connect_label[connect]);
}
if (more_info == 2 && drive_bay >= 0) {
format(buf, size, off, "SAS", ",%d", drive_bay);
}
format(buf, size, off, "SAS", ")");
return off;
}
#define class_helper(buf, size, off, label, dp) \
format(buf, size, off, label, \
"%s(0x%"PRIx16",0x%"PRIx16",%d,%d)", \
label, \
dp->usb_class.vendor_id, \
dp->usb_class.product_id, \
dp->usb_class.device_subclass, \
dp->usb_class.device_protocol)
static ssize_t
format_usb_class(unsigned char *buf, size_t size,
const char *dp_type UNUSED,
const_efidp dp)
{
ssize_t off = 0;
switch (dp->usb_class.device_class) {
case EFIDP_USB_CLASS_AUDIO:
class_helper(buf, size, off, "UsbAudio", dp);
break;
case EFIDP_USB_CLASS_CDC_CONTROL:
class_helper(buf, size, off, "UsbCDCControl", dp);
break;
case EFIDP_USB_CLASS_HID:
class_helper(buf, size, off, "UsbHID", dp);
break;
case EFIDP_USB_CLASS_IMAGE:
class_helper(buf, size, off, "UsbImage", dp);
break;
case EFIDP_USB_CLASS_PRINTER:
class_helper(buf, size, off, "UsbPrinter", dp);
break;
case EFIDP_USB_CLASS_MASS_STORAGE:
class_helper(buf, size, off, "UsbMassStorage", dp);
break;
case EFIDP_USB_CLASS_HUB:
class_helper(buf, size, off, "UsbHub", dp);
break;
case EFIDP_USB_CLASS_CDC_DATA:
class_helper(buf, size, off, "UsbCDCData", dp);
break;
case EFIDP_USB_CLASS_SMARTCARD:
class_helper(buf, size, off, "UsbSmartCard", dp);
break;
case EFIDP_USB_CLASS_VIDEO:
class_helper(buf, size, off, "UsbVideo", dp);
break;
case EFIDP_USB_CLASS_DIAGNOSTIC:
class_helper(buf, size, off, "UsbDiagnostic", dp);
break;
case EFIDP_USB_CLASS_WIRELESS:
class_helper(buf, size, off, "UsbWireless", dp);
break;
case EFIDP_USB_CLASS_254:
switch (dp->usb_class.device_subclass) {
case EFIDP_USB_SUBCLASS_FW_UPDATE:
format(buf, size, off, "UsbDeviceFirmwareUpdate",
"UsbDeviceFirmwareUpdate(0x%"PRIx16",0x%"PRIx16",%d)",
dp->usb_class.vendor_id,
dp->usb_class.product_id,
dp->usb_class.device_protocol);
break;
case EFIDP_USB_SUBCLASS_IRDA_BRIDGE:
format(buf, size, off, "UsbIrdaBridge",
"UsbIrdaBridge(0x%"PRIx16",0x%"PRIx16",%d)",
dp->usb_class.vendor_id,
dp->usb_class.product_id,
dp->usb_class.device_protocol);
break;
case EFIDP_USB_SUBCLASS_TEST_AND_MEASURE:
format(buf, size, off, "UsbTestAndMeasurement",
"UsbTestAndMeasurement(0x%"PRIx16",0x%"PRIx16",%d)",
dp->usb_class.vendor_id,
dp->usb_class.product_id,
dp->usb_class.device_protocol);
break;
}
break;
default:
format(buf, size, off, "UsbClass",
"UsbClass(%"PRIx16",%"PRIx16",%d,%d)",
dp->usb_class.vendor_id,
dp->usb_class.product_id,
dp->usb_class.device_subclass,
dp->usb_class.device_protocol);
break;
}
return off;
}
ssize_t
_format_message_dn(unsigned char *buf, size_t size, const_efidp dp)
{
ssize_t off = 0;
switch (dp->subtype) {
case EFIDP_MSG_ATAPI:
format(buf, size, off, "Ata", "Ata(%d,%d,%d)",
dp->atapi.primary, dp->atapi.slave,
dp->atapi.lun);
break;
case EFIDP_MSG_SCSI:
format(buf, size, off, "SCSI", "SCSI(%d,%d)",
dp->scsi.target, dp->scsi.lun);
break;
case EFIDP_MSG_FIBRECHANNEL:
format(buf, size, off, "Fibre", "Fibre(%"PRIx64",%"PRIx64")",
le64_to_cpu(dp->fc.wwn),
le64_to_cpu(dp->fc.lun));
break;
case EFIDP_MSG_FIBRECHANNELEX:
format(buf, size, off, "Fibre", "Fibre(%"PRIx64",%"PRIx64")",
be64_to_cpu(dp->fc.wwn),
be64_to_cpu(dp->fc.lun));
break;
case EFIDP_MSG_1394:
format(buf, size, off, "I1394", "I1394(0x%"PRIx64")",
dp->firewire.guid);
break;
case EFIDP_MSG_USB:
format(buf, size, off, "USB", "USB(%d,%d)",
dp->usb.parent_port, dp->usb.interface);
break;
case EFIDP_MSG_I2O:
format(buf, size, off, "I2O", "I2O(%d)", dp->i2o.target);
break;
case EFIDP_MSG_INFINIBAND:
format(buf, size, off, "Infiniband",
"Infiniband(%08x,%"PRIx64"%"PRIx64",%"PRIx64",%"PRIu64",%"PRIu64")",
dp->infiniband.resource_flags,
dp->infiniband.port_gid[1],
dp->infiniband.port_gid[0],
dp->infiniband.ioc_guid,
dp->infiniband.target_port_id,
dp->infiniband.device_id);
break;
case EFIDP_MSG_MAC_ADDR:
format(buf, size, off, "MAC", "MAC(");
format_hex(buf, size, off, "MAC", dp->mac_addr.mac_addr,
dp->mac_addr.if_type < 2 ? 6
: sizeof(dp->mac_addr.mac_addr));
format(buf, size, off, "MAC", ",%d)", dp->mac_addr.if_type);
break;
case EFIDP_MSG_IPv4: {
efidp_ipv4_addr const *a = &dp->ipv4_addr;
format(buf, size, off, "IPv4", "IPv4(");
format_ipv4_addr(buf, size, off,
a->remote_ipv4_addr, a->remote_port);
format(buf, size, off, "IPv4", ",");
format_ip_protocol(buf, size, off, "IPv4", a->protocol);
format(buf, size, off, "IPv4", ",%s,", a->static_ip_addr
?"Static" :"DHCP");
format_ipv4_addr(buf, size, off,
a->local_ipv4_addr, a->local_port);
format(buf, size, off, "IPv4", ",");
format_ipv4_addr(buf, size, off, a->gateway, 0);
format(buf, size, off, "IPv4", ",");
format_ipv4_addr(buf, size, off, a->netmask, 0);
format(buf, size, off, "IPv4", ")");
break;
}
case EFIDP_MSG_VENDOR: {
struct {
efi_guid_t guid;
char label[40];
ssize_t (*formatter)(unsigned char *buf, size_t size,
const char *dp_type UNUSED,
const_efidp dp);
} subtypes[] = {
{ .guid = EFIDP_PC_ANSI_GUID,
.label = "VenPcAnsi" },
{ .guid = EFIDP_VT_100_GUID,
.label = "VenVt100" },
{ .guid = EFIDP_VT_100_PLUS_GUID,
.label = "VenVt100Plus" },
{ .guid = EFIDP_VT_UTF8_GUID,
.label = "VenUtf8" },
{ .guid = EFIDP_MSG_DEBUGPORT_GUID,
.label = "DebugPort" },
{ .guid = EFIDP_MSG_UART_GUID,
.label = "",
.formatter = format_uart },
{ .guid = EFIDP_MSG_SAS_GUID,
.label = "",
.formatter = format_sas },
{ .guid = efi_guid_empty,
.label = "" }
};
char *label = NULL;
ssize_t (*formatter)(unsigned char *buf, size_t size,
const char *dp_type UNUSED,
const_efidp dp) = NULL;
for (int i = 0; !efi_guid_is_zero(&subtypes[i].guid); i++) {
if (efi_guid_cmp(&subtypes[i].guid,
&dp->msg_vendor.vendor_guid))
continue;
if (subtypes[i].label[0])
label = subtypes[i].label;
formatter = subtypes[i].formatter;
break;
}
if (!label && !formatter) {
format_vendor(buf, size, off, "VenMsg", dp);
break;
} else if (!label && formatter) {
format_helper(formatter, buf, size, off, "VenMsg", dp);
break;
}
format(buf, size, off, label, "%s(", label);
if (efidp_node_size(dp) >
(ssize_t)(sizeof (efidp_header)
+ sizeof (efi_guid_t))) {
format_hex(buf, size, off, label,
dp->msg_vendor.vendor_data,
efidp_node_size(dp)
- sizeof (efidp_header)
- sizeof (efi_guid_t));
}
format(buf, size, off, label, ")");
break;
}
case EFIDP_MSG_IPv6: {
efidp_ipv6_addr const *a = &dp->ipv6_addr;
format(buf, size, off, "IPv6", "IPv6(");
format_ipv6_addr(buf, size, off, a->remote_ipv6_addr,
a->remote_port);
format(buf, size, off, "IPv6",",");
format_ip_protocol(buf, size, off, "IPv6", a->protocol);
format(buf, size, off, "IPv6",",");
switch (a->ip_addr_origin) {
case EFIDP_IPv6_ORIGIN_STATIC:
format(buf, size, off, "IPv6", "Static,");
break;
case EFIDP_IPv6_ORIGIN_AUTOCONF:
format(buf, size, off, "IPv6",
"StatelessAutoConfigure,");
break;
case EFIDP_IPv6_ORIGIN_STATEFUL:
format(buf, size, off, "IPv6",
"StatefulAutoConfigure,");
break;
default:
format(buf, size, off, "IPv6",
"0x%hx,", a->ip_addr_origin);
break;
}
format_ipv6_addr(buf, size, off, a->local_ipv6_addr,
a->local_port);
format(buf, size, off, "IPv6",",");
format_ipv6_addr(buf, size, off, a->gateway_ipv6_addr, 0);
format(buf, size, off, "IPv6",",%u)", a->prefix_length);
break;
}
case EFIDP_MSG_UART: {
int parity = dp->uart.parity;
char parity_label[] = "DNEOMS";
int stop_bits = dp->uart.stop_bits;
char *sb_label[] = {"D", "1", "1.5", "2"};
format(buf, size, off, "Uart", "Uart(%"PRIu64",%d,",
dp->uart.baud_rate ? dp->uart.baud_rate : 115200,
dp->uart.data_bits ? dp->uart.data_bits : 8);
format(buf, size, off, "Uart",
parity > 5 ? "%d," : "%c,",
parity > 5 ? parity : parity_label[parity]);
if (stop_bits > 3)
format(buf, size, off, "Uart", "%d)", stop_bits);
else
format(buf, size, off, "Uart", "%s)",
sb_label[stop_bits]);
break;
}
case EFIDP_MSG_USB_CLASS:
format_helper(format_usb_class, buf, size, off, "UsbClass", dp);
break;
case EFIDP_MSG_USB_WWID: {
size_t limit = (efidp_node_size(dp)
- offsetof(efidp_usb_wwid, serial_number))
/ 2;
format(buf, size, off, "UsbWwid",
"UsbWwid(%"PRIx16",%"PRIx16",%d,",
dp->usb_wwid.vendor_id, dp->usb_wwid.product_id,
dp->usb_wwid.interface);
format_ucs2(buf, size, off, "UsbWwid",
dp->usb_wwid.serial_number, limit);
format(buf, size, off, "UsbWwid", ")");
break;
}
case EFIDP_MSG_LUN:
format(buf, size, off, "Unit", "Unit(%d)", dp->lun.lun);
break;
case EFIDP_MSG_SATA:
format(buf, size, off, "Sata", "Sata(%d,%d,%d)",
dp->sata.hba_port, dp->sata.port_multiplier_port,
dp->sata.lun);
break;
case EFIDP_MSG_ISCSI: {
ssize_t sz = efidp_node_size(dp)
- offsetof(efidp_iscsi, target_name);
if (sz < 0) {
efi_error("bad DP node size");
return -1;
}
if (sz > EFIDP_ISCSI_MAX_TARGET_NAME_LEN)
sz = EFIDP_ISCSI_MAX_TARGET_NAME_LEN;
char target_name[sz + 1];
memcpy(target_name, dp->iscsi.target_name, sz);
target_name[sz] = '\0';
uint64_t lun;
memcpy(&lun, dp->iscsi.lun, sizeof (lun));
format(buf, size, off, "iSCSI",
"iSCSI(%s,%d,0x%"PRIx64",%s,%s,%s,%s)",
target_name, dp->iscsi.tpgt,
be64_to_cpu(lun),
(dp->iscsi.options >> EFIDP_ISCSI_HEADER_DIGEST_SHIFT) & EFIDP_ISCSI_HEADER_CRC32 ? "CRC32" : "None",
(dp->iscsi.options >> EFIDP_ISCSI_DATA_DIGEST_SHIFT) & EFIDP_ISCSI_DATA_CRC32 ? "CRC32" : "None",
(dp->iscsi.options >> EFIDP_ISCSI_AUTH_SHIFT) & EFIDP_ISCSI_AUTH_NONE ? "None" : \
(dp->iscsi.options >> EFIDP_ISCSI_CHAP_SHIFT) & EFIDP_ISCSI_CHAP_UNI ? "CHAP_UNI" : "CHAP_BI",
dp->iscsi.protocol == 0 ? "TCP" : "Unknown");
break;
}
case EFIDP_MSG_VLAN:
format(buf, size, off, "Vlan", "Vlan(%d)", dp->vlan.vlan_id);
break;
case EFIDP_MSG_SAS_EX:
format_sas(buf, size, NULL, dp);
break;
case EFIDP_MSG_NVME:
format(buf, size, off, "NVMe", "NVMe(0x%"PRIx32","
"%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X)",
dp->nvme.namespace_id, dp->nvme.ieee_eui_64[0],
dp->nvme.ieee_eui_64[1], dp->nvme.ieee_eui_64[2],
dp->nvme.ieee_eui_64[3], dp->nvme.ieee_eui_64[4],
dp->nvme.ieee_eui_64[5], dp->nvme.ieee_eui_64[6],
dp->nvme.ieee_eui_64[7]);
break;
case EFIDP_MSG_URI: {
ssize_t sz = efidp_node_size(dp) - offsetof(efidp_uri, uri);
if (sz < 0) {
efi_error("bad DP node size");
return -1;
}
char uri[sz + 1];
memcpy(uri, dp->uri.uri, sz);
uri[sz] = '\0';
format(buf, size, off, "Uri", "Uri(%s)", uri);
break;
}
case EFIDP_MSG_UFS:
format(buf, size, off, "UFS", "UFS(%d,0x%02x)",
dp->ufs.target_id, dp->ufs.lun);
break;
case EFIDP_MSG_SD:
format(buf, size, off, "SD", "SD(%d)", dp->sd.slot_number);
break;
case EFIDP_MSG_BT:
format(buf, size, off, "Bluetooth", "Bluetooth(");
format_hex_separated(buf, size, off, "Bluetooth", ":", 1,
dp->bt.addr, sizeof(dp->bt.addr));
format(buf, size, off, "Bluetooth", ")");
break;
case EFIDP_MSG_WIFI:
format(buf, size, off, "Wi-Fi", "Wi-Fi(");
format_hex_separated(buf, size, off, "Wi-Fi", ":", 1,
dp->wifi.ssid, sizeof(dp->wifi.ssid));
format(buf, size, off, "Wi-Fi", ")");
break;
case EFIDP_MSG_EMMC:
format(buf, size, off, "eMMC", "eMMC(%d)", dp->emmc.slot);
break;
case EFIDP_MSG_BTLE:
format(buf, size, off, "BluetoothLE", "BluetoothLE(");
format_hex_separated(buf, size, off, "BluetoothLE", ":", 1,
dp->btle.addr, sizeof(dp->btle.addr));
format(buf, size, off, "BluetoothLE", ",%d)",
dp->btle.addr_type);
break;
case EFIDP_MSG_DNS: {
int end = (efidp_node_size(dp)
- sizeof(dp->dns.header)
- sizeof(dp->dns.is_ipv6)
) / sizeof(efi_ip_addr_t);
format(buf, size, off, "Dns", "Dns(");
for (int i=0; i < end; i++) {
efi_ip_addr_t addr;
memcpy(&addr, &dp->dns.addrs[i], sizeof(addr));
if (i != 0)
format(buf, size, off, "Dns", ",");
format_ip_addr(buf, size, off, "Dns",
dp->dns.is_ipv6, &addr);
}
format(buf, size, off, "Dns", ")");
break;
}
case EFIDP_MSG_NVDIMM:
format(buf, size, off, "NVDIMM", "NVDIMM(");
format_guid(buf, size, off, "NVDIMM", &dp->nvdimm.uuid);
format(buf, size, off, "NVDIMM", ")");
break;
default:
format(buf, size, off, "Msg", "Msg(%d,", dp->subtype);
format_hex(buf, size, off, "Msg", (uint8_t *)dp+4,
efidp_node_size(dp)-4);
format(buf, size, off, "Msg", ")");
break;
}
return off;
}
ssize_t PUBLIC
efidp_make_mac_addr(uint8_t *buf, ssize_t size, uint8_t if_type,
const uint8_t * const mac_addr, ssize_t mac_addr_size)
{
efidp_mac_addr *mac = (efidp_mac_addr *)buf;
ssize_t sz = efidp_make_generic(buf, size, EFIDP_MESSAGE_TYPE,
EFIDP_MSG_MAC_ADDR, sizeof (*mac));
ssize_t req = sizeof (*mac);
if (size && sz == req) {
mac->if_type = if_type;
memcpy(mac->mac_addr, mac_addr,
mac_addr_size > 32 ? 32 : mac_addr_size);
}
if (sz < 0)
efi_error("efidp_make_generic failed");
return sz;
}
ssize_t PUBLIC
efidp_make_ipv4(uint8_t *buf, ssize_t size, uint32_t local, uint32_t remote,
uint32_t gateway, uint32_t netmask,
uint16_t local_port, uint16_t remote_port,
uint16_t protocol, int is_static)
{
efidp_ipv4_addr *ipv4 = (efidp_ipv4_addr *)buf;
ssize_t sz = efidp_make_generic(buf, size, EFIDP_MESSAGE_TYPE,
EFIDP_MSG_IPv4, sizeof (*ipv4));
ssize_t req = sizeof (*ipv4);
if (size && sz == req) {
*((uint32_t *)ipv4->local_ipv4_addr) = htonl(local);
*((uint32_t *)ipv4->remote_ipv4_addr) = htonl(remote);
ipv4->local_port = htons(local_port);
ipv4->remote_port = htons(remote_port);
ipv4->protocol = htons(protocol);
ipv4->static_ip_addr = 0;
if (is_static)
ipv4->static_ip_addr = 1;
*((uint32_t *)ipv4->gateway) = htonl(gateway);
*((uint32_t *)ipv4->netmask) = htonl(netmask);
}
if (sz < 0)
efi_error("efidp_make_generic failed");
return sz;
}
ssize_t PUBLIC
efidp_make_scsi(uint8_t *buf, ssize_t size, uint16_t target, uint16_t lun)
{
efidp_scsi *scsi = (efidp_scsi *)buf;
ssize_t req = sizeof (*scsi);
ssize_t sz = efidp_make_generic(buf, size, EFIDP_MESSAGE_TYPE,
EFIDP_MSG_SCSI, sizeof (*scsi));
if (size && sz == req) {
scsi->target = target;
scsi->lun = lun;
}
if (sz < 0)
efi_error("efidp_make_generic failed");
return sz;
}
ssize_t PUBLIC
efidp_make_nvme(uint8_t *buf, ssize_t size, uint32_t namespace_id,
uint8_t *ieee_eui_64)
{
efidp_nvme *nvme = (efidp_nvme *)buf;
ssize_t req = sizeof (*nvme);
ssize_t sz;
sz = efidp_make_generic(buf, size, EFIDP_MESSAGE_TYPE,
EFIDP_MSG_NVME, sizeof (*nvme));
if (size && sz == req) {
nvme->namespace_id = namespace_id;
if (ieee_eui_64)
memcpy(nvme->ieee_eui_64, ieee_eui_64,
sizeof (nvme->ieee_eui_64));
else
memset(nvme->ieee_eui_64, '\0',
sizeof (nvme->ieee_eui_64));
}
if (sz < 0)
efi_error("efidp_make_generic failed");
return sz;
}
ssize_t PUBLIC
efidp_make_sata(uint8_t *buf, ssize_t size, uint16_t hba_port,
int16_t port_multiplier_port, uint16_t lun)
{
efidp_sata *sata = (efidp_sata *)buf;
ssize_t req = sizeof (*sata);
ssize_t sz;
sz = efidp_make_generic(buf, size, EFIDP_MESSAGE_TYPE,
EFIDP_MSG_SATA, sizeof (*sata));
if (size && sz == req) {
sata->hba_port = hba_port;
sata->port_multiplier_port = port_multiplier_port;
sata->lun = lun;
}
if (sz < 0)
efi_error("efidp_make_generic failed");
return sz;
}
ssize_t PUBLIC
efidp_make_atapi(uint8_t *buf, ssize_t size, uint16_t primary,
uint16_t slave, uint16_t lun)
{
efidp_atapi *atapi = (efidp_atapi *)buf;
ssize_t req = sizeof (*atapi);
ssize_t sz;
sz = efidp_make_generic(buf, size, EFIDP_MESSAGE_TYPE,
EFIDP_MSG_ATAPI, sizeof (*atapi));
if (size && sz == req) {
atapi->primary = primary;
atapi->slave = slave;
atapi->lun = lun;
}
if (sz < 0)
efi_error("efidp_make_generic failed");
return sz;
}
ssize_t PUBLIC
efidp_make_sas(uint8_t *buf, ssize_t size, uint64_t sas_address)
{
efidp_sas *sas = (efidp_sas *)buf;
ssize_t req = sizeof (*sas);
ssize_t sz;
sz = efidp_make_generic(buf, size, EFIDP_MESSAGE_TYPE,
EFIDP_MSG_VENDOR, sizeof (*sas));
if (size && sz == req) {
sas->vendor_guid = EFIDP_MSG_SAS_GUID;
sas->reserved = 0;
sas->sas_address = sas_address;
sas->lun = 0;
sas->device_topology_info = 0;
sas->drive_bay_id = 0;
sas->rtp = 0;
}
if (sz < 0)
efi_error("efidp_make_generic failed");
return sz;
}
ssize_t PUBLIC
efidp_make_nvdimm(uint8_t *buf, ssize_t size, efi_guid_t *uuid)
{
efidp_nvdimm *nvdimm = (efidp_nvdimm *)buf;
ssize_t req = sizeof (*nvdimm);
ssize_t sz;
sz = efidp_make_generic(buf, size, EFIDP_MESSAGE_TYPE,
EFIDP_MSG_NVDIMM, sizeof (*nvdimm));
if (size && sz == req) {
memcpy(&nvdimm->uuid, uuid, sizeof(*uuid));
}
if (sz < 0)
efi_error("efidp_make_generic failed");
return sz;
}
ssize_t PUBLIC
efidp_make_emmc(uint8_t *buf, ssize_t size, uint32_t slot_id)
{
efidp_emmc *emmc = (efidp_emmc *)buf;
ssize_t req = sizeof (*emmc);
ssize_t sz;
sz = efidp_make_generic(buf, size, EFIDP_MESSAGE_TYPE,
EFIDP_MSG_NVME, sizeof (*emmc));
if (size && sz == req)
emmc->slot = slot_id;
if (sz < 0)
efi_error("efidp_make_generic failed");
return sz;
}
// vim:fenc=utf-8:tw=75:noet
efivar-39/src/dp.c 0000664 0000000 0000000 00000021433 14556524316 0014137 0 ustar 00root root 0000000 0000000 // SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libefivar - library for the manipulation of EFI variables
* Copyright 2012-2015 Red Hat, Inc.
*/
#include "fix_coverity.h"
#include
#include
#include
#include "efivar.h"
static const efidp_header end_entire = {
.type = EFIDP_END_TYPE,
.subtype = EFIDP_END_ENTIRE,
.length = 4
};
static inline void *
efidp_data_address(const_efidp dp)
{
if (dp->length <= 4) {
errno = ENOSPC;
efi_error("DP was smaller than DP header");
return NULL;
}
return (void *)((uint8_t *)dp + sizeof (dp));
}
int PUBLIC
efidp_set_node_data(const_efidp dn, void *buf, size_t bufsize)
{
if (dn->length < 4 || bufsize > (size_t)dn->length - 4) {
errno = ENOSPC;
efi_error("DP was smaller than DP header");
return -1;
}
void *data = efidp_data_address(dn);
if (!data) {
efi_error("efidp_data_address failed");
return -1;
}
memcpy(data, buf, bufsize);
return 0;
}
static inline int
efidp_duplicate_extra(const_efidp dp, efidp *out, size_t extra)
{
ssize_t sz;
ssize_t plus;
efidp new;
sz = efidp_size(dp);
if (sz < 0) {
efi_error("efidp_size(dp) returned error");
return sz;
}
if (ADD(sz, extra, &plus)) {
errno = EOVERFLOW;
efi_error("arithmetic overflow computing allocation size");
return -1;
}
if (plus < (ssize_t)sizeof(efidp_header)) {
errno = EINVAL;
efi_error("allocation for new device path is smaller than device path header.");
return -1;
}
new = calloc(1, plus);
if (!new) {
efi_error("allocation failed");
return -1;
}
memcpy(new, dp, sz);
*out = new;
return 0;
}
int PUBLIC
efidp_duplicate_path(const_efidp dp, efidp *out)
{
int rc;
rc = efidp_duplicate_extra(dp, out, 0);
if (rc < 0)
efi_error("efi_duplicate_extra(dp, out, 0) returned error");
return rc;
}
int PUBLIC
efidp_append_path(const_efidp dp0, const_efidp dp1, efidp *out)
{
ssize_t lsz, rsz, newsz = 0;
const_efidp le;
int rc;
if (!dp0 && !dp1) {
rc = efidp_duplicate_path((const_efidp)&end_entire, out);
if (rc < 0)
efi_error("efidp_duplicate_path failed");
return rc;
}
if (dp0 && !dp1) {
rc = efidp_duplicate_path(dp0, out);
if (rc < 0)
efi_error("efidp_duplicate_path failed");
return rc;
}
if (!dp0 && dp1) {
rc = efidp_duplicate_path(dp1, out);
if (rc < 0)
efi_error("efidp_duplicate_path failed");
return rc;
}
lsz = efidp_size(dp0);
if (lsz < 0) {
efi_error("efidp_size(dp0) returned error");
return -1;
}
rsz = efidp_size(dp1);
if (rsz < 0) {
efi_error("efidp_size(dp1) returned error");
return -1;
}
le = dp0;
while (1) {
if (efidp_type(le) == EFIDP_END_TYPE &&
efidp_subtype(le) == EFIDP_END_ENTIRE) {
ssize_t lesz = efidp_size(le);
lsz -= lesz;
break;
}
rc = efidp_get_next_end(le, &le);
if (rc < 0) {
efi_error("efidp_get_next_end() returned error");
return -1;
}
}
efidp new;
if (ADD(lsz, rsz, &newsz)) {
errno = EOVERFLOW;
efi_error("arithmetic overflow computing allocation size");
return -1;
}
if (newsz < (ssize_t)sizeof(efidp_header)) {
errno = EINVAL;
efi_error("allocation for new device path is smaller than device path header.");
return -1;
}
new = malloc(newsz);
if (!new) {
efi_error("allocation failed");
return -1;
}
*out = new;
memcpy(new, dp0, lsz);
memcpy((uint8_t *)new + lsz, dp1, rsz);
return 0;
}
int PUBLIC
efidp_append_node(const_efidp dp, const_efidp dn, efidp *out)
{
ssize_t lsz = 0, rsz = 0, newsz;
int rc;
if (dp) {
lsz = efidp_size(dp);
if (lsz < 0) {
efi_error("efidp_size(dp) returned error");
return -1;
}
const_efidp le;
le = dp;
while (1) {
if (efidp_type(le) == EFIDP_END_TYPE &&
efidp_subtype(le) == EFIDP_END_ENTIRE) {
ssize_t lesz = efidp_size(le);
lsz -= lesz;
break;
}
rc = efidp_get_next_end(le, &le);
if (rc < 0) {
efi_error("efidp_get_next_end() returned error");
return -1;
}
}
}
if (dn) {
rsz = efidp_node_size(dn);
if (rsz < 0) {
efi_error("efidp_size(dn) returned error");
return -1;
}
}
if (ADD(lsz, rsz, &newsz) ||
ADD(newsz, sizeof(end_entire), &newsz)) {
errno = EOVERFLOW;
efi_error("arithmetic overflow computing allocation size");
return -1;
}
efidp new = malloc(newsz);
if (!new) {
efi_error("allocation failed");
return -1;
}
*out = new;
if (dp)
memcpy(new, dp, lsz);
if (dn)
memcpy((uint8_t *)new + lsz, dn, rsz);
memcpy((uint8_t *)new + lsz + rsz, &end_entire, sizeof (end_entire));
return 0;
}
int PUBLIC
efidp_append_instance(const_efidp dp, const_efidp dpi, efidp *out)
{
ssize_t lsz, rsz;
int rc;
if (!dp && !dpi) {
errno = EINVAL;
return -1;
}
if (!dp && dpi)
return efidp_duplicate_path(dpi, out);
lsz = efidp_size(dp);
if (lsz < 0)
return -1;
rsz = efidp_node_size(dpi);
if (rsz < 0)
return -1;
efidp le;
le = (efidp)dp;
while (1) {
if (le->type == EFIDP_END_TYPE &&
le->subtype == EFIDP_END_ENTIRE)
break;
rc = efidp_get_next_end(le, (const_efidp *)&le);
if (rc < 0)
return -1;
}
le->subtype = EFIDP_END_INSTANCE;
efidp new = malloc(lsz + rsz + sizeof (end_entire));
if (!new)
return -1;
*out = new;
memcpy(new, dp, lsz);
memcpy((uint8_t *)new + lsz, dpi, rsz);
return 0;
}
ssize_t PUBLIC
efidp_format_device_path(unsigned char *buf, size_t size, const_efidp dp,
ssize_t limit)
{
ssize_t off = 0;
int first = 1;
if (!dp)
return -1;
if (buf && size)
memset(buf, 0, size);
while (limit) {
if (limit >= 0 && (limit < 4 || efidp_node_size(dp) > limit)) {
if (off)
return off;
else
return -1;
}
if (first) {
first = 0;
} else {
if (dp->type == EFIDP_END_TYPE) {
if (dp->type == EFIDP_END_INSTANCE) {
format(buf, size, off, "\b", ",");
} else {
return off+1;
}
} else {
format(buf, size, off, "\b", "/");
}
}
switch (dp->type) {
case EFIDP_HARDWARE_TYPE:
format_hw_dn(buf, size, off, dp);
break;
case EFIDP_ACPI_TYPE:
format_acpi_dn(buf, size, off, dp);
break;
case EFIDP_MESSAGE_TYPE:
format_message_dn(buf, size, off, dp);
break;
case EFIDP_MEDIA_TYPE:
format_media_dn(buf, size, off, dp);
break;
case EFIDP_BIOS_BOOT_TYPE: {
char *types[] = {"", "Floppy", "HD", "CDROM", "PCMCIA",
"USB", "Network", "" };
if (dp->subtype != EFIDP_BIOS_BOOT) {
format(buf, size, off, "BbsPath",
"BbsPath(%d,", dp->subtype);
format_hex(buf, size, off, "BbsPath",
(uint8_t *)dp+4,
efidp_node_size(dp)-4);
format(buf, size, off, "BbsPath", ")");
break;
}
if (dp->bios_boot.device_type > 0 &&
dp->bios_boot.device_type < 7) {
format(buf, size, off, "BBS",
"BBS(%s,%s,0x%"PRIx32")",
types[dp->bios_boot.device_type],
dp->bios_boot.description,
dp->bios_boot.status);
} else {
format(buf, size, off, "BBS",
"BBS(%d,%s,0x%"PRIx32")",
dp->bios_boot.device_type,
dp->bios_boot.description,
dp->bios_boot.status);
}
break;
}
case EFIDP_END_TYPE:
if (dp->subtype == EFIDP_END_INSTANCE) {
format(buf, size, off, "End", ",");
break;
}
break;
default:
format(buf, size, off, "Path",
"Path(%d,%d,", dp->type, dp->subtype);
format_hex(buf, size, off, "Path", (uint8_t *)dp + 4,
efidp_node_size(dp) - 4);
format(buf, size, off, "Path", ")");
break;
}
if (limit)
limit -= efidp_node_size(dp);
int rc = efidp_next_node(dp, &dp);
if (rc < 0) {
efi_error("could not format DP");
return rc;
}
}
return off+1;
}
ssize_t PUBLIC
efidp_parse_device_node(unsigned char *path UNUSED,
efidp out UNUSED, size_t size UNUSED)
{
efi_error("not implented");
errno = -ENOSYS;
return -1;
}
ssize_t PUBLIC
efidp_parse_device_path(unsigned char *path UNUSED, efidp out UNUSED,
size_t size UNUSED)
{
efi_error("not implented");
errno = -ENOSYS;
return -1;
}
ssize_t PUBLIC
efidp_make_vendor(uint8_t *buf, ssize_t size, uint8_t type, uint8_t subtype,
efi_guid_t vendor_guid, void *data, size_t data_size)
{
efidp_hw_vendor *vend = (efidp_hw_vendor *)buf;
ssize_t sz;
ssize_t req = sizeof (*vend) + data_size;
sz = efidp_make_generic(buf, size, type, subtype, req);
if (size && sz == req) {
vend->vendor_guid = vendor_guid;
memcpy(vend->vendor_data, data, data_size);
}
return sz;
}
ssize_t PUBLIC
efidp_make_generic(uint8_t *buf, ssize_t size, uint8_t type, uint8_t subtype,
ssize_t total_size)
{
efidp_header *head = (efidp_header *)buf;
if (!size)
return total_size;
if (!buf) {
errno = EINVAL;
efi_error("%s was called with nonzero size and NULL buffer",
__func__);
return -1;
}
if (size < total_size) {
errno = ENOSPC;
efi_error("total size is bigger than size limit");
return -1;
}
head->type = type;
head->subtype = subtype;
head->length = total_size;
return head->length;
}
// vim:fenc=utf-8:tw=75:noet
efivar-39/src/dp.h 0000664 0000000 0000000 00000012641 14556524316 0014145 0 ustar 00root root 0000000 0000000 // SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libefivar - library for the manipulation of EFI variables
* Copyright 2012-2015 Red Hat, Inc.
*/
#ifndef _EFIVAR_INTERNAL_DP_H
#define _EFIVAR_INTERNAL_DP_H
#include
#include
#include
#include
#include "ucs2.h"
#define format(buf, size, off, dp_type, fmt, args...) ({ \
ssize_t _insize = 0; \
void *_inbuf = NULL; \
if ((buf) != NULL && (size) > 0) { \
_inbuf = (buf) + (off); \
_insize = (size) - (off); \
} \
if ((off) >= 0 && \
((buf == NULL && _insize == 0) || \
(buf != NULL && _insize >= 0))) { \
ssize_t _x = 0; \
_x = snprintf(_inbuf, _insize, fmt, ## args); \
if (_x < 0) { \
efi_error( \
"could not build %s DP string", \
(dp_type)); \
return _x; \
} \
(off) += _x; \
} \
off; \
})
#define format_helper(fn, buf, size, off, dp_type, args...) ({ \
ssize_t _x; \
_x = (fn)(((buf)+(off)), \
((size)?((size)-(off)):0), dp_type, ## args); \
if (_x < 0) \
efi_error("could not build %s DP string", \
dp_type); \
(off) += _x; \
})
#define onstack(buf, len) ({ \
char *__newbuf = alloca(len); \
memcpy(__newbuf, buf, len); \
free(buf); \
(void *)__newbuf; \
})
#define format_guid(buf, size, off, dp_type, guid) ({ \
int _rc; \
char *_guidstr = NULL; \
efi_guid_t _guid; \
const efi_guid_t * const _guid_p = &_guid; \
\
memmove(&_guid, guid, sizeof(_guid)); \
_rc = efi_guid_to_str(_guid_p, &_guidstr); \
if (_rc < 0) { \
efi_error("could not build %s GUID DP string", \
dp_type); \
} else { \
_guidstr = onstack(_guidstr, \
strlen(_guidstr)+1); \
_rc = format(buf, size, off, dp_type, "%s", \
_guidstr); \
} \
_rc; \
})
static inline ssize_t UNUSED
format_hex_helper(unsigned char *buf, size_t size, const char *dp_type,
char *separator, int stride, const void * const addr,
const size_t len)
{
ssize_t off = 0;
for (size_t i = 0; i < len; i++) {
if (i && separator && stride > 0 && i % stride == 0)
format(buf, size, off, dp_type, "%s", separator);
format(buf, size, off, dp_type, "%02x",
*((const unsigned char * const )addr+i));
}
return off;
}
#define format_hex(buf, size, off, dp_type, addr, len) \
format_helper(format_hex_helper, buf, size, off, dp_type, "", 0, \
addr, len)
#define format_hex_separated(buf, size, off, dp_type, sep, stride, addr, len) \
format_helper(format_hex_helper, buf, size, off, dp_type, sep, stride, \
addr, len)
static inline ssize_t UNUSED
format_vendor_helper(unsigned char *buf, size_t size, char *label,
const_efidp dp)
{
ssize_t off = 0;
ssize_t bytes = efidp_node_size(dp)
- sizeof (efidp_header)
- sizeof (efi_guid_t);
format(buf, size, off, label, "%s(", label);
format_guid(buf, size, off, label, &dp->hw_vendor.vendor_guid);
if (bytes) {
format(buf, size, off, label, ",");
format_hex(buf, size, off, label, dp->hw_vendor.vendor_data,
bytes);
}
format(buf, size, off, label, ")");
return off;
}
#define format_vendor(buf, size, off, label, dp) \
format_helper(format_vendor_helper, buf, size, off, label, dp)
#define format_ucs2(buf, size, off, dp_type, str, len) ({ \
uint16_t *_ucs2buf; \
uint32_t _ucs2size = sizeof(uint16_t) * len; \
_ucs2buf = alloca(_ucs2size); \
if (_ucs2buf == NULL || _ucs2size < sizeof(uint16_t)) \
return -1; \
memset(_ucs2buf, '\0', _ucs2size); \
memcpy(_ucs2buf, str, _ucs2size - sizeof(uint16_t)); \
unsigned char *_asciibuf; \
_asciibuf = ucs2_to_utf8(_ucs2buf, (len) - 1); \
if (_asciibuf == NULL) \
return -1; \
_asciibuf = onstack(_asciibuf, (len)); \
format(buf, size, off, dp_type, "%s", _asciibuf); \
})
#define format_array(buf, size, off, dp_type, fmt, type, addr, len) ({ \
for (size_t _i = 0; _i < len; _i++) { \
if (_i != 0) \
format(buf, size, off, dp_type, ","); \
format(buf, size, off, dp_type, fmt, \
((type *)addr)[_i]); \
} \
off; \
})
extern ssize_t _format_hw_dn(unsigned char *buf, size_t size, const_efidp dp);
extern ssize_t _format_acpi_dn(unsigned char *buf, size_t size, const_efidp dp);
extern ssize_t _format_message_dn(unsigned char *buf, size_t size, const_efidp dp);
extern ssize_t _format_media_dn(unsigned char *buf, size_t size, const_efidp dp);
extern ssize_t _format_bios_boot_dn(unsigned char *buf, size_t size, const_efidp dp);
#define format_helper_2(name, buf, size, off, dp) ({ \
ssize_t _sz; \
_sz = name(((buf)+(off)), \
((size)?((size)-(off)):0), \
(dp)); \
if (_sz < 0) { \
efi_error("%s failed", #name); \
return -1; \
} \
(off) += _sz; \
})
#define format_hw_dn(buf, size, off, dp) \
format_helper_2(_format_hw_dn, buf, size, off, dp)
#define format_acpi_dn(buf, size, off, dp) \
format_helper_2(_format_acpi_dn, buf, size, off, dp)
#define format_message_dn(buf, size, off, dp) \
format_helper_2(_format_message_dn, buf, size, off, dp)
#define format_media_dn(buf, size, off, dp) \
format_helper_2(_format_media_dn, buf, size, off, dp)
#define format_bios_boot_dn(buf, size, off, dp) \
format_helper_2(_format_bios_boot_dn, buf, size, off, dp)
#endif /* _EFIVAR_INTERNAL_DP_H */
// vim:fenc=utf-8:tw=75:noet
efivar-39/src/efiboot.h 0000664 0000000 0000000 00000000434 14556524316 0015166 0 ustar 00root root 0000000 0000000 // SPDX-License-Identifier: LGPL-2.1-or-later
/*
* efiboot.h
* Copyright 2018 Peter Jones
*/
#ifndef PRIVATE_EFIBOOT_H_
#define PRIVATE_EFIBOOT_H_
#include "efivar.h"
#include
#endif /* !PRIVATE_EFIBOOT_H_ */
// vim:fenc=utf-8:tw=75:noet
efivar-39/src/efiboot.pc.in 0000664 0000000 0000000 00000000372 14556524316 0015747 0 ustar 00root root 0000000 0000000 prefix=@@PREFIX@@
exec_prefix=@@EXEC_PREFIX@@
libdir=@@LIBDIR@@
includedir=@@INCLUDEDIR@@
Name: efiboot
Description: UEFI Boot variable support
Version: @@VERSION@@
Requires.private: efivar
Libs: -L${libdir} -lefiboot
Cflags: -I${includedir}/efivar
efivar-39/src/efisec.h 0000664 0000000 0000000 00000001066 14556524316 0014777 0 ustar 00root root 0000000 0000000 // SPDX-License-Identifier: LGPL-2.1-or-later
/*
* efisec.h
* Copyright 2018 Peter Jones
*/
#ifndef PRIVATE_EFISEC_H_
#define PRIVATE_EFISEC_H_
#include "fix_coverity.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "efivar.h"
#include "esl-iter.h"
#include "secdb.h"
#include "x509.h"
#endif /* !PRIVATE_EFISEC_H_ */
// vim:fenc=utf-8:tw=75:noet
efivar-39/src/efisec.pc.in 0000664 0000000 0000000 00000000367 14556524316 0015562 0 ustar 00root root 0000000 0000000 prefix=@@PREFIX@@
exec_prefix=@@EXEC_PREFIX@@
libdir=@@LIBDIR@@
includedir=@@INCLUDEDIR@@
Name: efisec
Description: UEFI Security Features
Version: @@VERSION@@
Libs: -L${libdir} -lefivar -lefisec
Libs.private: -ldl
Cflags: -I${includedir}/efivar
efivar-39/src/efisecdb.c 0000664 0000000 0000000 00000032754 14556524316 0015310 0 ustar 00root root 0000000 0000000 // SPDX-License-Identifier: LGPL-2.1-or-later
/*
* efisecdb.c - efi signature list management tool
* Copyright Peter Jones
* Copyright Red Hat, Inc.
*/
#include "fix_coverity.h"
#include "linux.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "efisec.h"
extern char *optarg;
extern int optind, opterr, optopt;
static efi_secdb_t *secdb = NULL;
static list_t infiles;
static list_t actions;
struct hash_param {
char *name;
efi_secdb_type_t algorithm;
ssize_t size;
bool def;
};
static struct hash_param hash_params[] = {
{.name = "sha512",
.algorithm = SHA512,
.size = 64,
.def = false,
},
{.name = "sha256",
.algorithm = SHA256,
.size = 32,
.def = true,
},
{.name = "sha1",
.algorithm = SHA1,
.size = 20,
.def = false,
},
};
static int n_hash_params = sizeof(hash_params) / sizeof(hash_params[0]);
static void
set_hash_parameters(char *name, int *hash_number)
{
FILE *out;
int def = -1;
if (strcmp(name, "help")) {
out = stderr;
for (int i = 0; i < n_hash_params; i++) {
if (!strcmp(name, hash_params[i].name)) {
*hash_number = i;
return;
}
}
warnx("Invalid hash type \"%s\"", name);
} else {
out = stdout;
}
fprintf(out, "Supported hashes:");
for (int i = 0; i < n_hash_params; i++) {
fprintf(out, " %s", hash_params[i].name);
if (hash_params[i].def)
def = i;
}
fprintf(out, "\n");
if (def >= 0)
fprintf(out, "Default hash is %s\n", hash_params[def].name);
exit(out == stderr);
}
static void
secdb_warnx(const char * const fmt, ...)
{
va_list ap;
int errnum = errno;
fflush(stdout);
fprintf(stderr, "%s: ", program_invocation_short_name);
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
errno = errnum;
fprintf(stderr, "\n");
show_errors();
}
static void NORETURN
secdb_err(int status, const char * const fmt, ...)
{
va_list ap;
int errnum = errno;
fflush(stdout);
fprintf(stderr, "%s: ", program_invocation_short_name);
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
errno = errnum;
fprintf(stderr, ": %m\n");
show_errors();
exit(status);
}
static void NORETURN
secdb_errx(int status, const char * const fmt, ...)
{
va_list ap;
int errnum = errno;
fflush(stdout);
fprintf(stderr, "%s: ", program_invocation_short_name);
va_start(ap, fmt);
errno = errnum;
vfprintf(stderr, fmt, ap);
va_end(ap);
show_errors();
exit(status);
}
static void NORETURN
usage(int status)
{
fprintf(status == 0 ? stdout : stderr,
"Usage: %s [OPTION...]\n"
" -i, --infile= input database\n"
" -o, --outfile= output database\n"
" -a, --add following hashes or certs are to be added (default)\n"
" -r, --remove following hashes or certs are to be removed\n"
" -g, --owner-guid= following added entries use GUID as the owner\n"
" -h, --hash= hash value to add (\n"
" -t, --type= hash type to add (\"help\" lists options)\n"
" -c, --certificate= certificate file to add\n"
" -L, --list-guids list well known guids\n",
program_invocation_short_name);
exit(status);
}
typedef enum {
ADD,
REMOVE
} action_type_t;
typedef struct {
list_t list;
action_type_t action;
efi_guid_t owner;
efi_secdb_type_t algorithm;
uint8_t *data;
size_t datasz;
} action_t;
#define for_each_action(pos, head) list_for_each(pos, head)
#define for_each_action_safe(pos, n, head) list_for_each_safe(pos, n, head)
static void
add_action(list_t *list, action_type_t action_type, const efi_guid_t *owner,
efi_secdb_type_t algorithm, uint8_t *data, size_t datasz)
{
action_t *action;
if (action_type == ADD && efi_guid_is_empty(owner))
errx(1, "no owner spefified for --add");
action = calloc(1, sizeof(action_t));
if (!action)
err(1, "could not allocate memory");
action->action = action_type;
action->owner = *owner;
action->algorithm = algorithm;
action->data = data;
action->datasz = datasz;
list_add_tail(&action->list, list);
}
static void
free_actions(void)
{
list_t *pos, *tmp;
for_each_action_safe(pos, tmp, &actions) {
action_t *action = list_entry(pos, action_t, list);
list_del(&action->list);
xfree(action->data);
free(action);
}
}
static void
free_infiles(void)
{
list_t *pos, *tmp;
for_each_ptr_safe(pos, tmp, &infiles) {
ptrlist_t *entry = list_entry(pos, ptrlist_t, list);
list_del(&entry->list);
free(entry);
}
}
static void
maybe_free_secdb(void)
{
if (secdb == NULL)
return;
efi_secdb_free(secdb);
}
static void
check_hash_index(int hash_index)
{
if (hash_index < 0 || hash_index >= n_hash_params)
errx(1, "hash type is not set");
}
static void
list_guids(void)
{
const struct efivar_guidname *guid = &efi_well_known_guids[0];
const uint64_t n = efi_n_well_known_guids;
unsigned int i;
debug("&guid[0]:%p n:%lu", &guid[0], n);
for (i = 0; i < n; i++) {
printf("{"GUID_FORMAT"}\t",
GUID_FORMAT_ARGS(&guid[i].guid));
printf("{%s}\t", guid[i].name);
printf("%s\t", guid[i].symbol);
printf("%s\n", guid[i].description);
}
}
/*
* The return value here is the UNIX shell convention, 0 is success, > 0 is
* failure.
*/
static int
parse_input_files(list_t *infiles, efi_secdb_t **secdb, bool dump)
{
int status = 0;
list_t *pos, *tmp;
int rc;
for_each_ptr_safe(pos, tmp, infiles) {
int infd = -1;
uint8_t *siglist = NULL;
size_t siglistsz = 0;
char *infile;
ptrlist_t *entry = list_entry(pos, ptrlist_t, list);
infile = entry->ptr;
debug("adding input file %s entry:%p", infile, entry);
infd = open(infile, O_RDONLY);
if (infd < 0)
err(1, "could not open \"%s\"", infile);
rc = read_file(infd, &siglist, &siglistsz);
if (rc < 0)
err(1, "could not read \"%s\"", infile);
siglistsz -= 1;
close(infd);
rc = efi_secdb_parse(siglist, siglistsz, secdb);
efi_error_clear();
if (rc < 0) {
/* haaaack city */
debug("*****************************");
debug(" starting over with offset 4");
debug("*****************************");
if (siglistsz > 4 && !(*(uint32_t *)siglist & ~0x7ffu))
rc = efi_secdb_parse(&siglist[4], siglistsz-4,
secdb);
if (rc < 0) {
secdb_warnx("could not parse input file \"%s\"", infile);
if (!dump)
exit(1);
status = 1;
break;
}
}
xfree(siglist);
list_del(&entry->list);
free(entry);
}
return status;
}
int
main(int argc, char *argv[])
{
efi_guid_t owner = efi_guid_empty;
int rc;
action_type_t mode = ADD;
list_t *pos, *tmp;
int c, i;
int hash_index = -1;
bool force = false;
int verbose = 0;
bool dump = false;
bool annotate = false;
bool wants_add_actions = false;
bool did_list_guids = false;
bool do_sort = true;
bool do_sort_data = false;
bool sort_descending = false;
int status = 0;
char *outfile = NULL;
const char sopts[] = ":aAc:dfg:h:i:Lo:rs:t:v?";
const struct option lopts[] = {
{"add", no_argument, NULL, 'a' },
{"annotate", no_argument, NULL, 'A' },
{"certificate", required_argument, NULL, 'c' },
{"dump", no_argument, NULL, 'd' },
{"force", no_argument, NULL, 'f' },
{"owner-guid", required_argument, NULL, 'g' },
{"hash", required_argument, NULL, 'h' },
{"infile", required_argument, NULL, 'i' },
{"list-guids", no_argument, NULL, 'L' },
{"outfile", required_argument, NULL, 'o' },
{"remove", no_argument, NULL, 'r' },
{"sort", required_argument, NULL, 's' },
{"type", required_argument, NULL, 't' },
{"verbose", no_argument, NULL, 'v' },
{"usage", no_argument, NULL, '?' },
{"help", no_argument, NULL, '?' },
{NULL, 0, NULL, '\0' }
};
INIT_LIST_HEAD(&infiles);
INIT_LIST_HEAD(&actions);
atexit(free_actions);
atexit(free_infiles);
atexit(maybe_free_secdb);
/*
* parse the command line.
*
* note that we don't really process the security database inputs
* here, and the cert and hash add/remove must be kept in order as
* supplied.
*/
opterr = 0;
while ((c = getopt_long(argc, argv, sopts, lopts, &i)) != -1) {
uint8_t *data;
ssize_t datasz;
switch (c) {
case 'A':
dump = true;
annotate = true;
break;
case 'a':
mode = ADD;
break;
case 'c':
if (optarg == NULL)
secdb_errx(1, "--certificate requires a value");
datasz = get_file(&data, "%s", optarg);
if (datasz < 0)
secdb_err(1, "could not read certificate \"%s\"",
optarg);
datasz -= 1;
// this is arbitrary but still much too small
if (datasz < 16)
secdb_err(1, "certificate \"%s\" is invalid",
optarg);
debug("%s certificate of %zd bytes",
mode == ADD ? "adding" : "removing", datasz);
if (mode == ADD)
wants_add_actions = true;
add_action(&actions, mode, &owner, X509_CERT, data, datasz);
break;
case 'd':
dump = true;
break;
case 'f':
force = true;
break;
case 'g':
if (optarg == NULL)
secdb_errx(1, "--owner-guid requires a value");
rc = efi_id_guid_to_guid(optarg, &owner);
if (rc < 0)
secdb_errx(1, "could not parse guid \"%s\"", optarg);
break;
case 'h':
if (optarg == NULL)
secdb_errx(1, "--hash requires a value");
check_hash_index(hash_index);
datasz = strlen(optarg);
if (datasz != hash_params[hash_index].size * 2)
secdb_errx(1,
"hash \"%s\" requires a %zd-bit value, but supplied value is %zd bits",
hash_params[hash_index].name,
hash_params[hash_index].size * 8,
datasz * 4);
datasz >>= 1;
data = hex_to_bin(optarg, datasz);
debug("%s hash %s", mode == ADD ? "adding" : "removing", optarg);
if (mode == ADD)
wants_add_actions = true;
add_action(&actions, mode, &owner,
hash_params[hash_index].algorithm,
data, datasz);
break;
case 'i':
if (optarg == NULL)
secdb_errx(1, "--infile requires a value");
ptrlist_add(&infiles, optarg);
break;
case 'L':
list_guids();
did_list_guids = true;
break;
case 'o':
if (outfile)
secdb_errx(1, "--outfile cannot be used multiple times.");
if (optarg == NULL)
secdb_errx(1, "--outfile requires a value");
outfile = optarg;
break;
case 'r':
mode = REMOVE;
break;
case 's':
if (optarg == NULL) {
sort_err:
secdb_errx(1, "--sort requires one of \"type\", \"data\", \"all\", or \"none\", \"ascending\", \"descending\"");
}
if (!strcmp(optarg, "type")) {
do_sort = true;
do_sort_data = false;
} else if (!strcmp(optarg, "data")) {
do_sort = false;
do_sort_data = true;
} else if (!strcmp(optarg, "all")) {
do_sort = true;
do_sort_data = true;
} else if (!strcmp(optarg, "none")) {
do_sort = false;
do_sort_data = false;
} else if (!strcmp(optarg, "ascending")) {
sort_descending = false;
} else if (!strcmp(optarg, "descending")) {
sort_descending = true;
} else if (!strcmp(optarg, "help")) {
printf("sort options are: type data all none ascending descending");
exit(0);
} else {
goto sort_err;
}
break;
case 't':
if (optarg == NULL)
secdb_errx(1, "--type requires a value");
set_hash_parameters(optarg, &hash_index);
break;
case 'v':
if (optarg) {
long v;
errno = 0;
v = strtol(optarg, NULL, 0);
verbose = (errno == ERANGE) ? verbose + 1 : v;
} else {
verbose += 1;
}
break;
case '?':
usage(0);
break;
case ':':
if (optarg != NULL)
errx(1, "option '%c' does not take an argument (\"%s\")",
optopt, optarg);
}
}
setenv("NSS_DEFAULT_DB_TYPE", "sql", 0);
efi_set_verbose(verbose, stderr);
if (verbose) {
setvbuf(stdout, NULL, _IONBF, 0);
}
if (!outfile && !dump) {
if (did_list_guids)
return 0;
errx(1, "no output file specified");
}
if (list_empty(&infiles) && !wants_add_actions)
errx(1, "no input files or database additions");
secdb = efi_secdb_new();
if (!secdb)
err(1, "could not allocate memory");
debug("top secdb:%p", secdb);
efi_secdb_set_bool(secdb, EFI_SECDB_SORT, do_sort);
efi_secdb_set_bool(secdb, EFI_SECDB_SORT_DATA, do_sort_data);
efi_secdb_set_bool(secdb, EFI_SECDB_SORT_DESCENDING, sort_descending);
status = parse_input_files(&infiles, &secdb, dump);
if (status == 0) {
for_each_action_safe(pos, tmp, &actions) {
action_t *action = list_entry(pos, action_t, list);
if (action->action == ADD) {
debug("adding %d entry", action->algorithm);
efi_secdb_add_entry(secdb, &action->owner,
action->algorithm,
(efi_secdb_data_t *)action->data,
action->datasz);
} else {
debug("removing %d entry", action->algorithm);
efi_secdb_del_entry(secdb, &action->owner,
action->algorithm,
(efi_secdb_data_t *)action->data,
action->datasz);
}
list_del(&action->list);
free(action->data);
free(action);
}
}
if (dump)
secdb_dump(secdb, annotate);
if (!outfile)
exit(status);
int outfd = -1;
int flags = O_WRONLY | O_CREAT | (force ? 0 : O_EXCL);
debug("adding output file %s", outfile);
outfd = open(outfile, flags, 0600);
if (outfd < 0) {
char *tmpoutfile = outfile;
if (errno != EEXIST)
unlink(outfile);
err(1, "could not open \"%s\"", tmpoutfile);
}
rc = ftruncate(outfd, 0);
if (rc < 0) {
unlink(outfile);
err(1, "could not truncate output file \"%s\"", outfile);
}
void *output;
size_t size = 0;
rc = efi_secdb_realize(secdb, &output, &size);
if (rc < 0) {
unlink(outfile);
secdb_err(1, "could not realize signature list");
}
rc = write(outfd, output, size);
if (rc < 0) {
unlink(outfile);
err(1, "could not write signature list");
}
close(outfd);
xfree(output);
return 0;
}
efivar-39/src/efivar.c 0000664 0000000 0000000 00000037656 14556524316 0015026 0 ustar 00root root 0000000 0000000 // SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libefivar - library for the manipulation of EFI variables
* Copyright 2012 Red Hat, Inc.
*/
#include "fix_coverity.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
extern char *optarg;
extern int optind, opterr, optopt;
#include "efivar.h"
#include "efivar/efivar-guids.h"
#define ACTION_USAGE 0x00
#define ACTION_LIST 0x01
#define ACTION_PRINT 0x02
#define ACTION_APPEND 0x04
#define ACTION_LIST_GUIDS 0x08
#define ACTION_WRITE 0x10
#define ACTION_PRINT_DEC 0x20
#define ACTION_IMPORT 0x40
#define ACTION_EXPORT 0x80
#define EDIT_APPEND 0
#define EDIT_WRITE 1
#define SHOW_VERBOSE 0
#define SHOW_DECIMAL 1
static const char *attribute_names[] = {
"Non-Volatile",
"Boot Service Access",
"Runtime Service Access",
"Hardware Error Record",
"Authenticated Write Access",
"Time-Based Authenticated Write Access",
"Append Write",
""
};
static inline void
validate_name(const char *name)
{
if (name == NULL) {
err:
warnx("Invalid variable name \"%s\"",
(name == NULL) ? "(null)" : name);
show_errors();
exit(1);
}
if (name[0] == '{') {
const char *next = strchr(name+1, '}');
if (!next)
goto err;
if (next[1] != '-')
goto err;
if (next[2] == '\000')
goto err;
} else {
if (strlen(name) < 38)
goto err;
if (name[8] != '-' || name[13] != '-' ||
name[18] != '-' || name[23] != '-' ||
name[36] != '-')
goto err;
}
}
static void
list_all_variables(void)
{
efi_guid_t *guid = NULL;
char *name = NULL;
int rc;
while ((rc = efi_get_next_variable_name(&guid, &name)) > 0)
printf(GUID_FORMAT "-%s\n", GUID_FORMAT_ARGS(guid), name);
if (rc < 0) {
fprintf(stderr, "efivar: error listing variables: %m\n");
show_errors();
exit(1);
}
}
static void
parse_name(const char *guid_name, char **name, efi_guid_t *guid)
{
unsigned int guid_len = sizeof("84be9c3e-8a32-42c0-891c-4cd3b072becc");
char guid_buf[guid_len + 2];
int rc;
off_t name_pos = 0;
const char *left, *right;
validate_name(guid_name);
left = strchr(guid_name, '{');
right = strchr(guid_name, '}');
if (left && right) {
if (right[1] != '-' || right[2] == '\0') {
bad_name:
errno = -EINVAL;
fprintf(stderr, "efivar: invalid name \"%s\"\n",
guid_name);
show_errors();
exit(1);
}
name_pos = right + 1 - guid_name;
strncpy(guid_buf, guid_name, name_pos);
guid_buf[name_pos++] = '\0';
rc = efi_id_guid_to_guid(guid_buf, guid);
if (rc < 0)
goto bad_name;
} else {
/* it has to be at least the length of the guid, a dash, and
* one more character */
if (strlen(guid_name) < guid_len + 2)
goto bad_name;
name_pos = guid_len - 1;
if (guid_name[name_pos] != '-' || guid_name[name_pos+1] == '\0')
goto bad_name;
name_pos++;
memset(guid_buf, 0, sizeof(guid_buf));
strncpy(guid_buf, guid_name, guid_len - 1);
rc = text_to_guid(guid_buf, guid);
if (rc < 0)
goto bad_name;
}
char *name_buf = NULL;
int name_len;
name_len = strlen(guid_name + name_pos) + 1;
name_buf = calloc(1, name_len);
if (!name_buf) {
fprintf(stderr, "efivar: %m\n");
exit(1);
}
strcpy(name_buf, guid_name + name_pos);
*name = name_buf;
}
static void
show_variable_data(efi_guid_t guid, const char *name, uint32_t attributes,
uint8_t *data, size_t data_size,
int display_type)
{
if (display_type == SHOW_VERBOSE) {
printf("GUID: "GUID_FORMAT "\n", GUID_FORMAT_ARGS(&guid));
printf("Name: \"%s\"\n", name);
printf("Attributes:\n");
for (int i = 0; attribute_names[i][0] != '\0'; i++) {
if(attributes & (1 << i))
printf("\t%s\n", attribute_names[i]);
}
printf("Value:\n");
uint32_t index = 0;
while (index < data_size) {
char charbuf[] = "................";
printf("%08x ", index);
/* print the hex values, and render the ascii bits into
* charbuf */
while (index < data_size) {
printf("%02x ", data[index]);
if (index % 8 == 7)
printf(" ");
if (safe_to_print(data[index]))
charbuf[index % 16] = data[index];
index++;
if (index % 16 == 0)
break;
}
/* If we're above data_size, finish out the line with
* space, and also finish out charbuf with space */
while (index >= data_size && index % 16 != 0) {
if (index % 8 == 7)
printf(" ");
printf(" ");
charbuf[index % 16] = ' ';
index++;
if (index % 16 == 0)
break;
}
printf("|%s|\n", charbuf);
}
} else if (display_type == SHOW_DECIMAL) {
uint32_t index = 0;
while (index < data_size) {
// print the dec values
while (index < data_size) {
printf("%d ", data[index]);
if (index % 8 == 7)
printf(" ");
index++;
if (index % 16 == 0)
break;
}
}
printf("\n");
}
}
static void
show_variable(char *guid_name, int display_type)
{
efi_guid_t guid = efi_guid_empty;
char *name = NULL;
int rc;
uint8_t *data = NULL;
size_t data_size = 0;
uint32_t attributes;
parse_name(guid_name, &name, &guid);
if (!name || efi_guid_is_empty(&guid)) {
fprintf(stderr, "efivar: could not parse variable name.\n");
show_errors();
exit(1);
}
errno = 0;
rc = efi_get_variable(guid, name, &data, &data_size, &attributes);
if (rc < 0) {
fprintf(stderr, "efivar: show variable: %m\n");
show_errors();
exit(1);
}
show_variable_data(guid, name, attributes,
data, data_size, display_type);
free(name);
if (data)
free(data);
}
static void
save_variable_data(efi_variable_t *var, char *outfile, bool dmpstore)
{
FILE *out = NULL;
ssize_t sz;
uint8_t *data = NULL;
size_t datasz = 0;
ssize_t (*export)(efi_variable_t *var, uint8_t *data, size_t size) =
dmpstore ? efi_variable_export_dmpstore : efi_variable_export;
out = fopen(outfile, "w");
if (!out)
err(1, "Could not open \"%s\" for writing", outfile);
sz = export(var, data, datasz);
data = calloc(sz, 1);
if (!data)
err(1, "Could not allocate memory");
datasz = sz;
sz = export(var, data, datasz);
if (sz < 0)
err(1, "Could not format data");
datasz = sz;
sz = fwrite(data, 1, datasz, out);
if (sz < (ssize_t)datasz)
err(1, "Could not write to \"%s\"", outfile);
fflush(out);
fclose(out);
}
static void
save_variable(char *guid_name, char *outfile, bool dmpstore)
{
efi_guid_t guid = efi_guid_empty;
char *name = NULL;
int rc;
uint8_t *data = NULL;
size_t data_size = 0;
uint32_t attributes = 7;
efi_variable_t *var;
parse_name(guid_name, &name, &guid);
if (!name || efi_guid_is_empty(&guid)) {
fprintf(stderr, "efivar: could not parse variable name.\n");
show_errors();
exit(1);
}
errno = 0;
rc = efi_get_variable(guid, name, &data, &data_size, &attributes);
if (rc < 0) {
fprintf(stderr, "efivar: show variable: %m\n");
show_errors();
exit(1);
}
var = efi_variable_alloc();
if (!var) {
fprintf(stderr, "efivar: could not allocate variable storage.\n");
show_errors();
exit(1);
}
efi_variable_set_name(var, (unsigned char *)name);
efi_variable_set_guid(var, &guid);
efi_variable_set_attributes(var, attributes);
efi_variable_set_data(var, data, data_size);
save_variable_data(var, outfile, dmpstore);
efi_variable_free(var, false);
free(name);
if (data)
free(data);
}
static void
edit_variable(const char *guid_name, void *data, size_t data_size,
uint32_t attrib, int edit_type)
{
efi_guid_t guid = efi_guid_empty;
char *name = NULL;
int rc;
uint8_t *old_data = NULL;
size_t old_data_size = 0;
uint32_t old_attributes = 0;
parse_name(guid_name, &name, &guid);
if (!name || efi_guid_is_empty(&guid)) {
fprintf(stderr, "efivar: could not parse variable name.\n");
show_errors();
exit(1);
}
rc = efi_get_variable(guid, name, &old_data, &old_data_size, &old_attributes);
/* Ignore errors, as -a can be used to create a variable */
if (attrib != 0)
old_attributes = attrib;
switch (edit_type){
case EDIT_APPEND:
rc = efi_append_variable(guid, name,
data, data_size,
old_attributes);
break;
case EDIT_WRITE:
rc = efi_set_variable(guid, name,
data, data_size,
old_attributes, 0644);
break;
}
free(name);
if (old_data)
free(old_data);
if (rc < 0) {
fprintf(stderr, "efivar: %m\n");
show_errors();
exit(1);
}
}
static void
prepare_data(const char *filename, uint8_t **data, size_t *data_size)
{
int fd = -1;
void *buf;
size_t buflen = 0;
struct stat statbuf;
int rc;
if (filename == NULL) {
fprintf(stderr, "Input filename must be provided.\n");
exit(1);
}
fd = open(filename, O_RDONLY);
if (fd < 0)
goto err;
memset(&statbuf, '\0', sizeof(statbuf));
rc = fstat(fd, &statbuf);
if (rc < 0)
goto err;
buflen = statbuf.st_size;
buf = mmap(NULL, buflen, PROT_READ, MAP_PRIVATE|MAP_POPULATE, fd, 0);
if (buf == MAP_FAILED)
goto err;
*data = buf;
*data_size = buflen;
close(fd);
return;
err:
if (fd >= 0)
close(fd);
fprintf(stderr, "Could not use \"%s\": %m\n", filename);
exit(1);
}
static void __attribute__((__noreturn__))
usage(int ret)
{
FILE *out = ret == 0 ? stdout : stderr;
fprintf(out,
"Usage: %s [OPTION...]\n"
" -A, --attributes= attributes to use on append\n"
" -l, --list list current variables\n"
" -p, --print print variable specified by --name\n"
" -D, --dmpstore use DMPSTORE format when exporting\n"
" -d, --print-decimal print variable in decimal values specified\n"
" by --name\n"
" -n, --name= variable to manipulate, in the form\n"
" 8be4df61-93ca-11d2-aa0d-00e098032b8c-Boot0000\n"
" -a, --append append to variable specified by --name\n"
" -f, --datafile= load or save variable contents from \n"
" -e, --export= export variable to \n"
" -i, --import= import variable from