summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKay Sievers <kay@vrfy.org>2015-07-07 11:35:30 +0200
committerKay Sievers <kay@vrfy.org>2015-07-07 11:35:30 +0200
commit55df1539c9d330732e88bd196afee386db6e4a1d (patch)
treec2d157cdf71040efdd79f195fd5e3b6f41e9b8e8
parent2bcd919c681c952eb867ef1bdb458f1bc49c2d55 (diff)
obsoletedHEADmaster
-rw-r--r--.gitignore40
-rw-r--r--.vimrc4
-rw-r--r--LICENSE502
-rw-r--r--Makefile.am203
-rw-r--r--README26
-rw-r--r--TODO0
-rwxr-xr-xautogen.sh36
-rw-r--r--configure.ac155
-rw-r--r--dead.package1
-rw-r--r--m4/arch.m413
-rw-r--r--man/gummiboot.xml137
-rw-r--r--src/efi/console.c141
-rw-r--r--src/efi/console.h34
-rw-r--r--src/efi/graphics.c389
-rw-r--r--src/efi/graphics.h26
-rw-r--r--src/efi/gummiboot.c2047
-rw-r--r--src/efi/linux.c130
-rw-r--r--src/efi/linux.h24
-rw-r--r--src/efi/pefile.c172
-rw-r--r--src/efi/pefile.h22
-rw-r--r--src/efi/stub.c106
-rw-r--r--src/efi/util.c342
-rw-r--r--src/efi/util.h50
-rw-r--r--src/setup/efivars.c647
-rw-r--r--src/setup/efivars.h55
-rw-r--r--src/setup/setup.c1425
-rw-r--r--test/gummiboot.svg1327
-rw-r--r--test/splash.bmpbin289238 -> 0 bytes
-rwxr-xr-xtest/test-create-disk.sh43
29 files changed, 1 insertions, 8096 deletions
diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index d482a5d..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,40 +0,0 @@
-*~
-*.o
-*.so
-*.cache
-*.log
-.deps
-.libs
-*.8
-.dirstamp
-/gummiboot
-/gummiboot.so
-/gummibootx64.efi
-/gummibootia32.efi
-/stub.so
-/stubx64.efi
-/stubia32.efi
-/test-disk
-
-Makefile
-aclocal.m4
-stamp-h.in
-Makefile.in
-configure
-config.h
-config.h.in
-config.guess
-config.status
-config.sub
-stamp-h
-stamp-h1
-m4/*.m4
-config.rpath
-mkinstalldirs
-compile
-depcomp
-install-sh
-missing
-
-# wanted files
-!m4/arch.m4
diff --git a/.vimrc b/.vimrc
deleted file mode 100644
index 366fbdc..0000000
--- a/.vimrc
+++ /dev/null
@@ -1,4 +0,0 @@
-" 'set exrc' in ~/.vimrc will read .vimrc from the current directory
-set tabstop=8
-set shiftwidth=8
-set expandtab
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index 4362b49..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,502 +0,0 @@
- GNU LESSER GENERAL PUBLIC LICENSE
- Version 2.1, February 1999
-
- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the Lesser GPL. It also counts
- as the successor of the GNU Library Public License, version 2, hence
- the version number 2.1.]
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
- This license, the Lesser General Public License, applies to some
-specially designated software packages--typically libraries--of the
-Free Software Foundation and other authors who decide to use it. You
-can use it too, but we suggest you first think carefully about whether
-this license or the ordinary General Public License is the better
-strategy to use in any particular case, based on the explanations below.
-
- When we speak of free software, we are referring to freedom of use,
-not price. Our General Public Licenses are designed to make sure that
-you have the freedom to distribute copies of free software (and charge
-for this service if you wish); that you receive source code or can get
-it if you want it; that you can change the software and use pieces of
-it in new free programs; and that you are informed that you can do
-these things.
-
- To protect your rights, we need to make restrictions that forbid
-distributors to deny you these rights or to ask you to surrender these
-rights. These restrictions translate to certain responsibilities for
-you if you distribute copies of the library or if you modify it.
-
- For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you. You must make sure that they, too, receive or can get the source
-code. If you link other code with the library, you must provide
-complete object files to the recipients, so that they can relink them
-with the library after making changes to the library and recompiling
-it. And you must show them these terms so they know their rights.
-
- We protect your rights with a two-step method: (1) we copyright the
-library, and (2) we offer you this license, which gives you legal
-permission to copy, distribute and/or modify the library.
-
- To protect each distributor, we want to make it very clear that
-there is no warranty for the free library. Also, if the library is
-modified by someone else and passed on, the recipients should know
-that what they have is not the original version, so that the original
-author's reputation will not be affected by problems that might be
-introduced by others.
-
- Finally, software patents pose a constant threat to the existence of
-any free program. We wish to make sure that a company cannot
-effectively restrict the users of a free program by obtaining a
-restrictive license from a patent holder. Therefore, we insist that
-any patent license obtained for a version of the library must be
-consistent with the full freedom of use specified in this license.
-
- Most GNU software, including some libraries, is covered by the
-ordinary GNU General Public License. This license, the GNU Lesser
-General Public License, applies to certain designated libraries, and
-is quite different from the ordinary General Public License. We use
-this license for certain libraries in order to permit linking those
-libraries into non-free programs.
-
- When a program is linked with a library, whether statically or using
-a shared library, the combination of the two is legally speaking a
-combined work, a derivative of the original library. The ordinary
-General Public License therefore permits such linking only if the
-entire combination fits its criteria of freedom. The Lesser General
-Public License permits more lax criteria for linking other code with
-the library.
-
- We call this license the "Lesser" General Public License because it
-does Less to protect the user's freedom than the ordinary General
-Public License. It also provides other free software developers Less
-of an advantage over competing non-free programs. These disadvantages
-are the reason we use the ordinary General Public License for many
-libraries. However, the Lesser license provides advantages in certain
-special circumstances.
-
- For example, on rare occasions, there may be a special need to
-encourage the widest possible use of a certain library, so that it becomes
-a de-facto standard. To achieve this, non-free programs must be
-allowed to use the library. A more frequent case is that a free
-library does the same job as widely used non-free libraries. In this
-case, there is little to gain by limiting the free library to free
-software only, so we use the Lesser General Public License.
-
- In other cases, permission to use a particular library in non-free
-programs enables a greater number of people to use a large body of
-free software. For example, permission to use the GNU C Library in
-non-free programs enables many more people to use the whole GNU
-operating system, as well as its variant, the GNU/Linux operating
-system.
-
- Although the Lesser General Public License is Less protective of the
-users' freedom, it does ensure that the user of a program that is
-linked with the Library has the freedom and the wherewithal to run
-that program using a modified version of the Library.
-
- The precise terms and conditions for copying, distribution and
-modification follow. Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library". The
-former contains code derived from the library, whereas the latter must
-be combined with the library in order to run.
-
- GNU LESSER GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License Agreement applies to any software library or other
-program which contains a notice placed by the copyright holder or
-other authorized party saying it may be distributed under the terms of
-this Lesser General Public License (also called "this License").
-Each licensee is addressed as "you".
-
- A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
- The "Library", below, refers to any such software library or work
-which has been distributed under these terms. A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language. (Hereinafter, translation is
-included without limitation in the term "modification".)
-
- "Source code" for a work means the preferred form of the work for
-making modifications to it. For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
- Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it). Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-
- 1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
- You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
- 2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) The modified work must itself be a software library.
-
- b) You must cause the files modified to carry prominent notices
- stating that you changed the files and the date of any change.
-
- c) You must cause the whole of the work to be licensed at no
- charge to all third parties under the terms of this License.
-
- d) If a facility in the modified Library refers to a function or a
- table of data to be supplied by an application program that uses
- the facility, other than as an argument passed when the facility
- is invoked, then you must make a good faith effort to ensure that,
- in the event an application does not supply such function or
- table, the facility still operates, and performs whatever part of
- its purpose remains meaningful.
-
- (For example, a function in a library to compute square roots has
- a purpose that is entirely well-defined independent of the
- application. Therefore, Subsection 2d requires that any
- application-supplied function or table used by this function must
- be optional: if the application does not supply it, the square
- root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library. To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License. (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.) Do not make any other change in
-these notices.
-
- Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
- This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
- 4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
- If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library". Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
- However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library". The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
- When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library. The
-threshold for this to be true is not precisely defined by law.
-
- If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work. (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
- Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-
- 6. As an exception to the Sections above, you may also combine or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
- You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License. You must supply a copy of this License. If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License. Also, you must do one
-of these things:
-
- a) Accompany the work with the complete corresponding
- machine-readable source code for the Library including whatever
- changes were used in the work (which must be distributed under
- Sections 1 and 2 above); and, if the work is an executable linked
- with the Library, with the complete machine-readable "work that
- uses the Library", as object code and/or source code, so that the
- user can modify the Library and then relink to produce a modified
- executable containing the modified Library. (It is understood
- that the user who changes the contents of definitions files in the
- Library will not necessarily be able to recompile the application
- to use the modified definitions.)
-
- b) Use a suitable shared library mechanism for linking with the
- Library. A suitable mechanism is one that (1) uses at run time a
- copy of the library already present on the user's computer system,
- rather than copying library functions into the executable, and (2)
- will operate properly with a modified version of the library, if
- the user installs one, as long as the modified version is
- interface-compatible with the version that the work was made with.
-
- c) Accompany the work with a written offer, valid for at
- least three years, to give the same user the materials
- specified in Subsection 6a, above, for a charge no more
- than the cost of performing this distribution.
-
- d) If distribution of the work is made by offering access to copy
- from a designated place, offer equivalent access to copy the above
- specified materials from the same place.
-
- e) Verify that the user has already received a copy of these
- materials or that you have already sent this user a copy.
-
- For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it. However, as a special exception,
-the materials to be distributed need not include anything that is
-normally distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
- It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system. Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
- 7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
- a) Accompany the combined library with a copy of the same work
- based on the Library, uncombined with any other library
- facilities. This must be distributed under the terms of the
- Sections above.
-
- b) Give prominent notice with the combined library of the fact
- that part of it is a work based on the Library, and explaining
- where to find the accompanying uncombined form of the same work.
-
- 8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License. Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License. However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
- 9. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Library or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
- 10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties with
-this License.
-
- 11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all. For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded. In such case, this License incorporates the limitation as if
-written in the body of this License.
-
- 13. The Free Software Foundation may publish revised and/or new
-versions of the Lesser General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation. If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-
- 14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission. For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this. Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
- NO WARRANTY
-
- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Libraries
-
- If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change. You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
- To apply these terms, attach the following notices to the library. It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
- <one line to give the library's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the
- library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
- <signature of Ty Coon>, 1 April 1990
- Ty Coon, President of Vice
-
-That's all there is to it!
diff --git a/Makefile.am b/Makefile.am
deleted file mode 100644
index 6568a35..0000000
--- a/Makefile.am
+++ /dev/null
@@ -1,203 +0,0 @@
-#
-# This file is part of gummiboot
-#
-# Copyright (C) 2013 Karel Zak <kzak@redhat.com>
-#
-# gummiboot 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.
-#
-# gummiboot 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 systemd; If not, see <http://www.gnu.org/licenses/>.
-
-ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
-AM_MAKEFLAGS = --no-print-directory
-
-gummibootlibdir = $(prefix)/lib/gummiboot
-
-AM_CPPFLAGS = -include config.h
-AM_CFLAGS = \
- -D_GNU_SOURCE \
- -Wall \
- -Wextra \
- -Wmissing-prototypes \
- -Wno-unused-parameter
-AM_LDFLAGS =
-
-EXTRA_DIST = autogen.sh README LICENSE
-CLEANFILES =
-
-# ------------------------------------------------------------------------------
-if HAVE_BLKID
-bin_PROGRAMS = gummiboot
-
-gummiboot_SOURCES = \
- src/setup/setup.c \
- src/setup/efivars.c \
- src/setup/efivars.h
-
-gummiboot_CPPFLAGS = \
- $(AM_CPPFLAGS) \
- -DMACHINE_TYPE_NAME=\"$(MACHINE_TYPE_NAME)\" \
- -DGUMMIBOOTLIBDIR=\"$(gummibootlibdir)\"
-
-gummiboot_CFLAGS = \
- $(AM_CFLAGS) \
- $(BLKID_CFLAGS)
-
-gummiboot_LDADD = \
- $(BLKID_LIBS)
-endif
-
-if ENABLE_MANPAGES
-%.8: %.xml
- $(AM_V_GEN)$(XSLTPROC) -o $@ --nonet \
- --stringparam man.output.quietly 1 \
- --stringparam man.th.extra1.suppress 1 \
- --stringparam man.authors.section.enabled 0 \
- --stringparam man.copyright.section.enabled 0 \
- http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
-
-dist_man_MANS = man/gummiboot.8
-endif
-
-EXTRA_DIST += man/gummiboot.xml
-CLEANFILES += man/gummiboot.8
-
-# ------------------------------------------------------------------------------
-# EFI compilation -- this part of the build system uses custom make rules and
-# bypasses regular automake to provide absolute control on compiler and linker
-# flags.
-efi_cppflags = \
- $(EFI_CPPFLAGS) \
- -I$(top_builddir) -include config.h \
- -I$(EFI_INC_DIR)/efi \
- -I$(EFI_INC_DIR)/efi/$(ARCH) \
- -DMACHINE_TYPE_NAME=\"$(MACHINE_TYPE_NAME)\"
-
-efi_cflags = \
- $(EFI_CFLAGS) \
- -Wall \
- -Wextra \
- -std=gnu90 \
- -nostdinc \
- -ggdb -O0 \
- -fpic \
- -fshort-wchar \
- -nostdinc \
- -ffreestanding \
- -fno-strict-aliasing \
- -fno-stack-protector \
- -Wsign-compare \
- -mno-sse \
- -mno-mmx
-
-if ARCH_X86_64
-efi_cflags += \
- -mno-red-zone \
- -DEFI_FUNCTION_WRAPPER \
- -DGNU_EFI_USE_MS_ABI
-endif
-
-efi_ldflags = \
- $(EFI_LDFLAGS) \
- -T $(EFI_LDS_DIR)/elf_$(ARCH)_efi.lds \
- -shared \
- -Bsymbolic \
- -nostdlib \
- -znocombreloc \
- -L $(EFI_LIB_DIR) \
- $(EFI_LDS_DIR)/crt0-efi-$(ARCH).o
-
-# ------------------------------------------------------------------------------
-gummiboot_headers = \
- src/efi/util.h \
- src/efi/console.h \
- src/efi/graphics.h \
- src/efi/pefile.h
-
-gummiboot_sources = \
- src/efi/util.c \
- src/efi/console.c \
- src/efi/graphics.c \
- src/efi/pefile.c \
- src/efi/gummiboot.c
-
-gummiboot_objects = $(addprefix $(top_builddir)/,$(gummiboot_sources:.c=.o))
-gummiboot_solib = $(top_builddir)/src/efi/gummiboot.so
-gummiboot = gummiboot$(MACHINE_TYPE_NAME).efi
-
-gummibootlib_DATA = $(gummiboot)
-CLEANFILES += $(gummiboot_objects) $(gummiboot_solib) $(gummiboot)
-EXTRA_DIST += $(gummiboot_sources) $(gummiboot_headers)
-
-$(top_builddir)/src/efi/%.o: $(top_srcdir)/src/efi/%.c $(addprefix $(top_srcdir)/,$(gummiboot_headers))
- @$(MKDIR_P) $(top_builddir)/src/efi/
- $(AM_V_CC)$(EFI_CC) $(efi_cppflags) $(efi_cflags) -c $< -o $@
-
-$(gummiboot_solib): $(gummiboot_objects)
- $(AM_V_CCLD)$(LD) $(efi_ldflags) $(gummiboot_objects) \
- -o $@ -lefi -lgnuefi $(shell $(CC) -print-libgcc-file-name); \
- nm -D -u $@ | grep ' U ' && exit 1 || :
-.DELETE_ON_ERROR: $(gummboot_solib)
-
-$(gummiboot): $(gummiboot_solib)
- $(AM_V_GEN) objcopy -j .text -j .sdata -j .data -j .dynamic \
- -j .dynsym -j .rel -j .rela -j .reloc \
- --target=efi-app-$(ARCH) $< $@
-
-# ------------------------------------------------------------------------------
-stub_headers = \
- src/efi/util.h \
- src/efi/pefile.h \
- src/efi/linux.h
-
-stub_sources = \
- src/efi/util.c \
- src/efi/pefile.c \
- src/efi/linux.c \
- src/efi/stub.c
-
-stub_objects = $(addprefix $(top_builddir)/,$(stub_sources:.c=.o))
-stub_solib = $(top_builddir)/src/efi/stub.so
-stub = linux$(MACHINE_TYPE_NAME).efi.stub
-
-gummibootlib_DATA += $(stub)
-CLEANFILES += $(stub_objects) $(stub_solib) $(stub)
-EXTRA_DIST += $(stub_sources) $(stub_headers)
-
-$(top_builddir)/src/efi/%.o: $(top_srcdir)/src/efi/%.c $(addprefix $(top_srcdir)/,$(stub_headers))
- @$(MKDIR_P) $(top_builddir)/src/efi/
- $(AM_V_CC)$(EFI_CC) $(efi_cppflags) $(efi_cflags) -c $< -o $@
-
-$(stub_solib): $(stub_objects)
- $(AM_V_CCLD)$(LD) $(efi_ldflags) $(stub_objects) \
- -o $@ -lefi -lgnuefi $(shell $(CC) -print-libgcc-file-name); \
- nm -D -u $@ | grep ' U ' && exit 1 || :
-.DELETE_ON_ERROR: $(gummboot_solib)
-
-$(stub): $(stub_solib)
- $(AM_V_GEN) objcopy -j .text -j .sdata -j .data -j .dynamic \
- -j .dynsym -j .rel -j .rela -j .reloc \
- --target=efi-app-$(ARCH) $< $@
-
-# ------------------------------------------------------------------------------
-CLEANFILES += test-disk.img
-EXTRA_DIST += test/test-create-disk.sh
-
-test-disk.img: gummiboot$(MACHINE_TYPE_NAME).efi test/test-create-disk.sh
- $(AM_V_GEN)test/test-create-disk.sh
-
-qemu: test-disk.img
- $(QEMU) -machine accel=kvm -m 1024 -bios $(QEMU_BIOS) -snapshot test-disk.img
-
-install-tree: all
- rm -rf $(abs_srcdir)/install-tree
- $(MAKE) install DESTDIR=$(abs_srcdir)/install-tree
- tree $(abs_srcdir)/install-tree
diff --git a/README b/README
deleted file mode 100644
index 09f835f..0000000
--- a/README
+++ /dev/null
@@ -1,26 +0,0 @@
-gummiboot Simple UEFI boot manager
-
-gummiboot executes EFI images. The default entry is selected by a configured
-pattern (glob) or an on-screen menu.
-
-gummiboot operates on the EFI System Partition (ESP) only. Configuration
-file fragments, kernels, initrds, other EFI images need to reside on the
-ESP. Linux kernels must be built with CONFIG_EFI_STUB to be able to be
-directly executed as an EFI image.
-
-gummiboot reads simple and entirely generic configurion files; one file
-per boot entry to select from.
-
-Pressing Space (or most other) keys during bootup will show an on-screen
-menu with all configured entries to select from. Pressing enter on the
-selected entry loads and starts the EFI image.
-
-If no timeout is configured and no key pressed during bootup, the default
-entry is booted right away.
-
-Further documentation is available in the gummiboot wiki at:
- http://freedesktop.org/wiki/Software/gummiboot
-
-Links:
- http://www.freedesktop.org/wiki/Specifications/BootLoaderSpec
- http://www.freedesktop.org/software/systemd/man/kernel-install.html
diff --git a/TODO b/TODO
deleted file mode 100644
index e69de29..0000000
--- a/TODO
+++ /dev/null
diff --git a/autogen.sh b/autogen.sh
deleted file mode 100755
index dfe9eba..0000000
--- a/autogen.sh
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/bin/sh
-
-# This file is part of gummiboot.
-#
-# gummiboot 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.
-#
-# gummiboot 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 systemd; If not, see <http://www.gnu.org/licenses/>.
-
-set -e
-
-autoreconf --force --install --symlink
-
-args="\
---prefix=/usr"
-
-if [ "x$1" = "xc" ]; then
- ./configure $args
- make clean
-else
- echo
- echo "----------------------------------------------------------------"
- echo "Initialized build system. For a common configuration please run:"
- echo "----------------------------------------------------------------"
- echo
- echo "./configure $args"
- echo
-fi
diff --git a/configure.ac b/configure.ac
deleted file mode 100644
index 27bbe1d..0000000
--- a/configure.ac
+++ /dev/null
@@ -1,155 +0,0 @@
-#
-# This file is part of gummiboot.
-#
-# Copyright (C) 2013 Karel Zak <kzak@redhat.com>
-#
-# gummiboot 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.
-#
-# gummiboot 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 systemd; If not, see <http://www.gnu.org/licenses/>.
-
-AC_INIT([gummiboot],
- [48],
- [systemd-devel@lists.freedesktop.org],
- [gummiboot],
- [http://freedesktop.org/wiki/Software/gummiboot])
-
-AC_CONFIG_SRCDIR([src/setup/setup.c])
-AC_CONFIG_MACRO_DIR([m4])
-AC_CONFIG_HEADERS([config.h])
-AC_CONFIG_AUX_DIR([build-aux])
-AC_PREFIX_DEFAULT([/usr])
-
-AM_INIT_AUTOMAKE([foreign 1.11 -Wall -Wno-portability silent-rules tar-pax no-dist-gzip dist-xz subdir-objects])
-AM_SILENT_RULES([yes])
-
-AC_CANONICAL_HOST
-AC_SYS_LARGEFILE
-
-AC_PROG_CC
-
-dnl Don't try to use things like -std=c99 for efi compilation
-EFI_CC=$CC
-AC_SUBST([EFI_CC])
-
-AC_PROG_CC_C99
-AM_PROG_CC_C_O
-AC_PROG_GCC_TRADITIONAL
-
-AC_PROG_MKDIR_P
-AC_PATH_PROG([XSLTPROC], [xsltproc])
-
-dnl Define ARCH_<NAME> conditionals
-SET_ARCH(IA32, i*86*)
-SET_ARCH(X86_64, x86_64*)
-SET_ARCH(IA64, ia64*)
-
-ARCH=`echo $host | sed "s/\(-\).*$//"`
-
-AM_COND_IF(ARCH_IA32, [
- ARCH=ia32
- MACHINE_TYPE_NAME=ia32])
-
-AM_COND_IF(ARCH_X86_64, [
- MACHINE_TYPE_NAME=x64])
-
-AC_SUBST([ARCH])
-AC_SUBST([MACHINE_TYPE_NAME])
-
-# QEMU and OVMF UEFI firmware
-AS_IF([test x"$cross_compiling" = "xyes"], [], [
- AC_PATH_PROG([QEMU], [qemu-system-x86_64])
- AC_CHECK_FILE([/usr/share/qemu/bios-ovmf.bin], [QEMU_BIOS=/usr/share/qemu/bios-ovmf.bin])
- AC_CHECK_FILE([/usr/share/qemu-ovmf/bios.bin], [QEMU_BIOS=/usr/share/qemu-ovmf/bios.bin])
- AC_SUBST([QEMU_BIOS])
-])
-
-# ------------------------------------------------------------------------------
-dnl GNU EFI doesn't use relative paths: efi.h includes efibind.h which is in
-dnl ${ARCH} relative to efi.h. I can't find a way to get AC_CHECK_HEADERS to
-dnl add -I/usr/include/efi/${ARCH} to the conftest.c build. So, just test for
-dnl efibind.h as the chances of efi.h not existing if it does are very low.
-AC_CHECK_HEADER(efi/${ARCH}/efibind.h, [],
- [AC_MSG_ERROR([*** GNU EFI header efibind.h not found])])
-
-efiroot=$(echo $(cd /usr/lib/$(gcc -print-multi-os-directory); pwd))
-EFI_LIB_DIR="$efiroot"
-AC_ARG_WITH(efi-libdir,
- AS_HELP_STRING([--with-efi-libdir=PATH], [Path to efi lib directory]),
- [EFI_LIB_DIR="$withval"], [EFI_LIB_DIR="$efiroot"]
-)
-AC_SUBST([EFI_LIB_DIR])
-
-dnl extra objects and linker scripts
-AC_ARG_WITH(efi-ldsdir,
- AS_HELP_STRING([--with-efi-ldsdir=PATH], [Path to efi lds directory]),
- [EFI_LDS_DIR="$withval"],
- [
- for EFI_LDS_DIR in "${efiroot}/gnuefi" "${efiroot}"; do
- for lds in ${EFI_LDS_DIR}/elf_${ARCH}_efi.lds; do
- test -f ${lds} && break 2
- done
- done
- ]
-)
-AC_SUBST([EFI_LDS_DIR])
-
-AC_ARG_WITH(efi-includedir,
- AS_HELP_STRING([--with-efi-includedir=PATH], [Path to efi include directory]),
- [EFI_INC_DIR="$withval"], [EFI_INC_DIR="/usr/include"]
-)
-AC_SUBST([EFI_INC_DIR])
-
-# ------------------------------------------------------------------------------
-AC_ARG_ENABLE(blkid, AS_HELP_STRING([--disable-blkid], [disable blkid support]))
-if test "x$enable_blkid" != "xno"; then
- PKG_CHECK_MODULES(BLKID, [ blkid >= 2.20 ],
- [AC_DEFINE(HAVE_BLKID, 1, [Define if blkid is available]) have_blkid=yes], have_blkid=no)
- if test "x$have_blkid" = xno -a "x$enable_blkid" = xyes; then
- AC_MSG_ERROR([*** blkid support requested but libraries not found])
- fi
-fi
-AM_CONDITIONAL(HAVE_BLKID, [test "$have_blkid" = "yes"])
-
-# ------------------------------------------------------------------------------
-have_manpages=no
-AC_ARG_ENABLE(manpages, AS_HELP_STRING([--disable-manpages], [disable manpages]))
-AS_IF([test "x$enable_manpages" != xno], [
- AS_IF([test "x$enable_manpages" = xyes -a "x$XSLTPROC" = x], [
- AC_MSG_ERROR([*** Manpages requested but xsltproc not found])
- ])
- AS_IF([test "x$XSLTPROC" != x], [have_manpages=yes])
-])
-AM_CONDITIONAL(ENABLE_MANPAGES, [test "x$have_manpages" = "xyes"])
-
-# ------------------------------------------------------------------------------
-AC_CONFIG_FILES([
- Makefile
-])
-
-AC_OUTPUT
-AC_MSG_RESULT([
- $PACKAGE_NAME $VERSION
-
- prefix: ${prefix}
- arch: $ARCH
- EFI machine type: $MACHINE_TYPE_NAME
-
- EFI libdir: ${EFI_LIB_DIR}
- EFI ldsdir: ${EFI_LDS_DIR}
- EFI includedir: ${EFI_INC_DIR}
-
- blkid: ${have_blkid}
- man pages: ${have_manpages}
-
- QEMU: ${QEMU}
- QEMU OVMF: ${QEMU_BIOS}
-])
diff --git a/dead.package b/dead.package
new file mode 100644
index 0000000..dbf503b
--- /dev/null
+++ b/dead.package
@@ -0,0 +1 @@
+obsoleted
diff --git a/m4/arch.m4 b/m4/arch.m4
deleted file mode 100644
index f17b427..0000000
--- a/m4/arch.m4
+++ /dev/null
@@ -1,13 +0,0 @@
-
-dnl SET_ARCH(ARCHNAME, PATTERN)
-dnl
-dnl Define ARCH_<archname> condition if the pattern match with the current
-dnl architecture
-dnl
-AC_DEFUN([SET_ARCH], [
- cpu_$1=false
- case "$host" in
- $2) cpu_$1=true ;;
- esac
- AM_CONDITIONAL(AS_TR_CPP(ARCH_$1), [test "x$cpu_$1" = xtrue])
-])
diff --git a/man/gummiboot.xml b/man/gummiboot.xml
deleted file mode 100644
index 36552f8..0000000
--- a/man/gummiboot.xml
+++ /dev/null
@@ -1,137 +0,0 @@
-<?xml version='1.0'?> <!--*-nxml-*-->
-<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
-
-<!--
- Copyright 2013 Kay Sievers
-
- gummiboot 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.
-
- systemd 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 systemd; If not, see <http://www.gnu.org/licenses/>.
--->
-
-<refentry id="gummiboot">
- <refentryinfo>
- <title>gummiboot</title>
- <productname>gummiboot</productname>
-
- <authorgroup>
- <author>
- <contrib>Developer</contrib>
- <firstname>Kay</firstname>
- <surname>Sievers</surname>
- <email>kay@vrfy.org</email>
- </author>
- </authorgroup>
- </refentryinfo>
-
- <refmeta>
- <refentrytitle>gummiboot</refentrytitle>
- <manvolnum>8</manvolnum>
- </refmeta>
-
- <refnamediv>
- <refname>gummiboot</refname>
- <refpurpose>Setup and manage Gummiboot Boot Manager</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <cmdsynopsis>
- <command>gummiboot <arg choice="opt" rep="repeat">OPTIONS</arg>status</command>
- </cmdsynopsis>
- <cmdsynopsis>
- <command>gummiboot <arg choice="opt" rep="repeat">OPTIONS</arg>update</command>
- </cmdsynopsis>
- <cmdsynopsis>
- <command>gummiboot <arg choice="opt" rep="repeat">OPTIONS</arg>install</command>
- </cmdsynopsis>
- <cmdsynopsis>
- <command>gummiboot <arg choice="opt" rep="repeat">OPTIONS</arg>remove</command>
- </cmdsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Description</title>
-
- <para><command>gummiboot</command> checks, updates,
- installs or removes the boot loader from the current
- system.</para>
-
- <para><command>gummiboot status</command> checks and prints the
- currently installed versions of the boot loader binaries and the
- all current EFI boot variables.</para>
-
- <para><command>gummiboot update</command> updates all installed
- versions of gummiboot, if the current version is newer than the
- version installed in the EFI system partition. This also includes
- the EFI default/fallback loader at /EFI/Boot/boot*.efi. An
- gummiboot entry in the EFI boot variables is created, if there
- is no current entry. A created entry will be added to the end of
- the boot order list.</para>
-
- <para><command>gummiboot install</command> installs gummiboot into
- the EFI system partition. A copy of gummiboot will be stored as
- the EFI default/fallback loader at /EFI/Boot/boot*.efi. An gummiboot
- entry in the EFI boot variables is created and added to the top
- of the boot order list.</para>
-
- <para><command>gummiboot remove</command> removes all installed
- versions of gummiboot from the EFI system partition, and removes
- gummiboot from the EFI boot variables.</para>
-
- <para>If no command is passed <command>status</command> is
- implied.</para>
- </refsect1>
-
- <refsect1>
- <title>Options</title>
- <para>The following options are understood:</para>
-
- <variablelist>
- <varlistentry>
- <term><option>-h</option></term>
- <term><option>--help</option></term>
-
- <listitem><para>Prints a short help
- text and exits.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>--path</option></term>
- <listitem><para>Path to the EFI system
- partition. The default is /boot.</para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>--no-variables</option></term>
- <listitem><para>Do not touch the EFI boot
- variables.</para></listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Exit status</title>
- <para>On success 0 is returned, a non-zero failure
- code otherwise.</para>
- </refsect1>
-
- <refsect1>
- <title>See Also</title>
- <para>
- <ulink url="http://freedesktop.org/wiki/Software/gummiboot">Gummiboot wiki</ulink>
- <ulink url="http://www.freedesktop.org/wiki/Specifications/BootLoaderSpec">Boot loader specification</ulink>
- <ulink url="http://www.freedesktop.org/wiki/Software/systemd/BootLoaderInterface">Systemd boot loader interface</ulink>
- <citerefentry><refentrytitle>bootctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- </para>
- </refsect1>
-</refentry>
diff --git a/src/efi/console.c b/src/efi/console.c
deleted file mode 100644
index 6206c80..0000000
--- a/src/efi/console.c
+++ /dev/null
@@ -1,141 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/*
- * This program 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 program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * Copyright (C) 2012-2013 Kay Sievers <kay@vrfy.org>
- * Copyright (C) 2012 Harald Hoyer <harald@redhat.com>
- */
-
-#include <efi.h>
-#include <efilib.h>
-
-#include "util.h"
-#include "console.h"
-
-#define EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID \
- { 0xdd9e7534, 0x7762, 0x4698, { 0x8c, 0x14, 0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa } }
-
-struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL;
-
-typedef EFI_STATUS (EFIAPI *EFI_INPUT_RESET_EX)(
- struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This;
- BOOLEAN ExtendedVerification;
-);
-
-typedef UINT8 EFI_KEY_TOGGLE_STATE;
-
-typedef struct {
- UINT32 KeyShiftState;
- EFI_KEY_TOGGLE_STATE KeyToggleState;
-} EFI_KEY_STATE;
-
-typedef struct {
- EFI_INPUT_KEY Key;
- EFI_KEY_STATE KeyState;
-} EFI_KEY_DATA;
-
-typedef EFI_STATUS (EFIAPI *EFI_INPUT_READ_KEY_EX)(
- struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This;
- EFI_KEY_DATA *KeyData;
-);
-
-typedef EFI_STATUS (EFIAPI *EFI_SET_STATE)(
- struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This;
- EFI_KEY_TOGGLE_STATE *KeyToggleState;
-);
-
-typedef EFI_STATUS (EFIAPI *EFI_KEY_NOTIFY_FUNCTION)(
- EFI_KEY_DATA *KeyData;
-);
-
-typedef EFI_STATUS (EFIAPI *EFI_REGISTER_KEYSTROKE_NOTIFY)(
- struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This;
- EFI_KEY_DATA KeyData;
- EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction;
- VOID **NotifyHandle;
-);
-
-typedef EFI_STATUS (EFIAPI *EFI_UNREGISTER_KEYSTROKE_NOTIFY)(
- struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This;
- VOID *NotificationHandle;
-);
-
-typedef struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL {
- EFI_INPUT_RESET_EX Reset;
- EFI_INPUT_READ_KEY_EX ReadKeyStrokeEx;
- EFI_EVENT WaitForKeyEx;
- EFI_SET_STATE SetState;
- EFI_REGISTER_KEYSTROKE_NOTIFY RegisterKeyNotify;
- EFI_UNREGISTER_KEYSTROKE_NOTIFY UnregisterKeyNotify;
-} EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL;
-
-EFI_STATUS console_key_read(UINT64 *key, BOOLEAN wait) {
- EFI_GUID EfiSimpleTextInputExProtocolGuid = EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID;
- static EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInputEx;
- static BOOLEAN checked;
- UINTN index;
- EFI_INPUT_KEY k;
- EFI_STATUS err;
-
- if (!checked) {
- err = LibLocateProtocol(&EfiSimpleTextInputExProtocolGuid, (VOID **)&TextInputEx);
- if (EFI_ERROR(err))
- TextInputEx = NULL;
-
- checked = TRUE;
- }
-
- /* wait until key is pressed */
- if (wait) {
- if (TextInputEx)
- uefi_call_wrapper(BS->WaitForEvent, 3, 1, &TextInputEx->WaitForKeyEx, &index);
- else
- uefi_call_wrapper(BS->WaitForEvent, 3, 1, &ST->ConIn->WaitForKey, &index);
- }
-
- if (TextInputEx) {
- EFI_KEY_DATA keydata;
- UINT64 keypress;
-
- err = uefi_call_wrapper(TextInputEx->ReadKeyStrokeEx, 2, TextInputEx, &keydata);
- if (!EFI_ERROR(err)) {
- UINT32 shift = 0;
-
- /* do not distinguish between left and right keys */
- if (keydata.KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) {
- if (keydata.KeyState.KeyShiftState & (EFI_RIGHT_CONTROL_PRESSED|EFI_LEFT_CONTROL_PRESSED))
- shift |= EFI_CONTROL_PRESSED;
- if (keydata.KeyState.KeyShiftState & (EFI_RIGHT_ALT_PRESSED|EFI_LEFT_ALT_PRESSED))
- shift |= EFI_ALT_PRESSED;
- };
-
- /* 32 bit modifier keys + 16 bit scan code + 16 bit unicode */
- keypress = KEYPRESS(shift, keydata.Key.ScanCode, keydata.Key.UnicodeChar);
- if (keypress > 0) {
- *key = keypress;
- return 0;
- }
- }
- }
-
- /* fallback for firmware which does not support SimpleTextInputExProtocol
- *
- * This is also called in case ReadKeyStrokeEx did not return a key, because
- * some broken firmwares offer SimpleTextInputExProtocol, but never acually
- * handle any key. */
- err = uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, &k);
- if (EFI_ERROR(err))
- return err;
-
- *key = KEYPRESS(0, k.ScanCode, k.UnicodeChar);
- return 0;
-}
diff --git a/src/efi/console.h b/src/efi/console.h
deleted file mode 100644
index 8c2a31a..0000000
--- a/src/efi/console.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/*
- * This program 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 program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * Copyright (C) 2012-2013 Kay Sievers <kay@vrfy.org>
- * Copyright (C) 2012 Harald Hoyer <harald@redhat.com>
- */
-
-#ifndef __GUMMIBOOT_CONSOLE_H
-#define __GUMMIBOOT_CONSOLE_H
-
-#define EFI_SHIFT_STATE_VALID 0x80000000
-#define EFI_RIGHT_CONTROL_PRESSED 0x00000004
-#define EFI_LEFT_CONTROL_PRESSED 0x00000008
-#define EFI_RIGHT_ALT_PRESSED 0x00000010
-#define EFI_LEFT_ALT_PRESSED 0x00000020
-
-#define EFI_CONTROL_PRESSED (EFI_RIGHT_CONTROL_PRESSED|EFI_LEFT_CONTROL_PRESSED)
-#define EFI_ALT_PRESSED (EFI_RIGHT_ALT_PRESSED|EFI_LEFT_ALT_PRESSED)
-#define KEYPRESS(keys, scan, uni) ((((UINT64)keys) << 32) | ((scan) << 16) | (uni))
-#define KEYCHAR(k) ((k) & 0xffff)
-#define CHAR_CTRL(c) ((c) - 'a' + 1)
-
-EFI_STATUS console_key_read(UINT64 *key, BOOLEAN wait);
-#endif
diff --git a/src/efi/graphics.c b/src/efi/graphics.c
deleted file mode 100644
index 11305b8..0000000
--- a/src/efi/graphics.c
+++ /dev/null
@@ -1,389 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/*
- * This program 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 program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * Copyright (C) 2012-2013 Kay Sievers <kay@vrfy.org>
- * Copyright (C) 2012 Harald Hoyer <harald@redhat.com>
- * Copyright (C) 2013 Intel Corporation
- * Authored by Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
- */
-
-#include <efi.h>
-#include <efilib.h>
-
-#include "util.h"
-#include "graphics.h"
-
-EFI_STATUS graphics_mode(BOOLEAN on) {
- #define EFI_CONSOLE_CONTROL_PROTOCOL_GUID \
- { 0xf42f7782, 0x12e, 0x4c12, { 0x99, 0x56, 0x49, 0xf9, 0x43, 0x4, 0xf7, 0x21 } };
-
- struct _EFI_CONSOLE_CONTROL_PROTOCOL;
-
- typedef enum {
- EfiConsoleControlScreenText,
- EfiConsoleControlScreenGraphics,
- EfiConsoleControlScreenMaxValue,
- } EFI_CONSOLE_CONTROL_SCREEN_MODE;
-
- typedef EFI_STATUS (EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_GET_MODE)(
- struct _EFI_CONSOLE_CONTROL_PROTOCOL *This,
- EFI_CONSOLE_CONTROL_SCREEN_MODE *Mode,
- BOOLEAN *UgaExists,
- BOOLEAN *StdInLocked
- );
-
- typedef EFI_STATUS (EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_SET_MODE)(
- struct _EFI_CONSOLE_CONTROL_PROTOCOL *This,
- EFI_CONSOLE_CONTROL_SCREEN_MODE Mode
- );
-
- typedef EFI_STATUS (EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_LOCK_STD_IN)(
- struct _EFI_CONSOLE_CONTROL_PROTOCOL *This,
- CHAR16 *Password
- );
-
- typedef struct _EFI_CONSOLE_CONTROL_PROTOCOL {
- EFI_CONSOLE_CONTROL_PROTOCOL_GET_MODE GetMode;
- EFI_CONSOLE_CONTROL_PROTOCOL_SET_MODE SetMode;
- EFI_CONSOLE_CONTROL_PROTOCOL_LOCK_STD_IN LockStdIn;
- } EFI_CONSOLE_CONTROL_PROTOCOL;
-
- EFI_GUID ConsoleControlProtocolGuid = EFI_CONSOLE_CONTROL_PROTOCOL_GUID;
- EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL;
- EFI_CONSOLE_CONTROL_SCREEN_MODE new;
- EFI_CONSOLE_CONTROL_SCREEN_MODE current;
- BOOLEAN uga_exists;
- BOOLEAN stdin_locked;
- EFI_STATUS err;
-
- err = LibLocateProtocol(&ConsoleControlProtocolGuid, (VOID **)&ConsoleControl);
- if (EFI_ERROR(err)) {
- /* console control protocol is nonstandard and might not exist. */
- return err == EFI_NOT_FOUND ? EFI_SUCCESS : err;
- }
-
- /* check current mode */
- err = uefi_call_wrapper(ConsoleControl->GetMode, 4, ConsoleControl, &current, &uga_exists, &stdin_locked);
- if (EFI_ERROR(err))
- return err;
-
- /* do not touch the mode */
- new = on ? EfiConsoleControlScreenGraphics : EfiConsoleControlScreenText;
- if (new == current)
- return EFI_SUCCESS;
-
- err = uefi_call_wrapper(ConsoleControl->SetMode, 2, ConsoleControl, new);
-
- /* some firmware enables the cursor when switching modes */
- uefi_call_wrapper(ST->ConOut->EnableCursor, 2, ST->ConOut, FALSE);
-
- return err;
-}
-
-struct bmp_file {
- CHAR8 signature[2];
- UINT32 size;
- UINT16 reserved[2];
- UINT32 offset;
-} __attribute__((packed));
-
-/* we require at least BITMAPINFOHEADER, later versions are
- accepted, but their features ignored */
-struct bmp_dib {
- UINT32 size;
- UINT32 x;
- UINT32 y;
- UINT16 planes;
- UINT16 depth;
- UINT32 compression;
- UINT32 image_size;
- INT32 x_pixel_meter;
- INT32 y_pixel_meter;
- UINT32 colors_used;
- UINT32 colors_important;
-} __attribute__((packed));
-
-struct bmp_map {
- UINT8 blue;
- UINT8 green;
- UINT8 red;
- UINT8 reserved;
-} __attribute__((packed));
-
-EFI_STATUS bmp_parse_header(UINT8 *bmp, UINTN size, struct bmp_dib **ret_dib,
- struct bmp_map **ret_map, UINT8 **pixmap) {
- struct bmp_file *file;
- struct bmp_dib *dib;
- struct bmp_map *map;
- UINTN row_size;
-
- if (size < sizeof(struct bmp_file) + sizeof(struct bmp_dib))
- return EFI_INVALID_PARAMETER;
-
- /* check file header */
- file = (struct bmp_file *)bmp;
- if (file->signature[0] != 'B' || file->signature[1] != 'M')
- return EFI_INVALID_PARAMETER;
- if (file->size != size)
- return EFI_INVALID_PARAMETER;
- if (file->size < file->offset)
- return EFI_INVALID_PARAMETER;
-
- /* check device-independent bitmap */
- dib = (struct bmp_dib *)(bmp + sizeof(struct bmp_file));
- if (dib->size < sizeof(struct bmp_dib))
- return EFI_UNSUPPORTED;
-
- switch (dib->depth) {
- case 1:
- case 4:
- case 8:
- case 24:
- if (dib->compression != 0)
- return EFI_UNSUPPORTED;
-
- break;
-
- case 16:
- case 32:
- if (dib->compression != 0 && dib->compression != 3)
- return EFI_UNSUPPORTED;
-
- break;
-
- default:
- return EFI_UNSUPPORTED;
- }
-
- row_size = (((dib->depth * dib->x) + 31) / 32) * 4;
- if (file->size - file->offset < dib->y * row_size)
- return EFI_INVALID_PARAMETER;
- if (row_size * dib->y > 64 * 1024 * 1024)
- return EFI_INVALID_PARAMETER;
-
- /* check color table */
- map = (struct bmp_map *)(bmp + sizeof(struct bmp_file) + dib->size);
- if (file->offset < sizeof(struct bmp_file) + dib->size)
- return EFI_INVALID_PARAMETER;
-
- if (file->offset > sizeof(struct bmp_file) + dib->size) {
- UINT32 map_count;
- UINTN map_size;
-
- if (dib->colors_used)
- map_count = dib->colors_used;
- else {
- switch (dib->depth) {
- case 1:
- case 4:
- case 8:
- map_count = 1 << dib->depth;
- break;
-
- default:
- map_count = 0;
- break;
- }
- }
-
- map_size = file->offset - (sizeof(struct bmp_file) + dib->size);
- if (map_size != sizeof(struct bmp_map) * map_count)
- return EFI_INVALID_PARAMETER;
- }
-
- *ret_map = map;
- *ret_dib = dib;
- *pixmap = bmp + file->offset;
-
- return EFI_SUCCESS;
-}
-
-static VOID pixel_blend(UINT32 *dst, const UINT32 source) {
- UINT32 alpha, src, src_rb, src_g, dst_rb, dst_g, rb, g;
-
- alpha = (source & 0xff);
-
- /* convert src from RGBA to XRGB */
- src = source >> 8;
-
- /* decompose into RB and G components */
- src_rb = (src & 0xff00ff);
- src_g = (src & 0x00ff00);
-
- dst_rb = (*dst & 0xff00ff);
- dst_g = (*dst & 0x00ff00);
-
- /* blend */
- rb = ((((src_rb - dst_rb) * alpha + 0x800080) >> 8) + dst_rb) & 0xff00ff;
- g = ((((src_g - dst_g) * alpha + 0x008000) >> 8) + dst_g) & 0x00ff00;
-
- *dst = (rb | g);
-}
-
-EFI_STATUS bmp_to_blt(EFI_GRAPHICS_OUTPUT_BLT_PIXEL *buf,
- struct bmp_dib *dib, struct bmp_map *map,
- UINT8 *pixmap) {
- UINT8 *in;
- UINTN y;
-
- /* transform and copy pixels */
- in = pixmap;
- for (y = 0; y < dib->y; y++) {
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL *out;
- UINTN row_size;
- UINTN x;
-
- out = &buf[(dib->y - y - 1) * dib->x];
- for (x = 0; x < dib->x; x++, in++, out++) {
- switch (dib->depth) {
- case 1: {
- UINTN i;
-
- for (i = 0; i < 8 && x < dib->x; i++) {
- out->Red = map[((*in) >> (7 - i)) & 1].red;
- out->Green = map[((*in) >> (7 - i)) & 1].green;
- out->Blue = map[((*in) >> (7 - i)) & 1].blue;
- out++;
- x++;
- }
- out--;
- x--;
- break;
- }
-
- case 4: {
- UINTN i;
-
- i = (*in) >> 4;
- out->Red = map[i].red;
- out->Green = map[i].green;
- out->Blue = map[i].blue;
- if (x < (dib->x - 1)) {
- out++;
- x++;
- i = (*in) & 0x0f;
- out->Red = map[i].red;
- out->Green = map[i].green;
- out->Blue = map[i].blue;
- }
- break;
- }
-
- case 8:
- out->Red = map[*in].red;
- out->Green = map[*in].green;
- out->Blue = map[*in].blue;
- break;
-
- case 16: {
- UINT16 i = *(UINT16 *) in;
-
- out->Red = (i & 0x7c00) >> 7;
- out->Green = (i & 0x3e0) >> 2;
- out->Blue = (i & 0x1f) << 3;
- in += 1;
- break;
- }
-
- case 24:
- out->Red = in[2];
- out->Green = in[1];
- out->Blue = in[0];
- in += 2;
- break;
-
- case 32: {
- UINT32 i = *(UINT32 *) in;
-
- pixel_blend((UINT32 *)out, i);
-
- in += 3;
- break;
- }
- }
- }
-
- /* add row padding; new lines always start at 32 bit boundary */
- row_size = in - pixmap;
- in += ((row_size + 3) & ~3) - row_size;
- }
-
- return EFI_SUCCESS;
-}
-
-EFI_STATUS graphics_splash(EFI_FILE *root_dir, CHAR16 *path,
- const EFI_GRAPHICS_OUTPUT_BLT_PIXEL *background) {
- EFI_GUID GraphicsOutputProtocolGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
- EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput = NULL;
- UINT8 *content;
- INTN len;
- struct bmp_dib *dib;
- struct bmp_map *map;
- UINT8 *pixmap;
- UINT64 blt_size;
- VOID *blt = NULL;
- UINTN x_pos = 0;
- UINTN y_pos = 0;
- EFI_STATUS err;
-
- err = LibLocateProtocol(&GraphicsOutputProtocolGuid, (VOID **)&GraphicsOutput);
- if (EFI_ERROR(err))
- return err;
-
- len = file_read(root_dir, path, 0, 0, &content);
- if (len < 0)
- return EFI_LOAD_ERROR;
-
- err = bmp_parse_header(content, len, &dib, &map, &pixmap);
- if (EFI_ERROR(err))
- goto err;
-
- if(dib->x < GraphicsOutput->Mode->Info->HorizontalResolution)
- x_pos = (GraphicsOutput->Mode->Info->HorizontalResolution - dib->x) / 2;
- if(dib->y < GraphicsOutput->Mode->Info->VerticalResolution)
- y_pos = (GraphicsOutput->Mode->Info->VerticalResolution - dib->y) / 2;
-
- uefi_call_wrapper(GraphicsOutput->Blt, 10, GraphicsOutput,
- (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)background,
- EfiBltVideoFill, 0, 0, 0, 0,
- GraphicsOutput->Mode->Info->HorizontalResolution,
- GraphicsOutput->Mode->Info->VerticalResolution, 0);
-
- /* EFI buffer */
- blt_size = dib->x * dib->y * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
- blt = AllocatePool(blt_size);
- if (!blt)
- return EFI_OUT_OF_RESOURCES;
-
- err = uefi_call_wrapper(GraphicsOutput->Blt, 10, GraphicsOutput,
- blt, EfiBltVideoToBltBuffer, x_pos, y_pos, 0, 0,
- dib->x, dib->y, 0);
- if (EFI_ERROR(err))
- goto err;
-
- err = bmp_to_blt(blt, dib, map, pixmap);
- if (EFI_ERROR(err))
- goto err;
-
- err = graphics_mode(TRUE);
- if (EFI_ERROR(err))
- goto err;
-
- err = uefi_call_wrapper(GraphicsOutput->Blt, 10, GraphicsOutput,
- blt, EfiBltBufferToVideo, 0, 0, x_pos, y_pos,
- dib->x, dib->y, 0);
-err:
- FreePool(blt);
- FreePool(content);
- return err;
-}
diff --git a/src/efi/graphics.h b/src/efi/graphics.h
deleted file mode 100644
index edec1f4..0000000
--- a/src/efi/graphics.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/*
- * This program 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 program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * Copyright (C) 2012-2013 Kay Sievers <kay@vrfy.org>
- * Copyright (C) 2012 Harald Hoyer <harald@redhat.com>
- * Copyright (C) 2013 Intel Corporation
- * Authored by Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
- */
-
-#ifndef __GUMMIBOOT_GRAPHICS_H
-#define __GUMMIBOOT_GRAPHICS_H
-
-EFI_STATUS graphics_mode(BOOLEAN on);
-EFI_STATUS graphics_splash(EFI_FILE *root_dir, CHAR16 *path,
- const EFI_GRAPHICS_OUTPUT_BLT_PIXEL *background);
-#endif
diff --git a/src/efi/gummiboot.c b/src/efi/gummiboot.c
deleted file mode 100644
index be5765c..0000000
--- a/src/efi/gummiboot.c
+++ /dev/null
@@ -1,2047 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/*
- * Simple UEFI boot loader which executes configured EFI images, where the
- * default entry is selected by a configured pattern (glob) or an on-screen
- * menu.
- *
- * All gummiboot code is LGPL not GPL, to stay out of politics and to give
- * the freedom of copying code from programs to possible future libraries.
- *
- * This program 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 program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * Copyright (C) 2012-2013 Kay Sievers <kay@vrfy.org>
- * Copyright (C) 2012 Harald Hoyer <harald@redhat.com>
- *
- * "Any intelligent fool can make things bigger, more complex, and more violent."
- * -- Albert Einstein
- */
-
-#include <efi.h>
-#include <efilib.h>
-
-#include "util.h"
-#include "console.h"
-#include "graphics.h"
-#include "pefile.h"
-#include "linux.h"
-
-#ifndef EFI_OS_INDICATIONS_BOOT_TO_FW_UI
-#define EFI_OS_INDICATIONS_BOOT_TO_FW_UI 0x0000000000000001ULL
-#endif
-
-#ifndef EFI_SECURITY_VIOLATION
-#define EFI_SECURITY_VIOLATION EFIERR(26)
-#endif
-
-/* magic string to find in the binary image */
-static const char __attribute__((used)) magic[] = "#### LoaderInfo: gummiboot " VERSION " ####";
-
-static const EFI_GUID global_guid = EFI_GLOBAL_VARIABLE;
-
-enum loader_type {
- LOADER_UNDEFINED,
- LOADER_EFI,
- LOADER_LINUX
-};
-
-typedef struct {
- CHAR16 *file;
- CHAR16 *title_show;
- CHAR16 *title;
- CHAR16 *version;
- CHAR16 *machine_id;
- EFI_HANDLE *device;
- enum loader_type type;
- CHAR16 *loader;
- CHAR16 *options;
- CHAR16 *splash;
- CHAR16 key;
- EFI_STATUS (*call)(VOID);
- BOOLEAN no_autoselect;
- BOOLEAN non_unique;
-} ConfigEntry;
-
-typedef struct {
- ConfigEntry **entries;
- UINTN entry_count;
- INTN idx_default;
- INTN idx_default_efivar;
- UINTN timeout_sec;
- UINTN timeout_sec_config;
- INTN timeout_sec_efivar;
- CHAR16 *entry_default_pattern;
- CHAR16 *splash;
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL *background;
- CHAR16 *entry_oneshot;
- CHAR16 *options_edit;
- CHAR16 *entries_auto;
- BOOLEAN no_editor;
-} Config;
-
-static VOID cursor_left(UINTN *cursor, UINTN *first)
-{
- if ((*cursor) > 0)
- (*cursor)--;
- else if ((*first) > 0)
- (*first)--;
-}
-
-static VOID cursor_right(UINTN *cursor, UINTN *first, UINTN x_max, UINTN len)
-{
- if ((*cursor)+1 < x_max)
- (*cursor)++;
- else if ((*first) + (*cursor) < len)
- (*first)++;
-}
-
-static BOOLEAN line_edit(CHAR16 *line_in, CHAR16 **line_out, UINTN x_max, UINTN y_pos) {
- CHAR16 *line;
- UINTN size;
- UINTN len;
- UINTN first;
- CHAR16 *print;
- UINTN cursor;
- UINTN clear;
- BOOLEAN exit;
- BOOLEAN enter;
-
- if (!line_in)
- line_in = L"";
- size = StrLen(line_in) + 1024;
- line = AllocatePool(size * sizeof(CHAR16));
- StrCpy(line, line_in);
- len = StrLen(line);
- print = AllocatePool((x_max+1) * sizeof(CHAR16));
-
- uefi_call_wrapper(ST->ConOut->EnableCursor, 2, ST->ConOut, TRUE);
-
- first = 0;
- cursor = 0;
- clear = 0;
- enter = FALSE;
- exit = FALSE;
- while (!exit) {
- EFI_STATUS err;
- UINT64 key;
- UINTN i;
-
- i = len - first;
- if (i >= x_max-1)
- i = x_max-1;
- CopyMem(print, line + first, i * sizeof(CHAR16));
- while (clear > 0 && i < x_max-1) {
- clear--;
- print[i++] = ' ';
- }
- print[i] = '\0';
-
- uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, y_pos);
- uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, print);
- uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, cursor, y_pos);
-
- err = console_key_read(&key, TRUE);
- if (EFI_ERROR(err))
- continue;
-
- switch (key) {
- case KEYPRESS(0, SCAN_ESC, 0):
- case KEYPRESS(EFI_CONTROL_PRESSED, 0, 'c'):
- case KEYPRESS(EFI_CONTROL_PRESSED, 0, 'g'):
- case KEYPRESS(EFI_CONTROL_PRESSED, 0, CHAR_CTRL('c')):
- case KEYPRESS(EFI_CONTROL_PRESSED, 0, CHAR_CTRL('g')):
- exit = TRUE;
- break;
-
- case KEYPRESS(0, SCAN_HOME, 0):
- case KEYPRESS(EFI_CONTROL_PRESSED, 0, 'a'):
- case KEYPRESS(EFI_CONTROL_PRESSED, 0, CHAR_CTRL('a')):
- /* beginning-of-line */
- cursor = 0;
- first = 0;
- continue;
-
- case KEYPRESS(0, SCAN_END, 0):
- case KEYPRESS(EFI_CONTROL_PRESSED, 0, 'e'):
- case KEYPRESS(EFI_CONTROL_PRESSED, 0, CHAR_CTRL('e')):
- /* end-of-line */
- cursor = len - first;
- if (cursor+1 >= x_max) {
- cursor = x_max-1;
- first = len - (x_max-1);
- }
- continue;
-
- case KEYPRESS(0, SCAN_DOWN, 0):
- case KEYPRESS(EFI_ALT_PRESSED, 0, 'f'):
- case KEYPRESS(EFI_CONTROL_PRESSED, SCAN_RIGHT, 0):
- /* forward-word */
- while (line[first + cursor] && line[first + cursor] == ' ')
- cursor_right(&cursor, &first, x_max, len);
- while (line[first + cursor] && line[first + cursor] != ' ')
- cursor_right(&cursor, &first, x_max, len);
- uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, cursor, y_pos);
- continue;
-
- case KEYPRESS(0, SCAN_UP, 0):
- case KEYPRESS(EFI_ALT_PRESSED, 0, 'b'):
- case KEYPRESS(EFI_CONTROL_PRESSED, SCAN_LEFT, 0):
- /* backward-word */
- if ((first + cursor) > 0 && line[first + cursor-1] == ' ') {
- cursor_left(&cursor, &first);
- while ((first + cursor) > 0 && line[first + cursor] == ' ')
- cursor_left(&cursor, &first);
- }
- while ((first + cursor) > 0 && line[first + cursor-1] != ' ')
- cursor_left(&cursor, &first);
- uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, cursor, y_pos);
- continue;
-
- case KEYPRESS(0, SCAN_RIGHT, 0):
- case KEYPRESS(EFI_CONTROL_PRESSED, 0, 'f'):
- case KEYPRESS(EFI_CONTROL_PRESSED, 0, CHAR_CTRL('f')):
- /* forward-char */
- if (first + cursor == len)
- continue;
- cursor_right(&cursor, &first, x_max, len);
- uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, cursor, y_pos);
- continue;
-
- case KEYPRESS(0, SCAN_LEFT, 0):
- case KEYPRESS(EFI_CONTROL_PRESSED, 0, 'b'):
- case KEYPRESS(EFI_CONTROL_PRESSED, 0, CHAR_CTRL('b')):
- /* backward-char */
- cursor_left(&cursor, &first);
- uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, cursor, y_pos);
- continue;
-
- case KEYPRESS(EFI_ALT_PRESSED, 0, 'd'):
- /* kill-word */
- clear = 0;
- for (i = first + cursor; i < len && line[i] == ' '; i++)
- clear++;
- for (; i < len && line[i] != ' '; i++)
- clear++;
-
- for (i = first + cursor; i + clear < len; i++)
- line[i] = line[i + clear];
- len -= clear;
- line[len] = '\0';
- continue;
-
- case KEYPRESS(EFI_CONTROL_PRESSED, 0, 'w'):
- case KEYPRESS(EFI_CONTROL_PRESSED, 0, CHAR_CTRL('w')):
- case KEYPRESS(EFI_ALT_PRESSED, 0, CHAR_BACKSPACE):
- /* backward-kill-word */
- clear = 0;
- if ((first + cursor) > 0 && line[first + cursor-1] == ' ') {
- cursor_left(&cursor, &first);
- clear++;
- while ((first + cursor) > 0 && line[first + cursor] == ' ') {
- cursor_left(&cursor, &first);
- clear++;
- }
- }
- while ((first + cursor) > 0 && line[first + cursor-1] != ' ') {
- cursor_left(&cursor, &first);
- clear++;
- }
- uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, cursor, y_pos);
-
- for (i = first + cursor; i + clear < len; i++)
- line[i] = line[i + clear];
- len -= clear;
- line[len] = '\0';
- continue;
-
- case KEYPRESS(0, SCAN_DELETE, 0):
- case KEYPRESS(EFI_CONTROL_PRESSED, 0, 'd'):
- case KEYPRESS(EFI_CONTROL_PRESSED, 0, CHAR_CTRL('d')):
- if (len == 0)
- continue;
- if (first + cursor == len)
- continue;
- for (i = first + cursor; i < len; i++)
- line[i] = line[i+1];
- clear = 1;
- len--;
- continue;
-
- case KEYPRESS(EFI_CONTROL_PRESSED, 0, 'k'):
- case KEYPRESS(EFI_CONTROL_PRESSED, 0, CHAR_CTRL('k')):
- /* kill-line */
- line[first + cursor] = '\0';
- clear = len - (first + cursor);
- len = first + cursor;
- continue;
-
- case KEYPRESS(0, 0, CHAR_LINEFEED):
- case KEYPRESS(0, 0, CHAR_CARRIAGE_RETURN):
- if (StrCmp(line, line_in) != 0) {
- *line_out = line;
- line = NULL;
- }
- enter = TRUE;
- exit = TRUE;
- break;
-
- case KEYPRESS(0, 0, CHAR_BACKSPACE):
- if (len == 0)
- continue;
- if (first == 0 && cursor == 0)
- continue;
- for (i = first + cursor-1; i < len; i++)
- line[i] = line[i+1];
- clear = 1;
- len--;
- if (cursor > 0)
- cursor--;
- if (cursor > 0 || first == 0)
- continue;
- /* show full line if it fits */
- if (len < x_max) {
- cursor = first;
- first = 0;
- continue;
- }
- /* jump left to see what we delete */
- if (first > 10) {
- first -= 10;
- cursor = 10;
- } else {
- cursor = first;
- first = 0;
- }
- continue;
-
- case KEYPRESS(0, 0, ' ') ... KEYPRESS(0, 0, '~'):
- case KEYPRESS(0, 0, 0x80) ... KEYPRESS(0, 0, 0xffff):
- if (len+1 == size)
- continue;
- for (i = len; i > first + cursor; i--)
- line[i] = line[i-1];
- line[first + cursor] = KEYCHAR(key);
- len++;
- line[len] = '\0';
- if (cursor+1 < x_max)
- cursor++;
- else if (first + cursor < len)
- first++;
- continue;
- }
- }
-
- uefi_call_wrapper(ST->ConOut->EnableCursor, 2, ST->ConOut, FALSE);
- FreePool(print);
- FreePool(line);
- return enter;
-}
-
-static UINTN entry_lookup_key(Config *config, UINTN start, CHAR16 key) {
- UINTN i;
-
- if (key == 0)
- return -1;
-
- /* select entry by number key */
- if (key >= '1' && key <= '9') {
- i = key - '0';
- if (i > config->entry_count)
- i = config->entry_count;
- return i-1;
- }
-
- /* find matching key in config entries */
- for (i = start; i < config->entry_count; i++)
- if (config->entries[i]->key == key)
- return i;
-
- for (i = 0; i < start; i++)
- if (config->entries[i]->key == key)
- return i;
-
- return -1;
-}
-
-static VOID print_status(Config *config, EFI_FILE *root_dir, CHAR16 *loaded_image_path) {
- UINT64 key;
- UINTN i;
- CHAR16 *s;
- CHAR8 *b;
- UINTN x;
- UINTN y;
- UINTN size;
- EFI_STATUS err;
- UINTN color = 0;
- const EFI_GRAPHICS_OUTPUT_BLT_PIXEL *pixel = config->background;
-
- uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_LIGHTGRAY|EFI_BACKGROUND_BLACK);
- uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
-
- /* show splash and wait for key */
- for (;;) {
- static const EFI_GRAPHICS_OUTPUT_BLT_PIXEL colors[] = {
- { .Red = 0xff, .Green = 0xff, .Blue = 0xff },
- { .Red = 0xc0, .Green = 0xc0, .Blue = 0xc0 },
- { .Red = 0xff, .Green = 0, .Blue = 0 },
- { .Red = 0, .Green = 0xff, .Blue = 0 },
- { .Red = 0, .Green = 0, .Blue = 0xff },
- { .Red = 0, .Green = 0, .Blue = 0 },
- };
-
- err = EFI_NOT_FOUND;
- if (config->splash)
- err = graphics_splash(root_dir, config->splash, pixel);
- if (EFI_ERROR(err))
- err = graphics_splash(root_dir, L"\\EFI\\gummiboot\\splash.bmp", pixel);
- if (EFI_ERROR(err))
- break;
-
- /* 'b' rotates through background colors */
- console_key_read(&key, TRUE);
- if (key == KEYPRESS(0, 0, 'b')) {
- pixel = &colors[color++];
- if (color == ELEMENTSOF(colors))
- color = 0;
-
- continue;
- }
-
- graphics_mode(FALSE);
- uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
- break;
- }
-
- Print(L"gummiboot version: " VERSION "\n");
- Print(L"gummiboot architecture: " MACHINE_TYPE_NAME "\n");
- Print(L"loaded image: %s\n", loaded_image_path);
- Print(L"UEFI specification: %d.%02d\n", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff);
- Print(L"firmware vendor: %s\n", ST->FirmwareVendor);
- Print(L"firmware version: %d.%02d\n", ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
-
- if (uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut, ST->ConOut->Mode->Mode, &x, &y) == EFI_SUCCESS)
- Print(L"console size: %d x %d\n", x, y);
-
- if (efivar_get_raw(&global_guid, L"SecureBoot", &b, &size) == EFI_SUCCESS) {
- Print(L"SecureBoot: %s\n", yes_no(*b > 0));
- FreePool(b);
- }
-
- if (efivar_get_raw(&global_guid, L"SetupMode", &b, &size) == EFI_SUCCESS) {
- Print(L"SetupMode: %s\n", *b > 0 ? L"setup" : L"user");
- FreePool(b);
- }
-
- if (efivar_get_raw(&global_guid, L"OsIndicationsSupported", &b, &size) == EFI_SUCCESS) {
- Print(L"OsIndicationsSupported: %d\n", (UINT64)*b);
- FreePool(b);
- }
- Print(L"\n");
-
- Print(L"timeout: %d\n", config->timeout_sec);
- if (config->timeout_sec_efivar >= 0)
- Print(L"timeout (EFI var): %d\n", config->timeout_sec_efivar);
- Print(L"timeout (config): %d\n", config->timeout_sec_config);
- if (config->entry_default_pattern)
- Print(L"default pattern: '%s'\n", config->entry_default_pattern);
- if (config->splash)
- Print(L"splash '%s'\n", config->splash);
- if (config->background)
- Print(L"background '#%02x%02x%02x'\n",
- config->background->Red,
- config->background->Green,
- config->background->Blue);
- Print(L"editor: %s\n", yes_no(!config->no_editor));
- Print(L"\n");
-
- Print(L"config entry count: %d\n", config->entry_count);
- Print(L"entry selected idx: %d\n", config->idx_default);
- if (config->idx_default_efivar >= 0)
- Print(L"entry EFI var idx: %d\n", config->idx_default_efivar);
- Print(L"\n");
-
- if (efivar_get_int(L"LoaderConfigTimeout", &i) == EFI_SUCCESS)
- Print(L"LoaderConfigTimeout: %d\n", i);
- if (config->entry_oneshot)
- Print(L"LoaderEntryOneShot: %s\n", config->entry_oneshot);
- if (efivar_get(L"LoaderDeviceIdentifier", &s) == EFI_SUCCESS) {
- Print(L"LoaderDeviceIdentifier: %s\n", s);
- FreePool(s);
- }
- if (efivar_get(L"LoaderDevicePartUUID", &s) == EFI_SUCCESS) {
- Print(L"LoaderDevicePartUUID: %s\n", s);
- FreePool(s);
- }
- if (efivar_get(L"LoaderEntryDefault", &s) == EFI_SUCCESS) {
- Print(L"LoaderEntryDefault: %s\n", s);
- FreePool(s);
- }
-
- Print(L"\n--- press key ---\n\n");
- console_key_read(&key, TRUE);
-
- for (i = 0; i < config->entry_count; i++) {
- ConfigEntry *entry;
-
- if (key == KEYPRESS(0, SCAN_ESC, 0) || key == KEYPRESS(0, 0, 'q'))
- break;
-
- entry = config->entries[i];
-
- if (entry->splash) {
- err = graphics_splash(root_dir, entry->splash, config->background);
- if (!EFI_ERROR(err)) {
- console_key_read(&key, TRUE);
- graphics_mode(FALSE);
- }
- }
-
- Print(L"config entry: %d/%d\n", i+1, config->entry_count);
- if (entry->file)
- Print(L"file '%s'\n", entry->file);
- Print(L"title show '%s'\n", entry->title_show);
- if (entry->title)
- Print(L"title '%s'\n", entry->title);
- if (entry->version)
- Print(L"version '%s'\n", entry->version);
- if (entry->machine_id)
- Print(L"machine-id '%s'\n", entry->machine_id);
- if (entry->device) {
- EFI_DEVICE_PATH *device_path;
- CHAR16 *str;
-
- device_path = DevicePathFromHandle(entry->device);
- if (device_path) {
- str = DevicePathToStr(device_path);
- Print(L"device handle '%s'\n", str);
- FreePool(str);
- }
- }
- if (entry->loader)
- Print(L"loader '%s'\n", entry->loader);
- if (entry->options)
- Print(L"options '%s'\n", entry->options);
- if (entry->splash)
- Print(L"splash '%s'\n", entry->splash);
- Print(L"auto-select %s\n", yes_no(!entry->no_autoselect));
- if (entry->call)
- Print(L"internal call yes\n");
-
- Print(L"\n--- press key ---\n\n");
- console_key_read(&key, TRUE);
- }
-
- uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
-}
-
-static BOOLEAN menu_run(Config *config, ConfigEntry **chosen_entry, EFI_FILE *root_dir, CHAR16 *loaded_image_path) {
- EFI_STATUS err;
- UINTN visible_max;
- UINTN idx_highlight;
- UINTN idx_highlight_prev;
- UINTN idx_first;
- UINTN idx_last;
- BOOLEAN refresh;
- BOOLEAN highlight;
- UINTN i;
- UINTN line_width;
- CHAR16 **lines;
- UINTN x_start;
- UINTN y_start;
- UINTN x_max;
- UINTN y_max;
- CHAR16 *status;
- CHAR16 *clearline;
- INTN timeout_remain;
- INT16 idx;
- BOOLEAN exit = FALSE;
- BOOLEAN run = TRUE;
- BOOLEAN wait = FALSE;
-
- graphics_mode(FALSE);
- uefi_call_wrapper(ST->ConIn->Reset, 2, ST->ConIn, FALSE);
- uefi_call_wrapper(ST->ConOut->EnableCursor, 2, ST->ConOut, FALSE);
- uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_LIGHTGRAY|EFI_BACKGROUND_BLACK);
-
- /* draw a single character to make ClearScreen work on some firmware */
- uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, L" ");
- uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
-
- err = uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut, ST->ConOut->Mode->Mode, &x_max, &y_max);
- if (EFI_ERROR(err)) {
- x_max = 80;
- y_max = 25;
- }
-
- /* we check 10 times per second for a keystroke */
- if (config->timeout_sec > 0)
- timeout_remain = config->timeout_sec * 10;
- else
- timeout_remain = -1;
-
- idx_highlight = config->idx_default;
- idx_highlight_prev = 0;
-
- visible_max = y_max - 2;
-
- if ((UINTN)config->idx_default >= visible_max)
- idx_first = config->idx_default-1;
- else
- idx_first = 0;
-
- idx_last = idx_first + visible_max-1;
-
- refresh = TRUE;
- highlight = FALSE;
-
- /* length of the longest entry */
- line_width = 5;
- for (i = 0; i < config->entry_count; i++) {
- UINTN entry_len;
-
- entry_len = StrLen(config->entries[i]->title_show);
- if (line_width < entry_len)
- line_width = entry_len;
- }
- if (line_width > x_max-6)
- line_width = x_max-6;
-
- /* offsets to center the entries on the screen */
- x_start = (x_max - (line_width)) / 2;
- if (config->entry_count < visible_max)
- y_start = ((visible_max - config->entry_count) / 2) + 1;
- else
- y_start = 0;
-
- /* menu entries title lines */
- lines = AllocatePool(sizeof(CHAR16 *) * config->entry_count);
- for (i = 0; i < config->entry_count; i++) {
- UINTN j, k;
-
- lines[i] = AllocatePool(((x_max+1) * sizeof(CHAR16)));
- for (j = 0; j < x_start; j++)
- lines[i][j] = ' ';
-
- for (k = 0; config->entries[i]->title_show[k] != '\0' && j < x_max; j++, k++)
- lines[i][j] = config->entries[i]->title_show[k];
-
- for (; j < x_max; j++)
- lines[i][j] = ' ';
- lines[i][x_max] = '\0';
- }
-
- status = NULL;
- clearline = AllocatePool((x_max+1) * sizeof(CHAR16));
- for (i = 0; i < x_max; i++)
- clearline[i] = ' ';
- clearline[i] = 0;
-
- while (!exit) {
- UINT64 key;
-
- if (refresh) {
- for (i = 0; i < config->entry_count; i++) {
- if (i < idx_first || i > idx_last)
- continue;
- uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, y_start + i - idx_first);
- if (i == idx_highlight)
- uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut,
- EFI_BLACK|EFI_BACKGROUND_LIGHTGRAY);
- else
- uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut,
- EFI_LIGHTGRAY|EFI_BACKGROUND_BLACK);
- uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, lines[i]);
- if ((INTN)i == config->idx_default_efivar) {
- uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, x_start-3, y_start + i - idx_first);
- uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, L"=>");
- }
- }
- refresh = FALSE;
- } else if (highlight) {
- uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, y_start + idx_highlight_prev - idx_first);
- uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_LIGHTGRAY|EFI_BACKGROUND_BLACK);
- uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, lines[idx_highlight_prev]);
- if ((INTN)idx_highlight_prev == config->idx_default_efivar) {
- uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, x_start-3, y_start + idx_highlight_prev - idx_first);
- uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, L"=>");
- }
-
- uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, y_start + idx_highlight - idx_first);
- uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_BLACK|EFI_BACKGROUND_LIGHTGRAY);
- uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, lines[idx_highlight]);
- if ((INTN)idx_highlight == config->idx_default_efivar) {
- uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, x_start-3, y_start + idx_highlight - idx_first);
- uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, L"=>");
- }
- highlight = FALSE;
- }
-
- if (timeout_remain > 0) {
- FreePool(status);
- status = PoolPrint(L"Boot in %d sec.", (timeout_remain + 5) / 10);
- }
-
- /* print status at last line of screen */
- if (status) {
- UINTN len;
- UINTN x;
-
- /* center line */
- len = StrLen(status);
- if (len < x_max)
- x = (x_max - len) / 2;
- else
- x = 0;
- uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_LIGHTGRAY|EFI_BACKGROUND_BLACK);
- uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, y_max-1);
- uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, clearline + (x_max - x));
- uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, status);
- uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, clearline+1 + x + len);
- }
-
- err = console_key_read(&key, wait);
- if (EFI_ERROR(err)) {
- /* timeout reached */
- if (timeout_remain == 0) {
- exit = TRUE;
- break;
- }
-
- /* sleep and update status */
- if (timeout_remain > 0) {
- uefi_call_wrapper(BS->Stall, 1, 100 * 1000);
- timeout_remain--;
- continue;
- }
-
- /* timeout disabled, wait for next key */
- wait = TRUE;
- continue;
- }
-
- timeout_remain = -1;
-
- /* clear status after keystroke */
- if (status) {
- FreePool(status);
- status = NULL;
- uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_LIGHTGRAY|EFI_BACKGROUND_BLACK);
- uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, y_max-1);
- uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, clearline+1);
- }
-
- idx_highlight_prev = idx_highlight;
-
- switch (key) {
- case KEYPRESS(0, SCAN_UP, 0):
- case KEYPRESS(0, 0, 'k'):
- if (idx_highlight > 0)
- idx_highlight--;
- break;
-
- case KEYPRESS(0, SCAN_DOWN, 0):
- case KEYPRESS(0, 0, 'j'):
- if (idx_highlight < config->entry_count-1)
- idx_highlight++;
- break;
-
- case KEYPRESS(0, SCAN_HOME, 0):
- case KEYPRESS(EFI_ALT_PRESSED, 0, '<'):
- if (idx_highlight > 0) {
- refresh = TRUE;
- idx_highlight = 0;
- }
- break;
-
- case KEYPRESS(0, SCAN_END, 0):
- case KEYPRESS(EFI_ALT_PRESSED, 0, '>'):
- if (idx_highlight < config->entry_count-1) {
- refresh = TRUE;
- idx_highlight = config->entry_count-1;
- }
- break;
-
- case KEYPRESS(0, SCAN_PAGE_UP, 0):
- if (idx_highlight > visible_max)
- idx_highlight -= visible_max;
- else
- idx_highlight = 0;
- break;
-
- case KEYPRESS(0, SCAN_PAGE_DOWN, 0):
- idx_highlight += visible_max;
- if (idx_highlight > config->entry_count-1)
- idx_highlight = config->entry_count-1;
- break;
-
- case KEYPRESS(0, 0, CHAR_LINEFEED):
- case KEYPRESS(0, 0, CHAR_CARRIAGE_RETURN):
- exit = TRUE;
- break;
-
- case KEYPRESS(0, SCAN_F1, 0):
- case KEYPRESS(0, 0, 'h'):
- case KEYPRESS(0, 0, '?'):
- status = StrDuplicate(L"(d)efault, (t/T)timeout, (e)dit, (v)ersion (Q)uit (P)rint (h)elp");
- break;
-
- case KEYPRESS(0, 0, 'Q'):
- exit = TRUE;
- run = FALSE;
- break;
-
- case KEYPRESS(0, 0, 'd'):
- if (config->idx_default_efivar != (INTN)idx_highlight) {
- /* store the selected entry in a persistent EFI variable */
- efivar_set(L"LoaderEntryDefault", config->entries[idx_highlight]->file, TRUE);
- config->idx_default_efivar = idx_highlight;
- status = StrDuplicate(L"Default boot entry selected.");
- } else {
- /* clear the default entry EFI variable */
- efivar_set(L"LoaderEntryDefault", NULL, TRUE);
- config->idx_default_efivar = -1;
- status = StrDuplicate(L"Default boot entry cleared.");
- }
- refresh = TRUE;
- break;
-
- case KEYPRESS(0, 0, '-'):
- case KEYPRESS(0, 0, 'T'):
- if (config->timeout_sec_efivar > 0) {
- config->timeout_sec_efivar--;
- efivar_set_int(L"LoaderConfigTimeout", config->timeout_sec_efivar, TRUE);
- if (config->timeout_sec_efivar > 0)
- status = PoolPrint(L"Menu timeout set to %d sec.", config->timeout_sec_efivar);
- else
- status = StrDuplicate(L"Menu disabled. Hold down key at bootup to show menu.");
- } else if (config->timeout_sec_efivar <= 0){
- config->timeout_sec_efivar = -1;
- efivar_set(L"LoaderConfigTimeout", NULL, TRUE);
- if (config->timeout_sec_config > 0)
- status = PoolPrint(L"Menu timeout of %d sec is defined by configuration file.",
- config->timeout_sec_config);
- else
- status = StrDuplicate(L"Menu disabled. Hold down key at bootup to show menu.");
- }
- break;
-
- case KEYPRESS(0, 0, '+'):
- case KEYPRESS(0, 0, 't'):
- if (config->timeout_sec_efivar == -1 && config->timeout_sec_config == 0)
- config->timeout_sec_efivar++;
- config->timeout_sec_efivar++;
- efivar_set_int(L"LoaderConfigTimeout", config->timeout_sec_efivar, TRUE);
- if (config->timeout_sec_efivar > 0)
- status = PoolPrint(L"Menu timeout set to %d sec.",
- config->timeout_sec_efivar);
- else
- status = StrDuplicate(L"Menu disabled. Hold down key at bootup to show menu.");
- break;
-
- case KEYPRESS(0, 0, 'e'):
- /* only the options of configured entries can be edited */
- if (config->no_editor || config->entries[idx_highlight]->type == LOADER_UNDEFINED)
- break;
- uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_LIGHTGRAY|EFI_BACKGROUND_BLACK);
- uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, y_max-1);
- uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, clearline+1);
- if (line_edit(config->entries[idx_highlight]->options, &config->options_edit, x_max-1, y_max-1))
- exit = TRUE;
- uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, y_max-1);
- uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, clearline+1);
- break;
-
- case KEYPRESS(0, 0, 'v'):
- status = PoolPrint(L"gummiboot " VERSION " (" MACHINE_TYPE_NAME "), UEFI Specification %d.%02d, Vendor %s %d.%02d",
- ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff,
- ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
- break;
-
- case KEYPRESS(0, 0, 'P'):
- print_status(config, root_dir, loaded_image_path);
- refresh = TRUE;
- break;
-
- case KEYPRESS(EFI_CONTROL_PRESSED, 0, 'l'):
- case KEYPRESS(EFI_CONTROL_PRESSED, 0, CHAR_CTRL('l')):
- refresh = TRUE;
- break;
-
- default:
- /* jump with a hotkey directly to a matching entry */
- idx = entry_lookup_key(config, idx_highlight+1, KEYCHAR(key));
- if (idx < 0)
- break;
- idx_highlight = idx;
- refresh = TRUE;
- }
-
- if (idx_highlight > idx_last) {
- idx_last = idx_highlight;
- idx_first = 1 + idx_highlight - visible_max;
- refresh = TRUE;
- }
- if (idx_highlight < idx_first) {
- idx_first = idx_highlight;
- idx_last = idx_highlight + visible_max-1;
- refresh = TRUE;
- }
-
- idx_last = idx_first + visible_max-1;
-
- if (!refresh && idx_highlight != idx_highlight_prev)
- highlight = TRUE;
- }
-
- *chosen_entry = config->entries[idx_highlight];
-
- for (i = 0; i < config->entry_count; i++)
- FreePool(lines[i]);
- FreePool(lines);
- FreePool(clearline);
-
- uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_WHITE|EFI_BACKGROUND_BLACK);
- uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
- return run;
-}
-
-static VOID config_add_entry(Config *config, ConfigEntry *entry) {
- if ((config->entry_count & 15) == 0) {
- UINTN i;
-
- i = config->entry_count + 16;
- if (config->entry_count == 0)
- config->entries = AllocatePool(sizeof(VOID *) * i);
- else
- config->entries = ReallocatePool(config->entries,
- sizeof(VOID *) * config->entry_count, sizeof(VOID *) * i);
- }
- config->entries[config->entry_count++] = entry;
-}
-
-static VOID config_entry_free(ConfigEntry *entry) {
- FreePool(entry->title_show);
- FreePool(entry->title);
- FreePool(entry->machine_id);
- FreePool(entry->loader);
- FreePool(entry->options);
-}
-
-static BOOLEAN is_digit(CHAR16 c)
-{
- return (c >= '0') && (c <= '9');
-}
-
-static UINTN c_order(CHAR16 c)
-{
- if (c == '\0')
- return 0;
- if (is_digit(c))
- return 0;
- else if ((c >= 'a') && (c <= 'z'))
- return c;
- else
- return c + 0x10000;
-}
-
-static INTN str_verscmp(CHAR16 *s1, CHAR16 *s2)
-{
- CHAR16 *os1 = s1;
- CHAR16 *os2 = s2;
-
- while (*s1 || *s2) {
- INTN first;
-
- while ((*s1 && !is_digit(*s1)) || (*s2 && !is_digit(*s2))) {
- INTN order;
-
- order = c_order(*s1) - c_order(*s2);
- if (order)
- return order;
- s1++;
- s2++;
- }
-
- while (*s1 == '0')
- s1++;
- while (*s2 == '0')
- s2++;
-
- first = 0;
- while (is_digit(*s1) && is_digit(*s2)) {
- if (first == 0)
- first = *s1 - *s2;
- s1++;
- s2++;
- }
-
- if (is_digit(*s1))
- return 1;
- if (is_digit(*s2))
- return -1;
-
- if (first)
- return first;
- }
-
- return StrCmp(os1, os2);
-}
-
-static CHAR8 *line_get_key_value(CHAR8 *content, CHAR8 *sep, UINTN *pos, CHAR8 **key_ret, CHAR8 **value_ret) {
- CHAR8 *line;
- UINTN linelen;
- CHAR8 *value;
-
-skip:
- line = content + *pos;
- if (*line == '\0')
- return NULL;
-
- linelen = 0;
- while (line[linelen] && !strchra((CHAR8 *)"\n\r", line[linelen]))
- linelen++;
-
- /* move pos to next line */
- *pos += linelen;
- if (content[*pos])
- (*pos)++;
-
- /* empty line */
- if (linelen == 0)
- goto skip;
-
- /* terminate line */
- line[linelen] = '\0';
-
- /* remove leading whitespace */
- while (strchra((CHAR8 *)" \t", *line)) {
- line++;
- linelen--;
- }
-
- /* remove trailing whitespace */
- while (linelen > 0 && strchra(sep, line[linelen-1]))
- linelen--;
- line[linelen] = '\0';
-
- if (*line == '#')
- goto skip;
-
- /* split key/value */
- value = line;
- while (*value && !strchra(sep, *value))
- value++;
- if (*value == '\0')
- goto skip;
- *value = '\0';
- value++;
- while (*value && strchra(sep, *value))
- value++;
-
- /* unquote */
- if (value[0] == '\"' && line[linelen-1] == '\"') {
- value++;
- line[linelen-1] = '\0';
- }
-
- *key_ret = line;
- *value_ret = value;
- return line;
-}
-
-static VOID config_defaults_load_from_file(Config *config, CHAR8 *content) {
- CHAR8 *line;
- UINTN pos = 0;
- CHAR8 *key, *value;
-
- line = content;
- while ((line = line_get_key_value(content, (CHAR8 *)" \t", &pos, &key, &value))) {
- if (strcmpa((CHAR8 *)"timeout", key) == 0) {
- CHAR16 *s;
-
- s = stra_to_str(value);
- config->timeout_sec_config = Atoi(s);
- config->timeout_sec = config->timeout_sec_config;
- FreePool(s);
- continue;
- }
-
- if (strcmpa((CHAR8 *)"default", key) == 0) {
- FreePool(config->entry_default_pattern);
- config->entry_default_pattern = stra_to_str(value);
- StrLwr(config->entry_default_pattern);
- continue;
- }
-
- if (strcmpa((CHAR8 *)"splash", key) == 0) {
- FreePool(config->splash);
- config->splash = stra_to_path(value);
- continue;
- }
-
- if (strcmpa((CHAR8 *)"background", key) == 0) {
- CHAR16 c[3];
-
- /* accept #RRGGBB hex notation */
- if (value[0] != '#')
- continue;
- if (value[7] != '\0')
- continue;
-
- FreePool(config->background);
- config->background = AllocateZeroPool(sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
- if (!config->background)
- continue;
-
- c[0] = value[1];
- c[1] = value[2];
- c[2] = '\0';
- config->background->Red = xtoi(c);
-
- c[0] = value[3];
- c[1] = value[4];
- config->background->Green = xtoi(c);
-
- c[0] = value[5];
- c[1] = value[6];
- config->background->Blue = xtoi(c);
- continue;
- }
-
- if (strcmpa((CHAR8 *)"editor", key) == 0) {
- BOOLEAN on;
-
- if (EFI_ERROR(parse_boolean(value, &on)))
- continue;
- config->no_editor = !on;
- }
- }
-}
-
-static VOID config_entry_add_from_file(Config *config, EFI_HANDLE *device, CHAR16 *file, CHAR8 *content, CHAR16 *loaded_image_path) {
- ConfigEntry *entry;
- CHAR8 *line;
- UINTN pos = 0;
- CHAR8 *key, *value;
- UINTN len;
- CHAR16 *initrd = NULL;
-
- entry = AllocateZeroPool(sizeof(ConfigEntry));
-
- line = content;
- while ((line = line_get_key_value(content, (CHAR8 *)" \t", &pos, &key, &value))) {
- if (strcmpa((CHAR8 *)"title", key) == 0) {
- FreePool(entry->title);
- entry->title = stra_to_str(value);
- continue;
- }
-
- if (strcmpa((CHAR8 *)"version", key) == 0) {
- FreePool(entry->version);
- entry->version = stra_to_str(value);
- continue;
- }
-
- if (strcmpa((CHAR8 *)"machine-id", key) == 0) {
- FreePool(entry->machine_id);
- entry->machine_id = stra_to_str(value);
- continue;
- }
-
- if (strcmpa((CHAR8 *)"linux", key) == 0) {
- FreePool(entry->loader);
- entry->type = LOADER_LINUX;
- entry->loader = stra_to_path(value);
- entry->key = 'l';
- continue;
- }
-
- if (strcmpa((CHAR8 *)"efi", key) == 0) {
- entry->type = LOADER_EFI;
- FreePool(entry->loader);
- entry->loader = stra_to_path(value);
-
- /* do not add an entry for ourselves */
- if (StriCmp(entry->loader, loaded_image_path) == 0) {
- entry->type = LOADER_UNDEFINED;
- break;
- }
- continue;
- }
-
- if (strcmpa((CHAR8 *)"architecture", key) == 0) {
- /* do not add an entry for an EFI image of architecture not matching with that of the gummiboot image */
- if (strcmpa((CHAR8 *)MACHINE_TYPE_NAME, value) != 0) {
- entry->type = LOADER_UNDEFINED;
- break;
- }
- continue;
- }
-
- if (strcmpa((CHAR8 *)"initrd", key) == 0) {
- CHAR16 *new;
-
- new = stra_to_path(value);
- if (initrd) {
- CHAR16 *s;
-
- s = PoolPrint(L"%s initrd=%s", initrd, new);
- FreePool(initrd);
- initrd = s;
- } else
- initrd = PoolPrint(L"initrd=%s", new);
- FreePool(new);
- continue;
- }
-
- if (strcmpa((CHAR8 *)"options", key) == 0) {
- CHAR16 *new;
-
- new = stra_to_str(value);
- if (entry->options) {
- CHAR16 *s;
-
- s = PoolPrint(L"%s %s", entry->options, new);
- FreePool(entry->options);
- entry->options = s;
- } else {
- entry->options = new;
- new = NULL;
- }
- FreePool(new);
- continue;
- }
-
- if (strcmpa((CHAR8 *)"splash", key) == 0) {
- FreePool(entry->splash);
- entry->splash = stra_to_path(value);
- continue;
- }
- }
-
- if (entry->type == LOADER_UNDEFINED) {
- config_entry_free(entry);
- FreePool(initrd);
- FreePool(entry);
- return;
- }
-
- /* add initrd= to options */
- if (entry->type == LOADER_LINUX && initrd) {
- if (entry->options) {
- CHAR16 *s;
-
- s = PoolPrint(L"%s %s", initrd, entry->options);
- FreePool(entry->options);
- entry->options = s;
- } else {
- entry->options = initrd;
- initrd = NULL;
- }
- }
- FreePool(initrd);
-
- if (entry->machine_id) {
- CHAR16 *var;
-
- /* append additional options from EFI variables for this machine-id */
- var = PoolPrint(L"LoaderEntryOptions-%s", entry->machine_id);
- if (var) {
- CHAR16 *s;
-
- if (efivar_get(var, &s) == EFI_SUCCESS) {
- if (entry->options) {
- CHAR16 *s2;
-
- s2 = PoolPrint(L"%s %s", entry->options, s);
- FreePool(entry->options);
- entry->options = s2;
- } else
- entry->options = s;
- }
- FreePool(var);
- }
-
- var = PoolPrint(L"LoaderEntryOptionsOneShot-%s", entry->machine_id);
- if (var) {
- CHAR16 *s;
-
- if (efivar_get(var, &s) == EFI_SUCCESS) {
- if (entry->options) {
- CHAR16 *s2;
-
- s2 = PoolPrint(L"%s %s", entry->options, s);
- FreePool(entry->options);
- entry->options = s2;
- } else
- entry->options = s;
- efivar_set(var, NULL, TRUE);
- }
- FreePool(var);
- }
- }
-
- entry->device = device;
- entry->file = StrDuplicate(file);
- len = StrLen(entry->file);
- /* remove ".conf" */
- if (len > 5)
- entry->file[len - 5] = '\0';
- StrLwr(entry->file);
-
- config_add_entry(config, entry);
-}
-
-static VOID config_load(Config *config, EFI_HANDLE *device, EFI_FILE *root_dir, CHAR16 *loaded_image_path) {
- EFI_FILE_HANDLE entries_dir;
- EFI_STATUS err;
- CHAR8 *content = NULL;
- UINTN sec;
- UINTN len;
- UINTN i;
-
- len = file_read(root_dir, L"\\loader\\loader.conf", 0, 0, &content);
- if (len > 0)
- config_defaults_load_from_file(config, content);
- FreePool(content);
-
- err = efivar_get_int(L"LoaderConfigTimeout", &sec);
- if (!EFI_ERROR(err)) {
- config->timeout_sec_efivar = sec;
- config->timeout_sec = sec;
- } else
- config->timeout_sec_efivar = -1;
-
- err = uefi_call_wrapper(root_dir->Open, 5, root_dir, &entries_dir, L"\\loader\\entries", EFI_FILE_MODE_READ, 0ULL);
- if (!EFI_ERROR(err)) {
- for (;;) {
- CHAR16 buf[256];
- UINTN bufsize;
- EFI_FILE_INFO *f;
- CHAR8 *content = NULL;
- UINTN len;
-
- bufsize = sizeof(buf);
- err = uefi_call_wrapper(entries_dir->Read, 3, entries_dir, &bufsize, buf);
- if (bufsize == 0 || EFI_ERROR(err))
- break;
-
- f = (EFI_FILE_INFO *) buf;
- if (f->FileName[0] == '.')
- continue;
- if (f->Attribute & EFI_FILE_DIRECTORY)
- continue;
- len = StrLen(f->FileName);
- if (len < 6)
- continue;
- if (StriCmp(f->FileName + len - 5, L".conf") != 0)
- continue;
-
- len = file_read(entries_dir, f->FileName, 0, 0, &content);
- if (len > 0)
- config_entry_add_from_file(config, device, f->FileName, content, loaded_image_path);
- FreePool(content);
- }
- uefi_call_wrapper(entries_dir->Close, 1, entries_dir);
- }
-
- /* sort entries after version number */
- for (i = 1; i < config->entry_count; i++) {
- BOOLEAN more;
- UINTN k;
-
- more = FALSE;
- for (k = 0; k < config->entry_count - i; k++) {
- ConfigEntry *entry;
-
- if (str_verscmp(config->entries[k]->file, config->entries[k+1]->file) <= 0)
- continue;
- entry = config->entries[k];
- config->entries[k] = config->entries[k+1];
- config->entries[k+1] = entry;
- more = TRUE;
- }
- if (!more)
- break;
- }
-}
-
-static VOID config_default_entry_select(Config *config) {
- CHAR16 *var;
- EFI_STATUS err;
- UINTN i;
-
- /*
- * The EFI variable to specify a boot entry for the next, and only the
- * next reboot. The variable is always cleared directly after it is read.
- */
- err = efivar_get(L"LoaderEntryOneShot", &var);
- if (!EFI_ERROR(err)) {
- BOOLEAN found = FALSE;
-
- for (i = 0; i < config->entry_count; i++) {
- if (StrCmp(config->entries[i]->file, var) == 0) {
- config->idx_default = i;
- found = TRUE;
- break;
- }
- }
-
- config->entry_oneshot = StrDuplicate(var);
- efivar_set(L"LoaderEntryOneShot", NULL, TRUE);
- FreePool(var);
- if (found)
- return;
- }
-
- /*
- * The EFI variable to select the default boot entry overrides the
- * configured pattern. The variable can be set and cleared by pressing
- * the 'd' key in the loader selection menu, the entry is marked with
- * an '*'.
- */
- err = efivar_get(L"LoaderEntryDefault", &var);
- if (!EFI_ERROR(err)) {
- BOOLEAN found = FALSE;
-
- for (i = 0; i < config->entry_count; i++) {
- if (StrCmp(config->entries[i]->file, var) == 0) {
- config->idx_default = i;
- config->idx_default_efivar = i;
- found = TRUE;
- break;
- }
- }
- FreePool(var);
- if (found)
- return;
- }
- config->idx_default_efivar = -1;
-
- if (config->entry_count == 0)
- return;
-
- /*
- * Match the pattern from the end of the list to the start, find last
- * entry (largest number) matching the given pattern.
- */
- if (config->entry_default_pattern) {
- i = config->entry_count;
- while (i--) {
- if (config->entries[i]->no_autoselect)
- continue;
- if (MetaiMatch(config->entries[i]->file, config->entry_default_pattern)) {
- config->idx_default = i;
- return;
- }
- }
- }
-
- /* select the last suitable entry */
- i = config->entry_count;
- while (i--) {
- if (config->entries[i]->no_autoselect)
- continue;
- config->idx_default = i;
- return;
- }
-
- /* no entry found */
- config->idx_default = -1;
-}
-
-/* generate a unique title, avoiding non-distinguishable menu entries */
-static VOID config_title_generate(Config *config) {
- UINTN i, k;
- BOOLEAN unique;
-
- /* set title */
- for (i = 0; i < config->entry_count; i++) {
- CHAR16 *title;
-
- FreePool(config->entries[i]->title_show);
- title = config->entries[i]->title;
- if (!title)
- title = config->entries[i]->file;
- config->entries[i]->title_show = StrDuplicate(title);
- }
-
- unique = TRUE;
- for (i = 0; i < config->entry_count; i++) {
- for (k = 0; k < config->entry_count; k++) {
- if (i == k)
- continue;
- if (StrCmp(config->entries[i]->title_show, config->entries[k]->title_show) != 0)
- continue;
-
- unique = FALSE;
- config->entries[i]->non_unique = TRUE;
- config->entries[k]->non_unique = TRUE;
- }
- }
- if (unique)
- return;
-
- /* add version to non-unique titles */
- for (i = 0; i < config->entry_count; i++) {
- CHAR16 *s;
-
- if (!config->entries[i]->non_unique)
- continue;
- if (!config->entries[i]->version)
- continue;
-
- s = PoolPrint(L"%s (%s)", config->entries[i]->title_show, config->entries[i]->version);
- FreePool(config->entries[i]->title_show);
- config->entries[i]->title_show = s;
- config->entries[i]->non_unique = FALSE;
- }
-
- unique = TRUE;
- for (i = 0; i < config->entry_count; i++) {
- for (k = 0; k < config->entry_count; k++) {
- if (i == k)
- continue;
- if (StrCmp(config->entries[i]->title_show, config->entries[k]->title_show) != 0)
- continue;
-
- unique = FALSE;
- config->entries[i]->non_unique = TRUE;
- config->entries[k]->non_unique = TRUE;
- }
- }
- if (unique)
- return;
-
- /* add machine-id to non-unique titles */
- for (i = 0; i < config->entry_count; i++) {
- CHAR16 *s;
- CHAR16 *m;
-
- if (!config->entries[i]->non_unique)
- continue;
- if (!config->entries[i]->machine_id)
- continue;
-
- m = StrDuplicate(config->entries[i]->machine_id);
- m[8] = '\0';
- s = PoolPrint(L"%s (%s)", config->entries[i]->title_show, m);
- FreePool(config->entries[i]->title_show);
- config->entries[i]->title_show = s;
- config->entries[i]->non_unique = FALSE;
- FreePool(m);
- }
-
- unique = TRUE;
- for (i = 0; i < config->entry_count; i++) {
- for (k = 0; k < config->entry_count; k++) {
- if (i == k)
- continue;
- if (StrCmp(config->entries[i]->title_show, config->entries[k]->title_show) != 0)
- continue;
-
- unique = FALSE;
- config->entries[i]->non_unique = TRUE;
- config->entries[k]->non_unique = TRUE;
- }
- }
- if (unique)
- return;
-
- /* add file name to non-unique titles */
- for (i = 0; i < config->entry_count; i++) {
- CHAR16 *s;
-
- if (!config->entries[i]->non_unique)
- continue;
- s = PoolPrint(L"%s (%s)", config->entries[i]->title_show, config->entries[i]->file);
- FreePool(config->entries[i]->title_show);
- config->entries[i]->title_show = s;
- config->entries[i]->non_unique = FALSE;
- }
-}
-
-static BOOLEAN config_entry_add_call(Config *config, CHAR16 *title, EFI_STATUS (*call)(VOID)) {
- ConfigEntry *entry;
-
- entry = AllocateZeroPool(sizeof(ConfigEntry));
- entry->title = StrDuplicate(title);
- entry->call = call;
- entry->no_autoselect = TRUE;
- config_add_entry(config, entry);
- return TRUE;
-}
-
-static ConfigEntry *config_entry_add_loader(Config *config, EFI_HANDLE *device,
- enum loader_type type,CHAR16 *file, CHAR16 key, CHAR16 *title, CHAR16 *loader) {
- ConfigEntry *entry;
-
- entry = AllocateZeroPool(sizeof(ConfigEntry));
- entry->type = type;
- entry->title = StrDuplicate(title);
- entry->device = device;
- entry->loader = StrDuplicate(loader);
- entry->file = StrDuplicate(file);
- StrLwr(entry->file);
- entry->key = key;
- config_add_entry(config, entry);
-
- return entry;
-}
-
-static BOOLEAN config_entry_add_loader_auto(Config *config, EFI_HANDLE *device, EFI_FILE *root_dir, CHAR16 *loaded_image_path,
- CHAR16 *file, CHAR16 key, CHAR16 *title, CHAR16 *loader) {
- EFI_FILE_HANDLE handle;
- ConfigEntry *entry;
- EFI_STATUS err;
-
- /* do not add an entry for ourselves */
- if (loaded_image_path && StriCmp(loader, loaded_image_path) == 0)
- return FALSE;
-
- /* check existence */
- err = uefi_call_wrapper(root_dir->Open, 5, root_dir, &handle, loader, EFI_FILE_MODE_READ, 0ULL);
- if (EFI_ERROR(err))
- return FALSE;
- uefi_call_wrapper(handle->Close, 1, handle);
-
- entry = config_entry_add_loader(config, device, LOADER_UNDEFINED, file, key, title, loader);
- if (!entry)
- return FALSE;
-
- /* do not boot right away into auto-detected entries */
- entry->no_autoselect = TRUE;
-
- /* do not show a splash; they do not need one, or they draw their own */
- entry->splash = StrDuplicate(L"");
-
- /* export identifiers of automatically added entries */
- if (config->entries_auto) {
- CHAR16 *s;
-
- s = PoolPrint(L"%s %s", config->entries_auto, file);
- FreePool(config->entries_auto);
- config->entries_auto = s;
- } else
- config->entries_auto = StrDuplicate(file);
-
- return TRUE;
-}
-
-static VOID config_entry_add_osx(Config *config) {
- EFI_STATUS err;
- UINTN handle_count = 0;
- EFI_HANDLE *handles = NULL;
-
- err = LibLocateHandle(ByProtocol, &FileSystemProtocol, NULL, &handle_count, &handles);
- if (!EFI_ERROR(err)) {
- UINTN i;
-
- for (i = 0; i < handle_count; i++) {
- EFI_FILE *root;
- BOOLEAN found;
-
- root = LibOpenRoot(handles[i]);
- if (!root)
- continue;
- found = config_entry_add_loader_auto(config, handles[i], root, NULL, L"auto-osx", 'a', L"OS X",
- L"\\System\\Library\\CoreServices\\boot.efi");
- uefi_call_wrapper(root->Close, 1, root);
- if (found)
- break;
- }
-
- FreePool(handles);
- }
-}
-
-static VOID config_entry_add_linux( Config *config, EFI_LOADED_IMAGE *loaded_image, EFI_FILE *root_dir) {
- EFI_FILE_HANDLE linux_dir;
- EFI_STATUS err;
-
- err = uefi_call_wrapper(root_dir->Open, 5, root_dir, &linux_dir, L"\\EFI\\Linux", EFI_FILE_MODE_READ, 0ULL);
- if (!EFI_ERROR(err)) {
- for (;;) {
- CHAR16 buf[256];
- UINTN bufsize;
- EFI_FILE_INFO *f;
- CHAR8 *sections[] = {
- (UINT8 *)".osrel",
- NULL
- };
- UINTN offs[ELEMENTSOF(sections)-1] = {};
- UINTN szs[ELEMENTSOF(sections)-1] = {};
- UINTN addrs[ELEMENTSOF(sections)-1] = {};
- CHAR8 *content = NULL;
- UINTN len;
- CHAR8 *line;
- UINTN pos = 0;
- CHAR8 *key, *value;
- CHAR16 *os_name = NULL;
- CHAR16 *os_id = NULL;
- CHAR16 *os_version = NULL;
-
- bufsize = sizeof(buf);
- err = uefi_call_wrapper(linux_dir->Read, 3, linux_dir, &bufsize, buf);
- if (bufsize == 0 || EFI_ERROR(err))
- break;
-
- f = (EFI_FILE_INFO *) buf;
- if (f->FileName[0] == '.')
- continue;
- if (f->Attribute & EFI_FILE_DIRECTORY)
- continue;
- len = StrLen(f->FileName);
- if (len < 5)
- continue;
- if (StriCmp(f->FileName + len - 4, L".efi") != 0)
- continue;
-
- /* look for an .osrel section in the .efi binary */
- err = pefile_locate_sections(linux_dir, f->FileName, sections, addrs, offs, szs);
- if (EFI_ERROR(err))
- continue;
-
- len = file_read(linux_dir, f->FileName, offs[0], szs[0], &content);
- if (len <= 0)
- continue;
-
- /* read properties from the embedded os-release file */
- line = content;
- while ((line = line_get_key_value(content, (CHAR8 *)"=", &pos, &key, &value))) {
- if (strcmpa((CHAR8 *)"PRETTY_NAME", key) == 0) {
- os_name = stra_to_str(value);
- continue;
- }
-
- if (strcmpa((CHAR8 *)"ID", key) == 0) {
- os_id = stra_to_str(value);
- continue;
- }
-
- if (strcmpa((CHAR8 *)"VERSION_ID", key) == 0) {
- os_version = stra_to_str(value);
- continue;
- }
- }
-
- if (os_name && os_id && os_version) {
- CHAR16 *conf;
- CHAR16 *path;
-
- conf = PoolPrint(L"%s-%s", os_id, os_version);
- path = PoolPrint(L"\\EFI\\Linux\\%s", f->FileName);
- config_entry_add_loader(config, loaded_image->DeviceHandle, LOADER_LINUX, conf, 'l', os_name, path);
- FreePool(conf);
- FreePool(path);
- FreePool(os_name);
- FreePool(os_id);
- FreePool(os_version);
- }
-
- FreePool(content);
- }
- uefi_call_wrapper(linux_dir->Close, 1, linux_dir);
- }
-}
-
-static EFI_STATUS image_start(EFI_HANDLE parent_image, const Config *config, const ConfigEntry *entry) {
- EFI_HANDLE image;
- EFI_DEVICE_PATH *path;
- CHAR16 *options;
- EFI_STATUS err;
-
- path = FileDevicePath(entry->device, entry->loader);
- if (!path) {
- Print(L"Error getting device path.");
- uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
- return EFI_INVALID_PARAMETER;
- }
-
- err = uefi_call_wrapper(BS->LoadImage, 6, FALSE, parent_image, path, NULL, 0, &image);
- if (EFI_ERROR(err)) {
- Print(L"Error loading %s: %r", entry->loader, err);
- uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
- goto out;
- }
-
- if (config->options_edit)
- options = config->options_edit;
- else if (entry->options)
- options = entry->options;
- else
- options = NULL;
- if (options) {
- EFI_LOADED_IMAGE *loaded_image;
-
- err = uefi_call_wrapper(BS->OpenProtocol, 6, image, &LoadedImageProtocol, (VOID **)&loaded_image,
- parent_image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
- if (EFI_ERROR(err)) {
- Print(L"Error getting LoadedImageProtocol handle: %r", err);
- uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
- goto out_unload;
- }
- loaded_image->LoadOptions = options;
- loaded_image->LoadOptionsSize = (StrLen(loaded_image->LoadOptions)+1) * sizeof(CHAR16);
- }
-
- efivar_set_time_usec(L"LoaderTimeExecUSec", 0);
- err = uefi_call_wrapper(BS->StartImage, 3, image, NULL, NULL);
-out_unload:
- uefi_call_wrapper(BS->UnloadImage, 1, image);
-out:
- FreePool(path);
- return err;
-}
-
-static EFI_STATUS reboot_into_firmware(VOID) {
- CHAR8 *b;
- UINTN size;
- UINT64 osind;
- EFI_STATUS err;
-
- osind = EFI_OS_INDICATIONS_BOOT_TO_FW_UI;
-
- err = efivar_get_raw(&global_guid, L"OsIndications", &b, &size);
- if (!EFI_ERROR(err))
- osind |= (UINT64)*b;
- FreePool(b);
-
- err = efivar_set_raw(&global_guid, L"OsIndications", (CHAR8 *)&osind, sizeof(UINT64), TRUE);
- if (EFI_ERROR(err))
- return err;
-
- err = uefi_call_wrapper(RT->ResetSystem, 4, EfiResetCold, EFI_SUCCESS, 0, NULL);
- Print(L"Error calling ResetSystem: %r", err);
- uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
- return err;
-}
-
-static VOID config_free(Config *config) {
- UINTN i;
-
- for (i = 0; i < config->entry_count; i++)
- config_entry_free(config->entries[i]);
- FreePool(config->entries);
- FreePool(config->entry_default_pattern);
- FreePool(config->options_edit);
- FreePool(config->entry_oneshot);
- FreePool(config->entries_auto);
- FreePool(config->splash);
- FreePool(config->background);
-}
-
-EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
- CHAR16 *s;
- CHAR8 *b;
- UINTN size;
- EFI_LOADED_IMAGE *loaded_image;
- EFI_FILE *root_dir;
- CHAR16 *loaded_image_path;
- EFI_DEVICE_PATH *device_path;
- EFI_STATUS err;
- Config config;
- UINT64 init_usec;
- BOOLEAN menu = FALSE;
-
- InitializeLib(image, sys_table);
- init_usec = time_usec();
- efivar_set_time_usec(L"LoaderTimeInitUSec", init_usec);
- efivar_set(L"LoaderInfo", L"gummiboot " VERSION, FALSE);
- s = PoolPrint(L"%s %d.%02d", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
- efivar_set(L"LoaderFirmwareInfo", s, FALSE);
- FreePool(s);
- s = PoolPrint(L"UEFI %d.%02d", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff);
- efivar_set(L"LoaderFirmwareType", s, FALSE);
- FreePool(s);
-
- err = uefi_call_wrapper(BS->OpenProtocol, 6, image, &LoadedImageProtocol, (VOID **)&loaded_image,
- image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
- if (EFI_ERROR(err)) {
- Print(L"Error getting a LoadedImageProtocol handle: %r ", err);
- uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
- return err;
- }
-
- /* export the device path this image is started from */
- device_path = DevicePathFromHandle(loaded_image->DeviceHandle);
- if (device_path) {
- CHAR16 *str;
- EFI_DEVICE_PATH *path, *paths;
-
- str = DevicePathToStr(device_path);
- efivar_set(L"LoaderDeviceIdentifier", str, FALSE);
- FreePool(str);
-
- paths = UnpackDevicePath(device_path);
- for (path = paths; !IsDevicePathEnd(path); path = NextDevicePathNode(path)) {
- HARDDRIVE_DEVICE_PATH *drive;
- CHAR16 uuid[37];
-
- if (DevicePathType(path) != MEDIA_DEVICE_PATH)
- continue;
- if (DevicePathSubType(path) != MEDIA_HARDDRIVE_DP)
- continue;
- drive = (HARDDRIVE_DEVICE_PATH *)path;
- if (drive->SignatureType != SIGNATURE_TYPE_GUID)
- continue;
-
- GuidToString(uuid, (EFI_GUID *)&drive->Signature);
- efivar_set(L"LoaderDevicePartUUID", uuid, FALSE);
- break;
- }
- FreePool(paths);
- }
-
- root_dir = LibOpenRoot(loaded_image->DeviceHandle);
- if (!root_dir) {
- Print(L"Unable to open root directory: %r ", err);
- uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
- return EFI_LOAD_ERROR;
- }
-
-
- /* the filesystem path to this image, to prevent adding ourselves to the menu */
- loaded_image_path = DevicePathToStr(loaded_image->FilePath);
- efivar_set(L"LoaderImageIdentifier", loaded_image_path, FALSE);
-
- /* scan "\loader\entries\*.conf" files */
- ZeroMem(&config, sizeof(Config));
- config_load(&config, loaded_image->DeviceHandle, root_dir, loaded_image_path);
-
- if (!config.background) {
- config.background = AllocateZeroPool(sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
- if (StriCmp(L"Apple", ST->FirmwareVendor) == 0) {
- config.background->Red = 0xc0;
- config.background->Green = 0xc0;
- config.background->Blue = 0xc0;
- }
- }
-
- /* if we find some well-known loaders, add them to the end of the list */
- config_entry_add_linux(&config, loaded_image, root_dir);
- config_entry_add_loader_auto(&config, loaded_image->DeviceHandle, root_dir, loaded_image_path,
- L"auto-windows", 'w', L"Windows Boot Manager", L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi");
- config_entry_add_loader_auto(&config, loaded_image->DeviceHandle, root_dir, loaded_image_path,
- L"auto-efi-shell", 's', L"EFI Shell", L"\\shell" MACHINE_TYPE_NAME ".efi");
- config_entry_add_loader_auto(&config, loaded_image->DeviceHandle, root_dir, loaded_image_path,
- L"auto-efi-default", '\0', L"EFI Default Loader", L"\\EFI\\Boot\\boot" MACHINE_TYPE_NAME ".efi");
- config_entry_add_osx(&config);
- efivar_set(L"LoaderEntriesAuto", config.entries_auto, FALSE);
-
- if (efivar_get_raw(&global_guid, L"OsIndicationsSupported", &b, &size) == EFI_SUCCESS) {
- UINT64 osind = (UINT64)*b;
-
- if (osind & EFI_OS_INDICATIONS_BOOT_TO_FW_UI)
- config_entry_add_call(&config, L"Reboot Into Firmware Interface", reboot_into_firmware);
- FreePool(b);
- }
-
- if (config.entry_count == 0) {
- Print(L"No loader found. Configuration files in \\loader\\entries\\*.conf are needed.");
- uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
- goto out;
- }
-
- config_title_generate(&config);
-
- /* select entry by configured pattern or EFI LoaderDefaultEntry= variable*/
- config_default_entry_select(&config);
-
- /* if no configured entry to select from was found, enable the menu */
- if (config.idx_default == -1) {
- config.idx_default = 0;
- if (config.timeout_sec == 0)
- config.timeout_sec = 10;
- }
-
- /* select entry or show menu when key is pressed or timeout is set */
- if (config.timeout_sec == 0) {
- UINT64 key;
-
- err = console_key_read(&key, FALSE);
- if (!EFI_ERROR(err)) {
- INT16 idx;
-
- /* find matching key in config entries */
- idx = entry_lookup_key(&config, config.idx_default, KEYCHAR(key));
- if (idx >= 0)
- config.idx_default = idx;
- else
- menu = TRUE;
- }
- } else
- menu = TRUE;
-
- for (;;) {
- ConfigEntry *entry;
-
- entry = config.entries[config.idx_default];
- if (menu) {
- efivar_set_time_usec(L"LoaderTimeMenuUSec", 0);
- uefi_call_wrapper(BS->SetWatchdogTimer, 4, 0, 0x10000, 0, NULL);
- if (!menu_run(&config, &entry, root_dir, loaded_image_path))
- break;
-
- /* run special entry like "reboot" */
- if (entry->call) {
- entry->call();
- continue;
- }
- } else {
- err = EFI_NOT_FOUND;
-
- /* splash from entry file */
- if (entry->splash) {
- /* some entries disable the splash because they draw their own */
- if (entry->splash[0] == '\0')
- err = EFI_SUCCESS;
- else
- err = graphics_splash(root_dir, entry->splash, config.background);
- }
-
- /* splash from config file */
- if (EFI_ERROR(err) && config.splash)
- err = graphics_splash(root_dir, config.splash, config.background);
-
- /* default splash */
- if (EFI_ERROR(err))
- graphics_splash(root_dir, L"\\EFI\\gummiboot\\splash.bmp", config.background);
- }
-
- /* export the selected boot entry to the system */
- efivar_set(L"LoaderEntrySelected", entry->file, FALSE);
-
- uefi_call_wrapper(BS->SetWatchdogTimer, 4, 5 * 60, 0x10000, 0, NULL);
- err = image_start(image, &config, entry);
-
- if (err == EFI_ACCESS_DENIED || err == EFI_SECURITY_VIOLATION) {
- /* Platform is secure boot and requested image isn't
- * trusted. Need to go back to prior boot system and
- * install more keys or hashes. Signal failure by
- * returning the error */
- Print(L"\nImage %s gives a security error\n", entry->title);
- Print(L"Please enrol the hash or signature of %s\n", entry->loader);
- uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
- goto out;
- }
-
- menu = TRUE;
- config.timeout_sec = 0;
- }
- err = EFI_SUCCESS;
-out:
- FreePool(loaded_image_path);
- config_free(&config);
- uefi_call_wrapper(root_dir->Close, 1, root_dir);
- uefi_call_wrapper(BS->CloseProtocol, 4, image, &LoadedImageProtocol, image, NULL);
- return err;
-}
diff --git a/src/efi/linux.c b/src/efi/linux.c
deleted file mode 100644
index 809c693..0000000
--- a/src/efi/linux.c
+++ /dev/null
@@ -1,130 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/*
- * This program 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 program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * Copyright (C) 2015 Kay Sievers <kay@vrfy.org>
- */
-
-#include <efi.h>
-#include <efilib.h>
-
-#include "util.h"
-#include "linux.h"
-
-#define SETUP_MAGIC 0x53726448 /* "HdrS" */
-struct SetupHeader {
- UINT8 boot_sector[0x01f1];
- UINT8 setup_secs;
- UINT16 root_flags;
- UINT32 sys_size;
- UINT16 ram_size;
- UINT16 video_mode;
- UINT16 root_dev;
- UINT16 signature;
- UINT16 jump;
- UINT32 header;
- UINT16 version;
- UINT16 su_switch;
- UINT16 setup_seg;
- UINT16 start_sys;
- UINT16 kernel_ver;
- UINT8 loader_id;
- UINT8 load_flags;
- UINT16 movesize;
- UINT32 code32_start;
- UINT32 ramdisk_start;
- UINT32 ramdisk_len;
- UINT32 bootsect_kludge;
- UINT16 heap_end;
- UINT8 ext_loader_ver;
- UINT8 ext_loader_type;
- UINT32 cmd_line_ptr;
- UINT32 ramdisk_max;
- UINT32 kernel_alignment;
- UINT8 relocatable_kernel;
- UINT8 min_alignment;
- UINT16 xloadflags;
- UINT32 cmdline_size;
- UINT32 hardware_subarch;
- UINT64 hardware_subarch_data;
- UINT32 payload_offset;
- UINT32 payload_length;
- UINT64 setup_data;
- UINT64 pref_address;
- UINT32 init_size;
- UINT32 handover_offset;
-} __attribute__((packed));
-
-#ifdef __x86_64__
-typedef VOID(*handover_f)(VOID *image, EFI_SYSTEM_TABLE *table, struct SetupHeader *setup);
-static inline VOID linux_efi_handover(EFI_HANDLE image, struct SetupHeader *setup) {
- handover_f handover;
-
- asm volatile ("cli");
- handover = (handover_f)((UINTN)setup->code32_start + 512 + setup->handover_offset);
- handover(image, ST, setup);
-}
-#else
-typedef VOID(*handover_f)(VOID *image, EFI_SYSTEM_TABLE *table, struct SetupHeader *setup) __attribute__((regparm(0)));
-static inline VOID linux_efi_handover(EFI_HANDLE image, struct SetupHeader *setup) {
- handover_f handover;
-
- handover = (handover_f)((UINTN)setup->code32_start + setup->handover_offset);
- handover(image, ST, setup);
-}
-#endif
-
-EFI_STATUS linux_exec(EFI_HANDLE *image,
- CHAR8 *cmdline, UINTN cmdline_len,
- UINTN linux_addr,
- UINTN initrd_addr, UINTN initrd_size) {
- struct SetupHeader *image_setup;
- struct SetupHeader *boot_setup;
- EFI_PHYSICAL_ADDRESS addr;
- EFI_STATUS err;
-
- image_setup = (struct SetupHeader *)(linux_addr);
- if (image_setup->signature != 0xAA55 || image_setup->header != SETUP_MAGIC)
- return EFI_LOAD_ERROR;
-
- if (image_setup->version < 0x20b || !image_setup->relocatable_kernel)
- return EFI_LOAD_ERROR;
-
- addr = 0x3fffffff;
- err = uefi_call_wrapper(BS->AllocatePages, 4, AllocateMaxAddress, EfiLoaderData,
- EFI_SIZE_TO_PAGES(0x4000), &addr);
- if (EFI_ERROR(err))
- return err;
- boot_setup = (struct SetupHeader *)(UINTN)addr;
- ZeroMem(boot_setup, 0x4000);
- CopyMem(boot_setup, image_setup, sizeof(struct SetupHeader));
- boot_setup->loader_id = 0xff;
-
- boot_setup->code32_start = (UINT32)linux_addr + (image_setup->setup_secs+1) * 512;
-
- if (cmdline) {
- addr = 0xA0000;
- err = uefi_call_wrapper(BS->AllocatePages, 4, AllocateMaxAddress, EfiLoaderData,
- EFI_SIZE_TO_PAGES(cmdline_len + 1), &addr);
- if (EFI_ERROR(err))
- return err;
- CopyMem((VOID *)(UINTN)addr, cmdline, cmdline_len);
- ((CHAR8 *)addr)[cmdline_len] = 0;
- boot_setup->cmd_line_ptr = (UINT32)addr;
- }
-
- boot_setup->ramdisk_start = (UINT32)initrd_addr;
- boot_setup->ramdisk_len = (UINT32)initrd_size;
-
- linux_efi_handover(image, boot_setup);
- return EFI_LOAD_ERROR;
-}
diff --git a/src/efi/linux.h b/src/efi/linux.h
deleted file mode 100644
index e5d4f5a..0000000
--- a/src/efi/linux.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/*
- * This program 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 program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * Copyright (C) 2015 Kay Sievers <kay@vrfy.org>
- */
-
-#ifndef __GUMMIBOOT_kernel_H
-#define __GUMMIBOOT_kernel_H
-
-EFI_STATUS linux_exec(EFI_HANDLE *image,
- CHAR8 *cmdline, UINTN cmdline_size,
- UINTN linux_addr,
- UINTN initrd_addr, UINTN initrd_size);
-#endif
diff --git a/src/efi/pefile.c b/src/efi/pefile.c
deleted file mode 100644
index e6fedbc..0000000
--- a/src/efi/pefile.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/*
- * This program 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 program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * Copyright (C) 2015 Kay Sievers <kay@vrfy.org>
- */
-
-#include <efi.h>
-#include <efilib.h>
-
-#include "util.h"
-#include "pefile.h"
-
-struct DosFileHeader {
- UINT8 Magic[2];
- UINT16 LastSize;
- UINT16 nBlocks;
- UINT16 nReloc;
- UINT16 HdrSize;
- UINT16 MinAlloc;
- UINT16 MaxAlloc;
- UINT16 ss;
- UINT16 sp;
- UINT16 Checksum;
- UINT16 ip;
- UINT16 cs;
- UINT16 RelocPos;
- UINT16 nOverlay;
- UINT16 reserved[4];
- UINT16 OEMId;
- UINT16 OEMInfo;
- UINT16 reserved2[10];
- UINT32 ExeHeader;
-} __attribute__((packed));
-
-#define PE_HEADER_MACHINE_I386 0x014c
-#define PE_HEADER_MACHINE_X64 0x8664
-struct PeFileHeader {
- UINT16 Machine;
- UINT16 NumberOfSections;
- UINT32 TimeDateStamp;
- UINT32 PointerToSymbolTable;
- UINT32 NumberOfSymbols;
- UINT16 SizeOfOptionalHeader;
- UINT16 Characteristics;
-} __attribute__((packed));
-
-struct PeSectionHeader {
- UINT8 Name[8];
- UINT32 VirtualSize;
- UINT32 VirtualAddress;
- UINT32 SizeOfRawData;
- UINT32 PointerToRawData;
- UINT32 PointerToRelocations;
- UINT32 PointerToLinenumbers;
- UINT16 NumberOfRelocations;
- UINT16 NumberOfLinenumbers;
- UINT32 Characteristics;
-} __attribute__((packed));
-
-
-EFI_STATUS pefile_locate_sections(EFI_FILE *dir, CHAR16 *path, CHAR8 **sections, UINTN *addrs, UINTN *offsets, UINTN *sizes) {
- EFI_FILE_HANDLE handle;
- struct DosFileHeader dos;
- uint8_t magic[4];
- struct PeFileHeader pe;
- UINTN len;
- UINTN i;
- EFI_STATUS err;
-
- err = uefi_call_wrapper(dir->Open, 5, dir, &handle, path, EFI_FILE_MODE_READ, 0ULL);
- if (EFI_ERROR(err))
- return err;
-
- /* MS-DOS stub */
- len = sizeof(dos);
- err = uefi_call_wrapper(handle->Read, 3, handle, &len, &dos);
- if (EFI_ERROR(err))
- goto out;
- if (len != sizeof(dos)) {
- err = EFI_LOAD_ERROR;
- goto out;
- }
-
- if (CompareMem(dos.Magic, "MZ", 2) != 0) {
- err = EFI_LOAD_ERROR;
- goto out;
- }
-
- err = uefi_call_wrapper(handle->SetPosition, 2, handle, dos.ExeHeader);
- if (EFI_ERROR(err))
- goto out;
-
- /* PE header */
- len = sizeof(magic);
- err = uefi_call_wrapper(handle->Read, 3, handle, &len, &magic);
- if (EFI_ERROR(err))
- goto out;
- if (len != sizeof(magic)) {
- err = EFI_LOAD_ERROR;
- goto out;
- }
-
- if (CompareMem(magic, "PE\0\0", 2) != 0) {
- err = EFI_LOAD_ERROR;
- goto out;
- }
-
- len = sizeof(pe);
- err = uefi_call_wrapper(handle->Read, 3, handle, &len, &pe);
- if (EFI_ERROR(err))
- goto out;
- if (len != sizeof(pe)) {
- err = EFI_LOAD_ERROR;
- goto out;
- }
-
- /* PE32+ Subsystem type */
- if (pe.Machine != PE_HEADER_MACHINE_X64 &&
- pe.Machine != PE_HEADER_MACHINE_I386) {
- err = EFI_LOAD_ERROR;
- goto out;
- }
-
- if (pe.NumberOfSections > 96) {
- err = EFI_LOAD_ERROR;
- goto out;
- }
-
- /* the sections start directly after the headers */
- err = uefi_call_wrapper(handle->SetPosition, 2, handle, dos.ExeHeader + sizeof(magic) + sizeof(pe) + pe.SizeOfOptionalHeader);
- if (EFI_ERROR(err))
- goto out;
-
- for (i = 0; i < pe.NumberOfSections; i++) {
- struct PeSectionHeader sect;
- UINTN j;
-
- len = sizeof(sect);
- err = uefi_call_wrapper(handle->Read, 3, handle, &len, &sect);
- if (EFI_ERROR(err))
- goto out;
- if (len != sizeof(sect)) {
- err = EFI_LOAD_ERROR;
- goto out;
- }
- for (j = 0; sections[j]; j++) {
- if (CompareMem(sect.Name, sections[j], strlena(sections[j])) != 0)
- continue;
-
- if (addrs)
- addrs[j] = (UINTN)sect.VirtualAddress;
- if (offsets)
- offsets[j] = (UINTN)sect.PointerToRawData;
- if (sizes)
- sizes[j] = (UINTN)sect.VirtualSize;
- }
- }
-
-out:
- uefi_call_wrapper(handle->Close, 1, handle);
- return err;
-}
diff --git a/src/efi/pefile.h b/src/efi/pefile.h
deleted file mode 100644
index 3adf1b0..0000000
--- a/src/efi/pefile.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/*
- * This program 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 program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * Copyright (C) 2015 Kay Sievers <kay@vrfy.org>
- */
-
-#ifndef __GUMMIBOOT_PEFILE_H
-#define __GUMMIBOOT_PEFILE_H
-
-EFI_STATUS pefile_locate_sections(EFI_FILE *dir, CHAR16 *path,
- CHAR8 **sections, UINTN *addrs, UINTN *offsets, UINTN *sizes);
-#endif
diff --git a/src/efi/stub.c b/src/efi/stub.c
deleted file mode 100644
index e18faac..0000000
--- a/src/efi/stub.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/* This program 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 program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * Copyright (C) 2015 Kay Sievers <kay@vrfy.org>
- */
-
-#include <efi.h>
-#include <efilib.h>
-
-#include "util.h"
-#include "pefile.h"
-#include "linux.h"
-
-/* magic string to find in the binary image */
-static const char __attribute__((used)) magic[] = "#### LoaderInfo: stub " VERSION " ####";
-
-static const EFI_GUID global_guid = EFI_GLOBAL_VARIABLE;
-
-EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
- EFI_LOADED_IMAGE *loaded_image;
- EFI_FILE *root_dir;
- CHAR16 *loaded_image_path;
- CHAR8 *b;
- UINTN size;
- BOOLEAN secure = FALSE;
- CHAR8 *sections[] = {
- (UINT8 *)".cmdline",
- (UINT8 *)".linux",
- (UINT8 *)".initrd",
- NULL
- };
- UINTN addrs[ELEMENTSOF(sections)-1] = {};
- UINTN offs[ELEMENTSOF(sections)-1] = {};
- UINTN szs[ELEMENTSOF(sections)-1] = {};
- CHAR8 *cmdline = NULL;
- UINTN cmdline_len;
- EFI_STATUS err;
-
- InitializeLib(image, sys_table);
-
- err = uefi_call_wrapper(BS->OpenProtocol, 6, image, &LoadedImageProtocol, (VOID **)&loaded_image,
- image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
- if (EFI_ERROR(err)) {
- Print(L"Error getting a LoadedImageProtocol handle: %r ", err);
- uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
- return err;
- }
-
- root_dir = LibOpenRoot(loaded_image->DeviceHandle);
- if (!root_dir) {
- Print(L"Unable to open root directory: %r ", err);
- uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
- return EFI_LOAD_ERROR;
- }
-
- loaded_image_path = DevicePathToStr(loaded_image->FilePath);
-
- if (efivar_get_raw(&global_guid, L"SecureBoot", &b, &size) == EFI_SUCCESS) {
- if (*b > 0)
- secure = TRUE;
- FreePool(b);
- }
-
- err = pefile_locate_sections(root_dir, loaded_image_path, sections, addrs, offs, szs);
- if (EFI_ERROR(err)) {
- Print(L"Unable to locate embedded .linux section: %r ", err);
- uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
- return err;
- }
-
- if (szs[0] > 0)
- cmdline = (CHAR8 *)(loaded_image->ImageBase + addrs[0]);
-
- cmdline_len = szs[0];
-
- /* if we are not in secure boot mode, accept a custom command line and replace the built-in one */
- if (!secure && loaded_image->LoadOptionsSize > 0) {
- CHAR16 *options;
- CHAR8 *line;
- UINTN i;
-
- options = (CHAR16 *)loaded_image->LoadOptions;
- cmdline_len = (loaded_image->LoadOptionsSize / sizeof(CHAR16)) * sizeof(CHAR8);
- line = AllocatePool(cmdline_len);
- for (i = 0; i < cmdline_len; i++)
- line[i] = options[i];
- cmdline = line;
- }
-
- err = linux_exec(image, cmdline, cmdline_len,
- (UINTN)loaded_image->ImageBase + addrs[1],
- (UINTN)loaded_image->ImageBase + addrs[2], szs[2]);
-
- Print(L"Execution of embedded linux image failed: %r\n", err);
- uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
- return err;
-}
diff --git a/src/efi/util.c b/src/efi/util.c
deleted file mode 100644
index ba5ed7d..0000000
--- a/src/efi/util.c
+++ /dev/null
@@ -1,342 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/*
- * This program 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 program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * Copyright (C) 2012-2013 Kay Sievers <kay@vrfy.org>
- * Copyright (C) 2012 Harald Hoyer <harald@redhat.com>
- */
-
-#include <efi.h>
-#include <efilib.h>
-
-#include "util.h"
-
-/*
- * Allocated random UUID, intended to be shared across tools that implement
- * the (ESP)\loader\entries\<vendor>-<revision>.conf convention and the
- * associated EFI variables.
- */
-static const EFI_GUID loader_guid = { 0x4a67b082, 0x0a4c, 0x41cf, {0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f} };
-
-#ifdef __x86_64__
-UINT64 ticks_read(VOID) {
- UINT64 a, d;
- __asm__ volatile ("rdtsc" : "=a" (a), "=d" (d));
- return (d << 32) | a;
-}
-#else
-UINT64 ticks_read(VOID) {
- UINT64 val;
- __asm__ volatile ("rdtsc" : "=A" (val));
- return val;
-}
-#endif
-
-/* count TSC ticks during a millisecond delay */
-UINT64 ticks_freq(VOID) {
- UINT64 ticks_start, ticks_end;
-
- ticks_start = ticks_read();
- uefi_call_wrapper(BS->Stall, 1, 1000);
- ticks_end = ticks_read();
-
- return (ticks_end - ticks_start) * 1000;
-}
-
-UINT64 time_usec(VOID) {
- UINT64 ticks;
- static UINT64 freq;
-
- ticks = ticks_read();
- if (ticks == 0)
- return 0;
-
- if (freq == 0) {
- freq = ticks_freq();
- if (freq == 0)
- return 0;
- }
-
- return 1000 * 1000 * ticks / freq;
-}
-
-EFI_STATUS parse_boolean(CHAR8 *v, BOOLEAN *b) {
- if (strcmpa(v, (CHAR8 *)"1") == 0 ||
- strcmpa(v, (CHAR8 *)"yes") == 0 ||
- strcmpa(v, (CHAR8 *)"y") == 0 ||
- strcmpa(v, (CHAR8 *)"true") == 0) {
- *b = TRUE;
- return EFI_SUCCESS;
- }
-
- if (strcmpa(v, (CHAR8 *)"0") == 0 ||
- strcmpa(v, (CHAR8 *)"no") == 0 ||
- strcmpa(v, (CHAR8 *)"n") == 0 ||
- strcmpa(v, (CHAR8 *)"false") == 0) {
- *b = FALSE;
- return EFI_SUCCESS;
- }
-
- return EFI_INVALID_PARAMETER;
-}
-
-EFI_STATUS efivar_set_raw(const EFI_GUID *vendor, CHAR16 *name, CHAR8 *buf, UINTN size, BOOLEAN persistent) {
- UINT32 flags;
-
- flags = EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS;
- if (persistent)
- flags |= EFI_VARIABLE_NON_VOLATILE;
-
- return uefi_call_wrapper(RT->SetVariable, 5, name, (EFI_GUID *)vendor, flags, size, buf);
-}
-
-EFI_STATUS efivar_set(CHAR16 *name, CHAR16 *value, BOOLEAN persistent) {
- return efivar_set_raw(&loader_guid, name, (CHAR8 *)value, value ? (StrLen(value)+1) * sizeof(CHAR16) : 0, persistent);
-}
-
-EFI_STATUS efivar_set_int(CHAR16 *name, UINTN i, BOOLEAN persistent) {
- CHAR16 str[32];
-
- SPrint(str, 32, L"%d", i);
- return efivar_set(name, str, persistent);
-}
-
-EFI_STATUS efivar_get(CHAR16 *name, CHAR16 **value) {
- CHAR8 *buf;
- CHAR16 *val;
- UINTN size;
- EFI_STATUS err;
-
- err = efivar_get_raw(&loader_guid, name, &buf, &size);
- if (EFI_ERROR(err))
- return err;
-
- val = StrDuplicate((CHAR16 *)buf);
- if (!val) {
- FreePool(buf);
- return EFI_OUT_OF_RESOURCES;
- }
-
- *value = val;
- return EFI_SUCCESS;
-}
-
-EFI_STATUS efivar_get_int(CHAR16 *name, UINTN *i) {
- CHAR16 *val;
- EFI_STATUS err;
-
- err = efivar_get(name, &val);
- if (!EFI_ERROR(err)) {
- *i = Atoi(val);
- FreePool(val);
- }
- return err;
-}
-
-EFI_STATUS efivar_get_raw(const EFI_GUID *vendor, CHAR16 *name, CHAR8 **buffer, UINTN *size) {
- CHAR8 *buf;
- UINTN l;
- EFI_STATUS err;
-
- l = sizeof(CHAR16 *) * EFI_MAXIMUM_VARIABLE_SIZE;
- buf = AllocatePool(l);
- if (!buf)
- return EFI_OUT_OF_RESOURCES;
-
- err = uefi_call_wrapper(RT->GetVariable, 5, name, (EFI_GUID *)vendor, NULL, &l, buf);
- if (!EFI_ERROR(err)) {
- *buffer = buf;
- if (size)
- *size = l;
- } else
- FreePool(buf);
- return err;
-
-}
-
-VOID efivar_set_time_usec(CHAR16 *name, UINT64 usec) {
- CHAR16 str[32];
-
- if (usec == 0)
- usec = time_usec();
- if (usec == 0)
- return;
-
- SPrint(str, 32, L"%ld", usec);
- efivar_set(name, str, FALSE);
-}
-
-static INTN utf8_to_16(CHAR8 *stra, CHAR16 *c) {
- CHAR16 unichar;
- UINTN len;
- UINTN i;
-
- if (stra[0] < 0x80)
- len = 1;
- else if ((stra[0] & 0xe0) == 0xc0)
- len = 2;
- else if ((stra[0] & 0xf0) == 0xe0)
- len = 3;
- else if ((stra[0] & 0xf8) == 0xf0)
- len = 4;
- else if ((stra[0] & 0xfc) == 0xf8)
- len = 5;
- else if ((stra[0] & 0xfe) == 0xfc)
- len = 6;
- else
- return -1;
-
- switch (len) {
- case 1:
- unichar = stra[0];
- break;
- case 2:
- unichar = stra[0] & 0x1f;
- break;
- case 3:
- unichar = stra[0] & 0x0f;
- break;
- case 4:
- unichar = stra[0] & 0x07;
- break;
- case 5:
- unichar = stra[0] & 0x03;
- break;
- case 6:
- unichar = stra[0] & 0x01;
- break;
- }
-
- for (i = 1; i < len; i++) {
- if ((stra[i] & 0xc0) != 0x80)
- return -1;
- unichar <<= 6;
- unichar |= stra[i] & 0x3f;
- }
-
- *c = unichar;
- return len;
-}
-
-CHAR16 *stra_to_str(CHAR8 *stra) {
- UINTN strlen;
- UINTN len;
- UINTN i;
- CHAR16 *str;
-
- len = strlena(stra);
- str = AllocatePool((len + 1) * sizeof(CHAR16));
-
- strlen = 0;
- i = 0;
- while (i < len) {
- INTN utf8len;
-
- utf8len = utf8_to_16(stra + i, str + strlen);
- if (utf8len <= 0) {
- /* invalid utf8 sequence, skip the garbage */
- i++;
- continue;
- }
-
- strlen++;
- i += utf8len;
- }
- str[strlen] = '\0';
- return str;
-}
-
-CHAR16 *stra_to_path(CHAR8 *stra) {
- CHAR16 *str;
- UINTN strlen;
- UINTN len;
- UINTN i;
-
- len = strlena(stra);
- str = AllocatePool((len + 2) * sizeof(CHAR16));
-
- str[0] = '\\';
- strlen = 1;
- i = 0;
- while (i < len) {
- INTN utf8len;
-
- utf8len = utf8_to_16(stra + i, str + strlen);
- if (utf8len <= 0) {
- /* invalid utf8 sequence, skip the garbage */
- i++;
- continue;
- }
-
- if (str[strlen] == '/')
- str[strlen] = '\\';
- if (str[strlen] == '\\' && str[strlen-1] == '\\') {
- /* skip double slashes */
- i += utf8len;
- continue;
- }
-
- strlen++;
- i += utf8len;
- }
- str[strlen] = '\0';
- return str;
-}
-
-CHAR8 *strchra(CHAR8 *s, CHAR8 c) {
- do {
- if (*s == c)
- return s;
- } while (*s++);
- return NULL;
-}
-
-INTN file_read(EFI_FILE_HANDLE dir, CHAR16 *name, UINTN off, UINTN size, CHAR8 **content) {
- EFI_FILE_HANDLE handle;
- CHAR8 *buf;
- UINTN buflen;
- EFI_STATUS err;
- UINTN len;
-
- err = uefi_call_wrapper(dir->Open, 5, dir, &handle, name, EFI_FILE_MODE_READ, 0ULL);
- if (EFI_ERROR(err))
- return err;
-
- if (size == 0) {
- EFI_FILE_INFO *info;
-
- info = LibFileInfo(handle);
- buflen = info->FileSize+1;
- FreePool(info);
- } else
- buflen = size;
-
- if (off > 0) {
- err = uefi_call_wrapper(handle->SetPosition, 2, handle, off);
- if (EFI_ERROR(err))
- return err;
- }
-
- buf = AllocatePool(buflen);
- err = uefi_call_wrapper(handle->Read, 3, handle, &buflen, buf);
- if (!EFI_ERROR(err)) {
- buf[buflen] = '\0';
- *content = buf;
- len = buflen;
- } else {
- len = err;
- FreePool(buf);
- }
-
- uefi_call_wrapper(handle->Close, 1, handle);
- return len;
-}
diff --git a/src/efi/util.h b/src/efi/util.h
deleted file mode 100644
index b86102e..0000000
--- a/src/efi/util.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/*
- * This program 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 program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * Copyright (C) 2012-2013 Kay Sievers <kay@vrfy.org>
- * Copyright (C) 2012 Harald Hoyer <harald@redhat.com>
- */
-
-#ifndef __GUMMIBOOT_UTIL_H
-#define __GUMMIBOOT_UTIL_H
-
-#include <efi.h>
-#include <efilib.h>
-
-#define ELEMENTSOF(x) (sizeof(x)/sizeof((x)[0]))
-
-static inline const CHAR16 *yes_no(BOOLEAN b) {
- return b ? L"yes" : L"no";
-}
-
-EFI_STATUS parse_boolean(CHAR8 *v, BOOLEAN *b);
-
-UINT64 ticks_read(void);
-UINT64 ticks_freq(void);
-UINT64 time_usec(void);
-
-EFI_STATUS efivar_set(CHAR16 *name, CHAR16 *value, BOOLEAN persistent);
-EFI_STATUS efivar_set_raw(const EFI_GUID *vendor, CHAR16 *name, CHAR8 *buf, UINTN size, BOOLEAN persistent);
-EFI_STATUS efivar_set_int(CHAR16 *name, UINTN i, BOOLEAN persistent);
-VOID efivar_set_time_usec(CHAR16 *name, UINT64 usec);
-
-EFI_STATUS efivar_get(CHAR16 *name, CHAR16 **value);
-EFI_STATUS efivar_get_raw(const EFI_GUID *vendor, CHAR16 *name, CHAR8 **buffer, UINTN *size);
-EFI_STATUS efivar_get_int(CHAR16 *name, UINTN *i);
-
-CHAR8 *strchra(CHAR8 *s, CHAR8 c);
-CHAR16 *stra_to_path(CHAR8 *stra);
-CHAR16 *stra_to_str(CHAR8 *stra);
-
-INTN file_read(EFI_FILE_HANDLE dir, CHAR16 *name, UINTN off, UINTN size, CHAR8 **content);
-#endif
diff --git a/src/setup/efivars.c b/src/setup/efivars.c
deleted file mode 100644
index 7123257..0000000
--- a/src/setup/efivars.c
+++ /dev/null
@@ -1,647 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
- Copyright 2013 Kay Sievers
-
- systemd 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.
-
- systemd 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 systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <assert.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <string.h>
-#include <stddef.h>
-#include <dirent.h>
-#include <ctype.h>
-
-#include "efivars.h"
-
-bool is_efi_boot(void) {
- return access("/sys/firmware/efi", F_OK) >= 0;
-}
-
-static int read_flag(const char *varname) {
- int r;
- void *v;
- size_t s;
- uint8_t b;
-
- r = efi_get_variable(EFI_VENDOR_GLOBAL, varname, &v, &s);
- if (r < 0)
- return r;
-
- if (s != 1) {
- r = -EINVAL;
- goto finish;
- }
-
- b = *(uint8_t *)v;
- r = b > 0;
-finish:
- free(v);
- return r;
-}
-
-int is_efi_secure_boot(void) {
- return read_flag("SecureBoot");
-}
-
-int is_efi_secure_boot_setup_mode(void) {
- return read_flag("SetupMode");
-}
-
-int efi_get_variable(
- const uint8_t vendor[16],
- const char *name,
- void **value,
- size_t *size) {
-
- int fd = -1;
- char *p = NULL;
- uint32_t a;
- ssize_t n;
- struct stat st;
- void *b;
- int r;
-
- assert(name);
- assert(value);
- assert(size);
-
- if (asprintf(&p,
- "/sys/firmware/efi/efivars/%s-%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
- name,
- vendor[0], vendor[1], vendor[2], vendor[3], vendor[4], vendor[5], vendor[6], vendor[7],
- vendor[8], vendor[9], vendor[10], vendor[11], vendor[12], vendor[13], vendor[14], vendor[15]) < 0)
- return -ENOMEM;
-
- fd = open(p, O_RDONLY|O_NOCTTY|O_CLOEXEC);
- if (fd < 0) {
- r = -errno;
- goto finish;
- }
-
- if (fstat(fd, &st) < 0) {
- r = -errno;
- goto finish;
- }
- if (st.st_size < 4) {
- r = -EIO;
- goto finish;
- }
- if (st.st_size > 4*1024*1024 + 4) {
- r = -E2BIG;
- goto finish;
- }
-
- n = read(fd, &a, sizeof(a));
- if (n < 0) {
- r = errno;
- goto finish;
- }
- if (n != sizeof(a)) {
- r = -EIO;
- goto finish;
- }
-
- b = malloc(st.st_size - 4 + 2);
- if (!b) {
- r = -ENOMEM;
- goto finish;
- }
-
- n = read(fd, b, (size_t) st.st_size - 4);
- if (n < 0) {
- free(b);
- r = errno;
- goto finish;
- }
- if (n != (ssize_t) st.st_size - 4) {
- free(b);
- r = -EIO;
- goto finish;
- }
-
- /* Always NUL terminate (2 bytes, to protect UTF-16) */
- ((char*) b)[st.st_size - 4] = 0;
- ((char*) b)[st.st_size - 4 + 1] = 0;
-
- *value = b;
- *size = (size_t) st.st_size - 4;
- r = 0;
-
-finish:
- if (fd >= 0)
- close(fd);
- free(p);
- return r;
-}
-
-int efi_set_variable(
- const uint8_t vendor[16],
- const char *name,
- const void *value,
- size_t size) {
-
- struct var {
- uint32_t attr;
- char buf[];
- } __attribute__((packed)) *buf = NULL;
- char *p = NULL;
- int fd = -1;
- int r;
-
- assert(vendor);
- assert(name);
-
- if (asprintf(&p,
- "/sys/firmware/efi/efivars/%s-%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
- name,
- vendor[0], vendor[1], vendor[2], vendor[3], vendor[4], vendor[5], vendor[6], vendor[7],
- vendor[8], vendor[9], vendor[10], vendor[11], vendor[12], vendor[13], vendor[14], vendor[15]) < 0)
- return -ENOMEM;
-
- if (size == 0) {
- r = unlink(p);
- goto finish;
- }
-
- fd = open(p, O_WRONLY|O_CREAT|O_NOCTTY|O_CLOEXEC, 0644);
- if (fd < 0) {
- r = -errno;
- goto finish;
- }
-
- buf = malloc(sizeof(uint32_t) + size);
- if (!buf) {
- r = -errno;
- goto finish;
- }
-
- buf->attr = EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS;
- memcpy(buf->buf, value, size);
-
- r = write(fd, buf, sizeof(uint32_t) + size);
- if (r < 0) {
- r = -errno;
- goto finish;
- }
-
- if ((size_t)r != sizeof(uint32_t) + size) {
- r = -EIO;
- goto finish;
- }
-
-finish:
- if (fd >= 0)
- close(fd);
- free(buf);
- free(p);
- return r;
-}
-
-int efi_get_variable_string(const uint8_t vendor[16], const char *name, char **p) {
- void *s = NULL;
- size_t ss;
- char *x;
- int r;
-
- r = efi_get_variable(vendor, name, &s, &ss);
- if (r < 0)
- return r;
-
- x = utf16_to_utf8(s, ss);
- free(s);
- if (!x)
- return -ENOMEM;
-
- *p = x;
- return 0;
-}
-
-static size_t utf16_size(const uint16_t *s) {
- size_t l = 0;
-
- while (s[l] > 0)
- l++;
-
- return (l+1) * sizeof(uint16_t);
-}
-
-struct guid {
- uint32_t u1;
- uint16_t u2;
- uint16_t u3;
- uint8_t u4[8];
-} __attribute__((packed));
-
-static void efi_guid_to_id128(const void *guid, uint8_t *bytes) {
- const struct guid *uuid = guid;
-
- bytes[0] = (uuid->u1 >> 24) & 0xff;
- bytes[1] = (uuid->u1 >> 16) & 0xff;
- bytes[2] = (uuid->u1 >> 8) & 0xff;
- bytes[3] = (uuid->u1) & 0xff;
- bytes[4] = (uuid->u2 >> 8) & 0xff;
- bytes[5] = (uuid->u2) & 0xff;
- bytes[6] = (uuid->u3 >> 8) & 0xff;
- bytes[7] = (uuid->u3) & 0xff;
- memcpy(bytes+8, uuid->u4, sizeof(uuid->u4));
-}
-
-static void id128_to_efi_guid(const uint8_t *bytes, void *guid) {
- struct guid *uuid = guid;
-
- uuid->u1 = bytes[0] << 24 | bytes[1] << 16 | bytes[2] << 8 | bytes[3];
- uuid->u2 = bytes[4] << 8 | bytes[5];
- uuid->u3 = bytes[6] << 8 | bytes[7];
- memcpy(uuid->u4, bytes+8, sizeof(uuid->u4));
-}
-
-char *tilt_backslashes(char *s) {
- char *p;
-
- for (p = s; *p; p++)
- if (*p == '\\')
- *p = '/';
-
- return s;
-}
-
-uint16_t *tilt_slashes(uint16_t *s) {
- uint16_t *p;
-
- for (p = s; *p; p++)
- if (*p == '/')
- *p = '\\';
-
- return s;
-}
-
-#define LOAD_OPTION_ACTIVE 0x00000001
-#define MEDIA_DEVICE_PATH 0x04
-#define MEDIA_HARDDRIVE_DP 0x01
-#define MEDIA_FILEPATH_DP 0x04
-#define SIGNATURE_TYPE_GUID 0x02
-#define MBR_TYPE_EFI_PARTITION_TABLE_HEADER 0x02
-#define END_DEVICE_PATH_TYPE 0x7f
-#define END_ENTIRE_DEVICE_PATH_SUBTYPE 0xff
-
-struct boot_option {
- uint32_t attr;
- uint16_t path_len;
- uint16_t title[];
-} __attribute__((packed));
-
-struct drive_path {
- uint32_t part_nr;
- uint64_t part_start;
- uint64_t part_size;
- char signature[16];
- uint8_t mbr_type;
- uint8_t signature_type;
-} __attribute__((packed));
-
-struct device_path {
- uint8_t type;
- uint8_t sub_type;
- uint16_t length;
- union {
- uint16_t path[0];
- struct drive_path drive;
- };
-} __attribute__((packed));
-
-int efi_get_boot_option(uint16_t id, char **title, uint8_t part_uuid[16], char **path, bool *active) {
- char boot_id[9];
- uint8_t *buf = NULL;
- size_t l;
- struct boot_option *header;
- size_t title_size;
- char *s = NULL;
- char *p = NULL;
- uint8_t p_uuid[16] = "";
- int err;
-
- snprintf(boot_id, sizeof(boot_id), "Boot%04X", id);
- err = efi_get_variable(EFI_VENDOR_GLOBAL, boot_id, (void **) &buf, &l);
- if (err < 0)
- return err;
- if (l < sizeof(struct boot_option)) {
- err = -ENOENT;
- goto err;
- }
-
- header = (struct boot_option *) buf;
- title_size = utf16_size(header->title);
- if (title_size > l - offsetof(struct boot_option, title)) {
- err = -EINVAL;
- goto err;
- }
-
- s = utf16_to_utf8(header->title, title_size);
- if (!s) {
- err = -ENOMEM;
- goto err;
- }
-
- if (header->path_len > 0) {
- uint8_t *dbuf;
- size_t dnext;
-
- dbuf = buf + offsetof(struct boot_option, title) + title_size;
- dnext = 0;
- while (dnext < header->path_len) {
- struct device_path *dpath;
-
- dpath = (struct device_path *)(dbuf + dnext);
- if (dpath->length < 4)
- break;
-
- /* Type 0x7F – End of Hardware Device Path, Sub-Type 0xFF – End Entire Device Path */
- if (dpath->type == END_DEVICE_PATH_TYPE && dpath->sub_type == END_ENTIRE_DEVICE_PATH_SUBTYPE)
- break;
-
- dnext += dpath->length;
-
- if (dpath->type != MEDIA_DEVICE_PATH)
- continue;
-
- if (dpath->sub_type == MEDIA_HARDDRIVE_DP) {
- /* GPT Partition Table */
- if (dpath->drive.mbr_type != MBR_TYPE_EFI_PARTITION_TABLE_HEADER)
- continue;
-
- if (dpath->drive.signature_type != SIGNATURE_TYPE_GUID)
- continue;
-
- efi_guid_to_id128(dpath->drive.signature, p_uuid);
- continue;
- }
-
- if (dpath->sub_type == MEDIA_FILEPATH_DP) {
- p = utf16_to_utf8(dpath->path, dpath->length-4);
- tilt_backslashes(p);
- continue;
- }
- }
- }
-
- if (title)
- *title = s;
- else
- free(s);
-
- if (part_uuid)
- memcpy(part_uuid, p_uuid, 16);
-
- if (path)
- *path = p;
- else
- free(p);
-
- if (active)
- *active = !!header->attr & LOAD_OPTION_ACTIVE;
-
- free(buf);
- return 0;
-err:
- free(s);
- free(p);
- free(buf);
- return err;
-}
-
-static void to_utf16(uint16_t *dest, const char *src) {
- int i;
-
- for (i = 0; src[i] != '\0'; i++)
- dest[i] = src[i];
- dest[i] = '\0';
-}
-
-int efi_add_boot_option(uint16_t id, const char *title,
- uint32_t part, uint64_t pstart, uint64_t psize,
- const uint8_t part_uuid[16],
- const char *path) {
- char boot_id[9];
- char *buf;
- size_t size;
- size_t title_len;
- size_t path_len;
- struct boot_option *option;
- struct device_path *devicep;
- int err;
-
- title_len = (strlen(title)+1) * 2;
- path_len = (strlen(path)+1) * 2;
-
- buf = calloc(sizeof(struct boot_option) + title_len +
- sizeof(struct drive_path) +
- sizeof(struct device_path) + path_len, 1);
- if (!buf) {
- err = -ENOMEM;
- goto finish;
- }
-
- /* header */
- option = (struct boot_option *)buf;
- option->attr = LOAD_OPTION_ACTIVE;
- option->path_len = offsetof(struct device_path, drive) + sizeof(struct drive_path) +
- offsetof(struct device_path, path) + path_len +
- offsetof(struct device_path, path);
- to_utf16(option->title, title);
- size = offsetof(struct boot_option, title) + title_len;
-
- /* partition info */
- devicep = (struct device_path *)(buf + size);
- devicep->type = MEDIA_DEVICE_PATH;
- devicep->sub_type = MEDIA_HARDDRIVE_DP;
- devicep->length = offsetof(struct device_path, drive) + sizeof(struct drive_path);
- devicep->drive.part_nr = part;
- devicep->drive.part_start = pstart;
- devicep->drive.part_size = psize;
- devicep->drive.signature_type = SIGNATURE_TYPE_GUID;
- devicep->drive.mbr_type = MBR_TYPE_EFI_PARTITION_TABLE_HEADER;
- id128_to_efi_guid(part_uuid, devicep->drive.signature);
- size += devicep->length;
-
- /* path to loader */
- devicep = (struct device_path *)(buf + size);
- devicep->type = MEDIA_DEVICE_PATH;
- devicep->sub_type = MEDIA_FILEPATH_DP;
- devicep->length = offsetof(struct device_path, path) + path_len;
- to_utf16(devicep->path, path);
- tilt_slashes(devicep->path);
- size += devicep->length;
-
- /* end of path */
- devicep = (struct device_path *)(buf + size);
- devicep->type = END_DEVICE_PATH_TYPE;
- devicep->sub_type = END_ENTIRE_DEVICE_PATH_SUBTYPE;
- devicep->length = offsetof(struct device_path, path);
- size += devicep->length;
-
- snprintf(boot_id, sizeof(boot_id), "Boot%04X", id);
- err = efi_set_variable(EFI_VENDOR_GLOBAL, boot_id, buf, size);
-
-finish:
- free(buf);
- return err;
-}
-
-int efi_remove_boot_option(uint16_t id) {
- char boot_id[9];
-
- snprintf(boot_id, sizeof(boot_id), "Boot%04X", id);
- return efi_set_variable(EFI_VENDOR_GLOBAL, boot_id, NULL, 0);
-}
-
-int efi_get_boot_order(uint16_t **order) {
- void *buf;
- size_t l;
- int r;
-
- r = efi_get_variable(EFI_VENDOR_GLOBAL, "BootOrder", &buf, &l);
- if (r < 0)
- return r;
-
- if (l <= 0) {
- free(buf);
- return -ENOENT;
- }
-
- if ((l % sizeof(uint16_t) > 0)) {
- free(buf);
- return -EINVAL;
- }
-
- *order = buf;
- return (int) (l / sizeof(uint16_t));
-}
-
-int efi_set_boot_order(uint16_t *order, size_t n) {
- return efi_set_variable(EFI_VENDOR_GLOBAL, "BootOrder", order, n * sizeof(uint16_t));
-}
-
-static int boot_id_hex(const char s[4]) {
- int i;
- int id = 0;
-
- for (i = 0; i < 4; i++)
- if (s[i] >= '0' && s[i] <= '9')
- id |= (s[i] - '0') << (3 - i) * 4;
- else if (s[i] >= 'A' && s[i] <= 'F')
- id |= (s[i] - 'A' + 10) << (3 - i) * 4;
- else
- return -1;
-
- return id;
-}
-
-static int cmp_uint16(const void *_a, const void *_b) {
- const uint16_t *a = _a, *b = _b;
-
- return (int)*a - (int)*b;
-}
-
-int efi_get_boot_options(uint16_t **options) {
- DIR *dir;
- struct dirent *de;
- uint16_t *list = NULL;
- int count = 0;
-
- assert(options);
-
- dir = opendir("/sys/firmware/efi/efivars/");
- if (!dir)
- return -errno;
-
- while ((de = readdir(dir))) {
- int id;
- uint16_t *t;
-
- if (strncmp(de->d_name, "Boot", 4) != 0)
- continue;
-
- if (strlen(de->d_name) != 45)
- continue;
-
- if (strcmp(de->d_name + 8, "-8be4df61-93ca-11d2-aa0d-00e098032b8c") != 0)
- continue;
-
- id = boot_id_hex(de->d_name + 4);
- if (id < 0)
- continue;
-
- t = realloc(list, (count + 1) * sizeof(uint16_t));
- if (!t) {
- free(list);
- closedir(dir);
- return -ENOMEM;
- }
- list = t;
-
- list[count++] = id;
- }
-
- closedir(dir);
- qsort(list, count, sizeof(uint16_t), cmp_uint16);
- *options = list;
-
- return count;
-}
-
-char *utf16_to_utf8(const void *s, size_t length) {
- char *r;
- const uint8_t *f;
- uint8_t *t;
-
- r = malloc((length*3+1)/2 + 1);
- if (!r)
- return NULL;
-
- t = (uint8_t*) r;
-
- for (f = s; f < (const uint8_t*) s + length; f += 2) {
- uint16_t c;
-
- c = (f[1] << 8) | f[0];
-
- if (c == 0) {
- *t = 0;
- return r;
- } else if (c < 0x80) {
- *(t++) = (uint8_t) c;
- } else if (c < 0x800) {
- *(t++) = (uint8_t) (0xc0 | (c >> 6));
- *(t++) = (uint8_t) (0x80 | (c & 0x3f));
- } else {
- *(t++) = (uint8_t) (0xe0 | (c >> 12));
- *(t++) = (uint8_t) (0x80 | ((c >> 6) & 0x3f));
- *(t++) = (uint8_t) (0x80 | (c & 0x3f));
- }
- }
-
- *t = 0;
-
- return r;
-}
diff --git a/src/setup/efivars.h b/src/setup/efivars.h
deleted file mode 100644
index dfe7355..0000000
--- a/src/setup/efivars.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd 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.
-
- systemd 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 systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdbool.h>
-#include <sys/types.h>
-#include <inttypes.h>
-
-#define EFI_VARIABLE_NON_VOLATILE 0x0000000000000001
-#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x0000000000000002
-#define EFI_VARIABLE_RUNTIME_ACCESS 0x0000000000000004
-
-#define EFI_VENDOR_GLOBAL ((uint8_t[16]) { 0x8b,0xe4,0xdf,0x61,0x93,0xca,0x11,0xd2,0xaa,0x0d,0x00,0xe0,0x98,0x03,0x2b,0x8c })
-#define EFI_VENDOR_LOADER ((uint8_t[16]) { 0x4a,0x67,0xb0,0x82,0x0a,0x4c,0x41,0xcf,0xb6,0xc7,0x44,0x0b,0x29,0xbb,0x8c,0x4f })
-
-bool is_efi_boot(void);
-int is_efi_secure_boot(void);
-int is_efi_secure_boot_setup_mode(void);
-int efi_get_variable(const uint8_t vendor[16], const char *name, void **value, size_t *size);
-int efi_set_variable( const uint8_t vendor[16], const char *name, const void *value, size_t size);
-int efi_get_variable_string(const uint8_t vendor[16], const char *name, char **p);
-int efi_get_boot_option(uint16_t id, char **title, uint8_t part_uuid[16], char **path, bool *active);
-
-int efi_get_boot_options(uint16_t **options);
-int efi_add_boot_option(uint16_t id, const char *title,
- uint32_t part, uint64_t pstart, uint64_t psize,
- const uint8_t part_uuid[16],
- const char *path);
-int efi_remove_boot_option(uint16_t id);
-
-int efi_get_boot_order(uint16_t **order);
-int efi_set_boot_order(uint16_t *order, size_t n);
-
-char *utf16_to_utf8(const void *s, size_t length);
-char *tilt_backslashes(char *s);
-uint16_t *tilt_slashes(uint16_t *s);
diff --git a/src/setup/setup.c b/src/setup/setup.c
deleted file mode 100644
index 6a4275a..0000000
--- a/src/setup/setup.c
+++ /dev/null
@@ -1,1425 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
- Copyright 2013 Kay Sievers
-
- systemd 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.
-
- systemd 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 systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdio.h>
-#include <getopt.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <sys/statfs.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <dirent.h>
-#include <ctype.h>
-#include <limits.h>
-#include <ftw.h>
-#include <stdbool.h>
-#include <blkid.h>
-
-#include "efivars.h"
-
-#define ELEMENTSOF(x) (sizeof(x)/sizeof((x)[0]))
-#define streq(a,b) (strcmp((a),(b)) == 0)
-#define UUID_EMPTY ((uint8_t[16]) {})
-
-static inline bool streq_ptr(const char *a, const char *b) {
- if (a && b)
- return streq(a, b);
- if (!a && !b)
- return true;
- return false;
-}
-
-static inline bool isempty(const char *p) {
- return !p || !p[0];
-}
-
-static inline const char *strna(const char *s) {
- return isempty(s) ? "n/a" : s;
-}
-
-static int uuid_parse(const char *s, uint8_t uuid[16]) {
- int u[16];
- int i;
-
- if (sscanf(s, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
- &u[0], &u[1], &u[2], &u[3], &u[4], &u[5], &u[6], &u[7],
- &u[8], &u[9], &u[10], &u[11], &u[12], &u[13], &u[14], &u[15]) != 16)
- return -EINVAL;
-
- for (i = 0; i < 16; i++)
- uuid[i] = u[i];
-
- return 0;
-}
-
-static int verify_esp(const char *p, uint32_t *part, uint64_t *pstart, uint64_t *psize, uint8_t uuid[16]) {
- struct statfs sfs;
- struct stat st, st2;
- char *t;
- blkid_probe b = NULL;
- int r;
- const char *v;
-
- if (statfs(p, &sfs) < 0) {
- fprintf(stderr, "Failed to check file system type of %s: %m\n", p);
- return -errno;
- }
-
- if (sfs.f_type != 0x4d44) {
- fprintf(stderr, "File system %s is not a FAT EFI System Partition (ESP) file system.\n", p);
- return -ENODEV;
- }
-
- if (stat(p, &st) < 0) {
- fprintf(stderr, "Failed to determine block device node of %s: %m\n", p);
- return -errno;
- }
-
- if (major(st.st_dev) == 0) {
- fprintf(stderr, "Block device node of %p is invalid.\n", p);
- return -ENODEV;
- }
-
- r = asprintf(&t, "%s/..", p);
- if (r < 0) {
- fprintf(stderr, "Out of memory.\n");
- return -ENOMEM;
- }
-
- r = stat(t, &st2);
- free(t);
- if (r < 0) {
- fprintf(stderr, "Failed to determine block device node of parent of %s: %m\n", p);
- return -errno;
- }
-
- if (st.st_dev == st2.st_dev) {
- fprintf(stderr, "Directory %s is not the root of the EFI System Partition (ESP) file system.\n", p);
- return -ENODEV;
- }
-
- r = asprintf(&t, "/dev/block/%u:%u", major(st.st_dev), minor(st.st_dev));
- if (r < 0) {
- fprintf(stderr, "Out of memory.\n");
- return -ENOMEM;
- }
-
- errno = 0;
- b = blkid_new_probe_from_filename(t);
- free(t);
- if (!b) {
- if (errno != 0) {
- fprintf(stderr, "Failed to open file system %s: %m\n", p);
- return -errno;
- }
-
- fprintf(stderr, "Out of memory.\n");
- return -ENOMEM;
- }
-
- blkid_probe_enable_superblocks(b, 1);
- blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE);
- blkid_probe_enable_partitions(b, 1);
- blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS);
-
- errno = 0;
- r = blkid_do_safeprobe(b);
- if (r == -2) {
- fprintf(stderr, "File system %s is ambigious.\n", p);
- r = -ENODEV;
- goto fail;
- } else if (r == 1) {
- fprintf(stderr, "File system %s does not contain a label.\n", p);
- r = -ENODEV;
- goto fail;
- } else if (r != 0) {
- r = errno ? -errno : -EIO;
- fprintf(stderr, "Failed to probe file system %s: %s\n", p, strerror(-r));
- goto fail;
- }
-
- errno = 0;
- r = blkid_probe_lookup_value(b, "TYPE", &v, NULL);
- if (r != 0) {
- r = errno ? -errno : -EIO;
- fprintf(stderr, "Failed to probe file system type %s: %s\n", p, strerror(-r));
- goto fail;
- }
-
- if (strcmp(v, "vfat") != 0) {
- fprintf(stderr, "File system %s is not a FAT EFI System Partition (ESP) file system after all.\n", p);
- r = -ENODEV;
- goto fail;
- }
-
- errno = 0;
- r = blkid_probe_lookup_value(b, "PART_ENTRY_SCHEME", &v, NULL);
- if (r != 0) {
- r = errno ? -errno : -EIO;
- fprintf(stderr, "Failed to probe partition scheme %s: %s\n", p, strerror(-r));
- goto fail;
- }
-
- if (strcmp(v, "gpt") != 0) {
- fprintf(stderr, "File system %s is not on a GPT partition table.\n", p);
- r = -ENODEV;
- goto fail;
- }
-
- errno = 0;
- r = blkid_probe_lookup_value(b, "PART_ENTRY_TYPE", &v, NULL);
- if (r != 0) {
- r = errno ? -errno : -EIO;
- fprintf(stderr, "Failed to probe partition type UUID %s: %s\n", p, strerror(-r));
- goto fail;
- }
-
- if (strcmp(v, "c12a7328-f81f-11d2-ba4b-00a0c93ec93b") != 0) {
- r = -ENODEV;
- fprintf(stderr, "File system %s is not an EFI System Partition (ESP).\n", p);
- goto fail;
- }
-
- errno = 0;
- r = blkid_probe_lookup_value(b, "PART_ENTRY_UUID", &v, NULL);
- if (r != 0) {
- r = errno ? -errno : -EIO;
- fprintf(stderr, "Failed to probe partition entry UUID %s: %s\n", p, strerror(-r));
- goto fail;
- }
- uuid_parse(v, uuid);
-
- errno = 0;
- r = blkid_probe_lookup_value(b, "PART_ENTRY_NUMBER", &v, NULL);
- if (r != 0) {
- r = errno ? -errno : -EIO;
- fprintf(stderr, "Failed to probe partition number %s: %s\n", p, strerror(-r));
- goto fail;
- }
- *part = strtoul(v, NULL, 10);
-
- errno = 0;
- r = blkid_probe_lookup_value(b, "PART_ENTRY_OFFSET", &v, NULL);
- if (r != 0) {
- r = errno ? -errno : -EIO;
- fprintf(stderr, "Failed to probe partition offset %s: %s\n", p, strerror(-r));
- goto fail;
- }
- *pstart = strtoul(v, NULL, 10);
-
- errno = 0;
- r = blkid_probe_lookup_value(b, "PART_ENTRY_SIZE", &v, NULL);
- if (r != 0) {
- r = errno ? -errno : -EIO;
- fprintf(stderr, "Failed to probe partition size %s: %s\n", p, strerror(-r));
- goto fail;
- }
- *psize = strtoul(v, NULL, 10);
-
- blkid_free_probe(b);
- return 0;
-fail:
- if (b)
- blkid_free_probe(b);
- return r;
-}
-
-/* search for "#### LoaderInfo: gummiboot 31 ####" string inside the binary */
-static int get_file_version(FILE *f, char **v) {
- struct stat st;
- char *buf;
- const char *s, *e;
- char *x = NULL;
- int r = 0;
-
- assert(f);
- assert(v);
-
- if (fstat(fileno(f), &st) < 0)
- return -errno;
-
- if (st.st_size < 27)
- return 0;
-
- buf = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fileno(f), 0);
- if (buf == MAP_FAILED)
- return -errno;
-
- s = memmem(buf, st.st_size - 8, "#### LoaderInfo: ", 17);
- if (!s)
- goto finish;
- s += 17;
-
- e = memmem(s, st.st_size - (s - buf), " ####", 5);
- if (!e || e - s < 3) {
- fprintf(stderr, "Malformed version string.\n");
- r = -EINVAL;
- goto finish;
- }
-
- x = strndup(s, e - s);
- if (!x) {
- fprintf(stderr, "Out of memory.\n");
- r = -ENOMEM;
- goto finish;
- }
- r = 1;
-
-finish:
- munmap(buf, st.st_size);
- *v = x;
- return r;
-}
-
-static int enumerate_binaries(const char *esp_path, const char *path, const char *prefix) {
- struct dirent *de;
- char *p = NULL, *q = NULL;
- DIR *d = NULL;
- int r = 0, c = 0;
-
- if (asprintf(&p, "%s/%s", esp_path, path) < 0) {
- fprintf(stderr, "Out of memory.\n");
- r = -ENOMEM;
- goto finish;
- }
-
- d = opendir(p);
- if (!d) {
- if (errno == ENOENT) {
- r = 0;
- goto finish;
- }
-
- fprintf(stderr, "Failed to read %s: %m\n", p);
- r = -errno;
- goto finish;
- }
-
- while ((de = readdir(d))) {
- char *v;
- size_t n;
- FILE *f;
-
- if (de->d_name[0] == '.')
- continue;
-
- n = strlen(de->d_name);
- if (n < 4 || strcasecmp(de->d_name + n - 4, ".efi") != 0)
- continue;
-
- if (prefix && strncasecmp(de->d_name, prefix, strlen(prefix)) != 0)
- continue;
-
- free(q);
- q = NULL;
- if (asprintf(&q, "%s/%s/%s", esp_path, path, de->d_name) < 0) {
- fprintf(stderr, "Out of memory.\n");
- r = -ENOMEM;
- goto finish;
- }
-
- f = fopen(q, "re");
- if (!f) {
- fprintf(stderr, "Failed to open %s for reading: %m\n", q);
- r = -errno;
- goto finish;
- }
-
- r = get_file_version(f, &v);
- fclose(f);
-
- if (r < 0)
- goto finish;
-
- if (r > 0)
- printf(" File: └─/%s/%s (%s)\n", path, de->d_name, v);
- else
- printf(" File: └─/%s/%s\n", path, de->d_name);
-
- c++;
- free(v);
- }
-
- r = c;
-
-finish:
- if (d)
- closedir(d);
-
- free(p);
- free(q);
- return r;
-}
-
-static int status_binaries(const char *esp_path, uint8_t partition[16]) {
- int r;
-
- printf("Boot Loader Binaries:\n");
-
- printf(" ESP: /dev/disk/by-partuuid/%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
- partition[0], partition[1], partition[2], partition[3], partition[4], partition[5], partition[6], partition[7],
- partition[8], partition[9], partition[10], partition[11], partition[12], partition[13], partition[14], partition[15]);
-
- r = enumerate_binaries(esp_path, "EFI/gummiboot", NULL);
- if (r == 0)
- fprintf(stderr, "Gummiboot not installed in ESP.\n");
- else if (r < 0)
- return r;
-
- r = enumerate_binaries(esp_path, "EFI/Boot", "boot");
- if (r == 0)
- fprintf(stderr, "No default/fallback boot loader installed in ESP.\n");
- else if (r < 0)
- return r;
-
- printf("\n");
- return 0;
-}
-
-static int print_efi_option(uint16_t id, bool in_order) {
- char *title = NULL;
- char *path = NULL;
- uint8_t partition[16];
- bool active;
- int r = 0;
-
- r = efi_get_boot_option(id, &title, partition, &path, &active);
- if (r < 0)
- goto finish;
-
- /* print only configured entries with partition information */
- if (!path || memcmp(partition, UUID_EMPTY, 16) == 0)
- return 0;
-
- printf(" Title: %s\n", strna(title));
- printf(" ID: 0x%04X\n", id);
- printf(" Status: %sactive%s\n", active ? "" : "in", in_order ? ", boot-order" : "");
- printf(" Partition: /dev/disk/by-partuuid/%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
- partition[0], partition[1], partition[2], partition[3], partition[4], partition[5], partition[6], partition[7],
- partition[8], partition[9], partition[10], partition[11], partition[12], partition[13], partition[14], partition[15]);
- printf(" File: └─%s\n", path);
- printf("\n");
-
-finish:
- free(title);
- free(path);
- return r;
-}
-
-static int status_variables(void) {
- int n_options, n_order;
- uint16_t *options = NULL, *order = NULL;
- int r, i;
-
- if (!is_efi_boot()) {
- fprintf(stderr, "Not booted with EFI, not showing EFI variables.\n");
- return 0;
- }
-
- n_options = efi_get_boot_options(&options);
- if (n_options < 0) {
- if (n_options == -ENOENT)
- fprintf(stderr, "Failed to access EFI variables, "
- "efivarfs needs to be available at /sys/firmware/efi/efivars/.\n");
- else
- fprintf(stderr, "Failed to read EFI boot entries: %s\n", strerror(-n_options));
- r = n_options;
- goto finish;
- }
-
- printf("Boot Loader Entries in EFI Variables:\n");
- n_order = efi_get_boot_order(&order);
- if (n_order == -ENOENT) {
- n_order = 0;
- } else if (n_order < 0) {
- fprintf(stderr, "Failed to read EFI boot order.\n");
- r = n_order;
- goto finish;
- }
-
- /* print entries in BootOrder first */
- for (i = 0; i < n_order; i++)
- print_efi_option(order[i], true);
-
- /* print remaining entries */
- for (i = 0; i < n_options; i++) {
- int j;
- bool found = false;
-
- for (j = 0; j < n_order; j++)
- if (options[i] == order[j]) {
- found = true;
- break;
- }
-
- if (found)
- continue;
-
- print_efi_option(options[i], false);
- }
-
- r = 0;
-finish:
- free(options);
- free(order);
-
- return r;
-}
-
-static int compare_product(const char *a, const char *b) {
- size_t x, y;
-
- assert(a);
- assert(b);
-
- x = strcspn(a, " ");
- y = strcspn(b, " ");
- if (x != y)
- return x < y ? -1 : x > y ? 1 : 0;
-
- return strncmp(a, b, x);
-}
-
-static int compare_version(const char *a, const char *b) {
- assert(a);
- assert(b);
-
- a += strcspn(a, " ");
- a += strspn(a, " ");
- b += strcspn(b, " ");
- b += strspn(b, " ");
-
- return strverscmp(a, b);
-}
-
-static int version_check(FILE *f, const char *from, const char *to) {
- FILE *g = NULL;
- char *a = NULL, *b = NULL;
- int r;
-
- assert(f);
- assert(from);
- assert(to);
-
- r = get_file_version(f, &a);
- if (r < 0)
- goto finish;
- if (r == 0) {
- r = -EINVAL;
- fprintf(stderr, "Source file %s does not carry version information!\n", from);
- goto finish;
- }
-
- g = fopen(to, "re");
- if (!g) {
- if (errno == ENOENT) {
- r = 0;
- goto finish;
- }
-
- r = -errno;
- fprintf(stderr, "Failed to open %s for reading: %m\n", to);
- goto finish;
- }
-
- r = get_file_version(g, &b);
- if (r < 0)
- goto finish;
- if (r == 0 || compare_product(a, b) != 0) {
- r = -EEXIST;
- fprintf(stderr, "Skipping %s, since it's owned by another boot loader.\n", to);
- goto finish;
- }
-
- if (compare_version(a, b) < 0) {
- r = -EEXIST;
- fprintf(stderr, "Skipping %s, since it's a newer boot loader version already.\n", to);
- goto finish;
- }
-
- r = 0;
-
-finish:
- free(a);
- free(b);
- if (g)
- fclose(g);
- return r;
-}
-
-static int copy_file(const char *from, const char *to, bool force) {
- FILE *f = NULL, *g = NULL;
- char *p = NULL;
- int r;
- struct timespec t[2];
- struct stat st;
-
- assert(from);
- assert(to);
-
- f = fopen(from, "re");
- if (!f) {
- fprintf(stderr, "Failed to open %s for reading: %m\n", from);
- return -errno;
- }
-
- if (!force) {
- /* If this is an update, then let's compare versions first */
- r = version_check(f, from, to);
- if (r < 0)
- goto finish;
- }
-
- if (asprintf(&p, "%s~", to) < 0) {
- fprintf(stderr, "Out of memory.\n");
- r = -ENOMEM;
- goto finish;
- }
-
- g = fopen(p, "wxe");
- if (!g) {
- /* Directory doesn't exist yet? Then let's skip this... */
- if (!force && errno == ENOENT) {
- r = 0;
- goto finish;
- }
-
- fprintf(stderr, "Failed to open %s for writing: %m\n", to);
- r = -errno;
- goto finish;
- }
-
- rewind(f);
- do {
- size_t k;
- uint8_t buf[32*1024];
-
- k = fread(buf, 1, sizeof(buf), f);
- if (ferror(f)) {
- fprintf(stderr, "Failed to read %s: %m\n", from);
- r = -errno;
- goto finish;
- }
- if (k == 0)
- break;
-
- fwrite(buf, 1, k, g);
- if (ferror(g)) {
- fprintf(stderr, "Failed to write %s: %m\n", to);
- r = -errno;
- goto finish;
- }
- } while (!feof(f));
-
- fflush(g);
- if (ferror(g)) {
- fprintf(stderr, "Failed to write %s: %m\n", to);
- r = -errno;
- goto finish;
- }
-
- r = fstat(fileno(f), &st);
- if (r < 0) {
- fprintf(stderr, "Failed to get file timestamps of %s: %m", from);
- r = -errno;
- goto finish;
- }
-
- t[0] = st.st_atim;
- t[1] = st.st_mtim;
-
- r = futimens(fileno(g), t);
- if (r < 0) {
- fprintf(stderr, "Failed to change file timestamps for %s: %m", p);
- r = -errno;
- goto finish;
- }
-
- if (rename(p, to) < 0) {
- fprintf(stderr, "Failed to rename %s to %s: %m\n", p, to);
- r = -errno;
- goto finish;
- }
-
- fprintf(stderr, "Copied %s to %s.\n", from, to);
-
- free(p);
- p = NULL;
- r = 0;
-
-finish:
- if (f)
- fclose(f);
- if (g)
- fclose(g);
- if (p) {
- unlink(p);
- free(p);
- }
- return r;
-}
-
-static char* strupper(char *s) {
- char *p;
-
- for (p = s; *p; p++)
- *p = toupper(*p);
-
- return s;
-}
-
-static int mkdir_one(const char *prefix, const char *suffix) {
- char *p;
-
- if (asprintf(&p, "%s/%s", prefix, suffix) < 0) {
- fprintf(stderr, "Out of memory.\n");
- return -ENOMEM;
- }
-
- if (mkdir(p, 0700) < 0) {
- if (errno != EEXIST) {
- fprintf(stderr, "Failed to create %s: %m\n", p);
- free(p);
- return -errno;
- }
- } else
- fprintf(stderr, "Created %s.\n", p);
-
- free(p);
- return 0;
-}
-
-static int create_dirs(const char *esp_path) {
- int r;
-
- r = mkdir_one(esp_path, "EFI");
- if (r < 0)
- return r;
-
- r = mkdir_one(esp_path, "EFI/gummiboot");
- if (r < 0)
- return r;
-
- r = mkdir_one(esp_path, "EFI/Boot");
- if (r < 0)
- return r;
-
- r = mkdir_one(esp_path, "loader");
- if (r < 0)
- return r;
-
- r = mkdir_one(esp_path, "loader/entries");
- if (r < 0)
- return r;
-
- return 0;
-}
-
-static int copy_one_file(const char *esp_path, const char *name, bool force) {
- char *p = NULL, *q = NULL, *v = NULL;
- int r;
-
- if (asprintf(&p, GUMMIBOOTLIBDIR "/%s", name) < 0) {
- fprintf(stderr, "Out of memory.\n");
- r = -ENOMEM;
- goto finish;
- }
-
- if (asprintf(&q, "%s/EFI/gummiboot/%s", esp_path, name) < 0) {
- fprintf(stderr, "Out of memory.\n");
- r = -ENOMEM;
- goto finish;
- }
-
- r = copy_file(p, q, force);
-
- if (strncmp(name, "gummiboot", 9) == 0) {
- int k;
-
- /* Create the EFI default boot loader name (specified for removable devices) */
- if (asprintf(&v, "%s/EFI/Boot/%s", esp_path, name + 5) < 0) {
- fprintf(stderr, "Out of memory.\n");
- r = -ENOMEM;
- goto finish;
- }
- strupper(strrchr(v, '/') + 1);
-
- k = copy_file(p, v, force);
- if (k < 0 && r == 0) {
- r = k;
- goto finish;
- }
- }
-
-finish:
- free(p);
- free(q);
- free(v);
- return r;
-}
-
-static int install_binaries(const char *esp_path, bool force) {
- struct dirent *de;
- DIR *d;
- int r = 0;
-
- if (force) {
- /* Don't create any of these directories when we are
- * just updating. When we update we'll drop-in our
- * files (unless there are newer ones already), but we
- * won't create the directories for them in the first
- * place. */
- r = create_dirs(esp_path);
- if (r < 0)
- return r;
- }
-
- d = opendir(GUMMIBOOTLIBDIR);
- if (!d) {
- fprintf(stderr, "Failed to open "GUMMIBOOTLIBDIR": %m\n");
- return -errno;
- }
-
- while ((de = readdir(d))) {
- size_t n;
- int k;
-
- if (de->d_name[0] == '.')
- continue;
-
- n = strlen(de->d_name);
- if (n < 4 || strcmp(de->d_name + n - 4, ".efi") != 0)
- continue;
-
- k = copy_one_file(esp_path, de->d_name, force);
- if (k < 0 && r == 0)
- r = k;
- }
-
- closedir(d);
- return r;
-}
-
-static bool same_entry(uint16_t id, const uint8_t uuid[16], const char *path) {
- char *opath = NULL;
- uint8_t ouuid[16];
- int err;
- bool same = false;
-
- err = efi_get_boot_option(id, NULL, ouuid, &opath, NULL);
- if (err < 0)
- return false;
- if (memcmp(uuid, ouuid, 16) != 0)
- goto finish;
-
- if (!streq_ptr(path, opath))
- goto finish;
-
- same = true;
-
-finish:
- free(opath);
- return same;
-}
-
-static int find_slot(const uint8_t uuid[16], const char *path, uint16_t *id) {
- uint16_t *options = NULL;
- int n_options;
- int i;
- uint16_t new_id = 0;
- bool existing = false;
-
- n_options = efi_get_boot_options(&options);
- if (n_options < 0)
- return n_options;
-
- /* find already existing gummiboot entry */
- for (i = 0; i < n_options; i++)
- if (same_entry(options[i], uuid, path)) {
- new_id = options[i];
- existing = true;
- goto finish;
- }
-
- /* find free slot in the sorted BootXXXX variable list */
- for (i = 0; i < n_options; i++)
- if (i != options[i]) {
- new_id = i;
- goto finish;
- }
-
- /* use the next one */
- if (i == 0xffff)
- return -ENOSPC;
- new_id = i;
-
-finish:
- *id = new_id;
- free(options);
- return existing;
-}
-
-static int insert_into_order(uint16_t slot, bool first) {
- uint16_t *order = NULL;
- uint16_t *new_order;
- int n_order;
- int i;
- int err = 0;
-
- n_order = efi_get_boot_order(&order);
- if (n_order <= 0) {
- /* no entry, add us */
- err = efi_set_boot_order(&slot, 1);
- goto finish;
- }
-
- /* are we the first and only one? */
- if (n_order == 1 && order[0] == slot)
- goto finish;
-
- /* are we already in the boot order? */
- for (i = 0; i < n_order; i++) {
- if (order[i] != slot)
- continue;
-
- /* we do not require to be the first one, all is fine */
- if (!first)
- goto finish;
-
- /* move us to the first slot */
- memmove(&order[1], order, i * sizeof(uint16_t));
- order[0] = slot;
- efi_set_boot_order(order, n_order);
- goto finish;
- }
-
- /* extend array */
- new_order = realloc(order, (n_order+1) * sizeof(uint16_t));
- if (!new_order) {
- err = -ENOMEM;
- goto finish;
- }
- order = new_order;
-
- /* add us to the top or end of the list */
- if (first) {
- memmove(&order[1], order, n_order * sizeof(uint16_t));
- order[0] = slot;
- } else
- order[n_order] = slot;
-
- efi_set_boot_order(order, n_order+1);
-
-finish:
- free(order);
- return err;
-}
-
-static int remove_from_order(uint16_t slot) {
- uint16_t *order = NULL;
- int n_order;
- int i;
- int err = 0;
-
- n_order = efi_get_boot_order(&order);
- if (n_order < 0)
- return n_order;
- if (n_order == 0)
- return 0;
-
- for (i = 0; i < n_order; i++) {
- if (order[i] != slot)
- continue;
-
- if (i+1 < n_order)
- memmove(&order[i], &order[i+1], (n_order - i) * sizeof(uint16_t));
- efi_set_boot_order(order, n_order-1);
- break;
- }
-
- free(order);
- return err;
-}
-
-static int install_variables(const char *esp_path,
- uint32_t part, uint64_t pstart, uint64_t psize,
- const uint8_t uuid[16], const char *path,
- bool first) {
- char *p = NULL;
- uint16_t *options = NULL;
- uint16_t slot;
- int r;
-
- if (!is_efi_boot()) {
- fprintf(stderr, "Not booted with EFI, skipping EFI variable setup.\n");
- return 0;
- }
-
- if (asprintf(&p, "%s%s", esp_path, path) < 0) {
- fprintf(stderr, "Out of memory.\n");
- return -ENOMEM;
- }
-
- if (access(p, F_OK) < 0) {
- if (errno == ENOENT)
- r = 0;
- else
- r = -errno;
- goto finish;
- }
-
- r = find_slot(uuid, path, &slot);
- if (r < 0) {
- if (r == -ENOENT)
- fprintf(stderr, "Failed to access EFI variables. Is the \"efivarfs\" filesystem mounted?\n");
- else
- fprintf(stderr, "Failed to determine current boot order: %s\n", strerror(-r));
- goto finish;
- }
-
- if (first || r == false) {
- r = efi_add_boot_option(slot, "Linux Boot Manager",
- part, pstart, psize,
- uuid, path);
- if (r < 0) {
- fprintf(stderr, "Failed to create EFI Boot variable entry: %s\n", strerror(-r));
- goto finish;
- }
- fprintf(stderr, "Created EFI boot entry \"Linux Boot Manager\".\n");
- }
-
- insert_into_order(slot, first);
-
-finish:
- free(p);
- free(options);
- return r;
-}
-
-static int delete_nftw(const char *path, const struct stat *sb, int typeflag, struct FTW *ftw) {
- int r;
-
- if (typeflag == FTW_D || typeflag == FTW_DNR || typeflag == FTW_DP)
- r = rmdir(path);
- else
- r = unlink(path);
-
- if (r < 0)
- fprintf(stderr, "Failed to remove %s: %m\n", path);
- else
- fprintf(stderr, "Removed %s.\n", path);
-
- return 0;
-}
-
-static int rm_rf(const char *p) {
- nftw(p, delete_nftw, 20, FTW_DEPTH|FTW_MOUNT|FTW_PHYS);
- return 0;
-}
-
-static int remove_boot_efi(const char *esp_path) {
- struct dirent *de;
- char *p = NULL, *q = NULL;
- DIR *d = NULL;
- int r = 0, c = 0;
-
- if (asprintf(&p, "%s/EFI/Boot", esp_path) < 0) {
- fprintf(stderr, "Out of memory.\n");
- return -ENOMEM;
- }
-
- d = opendir(p);
- if (!d) {
- if (errno == ENOENT) {
- r = 0;
- goto finish;
- }
-
- fprintf(stderr, "Failed to read %s: %m\n", p);
- r = -errno;
- goto finish;
- }
-
- while ((de = readdir(d))) {
- char *v;
- size_t n;
- FILE *f;
-
- if (de->d_name[0] == '.')
- continue;
-
- n = strlen(de->d_name);
- if (n < 4 || strcasecmp(de->d_name + n - 4, ".EFI") != 0)
- continue;
-
- if (strncasecmp(de->d_name, "Boot", 4) != 0)
- continue;
-
- free(q);
- q = NULL;
- if (asprintf(&q, "%s/%s", p, de->d_name) < 0) {
- fprintf(stderr, "Out of memory.\n");
- r = -ENOMEM;
- goto finish;
- }
-
- f = fopen(q, "re");
- if (!f) {
- fprintf(stderr, "Failed to open %s for reading: %m\n", q);
- r = -errno;
- goto finish;
- }
-
- r = get_file_version(f, &v);
- fclose(f);
-
- if (r < 0)
- goto finish;
-
- if (r > 0 && strncmp(v, "gummiboot ", 10) == 0) {
-
- r = unlink(q);
- if (r < 0) {
- fprintf(stderr, "Failed to remove %s: %m\n", q);
- r = -errno;
- free(v);
- goto finish;
- } else
- fprintf(stderr, "Removed %s.\n", q);
- }
-
- c++;
- free(v);
- }
-
- r = c;
-
-finish:
- if (d)
- closedir(d);
- free(p);
- free(q);
-
- return r;
-}
-
-static int rmdir_one(const char *prefix, const char *suffix) {
- char *p;
-
- if (asprintf(&p, "%s/%s", prefix, suffix) < 0) {
- fprintf(stderr, "Out of memory.\n");
- return -ENOMEM;
- }
-
- if (rmdir(p) < 0) {
- if (errno != ENOENT && errno != ENOTEMPTY) {
- fprintf(stderr, "Failed to remove %s: %m\n", p);
- free(p);
- return -errno;
- }
- } else
- fprintf(stderr, "Removed %s.\n", p);
-
- free(p);
- return 0;
-}
-
-
-static int remove_binaries(const char *esp_path) {
- char *p;
- int r, q;
-
- if (asprintf(&p, "%s/EFI/gummiboot", esp_path) < 0) {
- fprintf(stderr, "Out of memory.\n");
- return -ENOMEM;
- }
-
- r = rm_rf(p);
- free(p);
-
- q = remove_boot_efi(esp_path);
- if (q < 0 && r == 0)
- r = q;
-
- q = rmdir_one(esp_path, "loader/entries");
- if (q < 0 && r == 0)
- r = q;
-
- q = rmdir_one(esp_path, "loader");
- if (q < 0 && r == 0)
- r = q;
-
- q = rmdir_one(esp_path, "EFI/Boot");
- if (q < 0 && r == 0)
- r = q;
-
- q = rmdir_one(esp_path, "EFI/gummiboot");
- if (q < 0 && r == 0)
- r = q;
-
- q = rmdir_one(esp_path, "EFI");
- if (q < 0 && r == 0)
- r = q;
-
- return r;
-}
-
-static int remove_variables(const uint8_t uuid[16], const char *path, bool in_order) {
- uint16_t slot;
- int r;
-
- if (!is_efi_boot())
- return 0;
-
- r = find_slot(uuid, path, &slot);
- if (r != 1)
- return 0;
-
- r = efi_remove_boot_option(slot);
- if (r < 0)
- return r;
-
- if (in_order)
- remove_from_order(slot);
-
- return 0;
-}
-
-static int install_loader_config(const char *esp_path) {
- char *p = NULL;
- char line[64];
- char *machine = NULL;
- FILE *f;
-
- f = fopen("/etc/machine-id", "re");
- if (!f)
- return -errno;
-
- if (fgets(line, sizeof(line), f) != NULL) {
- char *s;
-
- s = strchr(line, '\n');
- if (s)
- s[0] = '\0';
- if (strlen(line) == 32)
- machine = line;
- }
-
- fclose(f);
-
- if (!machine)
- return -ESRCH;
-
- if (asprintf(&p, "%s/%s", esp_path, "loader/loader.conf") < 0) {
- fprintf(stderr, "Out of memory.\n");
- return -ENOMEM;
- }
-
- f = fopen(p, "wxe");
- if (f) {
- fprintf(f, "#timeout 3\n");
- fprintf(f, "default %s-*\n", machine);
- fclose(f);
- }
-
- free(p);
- return 0;
-}
-
-static int help(void) {
- printf("%s [COMMAND] [OPTIONS...]\n"
- "\n"
- "Install, update or remove the Gummiboot EFI boot loader.\n\n"
- " -h --help Show this help\n"
- " --version Print version\n"
- " --path=PATH Path to the EFI System Partition (ESP)\n"
- " --no-variables Don't touch EFI variables\n"
- "\n"
- "Comands:\n"
- " status Show status of installed Gummiboot and EFI variables\n"
- " install Install Gummiboot to the ESP and EFI variables\n"
- " update Update Gummiboot in the ESP and EFI variables\n"
- " remove Remove Gummiboot from the ESP and EFI variables\n",
- program_invocation_short_name);
-
- return 0;
-}
-
-static const char *arg_path = NULL;
-static bool arg_touch_variables = true;
-
-static int parse_argv(int argc, char *argv[]) {
- enum {
- ARG_PATH = 0x100,
- ARG_VERSION,
- ARG_NO_VARIABLES,
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "path", required_argument, NULL, ARG_PATH },
- { "no-variables", no_argument, NULL, ARG_NO_VARIABLES },
- { NULL, 0, NULL, 0 }
- };
-
- int c;
-
- assert(argc >= 0);
- assert(argv);
-
- while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
- switch (c) {
-
- case 'h':
- help();
- return 0;
-
- case ARG_VERSION:
- printf(VERSION "\n");
- return 0;
-
- case ARG_PATH:
- arg_path = optarg;
- break;
-
- case ARG_NO_VARIABLES:
- arg_touch_variables = false;
- break;
-
- case '?':
- return -EINVAL;
-
- default:
- fprintf(stderr, "Unknown option code '%c'.\n", c);
- return -EINVAL;
- }
- }
-
- return 1;
-}
-
-int main(int argc, char*argv[]) {
- enum action {
- ACTION_STATUS,
- ACTION_INSTALL,
- ACTION_UPDATE,
- ACTION_REMOVE
- } arg_action = ACTION_STATUS;
-
- static const struct {
- const char* verb;
- enum action action;
- } verbs[] = {
- { "status", ACTION_STATUS },
- { "install", ACTION_INSTALL },
- { "update", ACTION_UPDATE },
- { "remove", ACTION_REMOVE },
- };
-
- uint8_t uuid[16] = "";
- uint32_t part = 0;
- uint64_t pstart = 0;
- uint64_t psize = 0;
- unsigned int i;
- int q;
- int r;
-
- r = parse_argv(argc, argv);
- if (r <= 0)
- goto finish;
-
- if (argv[optind]) {
- for (i = 0; i < ELEMENTSOF(verbs); i++) {
- if (!streq(argv[optind], verbs[i].verb))
- continue;
- arg_action = verbs[i].action;
- break;
- }
- if (i >= ELEMENTSOF(verbs)) {
- fprintf(stderr, "Unknown operation %s\n", argv[optind]);
- r = -EINVAL;
- goto finish;
- }
- }
-
- if (!arg_path)
- arg_path = "/boot";
-
- if (geteuid() != 0) {
- fprintf(stderr, "Need to be root.\n");
- r = -EPERM;
- goto finish;
- }
-
- r = verify_esp(arg_path, &part, &pstart, &psize, uuid);
- if (r == -ENODEV && !arg_path)
- fprintf(stderr, "You might want to use --path= to indicate the path to your ESP, in case it is not mounted to /boot.\n");
- if (r < 0)
- goto finish;
-
- switch (arg_action) {
- case ACTION_STATUS:
- r = status_binaries(arg_path, uuid);
- if (r < 0)
- goto finish;
-
- if (arg_touch_variables)
- r = status_variables();
- break;
-
- case ACTION_INSTALL:
- case ACTION_UPDATE:
- umask(0002);
-
- r = install_binaries(arg_path, arg_action == ACTION_INSTALL);
- if (r < 0)
- goto finish;
-
- if (arg_action == ACTION_INSTALL)
- install_loader_config(arg_path);
-
- if (arg_touch_variables)
- r = install_variables(arg_path,
- part, pstart, psize, uuid,
- "/EFI/gummiboot/gummiboot" MACHINE_TYPE_NAME ".efi",
- arg_action == ACTION_INSTALL);
- break;
-
- case ACTION_REMOVE:
- r = remove_binaries(arg_path);
-
- if (arg_touch_variables) {
- q = remove_variables(uuid, "/EFI/gummiboot/gummiboot" MACHINE_TYPE_NAME ".efi", true);
- if (q < 0 && r == 0)
- r = q;
- }
- break;
- }
-
-finish:
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/test/gummiboot.svg b/test/gummiboot.svg
deleted file mode 100644
index aec7695..0000000
--- a/test/gummiboot.svg
+++ /dev/null
@@ -1,1327 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="295.12869"
- height="245.34628"
- id="svg2"
- version="1.1"
- inkscape:version="0.48.2 r9819"
- sodipodi:docname="gummiboot.svg"
- inkscape:export-filename="/home/gnokii/Downloads/gummiboot/gummiboot.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90">
- <defs
- id="defs4">
- <linearGradient
- inkscape:collect="always"
- id="linearGradient4535">
- <stop
- style="stop-color:white;stop-opacity:1;"
- offset="0"
- id="stop4537" />
- <stop
- style="stop-color:white;stop-opacity:0;"
- offset="1"
- id="stop4539" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
- id="linearGradient4476">
- <stop
- style="stop-color:white;stop-opacity:1;"
- offset="0"
- id="stop4478" />
- <stop
- style="stop-color:white;stop-opacity:0;"
- offset="1"
- id="stop4480" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
- id="linearGradient4298">
- <stop
- style="stop-color:black;stop-opacity:1;"
- offset="0"
- id="stop4300" />
- <stop
- style="stop-color:black;stop-opacity:0;"
- offset="1"
- id="stop4302" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
- id="linearGradient4288">
- <stop
- style="stop-color:black;stop-opacity:1;"
- offset="0"
- id="stop4290" />
- <stop
- style="stop-color:black;stop-opacity:0;"
- offset="1"
- id="stop4292" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
- id="linearGradient4247">
- <stop
- style="stop-color:maroon;stop-opacity:1;"
- offset="0"
- id="stop4249" />
- <stop
- style="stop-color:maroon;stop-opacity:0;"
- offset="1"
- id="stop4251" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
- id="linearGradient4234">
- <stop
- style="stop-color:white;stop-opacity:1;"
- offset="0"
- id="stop4236" />
- <stop
- style="stop-color:white;stop-opacity:0;"
- offset="1"
- id="stop4238" />
- </linearGradient>
- <linearGradient
- id="linearGradient4226">
- <stop
- style="stop-color:#999;stop-opacity:1"
- offset="0"
- id="stop4228" />
- <stop
- id="stop4508"
- offset="0.09241502"
- style="stop-color:white;stop-opacity:1;" />
- <stop
- style="stop-color:#999;stop-opacity:1"
- offset="1"
- id="stop4230" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
- id="linearGradient3997">
- <stop
- id="stop4001"
- offset="0"
- style="stop-color:#4d4d4d;stop-opacity:1" />
- <stop
- id="stop3999"
- offset="1"
- style="stop-color:black;stop-opacity:1;" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
- id="linearGradient3899">
- <stop
- id="stop3903"
- offset="0"
- style="stop-color:#3e3e3e;stop-opacity:0;" />
- <stop
- id="stop3901"
- offset="1"
- style="stop-color:#3e3e3e;stop-opacity:1;" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
- id="linearGradient3889">
- <stop
- id="stop3893"
- offset="0"
- style="stop-color:#3e3e3e;stop-opacity:0;" />
- <stop
- id="stop3891"
- offset="1"
- style="stop-color:#3e3e3e;stop-opacity:1;" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
- id="linearGradient3879">
- <stop
- id="stop3883"
- offset="0"
- style="stop-color:#3e3e3e;stop-opacity:0;" />
- <stop
- id="stop3881"
- offset="1"
- style="stop-color:#3e3e3e;stop-opacity:1;" />
- </linearGradient>
- <linearGradient
- id="linearGradient4140">
- <stop
- style="stop-color:#333;stop-opacity:1;"
- offset="0"
- id="stop4142" />
- <stop
- id="stop4148"
- offset="0.4896037"
- style="stop-color:#4d4d4d;stop-opacity:1" />
- <stop
- style="stop-color:#333;stop-opacity:1;"
- offset="1"
- id="stop4144" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
- id="linearGradient4127">
- <stop
- style="stop-color:black;stop-opacity:1;"
- offset="0"
- id="stop4129" />
- <stop
- style="stop-color:#333;stop-opacity:1"
- offset="1"
- id="stop4131" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
- id="linearGradient4061">
- <stop
- style="stop-color:#f60;stop-opacity:1;"
- offset="0"
- id="stop4063" />
- <stop
- style="stop-color:#f60;stop-opacity:0;"
- offset="1"
- id="stop4065" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
- id="linearGradient3213">
- <stop
- style="stop-color:#500;stop-opacity:1;"
- offset="0"
- id="stop3215" />
- <stop
- style="stop-color:#2b0000;stop-opacity:1"
- offset="1"
- id="stop3217" />
- </linearGradient>
- <linearGradient
- id="linearGradient3190">
- <stop
- style="stop-color:#f60;stop-opacity:0;"
- offset="0"
- id="stop3192" />
- <stop
- id="stop3198"
- offset="0.5"
- style="stop-color:#f60;stop-opacity:1;" />
- <stop
- style="stop-color:#f60;stop-opacity:0;"
- offset="1"
- id="stop3194" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
- id="linearGradient3083">
- <stop
- style="stop-color:#a00;stop-opacity:1;"
- offset="0"
- id="stop3085" />
- <stop
- style="stop-color:red;stop-opacity:1"
- offset="1"
- id="stop3087" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3083"
- id="linearGradient3135"
- x1="-155.19038"
- y1="430.61288"
- x2="-25.082302"
- y2="464.95807"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(443.72882,-203.52067)" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3190"
- id="linearGradient3205"
- gradientUnits="userSpaceOnUse"
- x1="-398.54465"
- y1="581.10352"
- x2="-359.37869"
- y2="555.38928" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3190"
- id="linearGradient3207"
- gradientUnits="userSpaceOnUse"
- x1="-433.73215"
- y1="585.09375"
- x2="-401.41965"
- y2="560.80798" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3190"
- id="linearGradient3209"
- gradientUnits="userSpaceOnUse"
- x1="-453.45709"
- y1="607.90222"
- x2="-423.75446"
- y2="587.90222" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3213"
- id="linearGradient3219"
- x1="216.15257"
- y1="284.21103"
- x2="149.5762"
- y2="-0.074683182"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(115.15739,5.0507627)" />
- <filter
- inkscape:collect="always"
- id="filter4057"
- color-interpolation-filters="sRGB">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="5.086231"
- id="feGaussianBlur4059" />
- </filter>
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4061"
- id="linearGradient4067"
- x1="261.48038"
- y1="262.50522"
- x2="-65.937302"
- y2="-63.209064"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(115.15739,5.0507627)" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4127"
- id="linearGradient4133"
- x1="108.05394"
- y1="137.08904"
- x2="501.89236"
- y2="515.66046"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(115.15739,5.0507627)" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4140"
- id="linearGradient4146"
- x1="298.94162"
- y1="195.93752"
- x2="314.65753"
- y2="215.13042"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(115.15739,5.0507627)" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4140"
- id="linearGradient4152"
- gradientUnits="userSpaceOnUse"
- x1="298.94162"
- y1="195.93752"
- x2="314.65753"
- y2="215.13042"
- gradientTransform="translate(-53.53809,100.0051)" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3083"
- id="linearGradient4154"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(443.72882,-203.52067)"
- x1="-129.6945"
- y1="326.69928"
- x2="-139.07919"
- y2="663.8421" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3190"
- id="linearGradient4317"
- gradientUnits="userSpaceOnUse"
- x1="-398.54465"
- y1="581.10352"
- x2="-359.37869"
- y2="555.38928" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3190"
- id="linearGradient4319"
- gradientUnits="userSpaceOnUse"
- x1="-433.73215"
- y1="585.09375"
- x2="-401.41965"
- y2="560.80798" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3190"
- id="linearGradient4321"
- gradientUnits="userSpaceOnUse"
- x1="-453.45709"
- y1="607.90222"
- x2="-423.75446"
- y2="587.90222" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3190"
- id="linearGradient4324"
- gradientUnits="userSpaceOnUse"
- x1="-453.45709"
- y1="607.90222"
- x2="-423.75446"
- y2="587.90222"
- gradientTransform="translate(745.15739,-317.80638)" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3190"
- id="linearGradient4327"
- gradientUnits="userSpaceOnUse"
- x1="-433.73215"
- y1="585.09375"
- x2="-401.41965"
- y2="560.80798"
- gradientTransform="translate(745.15739,-317.80638)" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3190"
- id="linearGradient4330"
- gradientUnits="userSpaceOnUse"
- x1="-398.54465"
- y1="581.10352"
- x2="-359.37869"
- y2="555.38928"
- gradientTransform="translate(745.15739,-317.80638)" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3083"
- id="linearGradient4332"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(443.72882,-203.52067)"
- x1="-129.6945"
- y1="326.69928"
- x2="-139.07919"
- y2="663.8421" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4061"
- id="linearGradient4403"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(115.15739,5.0507627)"
- x1="261.48038"
- y1="262.50522"
- x2="-65.937302"
- y2="-63.209064" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3190"
- id="linearGradient4411"
- gradientUnits="userSpaceOnUse"
- x1="-398.54465"
- y1="581.10352"
- x2="-359.37869"
- y2="555.38928" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3190"
- id="linearGradient4413"
- gradientUnits="userSpaceOnUse"
- x1="-433.73215"
- y1="585.09375"
- x2="-401.41965"
- y2="560.80798" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3190"
- id="linearGradient4415"
- gradientUnits="userSpaceOnUse"
- x1="-453.45709"
- y1="607.90222"
- x2="-423.75446"
- y2="587.90222" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4140"
- id="linearGradient3059"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(0.48994548,0,0,0.48994548,-40.747352,45.32306)"
- x1="298.94162"
- y1="195.93752"
- x2="314.65753"
- y2="215.13042" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4140"
- id="linearGradient3063"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(0.48994548,0,0,0.48994548,41.904236,-1.199388)"
- x1="298.94162"
- y1="195.93752"
- x2="314.65753"
- y2="215.13042" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3213"
- id="linearGradient3073"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(0.48994548,0,0,0.48994548,41.904236,-1.199388)"
- x1="216.15257"
- y1="284.21103"
- x2="149.5762"
- y2="-0.074683182" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3083"
- id="linearGradient3076"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(0.48994548,0,0,0.48994548,202.88632,-103.38802)"
- x1="-155.19038"
- y1="430.61288"
- x2="-25.082302"
- y2="464.95807" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4127"
- id="linearGradient3079"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(0.48994548,0,0,0.48994548,41.904236,-1.199388)"
- x1="108.05394"
- y1="137.08904"
- x2="501.89236"
- y2="515.66046" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3083"
- id="linearGradient3084"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(0.48994548,0,0,0.48994548,202.88632,-103.38802)"
- x1="-129.6945"
- y1="326.69928"
- x2="-139.07919"
- y2="663.8421" />
- <filter
- inkscape:collect="always"
- id="filter3861"
- x="-0.0061426144"
- width="1.0122852"
- y="-0.25842857"
- height="1.5168571"
- color-interpolation-filters="sRGB">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="0.26919643"
- id="feGaussianBlur3863" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter3951"
- x="-0.088288896"
- width="1.1765778"
- y="-0.18725839"
- height="1.3745168"
- color-interpolation-filters="sRGB">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="3.2523265"
- id="feGaussianBlur3953" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter3957"
- x="-0.10244129"
- width="1.2048826"
- y="-0.14482306"
- height="1.2896461"
- color-interpolation-filters="sRGB">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="2.7508259"
- id="feGaussianBlur3959" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter3991"
- x="-0.12006523"
- width="1.2401305"
- y="-0.064596489"
- height="1.1291929"
- color-interpolation-filters="sRGB">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="2.3246134"
- id="feGaussianBlur3993" />
- </filter>
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3997"
- id="radialGradient4003"
- cx="110.74842"
- cy="145.46278"
- fx="110.74842"
- fy="145.46278"
- r="8.5547333"
- gradientTransform="matrix(0.66713883,-0.31394736,0.35781001,0.76034708,-15.184192,69.62976)"
- gradientUnits="userSpaceOnUse" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3997"
- id="linearGradient4007"
- x1="-71.785713"
- y1="89.147903"
- x2="-70"
- y2="89.147903"
- gradientUnits="userSpaceOnUse" />
- <filter
- inkscape:collect="always"
- id="filter4020"
- color-interpolation-filters="sRGB">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="0.38324131"
- id="feGaussianBlur4022" />
- </filter>
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3889"
- id="linearGradient4032"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(-0.35714286,0.35714286)"
- x1="297.38904"
- y1="287.81311"
- x2="327.66589"
- y2="287.81311" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3879"
- id="linearGradient4034"
- gradientUnits="userSpaceOnUse"
- x1="297.01022"
- y1="296.93698"
- x2="328.17096"
- y2="296.93698" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3899"
- id="linearGradient4036"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(-2.1428571,-1.4285714)"
- x1="297.26276"
- y1="305.87143"
- x2="328.04468"
- y2="305.87143" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3889"
- id="linearGradient4052"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(-0.35714286,0.35714286)"
- x1="297.38904"
- y1="287.81311"
- x2="327.66589"
- y2="287.81311" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3879"
- id="linearGradient4054"
- gradientUnits="userSpaceOnUse"
- x1="297.01022"
- y1="296.93698"
- x2="328.17096"
- y2="296.93698" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3899"
- id="linearGradient4056"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(-2.1428571,-1.4285714)"
- x1="297.26276"
- y1="305.87143"
- x2="328.04468"
- y2="305.87143" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3190"
- id="linearGradient4120"
- gradientUnits="userSpaceOnUse"
- x1="-398.54465"
- y1="581.10352"
- x2="-359.37869"
- y2="555.38928" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3190"
- id="linearGradient4122"
- gradientUnits="userSpaceOnUse"
- x1="-433.73215"
- y1="585.09375"
- x2="-401.41965"
- y2="560.80798" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3190"
- id="linearGradient4124"
- gradientUnits="userSpaceOnUse"
- x1="-453.45709"
- y1="607.90222"
- x2="-423.75446"
- y2="587.90222" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3190"
- id="linearGradient4128"
- gradientUnits="userSpaceOnUse"
- x1="-453.45709"
- y1="607.90222"
- x2="-423.75446"
- y2="587.90222"
- gradientTransform="matrix(0.48994548,0,0,0.48994548,350.56989,-159.38179)" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3190"
- id="linearGradient4131"
- gradientUnits="userSpaceOnUse"
- x1="-433.73215"
- y1="585.09375"
- x2="-401.41965"
- y2="560.80798"
- gradientTransform="matrix(0.48994548,0,0,0.48994548,350.56989,-159.38179)" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3190"
- id="linearGradient4134"
- gradientUnits="userSpaceOnUse"
- x1="-398.54465"
- y1="581.10352"
- x2="-359.37869"
- y2="555.38928"
- gradientTransform="matrix(0.48994548,0,0,0.48994548,350.56989,-159.38179)" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3889"
- id="linearGradient4136"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(-0.35714286,0.35714286)"
- x1="297.38904"
- y1="287.81311"
- x2="327.66589"
- y2="287.81311" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3879"
- id="linearGradient4138"
- gradientUnits="userSpaceOnUse"
- x1="297.01022"
- y1="296.93698"
- x2="328.17096"
- y2="296.93698" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3899"
- id="linearGradient4141"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(-2.1428571,-1.4285714)"
- x1="297.26276"
- y1="305.87143"
- x2="328.04468"
- y2="305.87143" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3899"
- id="linearGradient4144"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(-30.427128,-201.43877)"
- x1="297.26276"
- y1="305.87143"
- x2="328.04468"
- y2="305.87143" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3879"
- id="linearGradient4147"
- gradientUnits="userSpaceOnUse"
- x1="297.01022"
- y1="296.93698"
- x2="328.17096"
- y2="296.93698"
- gradientTransform="translate(-28.284271,-200.0102)" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3889"
- id="linearGradient4150"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(-28.641414,-199.65306)"
- x1="297.38904"
- y1="287.81311"
- x2="327.66589"
- y2="287.81311" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3889"
- id="linearGradient4155"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(-0.35714286,0.35714286)"
- x1="297.38904"
- y1="287.81311"
- x2="327.66589"
- y2="287.81311" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3879"
- id="linearGradient4157"
- gradientUnits="userSpaceOnUse"
- x1="297.01022"
- y1="296.93698"
- x2="328.17096"
- y2="296.93698" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3899"
- id="linearGradient4159"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(-2.1428571,-1.4285714)"
- x1="297.26276"
- y1="305.87143"
- x2="328.04468"
- y2="305.87143" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3899"
- id="linearGradient4162"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(-0.52943173,0.84835255,0.84835255,0.52943173,-17.10484,-212.31631)"
- x1="297.26276"
- y1="305.87143"
- x2="328.04468"
- y2="305.87143" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3879"
- id="linearGradient4165"
- gradientUnits="userSpaceOnUse"
- x1="297.01022"
- y1="296.93698"
- x2="328.17096"
- y2="296.93698"
- gradientTransform="matrix(-0.52943173,0.84835255,0.84835255,0.52943173,-17.027404,-209.74208)" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3889"
- id="linearGradient4168"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(-0.52943173,0.84835255,0.84835255,0.52943173,-16.535338,-209.85598)"
- x1="297.38904"
- y1="287.81311"
- x2="327.66589"
- y2="287.81311" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3083"
- id="linearGradient4173"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(0.48994548,0,0,0.48994548,174.76488,-111.73254)"
- x1="-129.6945"
- y1="326.69928"
- x2="-139.07919"
- y2="663.8421" />
- <filter
- inkscape:collect="always"
- id="filter4184">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="3.4423031"
- id="feGaussianBlur4186" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter4216">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="1.9124443"
- id="feGaussianBlur4218" />
- </filter>
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4226"
- id="linearGradient4232"
- x1="201.85893"
- y1="201.62338"
- x2="88.238426"
- y2="29.098005"
- gradientUnits="userSpaceOnUse" />
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4234"
- id="radialGradient4240"
- cx="135.30005"
- cy="59.140411"
- fx="135.30005"
- fy="59.140411"
- r="40.136741"
- gradientTransform="matrix(1,0,0,0.81698548,0,17.046426)"
- gradientUnits="userSpaceOnUse" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4247"
- id="linearGradient4253"
- x1="35.157597"
- y1="70.196426"
- x2="56.52232"
- y2="71.26786"
- gradientUnits="userSpaceOnUse" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4247"
- id="linearGradient4260"
- x1="150.62947"
- y1="234.53995"
- x2="138.9509"
- y2="183.46852"
- gradientUnits="userSpaceOnUse" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4247"
- id="linearGradient4264"
- gradientUnits="userSpaceOnUse"
- x1="95.629471"
- y1="249.89709"
- x2="231.09375"
- y2="177.03995" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4247"
- id="linearGradient4271"
- x1="128.5759"
- y1="222.77562"
- x2="129.52232"
- y2="201.34705"
- gradientUnits="userSpaceOnUse" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4247"
- id="linearGradient4278"
- x1="213.71428"
- y1="172.97545"
- x2="201.10735"
- y2="166.54688"
- gradientUnits="userSpaceOnUse" />
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4288"
- id="radialGradient4294"
- cx="132.05447"
- cy="100.1967"
- fx="132.05447"
- fy="100.1967"
- r="25.40625"
- gradientTransform="matrix(0.83734013,-0.54668227,1.2370409,1.8947461,-102.46746,-27.168077)"
- gradientUnits="userSpaceOnUse" />
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4298"
- id="radialGradient4304"
- cx="123.48306"
- cy="113.45441"
- fx="123.48306"
- fy="113.45441"
- r="25.40625"
- gradientTransform="matrix(0.82472039,-0.5655407,1.2510982,1.8244597,-120.29854,-30.956633)"
- gradientUnits="userSpaceOnUse" />
- <filter
- inkscape:collect="always"
- id="filter4310">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="0.31593749"
- id="feGaussianBlur4312" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter4330">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="0.3159375"
- id="feGaussianBlur4332" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter4400"
- x="-0.34000003"
- width="1.6800001"
- y="-0.1115625"
- height="1.223125">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="1.5026018"
- id="feGaussianBlur4402" />
- </filter>
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4140"
- id="linearGradient4406"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(0.48994548,0,0,0.48994548,-40.747352,45.32306)"
- x1="298.94162"
- y1="195.93752"
- x2="314.65753"
- y2="215.13042" />
- <filter
- inkscape:collect="always"
- id="filter4472"
- x="-0.15124256"
- width="1.3024851"
- y="-0.11710123"
- height="1.2342025">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="0.72078202"
- id="feGaussianBlur4474" />
- </filter>
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4476"
- id="radialGradient4482"
- cx="110.59362"
- cy="145.605"
- fx="110.59362"
- fy="145.605"
- r="7.4487594"
- gradientTransform="matrix(1,0,0,1.2238444,0,-32.592856)"
- gradientUnits="userSpaceOnUse" />
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4476"
- id="radialGradient4486"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(1,0,0,1.2238444,82.57997,-79.312411)"
- cx="110.59362"
- cy="145.605"
- fx="110.59362"
- fy="145.605"
- r="7.4487594" />
- <filter
- inkscape:collect="always"
- id="filter4502"
- x="-0.25105351"
- width="1.502107"
- y="-0.026536847"
- height="1.0530737">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="0.79301865"
- id="feGaussianBlur4504" />
- </filter>
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3213"
- id="linearGradient4519"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(0.48994548,0,0,0.48994548,41.904236,-1.199388)"
- x1="216.15257"
- y1="284.21103"
- x2="149.5762"
- y2="-0.074683182" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient4535"
- id="linearGradient4541"
- x1="171.71072"
- y1="169.34375"
- x2="200.78407"
- y2="142.91518"
- gradientUnits="userSpaceOnUse" />
- </defs>
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="0.9899495"
- inkscape:cx="151.67058"
- inkscape:cy="130.22692"
- inkscape:document-units="px"
- inkscape:current-layer="layer1"
- showgrid="false"
- inkscape:window-width="1280"
- inkscape:window-height="965"
- inkscape:window-x="0"
- inkscape:window-y="27"
- inkscape:window-maximized="1"
- fit-margin-top="20"
- fit-margin-right="20"
- fit-margin-bottom="20"
- fit-margin-left="20"
- inkscape:showpageshadow="false"
- borderlayer="true"
- showguides="true"
- inkscape:guide-bbox="true" />
- <metadata
- id="metadata7">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:label="Ebene 1"
- inkscape:groupmode="layer"
- id="layer1"
- transform="translate(-28.121442,-8.3445206)">
- <path
- style="opacity:0.5;fill:black;stroke:none;filter:url(#filter4184)"
- d="m 119.13037,34.558806 c -6.46995,0.102869 -12.93557,1.164239 -19.125,3.25 -7.073636,2.257821 -13.06569,7.125218 -17.749999,12.78125 -13.954711,17.440697 -17.137321,41.958601 -12.0625,63.281254 6.826837,18.85682 15.530888,37.16266 26.21875,54.21875 -0.992147,1.64344 -1.626584,2.68403 -2,3.15625 l -1.5625,-0.15625 -0.65625,1.28125 c -0.0097,0.01 -0.02246,-0.0103 -0.03125,0 -0.48075,0.50119 -0.495877,0.70011 -0.15625,1.5 l 0.375,0.90625 -2.90625,4.625 c -2.464107,3.90972 -3.013095,4.6489 -3.40625,4.65625 -0.256449,0.005 -0.604724,0.21991 -0.78125,0.5 -0.176987,0.27982 -0.628647,0.67362 -1,0.84375 -0.451297,0.20673 -0.976977,0.77897 -1.59375,1.75 -0.838625,1.32056 -0.986193,1.45743 -1.59375,1.40625 -0.404286,-0.0341 -0.875575,0.13221 -1.21875,0.46875 -0.705691,0.69205 -1.678336,1.1556 -4.375,2.0625 -2.40709,0.80951 -5.417848,2.20923 -8,3.6875 -4.890367,2.25417 -13.565719,12.51622 -17.28125,18.53125 -0.530479,0.85948 -0.946652,1.63187 -1.25,2.28125 -0.896073,1.90319 -2.299489,6.22356 -2.28125,7.03125 1.412554,5.50433 16.597841,15.78411 25.03125,15.78125 0.736522,-0.332 4.044644,-3.46426 5.375,-5.09375 0.454909,-0.55384 0.953779,-1.27543 1.5,-2.125 3.823544,-5.94696 9.357354,-18.17817 9.28125,-23.5625 0.219652,-2.96725 0.151892,-6.2917 -0.15625,-8.8125 -0.345215,-2.82406 -0.351119,-3.90855 -0.03125,-4.84375 0.155594,-0.45476 0.14264,-0.96247 -0.0625,-1.3125 -0.308338,-0.52604 -0.266924,-0.7049 0.5625,-2.03125 0.609885,-0.97538 0.914412,-1.72243 0.90625,-2.21875 -0.0067,-0.40841 0.135983,-0.96991 0.3125,-1.25 0.176976,-0.27981 0.231314,-0.70407 0.125,-0.9375 -0.162999,-0.35786 0.254635,-1.15279 2.71875,-5.0625 l 2.9375,-4.625 0.96875,-0.0312 c 0.868137,-0.0387 1.036509,-0.13131 1.28125,-0.78125 0.0046,-0.013 -0.0054,-0.0187 0,-0.0312 l 0.875,-1.15625 -0.84375,-1.34375 c 0.178207,-0.36368 0.557982,-0.96013 1.0625,-1.75 4.099979,6.32493 8.499389,12.45778 13.156249,18.375 0.48509,0.61645 0.97761,1.2322 1.46875,1.84375 1.8736,2.33253 3.78752,4.64786 5.75,6.90625 0.74439,0.85673 1.52399,1.71693 2.28125,2.5625 1.75433,1.95812 3.55158,3.88531 5.375,5.78125 0.0817,0.0849 0.16818,0.1652 0.25,0.25 2.54216,2.63479 5.13572,5.21231 7.8125,7.71875 8.50027,9.95425 22.88939,10.296 34.75,7.875 10.57416,-3.28393 20.74676,-8.10548 30.71875,-12.96875 9.02977,-5.71216 19.12361,-10.46239 26.09375,-18.78125 7.1065,-6.63597 9.36094,-16.9079 7.03125,-26.15625 -0.87215,-3.12221 -1.80086,-6.24194 -2.78125,-9.34375 -0.28444,-0.89998 -0.58127,-1.78975 -0.875,-2.6875 -2.35945,-7.21433 -5.0026,-14.36085 -7.96875,-21.375 -0.31468,-0.74302 -0.64712,-1.47864 -0.96875,-2.21875 -3.80762,-8.77496 -8.09911,-17.34196 -12.90625,-25.59375 8.25065,-0.11748 15.08852,-0.25018 17.40625,-0.3125 2.61172,-0.0703 3.92372,-0.072 4.625,0 l 0.71875,1.40625 1.40625,-0.125 c 0.0134,0.002 0.0178,-0.003 0.0312,0 0.68095,0.13647 0.85132,0.0598 1.34375,-0.65625 l 0.5625,-0.8125 5.46875,-0.0312 c 4.6214,-0.0205 5.53271,0.0473 5.75,0.375 0.14175,0.21378 0.51268,0.377 0.84375,0.375 0.33107,-0.001 0.90709,0.18431 1.25,0.40625 0.41673,0.26969 1.19339,0.40725 2.34375,0.40625 1.56434,-0.001 1.74823,0.0537 2.03125,0.59375 0.18834,0.35935 0.59432,0.67248 1.0625,0.78125 0.96273,0.22376 1.88072,0.77449 4.09375,2.5625 1.97538,1.596 4.74144,3.39664 7.375,4.78125 4.52752,2.9152 17.86807,4.7202 24.9375,4.625 1.00992,-0.0136 1.88305,-0.0635 2.59375,-0.15625 2.08671,-0.26591 6.48466,-1.42594 7.15625,-1.875 4.46734,-7.15299 3.79676,-25.449994 -0.125,-29.562504 -0.67555,-0.44309 -5.06727,-1.56508 -7.15625,-1.8125 -0.71151,-0.08646 -1.61501,-0.12 -2.625,-0.125 -7.06999,-0.03247 -20.37356,1.85717 -24.875,4.8125 -2.62117,1.40793 -5.38261,3.26152 -7.34375,4.875 -2.19707,1.80758 -3.10178,2.36147 -4.0625,2.59375 -0.46719,0.11296 -0.87737,0.42023 -1.0625,0.78125 -0.27824,0.54252 -0.46695,0.6127 -2.03125,0.625 -1.15031,0.0091 -1.92944,0.16409 -2.34375,0.4375 -0.34093,0.22497 -0.88766,0.40425 -1.21875,0.40625 -0.33107,0.0015 -0.73516,0.15998 -0.875,0.375 -0.21439,0.32964 -1.09735,0.417 -5.71875,0.4375 l -5.5,0 -0.5625,-0.8125 c -0.49878,-0.71161 -0.63279,-0.7675 -1.3125,-0.625 -0.0134,0.002 -0.0177,-0.003 -0.0312,0 l -1.4375,-0.125 -0.6875,1.40625 c -0.70061,0.0782 -2.01276,0.07825 -4.625,0.03125 -2.52621,-0.04549 -10.51861,-0.07748 -19.84375,-0.125 -10.99838,-18.001163 -24.49526,-34.379543 -40.75,-48 -12.29389,-11.240981 -28.87193,-17.262888 -45.40625,-17 z"
- id="path4058"
- inkscape:connector-curvature="0" />
- <path
- style="fill:url(#linearGradient3084);stroke:none"
- d="m 101.4278,33.103606 c 22.00686,-7.41604 47.43988,-1.904589 64.54442,13.735037 34.53894,28.941476 56.68428,70.344647 68.6772,113.278217 2.32969,9.24835 0.0805,19.51595 -7.026,26.15192 -6.97014,8.31886 -17.07619,13.08807 -26.10596,18.80023 -9.97199,4.86327 -20.14535,9.69152 -30.71951,12.97545 -11.86061,2.421 -26.24237,2.07569 -34.74264,-7.87856 C 106.58411,182.57008 85.298526,146.92722 71.619341,109.14311 66.54452,87.820461 69.73869,63.30161 83.693401,45.860913 88.37771,40.204881 94.354163,35.361427 101.4278,33.103606 z"
- id="path3060"
- inkscape:connector-curvature="0" />
- <path
- style="opacity:0.50914636;fill:url(#linearGradient4403);stroke:none;filter:url(#filter4057)"
- d="m 275.09489,77.582013 c -25.48954,-0.0341 -53.23884,9.303263 -67.65625,31.593747 -29.34598,40.0012 -31.35591,96.06645 -10.15625,140.1875 28.40061,68.57333 69.87976,132.82934 125.71875,181.875 18.83018,13.75543 44.70925,9.94441 65.2843,2.19161 31.84184,-12.08972 63.14991,-27.48346 89.54425,-49.21364 12.02569,-9.65157 21.4953,-23.66814 20.54645,-39.57172 C 497.25128,329.51069 490.84796,315.277 486.42547,300.85528 459.98101,225.34605 416.99674,153.47738 353.15739,103.55076 331.45029,85.766501 303.01267,77.038582 275.09489,77.582013 z m 18.5,35.281247 c 33.49963,-0.16647 62.76474,21.30865 82.35166,46.955 33.60869,44.23485 60.18853,94.91388 70.61709,149.82625 1.85099,21.10638 -10.76826,41.10271 -28.34873,51.8572 -14.67831,10.02452 -31.37172,18.53922 -49.05752,21.11155 -20.86965,1.52845 -39.4515,-10.98641 -52.66421,-26.00796 -21.68266,-22.65013 -40.72161,-47.99611 -57.53199,-74.53539 -19.73396,-32.86952 -33.92671,-71.75049 -28.21005,-110.6754 5.66976,-29.99665 30.88766,-57.96287 62.84375,-58.53125 z"
- id="path3225"
- inkscape:connector-curvature="0"
- transform="matrix(0.48994548,0,0,0.48994548,-14.516607,-3.6739864)" />
- <path
- style="fill:url(#linearGradient3079);stroke:none;stroke-width:0.48994546999999999"
- d="m 122.62713,32.816827 c -0.45601,-0.0029 -0.92372,0.0078 -1.37797,0.01529 -7.61411,0.125372 -14.95375,1.734064 -21.312631,5.220981 -14.297942,7.840331 -19.751829,27.814615 -21.282007,44.049159 -2.628651,27.888823 9.472253,55.994813 21.771948,81.162523 3.11536,6.37465 6.12356,12.07802 9.09462,17.13279 0.004,0.006 0.011,0.01 0.0153,0.0153 6.60116,8.82634 13.79399,17.19442 21.60354,24.98722 3.86943,2.36591 7.93954,3.84064 12.35581,4.3942 21.58464,2.70555 39.79412,1.82298 55.42508,-8.42094 16.71358,-10.95342 36.39004,-31.21492 32.94884,-50.58687 -5.13967,-16.26239 -11.79429,-32.17661 -20.05715,-47.15725 -0.0645,-0.11087 -0.11898,-0.226 -0.18373,-0.33684 C 197.79062,79.603321 179.38585,56.647788 162.78732,45.478804 151.65959,37.991067 136.76345,32.908961 122.6271,32.816778 z m -5.68031,1.454525 c 14.68779,0.138366 30.82466,9.423631 44.01854,17.086847 32.65271,18.965206 59.81676,65.422781 67.22971,96.840791 4.4609,18.90644 -13.38155,41.90571 -29.73395,52.62243 -14.93666,9.7889 -33.81894,7.65402 -54.44481,5.06865 -16.13613,-2.0226 -27.54641,-16.60043 -41.15542,-44.44725 C 91.10753,137.39303 82.58703,110.70225 84.533868,84.368276 85.779304,67.521824 88.362194,45.064993 103.38146,37.333512 c 3.8426,-1.978062 7.92469,-2.913035 12.14146,-3.046849 0.47062,-0.01494 0.9501,-0.01979 1.4239,-0.01529 z"
- id="path3067"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="ssssscccssccsssssssssssss" />
- <path
- style="fill:url(#linearGradient3076);fill-opacity:1"
- d="m 170.48143,170.96997 c 7.9039,-2.80386 9.4391,-3.71745 14.76747,-8.78809 5.28084,-5.0254 5.88037,-6.37731 5.03237,-11.34777 -0.54581,-3.19924 -2.12664,-8.17139 -2.93655,-9.23632 -0.20744,-0.27274 -2.09771,-3.80302 -4.20062,-7.84507 -10.31205,-19.82106 -24.17432,-40.715325 -32.77801,-49.405517 -4.77866,-4.826708 -10.87279,-7.384017 -20.27372,-8.507565 -4.91187,-0.587038 -7.50695,0.407973 -11.5781,4.439293 -5.19358,5.142772 -6.33742,9.372628 -5.017,18.552643 1.9554,13.594616 10.06269,31.133146 21.57803,46.679836 5.80487,7.83707 8.51242,11.05372 16.21908,19.26876 3.91594,4.17426 9.72372,8.27527 11.84917,8.36698 0.5887,0.0254 3.89075,-0.95433 7.33788,-2.17718 z"
- id="path3115"
- inkscape:connector-curvature="0" />
- <path
- style="fill:url(#linearGradient4519)"
- d="m 130.84074,58.923726 c -7.60891,-0.350673 -14.85403,3.428624 -19.50456,9.363275 -7.15812,7.872993 -8.76006,19.344218 -6.92564,29.513125 1.31869,14.540904 8.47163,27.606394 15.84606,39.895614 6.45437,9.19151 13.24056,18.21299 20.7056,26.61653 6.38854,6.86584 13.60394,15.25582 23.86911,15.08518 8.33851,-0.68382 15.73802,-5.30641 22.649,-9.67979 6.8134,-4.37968 12.0669,-12.08126 10.81292,-20.48258 -1.3419,-9.21799 -4.87937,-17.96964 -8.13844,-26.64906 -5.23797,-11.46211 -10.79354,-22.815147 -18.03913,-33.159679 -8.50676,-12.978882 -19.6145,-26.077692 -35.39552,-29.783007 -1.92747,-0.443852 -3.90128,-0.691455 -5.8794,-0.719608 z m -3.41428,17.117471 c 9.47621,0.329223 19.44533,3.578248 25.36433,11.405622 14.22558,16.928041 24.97515,36.420361 35.14857,55.949291 1.35182,4.42143 3.75936,9.50153 1.69397,14.03969 -4.51526,5.99515 -10.52686,11.23752 -17.86566,13.37943 -4.9001,2.08509 -10.68904,4.17452 -14.83439,-0.57642 -9.1776,-7.5501 -16.59474,-17.02466 -23.58578,-26.57917 -9.84934,-14.24824 -18.48273,-30.22495 -20.35268,-47.705266 -0.90187,-5.951667 1.33796,-12.074001 6.00755,-15.910788 2.25429,-2.228885 5.12844,-4.095401 8.42409,-4.002389 z"
- id="path3129"
- inkscape:connector-curvature="0" />
- <path
- style="fill:url(#radialGradient4240);filter:url(#filter4216);opacity:0.20000000000000001;fill-opacity:1"
- d="m 128.4375,65 c -7.55257,0.752539 -13.75463,6.817427 -16.5625,13.71875 5.8224,-8.006494 16.76877,-10.73731 25.9375,-7.40625 14.07275,3.2128 23.28411,15.378897 30.59375,26.90625 5.17978,7.51743 10.0853,15.15976 14.5625,23.125 C 173.38287,101.9067 163.01642,80.924945 144.28125,69 139.39108,66.242245 134.02863,64.603592 128.4375,65 z"
- id="path4188"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="cacac"
- inkscape:connector-curvature="0"
- id="path3995"
- d="m 168.1904,63.422847 c 0,0 19.65859,24.838941 27.77919,38.385793 10.385,17.32433 26.55208,54.46844 26.55208,54.46844 0,0 -11.10228,-38.91122 -21.50132,-55.98367 C 192.45975,86.239191 168.1904,63.422847 168.1904,63.422847 z"
- style="opacity:0.45;fill:white;stroke:none;filter:url(#filter3991)"
- transform="matrix(-0.53741363,0.8433188,0.8433188,0.53741363,127.92952,-82.227985)" />
- <path
- style="fill:url(#radialGradient4003);fill-opacity:1"
- d="m 107.75379,134.95077 c -1.30345,0.0904 -2.48714,0.63971 -3.65929,1.65357 -1.83229,1.58486 -1.9196,1.78945 -1.89853,4.53199 0.0379,4.93646 3.957,11.76337 7.97692,13.8869 0.98849,0.52216 2.12208,0.9586 2.52628,0.96458 1.41684,0.021 4.83158,-1.8527 5.43534,-2.98561 1.19295,-2.06862 1.40968,-5.12061 0.93395,-7.54822 -0.74195,-3.57395 -3.96059,-7.91748 -6.9511,-9.40083 -1.64938,-0.81813 -3.06013,-1.1928 -4.36357,-1.10238 z"
- id="path3139"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="sssscccss" />
- <path
- style="opacity:0.45;fill:white;stroke:none;filter:url(#filter3991)"
- d="m 162.83326,57.708561 c 0,0 24.19388,28.033804 33.13633,44.100079 8.34768,14.99769 18.68782,47.98225 18.68782,47.98225 0,0 -5.43338,-34.47799 -13.63706,-49.49748 -9.13959,-16.732981 -38.18709,-42.584849 -38.18709,-42.584849 z"
- id="path3961"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cacac" />
- <path
- sodipodi:nodetypes="sssscccss"
- inkscape:connector-curvature="0"
- id="path3148"
- d="m 185.20338,91.946502 c 0.70476,-1.100206 1.75466,-1.875158 3.20661,-2.417072 2.26969,-0.847116 2.49109,-0.825543 4.88717,0.508897 4.31286,2.401947 8.42201,9.116165 8.35622,13.662023 -0.0162,1.11781 -0.1772,2.32179 -0.36591,2.67929 -0.6614,1.25316 -3.94383,3.35005 -5.2275,3.33616 -2.38735,0.0541 -5.16903,-1.22024 -7.07065,-2.80247 -2.77963,-2.36585 -5.04606,-7.273929 -4.91255,-10.609444 0.0736,-1.839671 0.42184,-3.257182 1.12661,-4.357384 z"
- style="fill:url(#linearGradient4007);fill-opacity:1" />
- <g
- id="g3200"
- transform="matrix(0.48994548,0,0,0.48994548,350.56989,-159.38179)"
- style="opacity:0.5">
- <path
- inkscape:connector-curvature="0"
- id="path3166"
- d="m -455.20089,479.79464 c -1.17062,0.0161 -2.27669,0.1147 -3.34375,0.28125 l 120.71875,176.625 c 0.14376,-0.13638 0.25973,-0.23557 0.40625,-0.375 10.77843,-10.25706 11.9808,-13.01132 10.25,-23.15625 -1.11402,-6.52979 -4.31568,-16.67019 -5.96875,-18.84375 -0.42338,-0.55668 -4.30163,-7.78125 -8.59375,-16.03125 -0.36367,-0.69901 -0.7571,-1.39357 -1.125,-2.09375 l -70.1875,-102.71875 c -9.0802,-7.31226 -20.55483,-11.4133 -36.96875,-13.375 -1.87975,-0.22466 -3.5892,-0.33445 -5.1875,-0.3125 z"
- style="fill:url(#linearGradient4411);fill-opacity:1" />
- <path
- inkscape:connector-curvature="0"
- id="path3164"
- d="m -463.45089,481.51339 c -3.25944,1.45791 -6.41012,3.91583 -10.1875,7.65625 -5.30016,5.24831 -8.52193,10.03124 -10.09375,15.84375 l 115.78125,169.375 c 0.12815,-0.0452 0.24662,-0.0795 0.375,-0.125 13.96734,-4.95482 18.21591,-7.03738 26.15625,-14.21875 L -463.45089,481.51339 z"
- style="fill:url(#linearGradient4413);fill-opacity:1" />
- <path
- inkscape:connector-curvature="0"
- id="path3150"
- d="m -484.76339,511.38839 c -0.31802,4.40449 -0.012,9.45827 0.875,15.625 3.99106,27.7472 20.55919,63.54978 44.0625,95.28125 11.84799,15.9958 17.36412,22.5765 33.09375,39.34375 7.9926,8.51985 19.84936,16.87532 24.1875,17.0625 0.9231,0.0398 5.13529,-1.13592 10.21875,-2.8125 l -112.4375,-164.5 z"
- style="fill:url(#linearGradient4415);fill-opacity:1" />
- </g>
- <path
- style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:black;fill:url(#linearGradient4232);fill-opacity:1;stroke:none;stroke-width:0.48994546999999999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans"
- d="m 122.1875,32.5625 c -0.31633,0.0028 -0.62844,0.02615 -0.9375,0.03125 -7.64601,0.125897 -15.03679,1.740145 -21.4375,5.25 -14.428716,7.912041 -19.87273,27.980004 -21.40625,44.25 -2.636685,27.97406 9.509045,56.10585 21.8125,81.28125 3.11737,6.37875 6.1185,12.09436 9.09375,17.15625 0.0493,0.0739 0.0709,0.0801 0.0312,0.0312 6.6078,8.83522 13.80662,17.19839 21.625,25 l 0.0312,0.0312 c 3.896,2.38216 8.01763,3.87957 12.46875,4.4375 21.60803,2.70848 39.89523,1.85069 55.59375,-8.4375 8.37785,-5.49051 17.4922,-13.33121 24.09375,-22.21875 6.60155,-8.88754 10.70599,-18.84538 8.96875,-28.625 l -0.0312,-0.0312 c -5.14414,-16.27654 -11.79107,-32.22257 -20.0625,-47.21875 -0.0576,-0.099 -0.11567,-0.22079 -0.1875,-0.34375 C 197.99264,79.445011 179.59543,56.490203 162.9375,45.28125 151.76835,37.765645 136.81894,32.655059 122.625,32.5625 l -0.4375,0 z m -0.9375,0.5 c 0.45532,-0.0075 0.92389,-0.0029 1.375,0 14.07876,0.09181 28.94494,5.165131 40.03125,12.625 16.53913,11.129015 34.92479,34.051851 48.75,57.71875 0.0577,0.0987 0.11608,0.22099 0.1875,0.34375 8.24952,14.95646 14.89727,30.85529 20.03125,47.09375 0.002,0.0103 -0.002,0.0209 0,0.0312 1.68984,9.58256 -2.32728,19.40368 -8.875,28.21875 -6.55477,8.82455 -15.63302,16.59959 -23.96875,22.0625 -15.5634,10.19965 -33.68875,11.10887 -55.25,8.40625 -4.36748,-0.54744 -8.38691,-2.0072 -12.21875,-4.34375 -0.0104,-0.0104 -0.0208,-0.0208 -0.0312,-0.0312 -7.78865,-7.77512 -14.9768,-16.10058 -21.5625,-24.90625 -0.004,-0.007 0.004,-0.024 0,-0.0312 -2.96275,-5.0423 -5.95358,-10.73229 -9.0625,-17.09375 C 88.360315,137.99623 76.285633,109.92859 78.90625,82.125 80.433086,65.925908 85.895332,46.049871 100.0625,38.28125 106.37955,34.817271 113.66779,33.187347 121.25,33.0625 z m -5.75,0.96875 c -4.24792,0.134802 -8.34131,1.097752 -12.21875,3.09375 -7.590368,3.9073 -12.029451,11.529539 -14.71875,20.25 -2.689299,8.720461 -3.658204,18.541088 -4.28125,26.96875 -1.95161,26.39852 6.610753,53.14668 18.375,77.21875 6.80896,13.93252 13.05934,24.52995 19.65625,31.9375 6.59691,7.40755 13.55444,11.60555 21.6875,12.625 20.62766,2.58559 39.56427,4.75598 54.59375,-5.09375 8.20923,-5.38001 16.78156,-13.82578 22.75,-23.3125 5.96844,-9.48672 9.34606,-20.01662 7.09375,-29.5625 -7.43127,-31.49566 -34.59182,-77.977165 -67.34375,-97 -13.19458,-7.663622 -29.36692,-16.985677 -44.15625,-17.125 -0.083,-7.88e-4 -0.16677,2.15e-4 -0.25,0 -0.39536,-0.001 -0.79576,-0.01244 -1.1875,0 z m 0.0312,0.5 c 0.46703,-0.01483 0.93569,-0.0045 1.40625,0 14.58625,0.137409 30.71307,9.36844 43.90625,17.03125 32.55349,18.907577 59.73037,65.34714 67.125,96.6875 2.20859,9.36056 -1.10559,19.76879 -7.03125,29.1875 -5.92566,9.41871 -14.48183,17.85079 -22.625,23.1875 -14.84384,9.72807 -33.65717,7.6164 -54.28125,5.03125 -8.00307,-1.00315 -14.79923,-5.12003 -21.34375,-12.46875 -6.54452,-7.34872 -12.7937,-17.92945 -19.59375,-31.84375 C 91.351277,137.31624 82.839184,110.64443 84.78125,84.375 85.40364,75.95621 86.362928,66.152438 89.03125,57.5 91.699572,48.847562 96.071102,41.386681 103.5,37.5625 c 3.80776,-1.960126 7.84563,-2.898424 12.03125,-3.03125 z"
- id="path4220"
- inkscape:connector-curvature="0" />
- <g
- id="g4024"
- transform="translate(-28.284271,-200.0102)">
- <path
- style="fill:#1a1a1a"
- d="m 318.53887,279.75654 c 1.00999,0.005 1.89177,0.0482 2.60328,0.13466 2.08898,0.24742 6.49786,1.35249 7.17341,1.79558 3.92176,4.11251 4.59865,22.42631 0.13131,29.5793 -0.67159,0.44906 -5.07047,1.5933 -7.15718,1.85921 -0.7107,0.0927 -1.59206,0.14415 -2.60198,0.15775 -7.06943,0.0952 -20.39523,-1.69296 -24.92275,-4.60816 -2.63356,-1.38461 -5.42336,-3.18744 -7.39874,-4.78344 -2.21303,-1.78801 -3.11021,-2.35716 -4.07294,-2.58092 -0.46818,-0.10877 -0.89474,-0.41554 -1.08308,-0.77489 -0.28302,-0.54008 -0.46902,-0.59343 -2.03336,-0.592 -1.15036,0.001 -1.92427,-0.13413 -2.341,-0.40382 -0.34291,-0.22194 -0.89816,-0.4021 -1.22923,-0.40064 -0.33107,0.002 -0.71467,-0.17225 -0.85642,-0.38603 -0.21729,-0.32774 -1.11898,-0.38489 -5.74038,-0.36438 l -5.48162,0.0243 -0.55547,0.81465 c -0.49243,0.71601 -0.65283,0.79214 -1.33378,0.65567 -0.0135,-0.003 -0.0187,-0.006 -0.0321,-0.008 l -1.42609,0.12817 -0.70028,-1.40198 c -0.70128,-0.072 -2.01523,-0.0578 -4.62695,0.0125 -7.97877,0.21454 -64.83584,0.92806 -76.08428,0.95504 -8.76866,0.0211 -10.16589,-0.0269 -10.43811,-0.36787 -0.27961,-0.35014 -0.36962,-1.21907 -0.28528,-2.01296 -0.0917,-0.79356 -0.009,-1.66255 0.2674,-2.01541 0.26919,-0.34333 1.66593,-0.40374 10.43442,-0.46054 11.24824,-0.0729 68.10941,0.13575 76.08977,0.27946 2.61224,0.047 3.92627,0.0496 4.62688,-0.0286 l 0.68781,-1.40814 1.42719,0.11514 c 0.0136,-0.003 0.0187,-0.006 0.0321,-0.008 0.67971,-0.1425 0.84077,-0.0678 1.33955,0.64381 l 0.56269,0.80969 5.48161,-0.0243 c 4.6214,-0.0205 5.52254,-0.0857 5.73693,-0.41534 0.13984,-0.21502 0.52188,-0.39216 0.85295,-0.39363 0.33109,-0.002 0.88469,-0.18656 1.22562,-0.41153 0.41431,-0.27341 1.18701,-0.41544 2.33732,-0.42459 1.5643,-0.0123 1.7498,-0.0675 2.02804,-0.61002 0.18513,-0.36102 0.60895,-0.67153 1.07614,-0.78449 0.96072,-0.23228 1.8528,-0.8094 4.04987,-2.61698 1.96114,-1.61348 4.73481,-3.44101 7.35598,-4.84894 4.50144,-2.95533 17.81085,-4.86179 24.88084,-4.82932 z"
- id="path4285"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="sccccscssssssssccccccssscsssccccccsssssssscs" />
- <path
- inkscape:connector-curvature="0"
- id="path3087"
- d="m 169.10714,296.11219 105,-0.17858 -0.35714,1.42858 -104.82143,1.07142 z"
- style="opacity:0.5;fill:#666;stroke:none;filter:url(#filter3861)" />
- <path
- inkscape:connector-curvature="0"
- id="path4009"
- d="m 317.53125,282.15178 c -11.36706,0.26523 -23.23057,2.55643 -31.6875,10.8125 -1.86956,1.14115 -4.05821,1.47538 -2.78125,4.53125 -0.84939,3.46529 4.1566,3.28051 5.65625,5.75 9.51653,7.68063 22.72213,8.97735 34.38448,7.94875 4.21291,0.28872 5.90132,-3.25103 6.14677,-6.98 0.9191,-6.73052 1.37996,-14.32892 -1.84375,-20.53125 -3.23537,-1.02214 -6.47262,-1.79974 -9.875,-1.53125 z"
- style="opacity:0.5;fill:#333;filter:url(#filter4020)" />
- <path
- sodipodi:nodetypes="cccc"
- inkscape:connector-curvature="0"
- id="path3865"
- d="m 297.0319,288.01519 30.27684,-1.83276 -30.27684,3.97562 z"
- style="fill:url(#linearGradient4032);fill-opacity:1;stroke:none" />
- <path
- style="fill:url(#linearGradient4034);fill-opacity:1;stroke:none"
- d="m 297.01023,295.86554 31.16072,1.07143 -31.16072,1.07143 z"
- id="path3867"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cccc" />
- <path
- sodipodi:nodetypes="cccc"
- inkscape:connector-curvature="0"
- id="path3869"
- d="m 295.11991,302.01312 30.78191,4.8595 -30.78191,-2.71664 z"
- style="fill:url(#linearGradient4036);fill-opacity:1;stroke:none" />
- </g>
- <path
- style="fill:url(#linearGradient3063)"
- d="m 190.26363,89.34866 c -0.43987,0.06867 -0.94061,0.240548 -1.66911,0.512448 -1.38847,0.518221 -2.40074,1.261233 -3.07469,2.313337 -0.25496,0.398012 -0.45333,0.827434 -0.61494,1.317728 l 10.96639,15.666277 c 0.01,-1.8e-4 0.0194,2.2e-4 0.0293,0 1.22755,0.0133 4.37487,-1.99345 5.00735,-3.19182 0.0946,-0.17924 0.17036,-0.58776 0.23427,-1.08346 L 190.26365,89.34866 z"
- id="path4135"
- inkscape:connector-curvature="0" />
- <path
- style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;opacity:0.3;color:black;fill:url(#radialGradient4304);fill-opacity:1;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter4330);enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans"
- d="m 113.35358,88.956128 -0.8125,0.5625 50.89286,76.607142 0.8125,-0.5625 z"
- id="path4280"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="ccccc" />
- <path
- inkscape:connector-curvature="0"
- id="path4286"
- d="m 125.85359,76.456128 -0.8125,0.5625 53.03571,80.892852 0.8125,-0.5625 z"
- style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;opacity:0.3;color:black;fill:url(#radialGradient4294);fill-opacity:1;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter4310);enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans"
- sodipodi:nodetypes="ccccc" />
- <g
- transform="matrix(-0.52943173,0.84835255,0.84835255,0.52943173,-17.027404,-209.74208)"
- id="g4038">
- <path
- sodipodi:nodetypes="sccccscssssssssccccccssscsssccccccsssssssscs"
- inkscape:connector-curvature="0"
- id="path4040"
- d="m 318.53887,279.75654 c 1.00999,0.005 1.89177,0.0482 2.60328,0.13466 2.08898,0.24742 6.49786,1.35249 7.17341,1.79558 3.92176,4.11251 4.59865,22.42631 0.13131,29.5793 -0.67159,0.44906 -5.07047,1.5933 -7.15718,1.85921 -0.7107,0.0927 -1.59206,0.14415 -2.60198,0.15775 -7.06943,0.0952 -20.39523,-1.69296 -24.92275,-4.60816 -2.63356,-1.38461 -5.42336,-3.18744 -7.39874,-4.78344 -2.21303,-1.78801 -3.11021,-2.35716 -4.07294,-2.58092 -0.46818,-0.10877 -0.89474,-0.41554 -1.08308,-0.77489 -0.28302,-0.54008 -0.46902,-0.59343 -2.03336,-0.592 -1.15036,0.001 -1.92427,-0.13413 -2.341,-0.40382 -0.34291,-0.22194 -0.89816,-0.4021 -1.22923,-0.40064 -0.33107,0.002 -0.71467,-0.17225 -0.85642,-0.38603 -0.21729,-0.32774 -1.11898,-0.38489 -5.74038,-0.36438 l -5.48162,0.0243 -0.55547,0.81465 c -0.49243,0.71601 -0.65283,0.79214 -1.33378,0.65567 -0.0135,-0.003 -0.0187,-0.006 -0.0321,-0.008 l -1.42609,0.12817 -0.70028,-1.40198 c -0.70128,-0.072 -2.01523,-0.0578 -4.62695,0.0125 -7.97877,0.21454 -64.83584,0.92806 -76.08428,0.95504 -8.76866,0.0211 -10.16589,-0.0269 -10.43811,-0.36787 -0.27961,-0.35014 -0.36962,-1.21907 -0.28528,-2.01296 -0.0917,-0.79356 -0.009,-1.66255 0.2674,-2.01541 0.26919,-0.34333 1.66593,-0.40374 10.43442,-0.46054 11.24824,-0.0729 68.10941,0.13575 76.08977,0.27946 2.61224,0.047 3.92627,0.0496 4.62688,-0.0286 l 0.68781,-1.40814 1.42719,0.11514 c 0.0136,-0.003 0.0187,-0.006 0.0321,-0.008 0.67971,-0.1425 0.84077,-0.0678 1.33955,0.64381 l 0.56269,0.80969 5.48161,-0.0243 c 4.6214,-0.0205 5.52254,-0.0857 5.73693,-0.41534 0.13984,-0.21502 0.52188,-0.39216 0.85295,-0.39363 0.33109,-0.002 0.88469,-0.18656 1.22562,-0.41153 0.41431,-0.27341 1.18701,-0.41544 2.33732,-0.42459 1.5643,-0.0123 1.7498,-0.0675 2.02804,-0.61002 0.18513,-0.36102 0.60895,-0.67153 1.07614,-0.78449 0.96072,-0.23228 1.8528,-0.8094 4.04987,-2.61698 1.96114,-1.61348 4.73481,-3.44101 7.35598,-4.84894 4.50144,-2.95533 17.81085,-4.86179 24.88084,-4.82932 z"
- style="fill:#1a1a1a" />
- <path
- style="opacity:0.5;fill:#666;stroke:none;filter:url(#filter3861)"
- d="m 169.10714,296.11219 105,-0.17858 -0.35714,1.42858 -104.82143,1.07142 z"
- id="path4042"
- inkscape:connector-curvature="0" />
- <path
- style="opacity:0.5;fill:#333;filter:url(#filter4020)"
- d="m 317.53125,282.15178 c -11.36706,0.26523 -23.23057,2.55643 -31.6875,10.8125 -1.86956,1.14115 -4.05821,1.47538 -2.78125,4.53125 -0.84939,3.46529 4.1566,3.28051 5.65625,5.75 9.51653,7.68063 22.72213,8.97735 34.38448,7.94875 4.21291,0.28872 5.90132,-3.25103 6.14677,-6.98 0.9191,-6.73052 1.37996,-14.32892 -1.84375,-20.53125 -3.23537,-1.02214 -6.47262,-1.79974 -9.875,-1.53125 z"
- id="path4044"
- inkscape:connector-curvature="0" />
- <path
- style="fill:url(#linearGradient4052);fill-opacity:1;stroke:none"
- d="m 297.0319,288.01519 30.27684,-1.83276 -30.27684,3.97562 z"
- id="path4046"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cccc" />
- <path
- sodipodi:nodetypes="cccc"
- inkscape:connector-curvature="0"
- id="path4048"
- d="m 297.01023,295.86554 31.16072,1.07143 -31.16072,1.07143 z"
- style="fill:url(#linearGradient4054);fill-opacity:1;stroke:none" />
- <path
- style="fill:url(#linearGradient4056);fill-opacity:1;stroke:none"
- d="m 295.11991,302.01312 30.78191,4.8595 -30.78191,-2.71664 z"
- id="path4050"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cccc" />
- </g>
- <path
- inkscape:connector-curvature="0"
- id="path4150"
- d="m 107.61204,135.87111 c -0.43987,0.0687 -0.94061,0.24055 -1.66911,0.51245 -1.38847,0.51822 -2.40074,1.26123 -3.07469,2.31333 -0.25496,0.39802 -0.45333,0.82744 -0.61494,1.31773 l 10.9664,15.66628 c 0.01,-1.8e-4 0.0194,2.2e-4 0.0293,0 1.22755,0.0133 4.37487,-1.99345 5.00735,-3.19182 0.0946,-0.17924 0.17036,-0.58776 0.23427,-1.08347 l -10.87855,-15.5345 z"
- style="fill:url(#linearGradient3059)" />
- <path
- style="opacity:0.45;fill:white;stroke:none;filter:url(#filter3951)"
- d="m 140.06407,195.32811 c 0,0 29.07782,-4.37183 42.39494,-10.1947 14.78259,-6.46364 40.26186,-26.86477 40.26186,-26.86477 0,0 -19.03151,32.17765 -35.15464,38.96292 -14.60604,6.14682 -47.50216,-1.90345 -47.50216,-1.90345 z"
- id="path3909"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cacac"
- transform="matrix(0.99690053,-0.07867232,0.07867232,0.99690053,-13.51203,13.166988)" />
- <path
- sodipodi:nodetypes="cacac"
- inkscape:connector-curvature="0"
- id="path3955"
- d="m 91.374375,85.871906 c 0,0 9.256535,-26.696739 20.754205,-32.346171 13.12094,-6.447035 43.69229,3.807076 43.69229,3.807076 0,0 -34.41022,-23.358229 -49.87846,-15.390694 -13.71495,7.06443 -14.568035,43.929789 -14.568035,43.929789 z"
- style="opacity:0.4;fill:#faa;stroke:none;filter:url(#filter3957)" />
- <path
- style="fill:url(#linearGradient4253);stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="M 55.09375 38.125 C 41.536468 55.525521 38.482469 79.730562 43.5 100.8125 C 44.024201 102.26043 44.578426 103.68369 45.125 105.125 C 44.024016 92.475252 43.404295 78.251935 44.9375 68.5625 C 46.28173 60.067328 50.756241 48.257598 55.09375 38.125 z "
- transform="translate(28.121442,8.3445206)"
- id="path4242" />
- <path
- style="fill:url(#linearGradient4271);stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="M 114.28125 204.625 C 113.32558 204.67041 112.29016 204.8007 111.21875 204.96875 C 119.83569 211.80541 132.24015 211.82002 142.6875 209.6875 C 146.03427 208.64812 149.32096 207.45718 152.59375 206.15625 C 151.9534 205.85401 151.33022 205.57328 150.71875 205.34375 C 143.65393 202.69182 135.75218 208.28171 128.21875 207.84375 C 123.4619 207.56721 119.04076 204.39887 114.28125 204.625 z "
- transform="translate(28.121442,8.3445206)"
- id="path4266" />
- <path
- style="fill:url(#linearGradient4278);stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="M 207.03125 154.34375 L 193.5 183.75 C 195.65989 181.9894 197.68946 180.09837 199.5 177.9375 C 205.95635 171.90863 208.38452 162.88007 207.03125 154.34375 z "
- transform="translate(28.121442,8.3445206)"
- id="path4273" />
- <path
- style="fill:url(#radialGradient4482);opacity:0.4;filter:url(#filter4472);fill-opacity:1"
- d="m 106.75,138.21875 c -5.01915,1.36431 1.53172,5.62694 2.37808,8.14121 2.30839,1.7736 3.89374,9.63491 7.18442,5.39004 -3.19444,-4.47938 -6.33093,-9.19988 -9.5625,-13.53125 z"
- id="path4404"
- inkscape:connector-curvature="0" />
- <path
- inkscape:connector-curvature="0"
- id="path4484"
- d="m 189.32997,91.499195 c -5.01915,1.36431 1.53172,5.62694 2.37808,8.14121 2.30839,1.773605 3.89374,9.634915 7.18442,5.390045 -3.19444,-4.47938 -6.33093,-9.199885 -9.5625,-13.531255 z"
- style="opacity:0.4;fill:url(#radialGradient4486);fill-opacity:1;filter:url(#filter4472)" />
- <path
- style="fill:white;stroke:none;filter:url(#filter4502);opacity:0.2"
- d="m 57.578695,49.881767 c 0,0 -5.45362,18.676558 -5.555839,28.284271 -0.156361,14.696609 3.461299,29.155632 7.576144,43.436562 0,0 -4.701076,-23.455716 -5.050762,-35.355342 -0.357297,-12.158599 3.030457,-36.365491 3.030457,-36.365491 z"
- id="path4488"
- inkscape:connector-curvature="0"
- transform="translate(28.121442,8.3445206)"
- sodipodi:nodetypes="cacac" />
- <path
- sodipodi:nodetypes="cacac"
- transform="matrix(-0.47323097,0.88093839,0.88093839,0.47323097,107.53763,-41.655538)"
- inkscape:connector-curvature="0"
- id="path4506"
- d="m 57.578695,49.881767 c 0,0 -5.45362,18.676558 -5.555839,28.284271 -0.156361,14.696609 3.461299,29.155632 7.576144,43.436562 0,0 -4.701076,-23.455716 -5.050762,-35.355342 -0.357297,-12.158599 3.030457,-36.365491 3.030457,-36.365491 z"
- style="opacity:0.2;fill:white;stroke:none;filter:url(#filter4502)" />
- <path
- style="opacity:0.2;color:black;fill:black;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 127.43394,76.032021 c -3.29565,-0.09301 -6.18321,1.771115 -8.4375,4 -4.60463,3.783417 -6.83452,9.814408 -6.03125,15.6875 2.14745,-4.274005 5.28349,-8.111538 9.34375,-11.125 5.34892,-3.969885 11.5628,-5.967746 17.84375,-6.15625 -4.06323,-1.493367 -8.43787,-2.257524 -12.71875,-2.40625 z"
- id="path4526" />
- <path
- style="opacity:0.20000000000000001;color:black;fill:url(#linearGradient4541);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.50000000000000000;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- d="m 187.18394,142.00077 c -0.63298,9.16177 -4.9691,17.87333 -12.71875,23.625 -4.81784,3.57573 -10.32971,5.53466 -15.96875,6.03125 3.96322,2.82465 8.96853,0.9914 13.28125,-0.84375 7.3388,-2.14191 13.32849,-7.37985 17.84375,-13.375 2.06539,-4.53816 -0.33568,-9.60982 -1.6875,-14.03125 -0.24533,-0.47093 -0.50396,-0.9354 -0.75,-1.40625 z"
- id="path4533" />
- </g>
-</svg>
diff --git a/test/splash.bmp b/test/splash.bmp
deleted file mode 100644
index 27247f7..0000000
--- a/test/splash.bmp
+++ /dev/null
Binary files differ
diff --git a/test/test-create-disk.sh b/test/test-create-disk.sh
deleted file mode 100755
index a5cd4cc..0000000
--- a/test/test-create-disk.sh
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/bin/bash -e
-
-# create GPT table with EFI System Partition
-rm -f test-disk.img
-dd if=/dev/null of=test-disk.img bs=1M seek=512 count=1
-parted --script test-disk.img "mklabel gpt" "mkpart ESP fat32 1MiB 511MiB" "set 1 boot on"
-
-# create FAT32 file system
-LOOP=$(losetup --show -f -P test-disk.img)
-mkfs.vfat -F32 ${LOOP}p1
-mkdir -p mnt
-mount ${LOOP}p1 mnt
-
-# install gummiboot
-mkdir -p mnt/EFI/{Boot,gummiboot}
-cp gummibootx64.efi mnt/EFI/Boot/bootx64.efi
-cp test/splash.bmp mnt/EFI/gummiboot/
-
-[ -e /boot/shellx64.efi ] && cp /boot/shellx64.efi mnt/
-
-mkdir mnt/EFI/Linux
-echo -n "foo=yes bar=no root=/dev/fakeroot debug rd.break=initqueue" > mnt/cmdline.txt
-objcopy \
- --add-section .osrel=/etc/os-release --change-section-vma .osrel=0x20000 \
- --add-section .cmdline=mnt/cmdline.txt --change-section-vma .cmdline=0x30000 \
- --add-section .linux=/boot/$(cat /etc/machine-id)/$(uname -r)/linux --change-section-vma .linux=0x40000 \
- --add-section .initrd=/boot/$(cat /etc/machine-id)/$(uname -r)/initrd --change-section-vma .initrd=0x3000000 \
- linuxx64.efi.stub mnt/EFI/Linux/linux-test.efi
-
-# install entries
-mkdir -p mnt/loader/entries
-echo -e "timeout 3\nsplash /EFI/gummiboot/splash.bmp\n" > mnt/loader/loader.conf
-echo -e "title Test\nefi /test\n" > mnt/loader/entries/test.conf
-echo -e "title Test2\nlinux /test2\noptions option=yes word number=1000 more\n" > mnt/loader/entries/test2.conf
-echo -e "title Test3\nlinux /test3\n" > mnt/loader/entries/test3.conf
-echo -e "title Test4\nlinux /test4\n" > mnt/loader/entries/test4.conf
-echo -e "title Test5\nefi /test5\n" > mnt/loader/entries/test5.conf
-echo -e "title Test6\nlinux /test6\n" > mnt/loader/entries/test6.conf
-
-sync
-umount mnt
-rmdir mnt
-losetup -d $LOOP