-From rEFIt to rEFInd
-====================
-
-rEFInd is derived from rEFIt (http://refit.sourceforge.net), but the two
-programs support different build environments. rEFIt was created with
-Intel's EFI Application Toolkit
-(http://www.intel.com/technology/efi/toolkit_overview.htm) or TianoCore's
-EFI Toolkit (https://efi-toolkit.tianocore.org), along with Microsoft's
-Visual C compiler.
-
-Compiling the source code provided on the rEFIt site under Linux never
-worked for me, although the documentation claimed it would. Apparently
-other Linux developers have run into the same problem; Debian provides a
-rEFIt package (http://packages.debian.org/sid/refit) that includes
-extensive patches to enable the program to compile under Linux using the
-GNU-EFI package (http://sourceforge.net/projects/gnu-efi/). Although
-GNU-EFI is less sophisticated than recent versions of TianoCore's toolkit,
-GNU-EFI was initially my preferred environment because it's provided with
-many Linux distributions and it was easy to get started with rEFInd
-development by using GNU-EFI and the Debian rEFIt package as a starting
-point.
-
-Over time, though, I've found that the recent TianoCore EDK2 toolkit has
-its advantages. Two features, in particular, require the TianoCore EDK2
-toolkit:
-
-- The EFI filesystem drivers, added with rEFInd 0.4.0. This requirement is
- a consequence of the derivation of the drivers, which is via VirtualBox
- and the Clover boot loader, both of which are based on EDK2.
-
-- The legacy BIOS boot feature for UEFI-based PCs. EDK2 is needed in this
- case because of features unique to that environment. Note that the legacy
- BIOS boot feature for Macs works when rEFInd is built via either GNU-EFI
- or the TianoCore EDK2.
-
-For these reasons, effective with rEFInd 0.4.6, I've switched the primary
-build environment from GNU-EFI to TianoCore EDK2. The rEFInd binary itself
-still builds via GNU-EFI, but you must pass the "gnuefi" build target to
-make in order to build in this way, and the resulting binary can't boot
-BIOS-based OSes on UEFI PCs.
-
-I've dropped ancillary programs, such as the gptsync program, from rEFInd.
-You can still use these tools with rEFInd, but you'll need to install them
-separately.
-
-
Requirements
============
* The GNU-EFI package (http://sourceforge.net/projects/gnu-efi/). You can
install this from a package called "gnu-efi"; however, rEFInd relies on
features that were added in (I think) 3.0l to provide driver-loading
- capabilities. The versions I've used and that work are 3.0p and 3.0q.
- Through mid-to-late 2012, most Linux distributions delivered rather
- elderly versions of GNU-EFI, but many are catching up by late 2012. You
- should check your GNU-EFI version number; you may need to download the
- latest source code, compile it, and install it locally. Between rEFInd
- version 0.2.7 and 0.6.1, the Makefiles assumed a locally-compiled
- GNU-EFI package, but older and more recent versions assume GNU-EFI
- installation in typical locations for distribution-provided packages.
- The legacy BIOS boot support on UEFI-based PCs doesn't work when
- GNU-EFI is compiled under GNU-EFI, so as of rEFInd 0.4.6, GNU-EFI is no
- longer the primary build environment, although it's easier to set up on
- a Linux system.
+ capabilities. The versions I've used and that work are 3.0p, 3.0q,
+ 3.0r, and 3.0s, with the caveat that 3.0s works when I installed it via
+ a Gentoo package, but not when I installed it by compiling the source
+ code locally. Through mid-to-late 2012, most Linux distributions
+ delivered rather elderly versions of GNU-EFI, but many are catching up
+ by late 2012. You should check your GNU-EFI version number; you may
+ need to download the latest source code, compile it, and install it
+ locally. Between rEFInd version 0.2.7 and 0.6.1, the Makefiles assumed
+ a locally-compiled GNU-EFI package, but older and more recent versions
+ assume GNU-EFI installation in typical locations for
+ distribution-provided packages. The legacy BIOS boot support on
+ UEFI-based PCs doesn't work when GNU-EFI is compiled under GNU-EFI, so
+ as of rEFInd 0.4.6, GNU-EFI is no longer the primary build environment,
+ although it's easier to set up on a Linux system.
+
+Of the two toolkits, I prefer to use TianoCore because it produces binaries
+that can boot BIOS/legacy-mode OSes and because the TianoCore-produced
+binaries are about 20-30KiB smaller than those made by GNU-EFI. Also, I've
+had problems on a 32-bit Mac Mini with the drivers produced by GNU-EFI
+hanging the system if I try to load more than one of them. (I haven't
+encountered this problem on UEFI-based PCs.) That said, the TianoCore EDK2
+package is much harder to install, so if you don't need the ability to boot
+BIOS/legacy OSes from rEFInd, GNU-EFI can work as well.
It's possible to use a non-Linux platform to compile rEFInd. To the best of
my knowledge, the rEFInd code doesn't rely on anything Linux-specific in
Preparing Your Development Kit
==============================
-If you want to build the rEFInd binary but not the drivers, if you don't
-care about booting BIOS-based OSes on UEFI PCs, and if you're using Linux,
-GNU-EFI is the easiest way to do the job. I don't describe its setup here
-because it's likely to be fairly easy. If your distribution provides a
-recent enough version, you should be able to install a package called
-gnu-efi and be done with it. If not, you'll need to download the source
-code tarball, build it, and install it. This process is fairly typical of
-Linux packages. Read the GNU-EFI documentation if you need help. If you're
-using GNU-EFI, you can skip the rest of this section.
-
-To build the EFI drivers, or if you want support for booting BIOS-based
-OSes on UEFI PCs, the TianoCore toolkit is required. You might also want to
-use it if you have problems with GNU-EFI or if you want to build rEFInd on
-a non-Linux platform. Unfortunately, the TianoCore toolkit is weird by
-Linux programming standards. It's also quite large -- it's intended as a
-means to develop a complete EFI firmware implementation, so it contains
-much more code than is needed to develop standalone EFI applications. I
-don't know of any Linux distribution packages for it in RPM, Debian package
-file, or other formats; you MUST install the kit from source code using its
-own unusual compilation procedure. The installation documentation also
-omits at least one step and is a bit unclear about others. Here's how I
-installed the toolkit:
+If you don't care about booting BIOS-based OSes on UEFI PCs and if you're
+using Linux, GNU-EFI is the easiest way to compile rEFInd. I don't describe
+GNU-EFI's setup here because it's likely to be fairly easy. If your
+distribution provides a recent enough version, you should be able to
+install a package called gnu-efi and be done with it. If not, you'll need
+to download the source code tarball, build it, and install it. This process
+is fairly typical of Linux packages. Read the GNU-EFI documentation if you
+need help. If you're using GNU-EFI, you can skip the rest of this section.
+
+If you need support for booting BIOS-based OSes on UEFI PCs, the TianoCore
+toolkit is required. You might also want to use it if you have problems
+with GNU-EFI or if you want to build rEFInd on a non-Linux platform.
+Unfortunately, the TianoCore toolkit is weird by Linux programming
+standards. It's also quite large -- it's intended as a means to develop a
+complete EFI firmware implementation, so it contains much more code than is
+needed to develop standalone EFI applications. I don't know of any Linux
+distribution packages for it in RPM, Debian package file, or other formats;
+you MUST install the kit from source code using its own unusual compilation
+procedure. The installation documentation also omits at least one step and
+is a bit unclear about others. Here's how I installed the toolkit:
1) Download UDK2010.SR1.UP1 from
https://sourceforge.net/apps/mediawiki/tianocore/index.php?title=UDK2010.
3) Change into the archive's main directory. You should see several files
including this BUILDING.txt file and several subdirectories such as
- "refind", "libeg", and "include".
+ "refind", "libeg", "mok", "filesystems", and "include".
4) Type "make gnuefi" to build with GNU-EFI, or either "make" alone or
"make tiano" to build with TianoCore EDK2. With any luck, rEFInd will
want to build IA32 binaries on an x86-64 (X64) system, type "ARCH=ia32
make". This works only if you're using the TianoCore build kit, and only
if you set TARGET_ARCH to either "IA32" or "IA32 X64" in target.txt when
- you set up the TianoCore. If you plan to build both architectures, be
- sure to copy the .efi file for the first build out of the refind
- subdirectory before building the second architecture.
+ you set up the TianoCore toolkit. If you plan to build both
+ architectures, be sure to copy the .efi file for the first build out of
+ the refind subdirectory before building the second architecture.
5) The default build process does NOT build the filesystem drivers. If you
want to build them, you must type "make fs" in the main rEFInd source
- directory. (Typing "ARCH=ia32 make fs" builds IA32 filesystem drivers on
- an x86-64 system, provided TianoCore is properly configured, as
+ directory to build with the TianoCore EDK2, or "make fs_gnuefi" to build
+ with GNU-EFI. (Typing "ARCH=ia32 make fs" builds IA32 filesystem drivers
+ on an x86-64 system, provided TianoCore is properly configured, as
described earlier.) The result is filesystem drivers in the filesystems
subdirectory, and also copies placed in the drivers_{arch} subdirectory.
- You must install the TianoCore EDK2 to build the drivers.
If rEFInd doesn't compile correctly, you'll need to track down the source
of the problem. Double-check that you've got all the necessary development
Compiling the EFI Filesystem Drivers
====================================
-To build all the drivers, you can type "make fs" from the main directory,
-which builds the drivers and places copies in both the filesystems and
-drivers_{arch} subdirectories. If you want to build just one driver, you
-can change into the "filesystems" directory and type "make {fsname}", where
-{fsname} is a filesystem name -- "ext2", "ext4", "reiserfs", "iso9660",
-or "hfs".
+To build all the drivers, you can type "make fs" or "make fs_gnuefi" from
+the main directory, which builds the drivers and places copies in both the
+filesystems and drivers_{arch} subdirectories. If you want to build just
+one driver, you can change into the "filesystems" directory and type "make
+{fsname}" or "make {fsname}_gnuefi", where {fsname} is a filesystem name --
+"ext2", "ext4", "reiserfs", "iso9660", or "hfs". In all cases, the build
+target that appends "_gnuefi" builds with GNU-EFI and the one that doesn't
+builds with TianoCore.
To install drivers, you can type "make install" in the "filesystems"
directory. This copies all the drivers to the
make -C $(LIBEG_DIR)
make -C $(MOK_DIR)
make -C $(LOADER_DIR)
-# make -C $(FS_DIR)
+# make -C $(FS_DIR) all_gnuefi
fs:
make -C $(FS_DIR)
+fs_gnuefi:
+ make -C $(FS_DIR) all_gnuefi
+
tiano:
make AR_TARGET=EfiLib -C $(EFILIB_DIR) -f Make.tiano
make AR_TARGET=libeg -C $(LIBEG_DIR) -f Make.tiano
0.6.2 (12/??/2012):
-------------------
+- The drivers can now be built with the GNU-EFI toolkit as well as with the
+ TianoCore EDK2. See the BUILDING.txt file for details on how to build
+ them with either toolkit. This improvement doesn't affect users of my
+ binary packages, but it should make it easier for Linux distributions to
+ adopt rEFInd into their package systems.
+
+- Tweaked refind.inf file for better build results using "native" TianoCore
+ EDK2 build process (vs. the Makefile-based build process that I use under
+ Linux). This won't affect those who use my binary builds or build under
+ Linux with the "make" command.
+
- Fixed bug that prevented Secure Boot launches from working when rEFInd
was built with GNU-EFI rather than the TianoCore EDK2.
- Substantial reworking of Secure Boot code, based on James Bottomley's
PreLoader program. This new code eliminates the limitation of launching
just one driver in Secure Boot mode and is likely to be more reliable
- with future or obscure boot loaders. The basic features are the same as
- before, though -- rEFInd relies on shim for authentication functions and
- will launch programs that are signed by Secure Boot keys, shim keys, or
- MOKs.
-
-- Altered default for "textmode" option to not adjust the text mode
- at all. (Prior versions set it to mode 0 by default.)
+ with future or obscure boot loaders. It should also work with non-x86-64
+ systems, although this relies on a platform-specific shim program, which
+ to date exists only for x86-64. The basic features are the same as before
+ -- rEFInd relies on shim for authentication functions and will launch
+ programs that are signed by Secure Boot keys, shim keys, or MOKs.
+
+- Altered default for "textmode" option (when it's commented out) to not
+ adjust the text mode at all. (Prior versions set it to mode 0 by
+ default.)
0.6.1 (12/21/2012):
-------------------
as well download the rEFInd binary <tt>.zip</tt> file from Sourceforge
instead.</li>
+<li><b>Slackware</b>—Although it doesn't seem to be an official build, <a
+ href="http://franck-barbenoire.fr/spip.php?article198">this site</a> has links to rEFInd
+ binary packages for Slackware 13.37 and 14.0.</li>
+
</ul>
<p>To the best of my knowledge, no other Linux distribution yet includes rEFInd in its repositories. That's likely to change in time. If you hear of rEFInd being included in an OS's official package set, feel free to <a href="mailto:rodsmith@rodsbooks.com">drop me a line.</a></p>
<p class="sidebar"><b>Important:</b> A rEFInd zip file, when uncompressed, creates a directory called <tt>refind-<i>version</i></tt>, where <tt><i>version</i></tt> is the version number. This directory includes a subdirectory called <tt>refind</tt> that holds the boot loader, along with another that holds documentation, as well as miscellaneous files in <tt>refind-<i>version</i></tt> itself. When I refer to "the <tt>refind</tt> directory" on this page, I mean the directory with that precise name, not the <tt>refind-<i>version</i></tt> directory that is its parent.</p>
-<p>Once you've uncompressed a rEFInd binary zip file, you must install it to your computer's ESP (or conceivably to some other location). The details of how you do this depend on your OS and your computer (UEFI-based PC vs. Macintosh). The upcoming sections provide details. For Linux and Mac OS X, you can use the installation script, <a href="#installsh"><tt>install.sh</tt>,</a> which provides easy one-command installation on most systems. Occasionally this script will fail, though, so I also provide explicit instructions for <a href="#linux">Linux</a> and <a href="#osx">Mac OS X.</a> Installation under <a href="#windows">Windows</a> also must be done manually. In some cases, you'll have to deviate from the default naming conventions, as described in <a href="#naming">a section on this topic.</a> If you're upgrading rEFInd, see the <a href="#upgrading">section on upgrading.</a> Finally, I describe how to install some <a href="#addons">additional components</a> you might find useful.</a></p>
+<p>Once you've uncompressed a rEFInd binary zip file, you must install it to your computer's ESP (or conceivably to some other location). The details of how you do this depend on your OS and your computer (UEFI-based PC vs. Macintosh). The upcoming sections provide details. For Linux and Mac OS X, you can use the installation script, <a href="#installsh"><tt>install.sh</tt>,</a> which provides easy one-command installation on most systems. Occasionally this script will fail, though, so I also provide explicit instructions for <a href="#linux">Linux</a> and <a href="#osx">Mac OS X.</a> Installation under <a href="#windows">Windows</a> also must be done manually. You can even install rEFInd using an <a href="#efishell">EFI shell</a> (version 2 only). In some cases, you'll have to deviate from the default naming conventions, as described in <a href="#naming">a section on this topic.</a> If you're upgrading rEFInd, see the <a href="#upgrading">section on upgrading.</a> Finally, I describe how to install some <a href="#addons">additional components</a> you might find useful.</a></p>
<a name="installsh">
<h2>Installing rEFInd Using <tt>install.sh</tt> under Linux or Mac OS X</h2>
</ul>
+<a name="efishell">
+<h2>Installing rEFInd Manually Using Windows</h2>
+</a>
+
+<p>If you can't currently boot any OS (say, because a firmware update has wiped your NVRAM entries), you may find it convenient to install rEFInd using an EFI version 2 shell. Unfortunately, the <tt>bcfg</tt> command described here is not available in the EFI version 1 shell, and the version 2 shell is unusable on many firmware implementations prior to 2.3.1. Thus, this procedure won't work for all systems.</p>
+
+<p>In addition to emergency situations, using <tt>bcfg</tt> can be desirable if <tt>efibootmgr</tt> or other OS-hosted tools don't do the job. This happens under VirtualBox, for instance. An alternative in such cases can be to use <a href="#naming">alternative names for rEFInd.</a></p>
+
+<p>To begin, you must have a way to launch your shell. Unfortunately, this can pose a dilemma, since without rEFInd or some other boot manager, many EFI implementations lack the means to launch a shell. Some will do so, though, if the shell is stored as <tt>shellx64.efi</tt> (for <i>x</i>86-64) or <tt>shellia32.efi</tt> (for <i>x</i>86) in the root directory of the ESP. Thus, you can try copying your shell file there. You can obtain EFI 2 shells here:</p>
+
+<ul>
+
+<li><a href="https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2/ShellBinPkg/UefiShell/X64/Shell.efi"><i>x</i>86-64 (64-bit) shell 2</a></li>
+
+<li><a href="https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2/ShellBinPkg/UefiShell/Ia32/Shell.efi"><i>x</i>86 (32-bit) shell 2</a></li>
+
+</ul>
+
+<p>Note that the shell included in rEFInd's CD-R image version is a version 1 shell, so you can't use it for this purpose. You can, however, copy rEFInd's files from the CD-R. You can even launch the version 1 shell included with rEFInd and then use that to launch a version 2 shell. Once you've booted the shell, you can proceed as follows:</p>
+
+<ol>
+
+<li>If you haven't installed rEFInd previously, unpack its zip file to a
+ FAT partition. This can be the ESP itself or another partition, such as
+ a USB flash drive. If you're simply repairing a lost NVRAM entry, you
+ needn't move your existing rEFInd files.</li>
+
+<li>Identify your filesystems, which are labelled with the form <tt>fs<tt
+ style="variable">n</tt>:</tt>, as in <tt>fs0:</tt> for the first
+ filesystem, <tt>fs1:</tt> for the second, and so on. Type the
+ filesystem number followed by the Enter key to begin using it. You can
+ then type <tt class="userinput">ls</tt> or <tt
+ class="userinput">dir</tt> to see the contents of the filesystem.
+ Chances are your ESP will be <tt>fs0:</tt>, but it could be something
+ else. (The following steps assume your ESP is <tt>fs0:</tt>; you'll
+ need to adjust them if it's not.) If rEFInd's source files are on
+ another device, you must identify it, too.</li>
+
+<p class="sidebar"><b>Note:</b> Skip ahead to step #9 if you're merely re-activating an already-installed rEFInd binary. If an entry exists but it's no longer the primary one, you can skip ahead to step #14.</p>
+
+<li>If necessary, create a directory for rEFInd by typing <tt
+ class="userinput">mkdir fs0:\EFI\refind</tt>. (If the <tt>fs0:\EFI</tt>
+ directory doesn't already exist, you must create it first,
+ though.)</li>
+
+<li>Change to the directory in which rEFInd's files exist.</li>
+
+<li>Type <tt class="userinput">cp refind_x64.efi fs0:\EFI\refind</tt> to
+ copy the rEFInd binary file. (Adjust the name if you're using a 32-bit
+ computer.)</li>
+
+<li>Type <tt class="userinput">cp refind.conf-sample
+ fs0:\EFI\refind\refind.conf</tt> to copy and rename the sample rEFInd
+ configuration file.</li>
+
+<li>Type <tt class="userinput">cp -r icons fs0:\EFI\refind\</tt> to copy
+ rEFInd's icons.</li>
+
+<li>Optionally, type <tt class="userinput">cp -r drivers_x64
+ fs0:\EFI\refind\</tt> to copy rEFInd's 64-bit drivers. (You could
+ instead copy the 32-bit drivers or limit yourself to just the drivers
+ you need, of course.)</li>
+
+<li>Type <tt class="userinput">fs0:</tt>, if necessary, to change to the
+ ESP.</li>
+
+<li>Type <tt class="userinput">cd \EFI\refind</tt> to change to rEFInd's
+ installation directory.</li>
+
+<li>If you want to edit rEFInd's options, type <tt class="userinput">edit
+ refind.conf</tt> and use the shell's built-in text editor to do so.
+ Press F2 followed by the Enter key to save your changes and F3 to
+ exit.</li>
+
+<li>Type <tt class="userinput">bcfg boot dump -b</tt> to see a list of
+ existing NVRAM entries. Pay attention to their numbers (labelled
+ <tt>Option:</tt> and <tt>Variable:</tt>, with the latter number
+ preceded by the string <tt>Boot</tt>, as in <tt>Boot0007</tt>). You'll
+ want to create a boot entry for rEFInd using a number that's not in
+ use.</li>
+
+<li>Type <tt class="userinput">bcfg boot add 3
+ fs0:\EFI\refind\refind_x64.efi "rEFInd"</tt>, adjusting the number
+ (<tt>3</tt> in this example), filesystem (<tt>fs0:</tt>), and filename
+ (<tt>\EFI\refind\refind_x64.efi</tt>) as necessary for your system. If
+ you're used to Linux, be sure to use backslashes (<tt>\</tt>), not
+ Linux-style forward slashes (<tt>/</tt>) as directory separators. Note
+ that some shells may ignore the number you entered and use another one,
+ so watch for this possibility.</li>
+
+<li>Type <tt class="userinput">bcfg boot mv <i>3</i> 0</tt>, substituting
+ the option number for the entry you created for <tt
+ class="variable">3</tt>. This moves rEFInd to the top of the boot
+ order.</li>
+
+<li>Type <tt class="userinput">reset</tt> to reboot the computer.</li>
+
+</ol>
+
+<p>With any luck, rEFInd will start up at this point. If not, you can check your settings using a shell or an emergency system for your OS of choice. In an EFI shell, you might type <tt class="userinput">bcfg boot dump -b</tt> to view your boot loader entries and verify that rEFInd appears at the top of the list. Be sure to check the pathname for typos. If you continue to have problems, you might look into giving rEFInd a <a href="#naming">fallback filename</a> that your firmware will recognize.</p>
+
<a name="naming">
<h2>Alternative Naming Options</h2>
</a>
href="http://www.codon.org.uk/~mjg59/shim-signed/">Matthew J. Garrett's
download site</a> or from your distribution. (Don't use Ubuntu 12.10's
version, though; as noted earlier, it's inadequate for use with
- rEFInd.)</li>
+ rEFInd.) The most recent beta versions of Fedora 18 reportedly ship
+ with a signed shim, but I've not yet tested them.</li>
<p class="sidebar"><b>Tip:</b> If you're running Linux, you can save some effort by using the <tt>install.sh</tt> script with its <tt>--shim <tt class="variable">/path/to/shim.efi</tt></tt> option rather than installing manually, as in steps 4–6 of this procedure. If you've installed <tt>openssl</tt> and <tt>sbsign</tt>, using <tt>--localkeys</tt> will generate local signing keys and re-sign the rEFInd binaries with your own key, too. You can then use <tt>sbsign</tt> and the keys in <tt>/etc/refind.d/keys</tt> to sign your kernels or boot loaders.</p>
<li>Each of the lines with a long awkward string represents a disk
partition. Select one and you'll see a list of files. Continue
selecting subdirectories until you find the <tt>refind.cer</tt> file
- you copied to the ESP earlier.</li>
+ you copied to the ESP earlier. (Note that the long lines can wrap
+ and hide valid entries on the next line, so you may need to select
+ a disk whose entry is masked by another one!)</li>
<li>Select <tt>refind.cer</tt>. You can type <tt class="userinput">1</tt>
to view the certificate's details if you like, or skip that and type
<h2>Secure Boot Caveats</h2>
</a>
-<p>rEFInd's Secure Boot support is brand-new with version 0.5.0 of the program. Unfortunately, rEFInd, like shim, must essentially bypass UEFI security features, and must simultaneously not create security problems, in order to work. Unfortunately, the procedures that rEFInd uses to do this (which were lifted straight from shim) play "fast and loose" with the UEFI rules. This fact creates a number of limitations, which include (but are almost certainly not limited to) the following:</p>
+<p>rEFInd's Secure Boot support is brand-new with version 0.5.0 of the program, and was revamped for version 0.6.2. I believe rEFInd 0.6.2's Secure Boot support to be significantly superior to that of previous versions, but you might still run into problems. Some issues you might encounter include the following:</p>
<ul>
-<li>rEFInd can launch <i>one</i> shim/MOK-signed driver, no more. If you
- try to launch two drivers, rEFInd throws up an <tt>Access Denied</tt>
- error for the second driver.</li>
-
-<li>Signing the Windows boot loader with a MOK won't work; it hangs.
- Fortunately, the Windows 8 boot loader should work because it should be
- verified and launched via EFI calls rather than via the new
- shim-derived code. (I lack a Windows 8 installation for testing,
- though.) This limitation could affect you if you want to boot Windows 7
- with Secure Boot active.</li>
-
<li>Under certain circumstances, the time required to launch a boot loader
can increase. This is unlikely to be noticeable for the average small
boot loader, but could be significant for larger boot loaders on slow
filesystems, such as Linux kernels on ext2fs, ext3fs, or ReiserFS
partitions.</li>
-<li>Secure Boot mode doesn't work on <i>x</i>86 (IA32) or ARM systems, just
- on <i>x</i>86-64 (AMD64) computers. This is largely because shim has
- the same limitations.</li>
+<li>As of version 0.6.2, rEFInd's own Secure Boot support is theoretically
+ able to work on non-<i>x</i>86-64 platforms; however, shim 0.2 works
+ only on <i>x</i>86-64, and rEFInd is dependent upon shim. Thus, you'll
+ have to wait for future shim developments if you want to use Secure
+ Boot on <i>x</i>86 or ARM computers.</li>
+
+<li>I currently lack a Windows 8 installation with which to test, so I can't
+ even be 100% positive that rEFInd will launch Windows 8 in Secure Boot
+ ode. (It should, though, since it can launch other boot loaders that have
+ been signed with Microsoft's keys.) In theory, signing Microsoft's boot
+ loader with a MOK should work. This might be handy if you want to replace
+ your computer's built-in keys with your own but still boot Windows—but
+ be aware that if Windows replaces its boot loader, it will then stop
+ working.</li>
</ul>
-<p>My focus in testing rEFInd's Secure Boot capabilities has been on getting Linux kernels with EFI stub loaders to launch correctly. I've done some minimal testing with GRUB 2, though. I've also tested some self-signed binaries, such as an EFI shell and MokManager. (The EFI shell launches, but will not itself launch anything that's not been signed with a UEFI Secure Boot key. This of course limits its utility.)</p>
+<p>If you launch a boot loader or other program from rEFInd that relies on the EFI's standard program-launching code, that program should take advantage of shim and its MOKs. For instance, if you launch <a href="http://freedesktop.org/wiki/Software/gummiboot">gummiboot</a> from rEFInd (and rEFInd from shim), gummiboot should be able to launch shim/MOK-signed Linux kernels. This is not currently true if you launch gummiboot directly from shim.</p>
+
+<p>My focus in testing rEFInd's Secure Boot capabilities has been on getting Linux kernels with EFI stub loaders to launch correctly. I've done some minimal testing with GRUB 2, though. I've also tested some self-signed binaries, such as an EFI shell and MokManager. (The EFI shell launches, but will not itself launch anything that's not been signed with a UEFI Secure Boot key, even with rEFInd 0.6.2. This of course limits its utility.)</p>
-<p>At the moment, I consider rEFInd's shim/MOK support to be of alpha quality. I'm releasing it in this state in the hope of getting feedback from adventurous early adopters. I expect to improve the installation procedure, and with any luck fix some of the known bugs, in the next couple of versions. Some of the usability improvements are dependent upon MOK-capable versions of shim being released with major distributions; such versions of shim, with kernels signed with the key that matches the one built into shim, will greatly reduce the need for users to sign boot loaders.</p>
+<p>At the moment, I consider rEFInd's shim/MOK support to be of late alpha quality. I'm releasing it in this state in the hope of getting feedback from adventurous early adopters. Some of the usability improvements are dependent upon MOK-capable versions of shim being released with major distributions; such versions of shim, with kernels signed with the key that matches the one built into shim, will greatly reduce the need for users to sign boot loaders.</p>
<hr />
stanzas override auto-detected boot loader definitions for the same
boot loader file.</li>
+ <li>I have thoughts about creating an EFI configuration tool and
+ information utility—something to tell you about your hard
+ disks, enable you to manage MOKs, adjust boot loader priority in
+ the NVRAM, and so on. This would be useful in system maintenance
+ and in recovering from boot problems.</li>
+
+ <li>An installation tool for the EFI environment would be useful.
+ A simple EFI shell script might work, but because this function
+ requires access to the <tt>bcfg</tt> command, this would work
+ only from a version 2 shell or if <tt>bcfg</tt> were implemented
+ as a standalone program. Another alternative would be a program
+ written in C.</li>
+
<li>It should be possible to override specific auto-detected boot
loader settings—say, to disable one specific boot loader or
change its icon.</li>
</ul></li> <!-- New features -->
- <li><b>Improvements to the EFI drivers:</b>
+<li><b>Improvements to the EFI drivers:</b>
<ul>
endif
ifeq ($(ARCH),x86_64)
- ARCH_C_FLAGS = "-DEFIAPI=__attribute__((ms_abi))" -mcmodel=large -m64
+# ARCH_C_FLAGS = "-DEFIAPI=__attribute__((ms_abi))" -mcmodel=large -m64
+ ARCH_C_FLAGS = "-DEFIAPI=__attribute__((ms_abi))" -m64
ARCHDIR = X64
UC_ARCH = X64
FILENAME_CODE = x64
-I $(EDK2BASE)/EdkCompatibilityPkg/Foundation/Library/Dxe/Include
FSW_NAMES = fsw_efi fsw_core fsw_efi_lib fsw_lib AutoGen
-OBJS = $(FSW_NAMES:=.o)
+OBJS = $(FSW_NAMES:=.obj)
#DRIVERNAME = ext2
BUILDME = $(DRIVERNAME)_$(FILENAME_CODE).efi
LDFLAGS = -nostdlib -n -q --gc-sections --script=$(EDK2BASE)/BaseTools/Scripts/gcc4.4-ld-script \
--entry _ModuleEntryPoint -u _ModuleEntryPoint -m $(LD_CODE)
-%.o: %.c
+%.obj: %.c
$(CC) $(ARCH_C_FLAGS) $(CFLAGS) $(INCLUDE_DIRS) -DFSTYPE=$(DRIVERNAME) -DNO_BUILTIN_VA_FUNCS -c $< -o $@
ifneq (,$(filter %.efi,$(BUILDME)))
all: $(BUILDME)
-$(DLL_TARGET): $(OBJS) fsw_$(DRIVERNAME).o
- $(LD) -o $(DRIVERNAME)_$(FILENAME_CODE).dll $(LDFLAGS) --start-group $(ALL_EFILIBS) $(OBJS) fsw_$(DRIVERNAME).o --end-group
+$(DLL_TARGET): $(OBJS) fsw_$(DRIVERNAME).obj
+ $(LD) -o $(DRIVERNAME)_$(FILENAME_CODE).dll $(LDFLAGS) --start-group $(ALL_EFILIBS) $(OBJS) fsw_$(DRIVERNAME).obj --end-group
$(BUILDME): $(DLL_TARGET)
$(OBJCOPY) --strip-unneeded $(DLL_TARGET)
INSTALL_DIR = /boot/efi/EFI/refind/drivers
-FILESYSTEMS = ext2 reiserfs iso9660 hfs ext4
+FILESYSTEMS = ext2 ext4 reiserfs iso9660 hfs
+FILESYSTEMS_GNUEFI = ext2_gnuefi ext4_gnuefi reiserfs_gnuefi iso9660_gnuefi hfs_gnuefi
TEXTFILES = $(FILESYSTEMS:=*.txt)
+# Build the drivers with TianoCore EDK2.....
+
all: $(FILESYSTEMS)
ext2:
- rm -f fsw_efi.o
+ rm -f fsw_efi.obj
make DRIVERNAME=ext2 -f Make.tiano
+ext4:
+ rm -f fsw_efi.obj
+ make DRIVERNAME=ext4 -f Make.tiano
+
reiserfs:
- rm -f fsw_efi.o
+ rm -f fsw_efi.obj
make DRIVERNAME=reiserfs -f Make.tiano
iso9660:
- rm -f fsw_efi.o
+ rm -f fsw_efi.obj
make DRIVERNAME=iso9660 -f Make.tiano
hfs:
- rm -f fsw_efi.o
+ rm -f fsw_efi.obj
make DRIVERNAME=hfs -f Make.tiano
-ext4:
+# Build the drivers with GNU-EFI....
+
+all_gnuefi: $(FILESYSTEMS_GNUEFI)
+
+ext2_gnuefi:
rm -f fsw_efi.o
- make DRIVERNAME=ext4 -f Make.tiano
+ make DRIVERNAME=ext2 -f Make.gnuefi
+
+ext4_gnuefi:
+ rm -f fsw_efi.o
+ make DRIVERNAME=ext4 -f Make.gnuefi
+
+reiserfs_gnuefi:
+ rm -f fsw_efi.o
+ make DRIVERNAME=reiserfs -f Make.gnuefi
+
+iso9660_gnuefi:
+ rm -f fsw_efi.o
+ make DRIVERNAME=iso9660 -f Make.gnuefi
+
+hfs_gnuefi:
+ rm -f fsw_efi.o
+ make DRIVERNAME=hfs -f Make.gnuefi
# utility rules
clean:
- rm -f *~ *.bak *.o *.efi *.dll err.txt $(TEXTFILES)
+ rm -f *~ *.bak *.o *.obj *.so *.efi *.dll err.txt $(TEXTFILES)
install:
#define _FSW_CORE_H_
#include "fsw_base.h"
+#include "fsw_efi_base.h"
/** Maximum size for a path, specifically symlink target paths. */
#include "fsw_efi.h"
#include "fsw_core.h"
-//#include <EfiCommonLib.h>
-//#include <EfiDriverLib.h>
+#ifdef __MAKEWITH_GNUEFI
+#include "edk2/DriverBinding.h"
+#include "edk2/ComponentName.h"
+#endif
+#include "../include/refit_call_wrapper.h"
#define DEBUG_LEVEL 0
#endif
#define DEBUG_VBFS 1
-// CHAR8 *msgCursor;
-// MESSAGE_LOG_PROTOCOL *Msg = NULL;
#if DEBUG_VBFS==2
#define DBG(x...) AsciiPrint(x)
#define DBG(x...)
#endif
+#define EFI_DISK_IO_PROTOCOL_GUID \
+ { \
+ 0xce345171, 0xba0b, 0x11d2, {0x8e, 0x4f, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \
+ }
+
+#define EFI_BLOCK_IO_PROTOCOL_GUID \
+ { \
+ 0x964e5b21, 0x6459, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \
+ }
+
+#ifdef __MAKEWITH_GNUEFI
+EFI_GUID gEfiDriverBindingProtocolGuid = EFI_DRIVER_BINDING_PROTOCOL_GUID;
+EFI_GUID gEfiComponentNameProtocolGuid = EFI_COMPONENT_NAME_PROTOCOL_GUID;
+EFI_GUID gEfiDiskIoProtocolGuid = EFI_DISK_IO_PROTOCOL_GUID;
+EFI_GUID gEfiBlockIoProtocolGuid = EFI_BLOCK_IO_PROTOCOL_GUID;
+EFI_GUID gEfiFileInfoGuid = EFI_FILE_INFO_ID;
+EFI_GUID gEfiFileSystemInfoGuid = EFI_FILE_SYSTEM_INFO_ID;
+EFI_GUID gEfiFileSystemVolumeLabelInfoIdGuid = EFI_FILE_SYSTEM_VOLUME_LABEL_INFO_ID;
+#define SimpleFileSystemProtocol FileSystemProtocol
+#endif
/** Helper macro for stringification. */
#define FSW_EFI_STRINGIFY(x) #x
/** Expands to the EFI driver name given the file system type name. */
-#define FSW_EFI_DRIVER_NAME(t) L"rEFInd 0.6.1 " FSW_EFI_STRINGIFY(t) L" File System Driver"
+#define FSW_EFI_DRIVER_NAME(t) L"rEFInd 0.6.2 " FSW_EFI_STRINGIFY(t) L" File System Driver"
// function prototypes
EFI_COMPONENT_NAME_PROTOCOL fsw_efi_ComponentName_table = {
fsw_efi_ComponentName_GetDriverName,
fsw_efi_ComponentName_GetControllerName,
- "eng"
+ (CHAR8*) "eng"
};
/**
fsw_efi_DriverBinding_table.ImageHandle = ImageHandle;
fsw_efi_DriverBinding_table.DriverBindingHandle = ImageHandle;
// install Driver Binding protocol
- Status = BS->InstallProtocolInterface(&fsw_efi_DriverBinding_table.DriverBindingHandle,
- &PROTO_NAME(DriverBindingProtocol),
+ Status = refit_call4_wrapper(BS->InstallProtocolInterface, &fsw_efi_DriverBinding_table.DriverBindingHandle,
+ &gEfiDriverBindingProtocolGuid,
EFI_NATIVE_INTERFACE,
&fsw_efi_DriverBinding_table);
if (EFI_ERROR (Status)) {
}
// install Component Name protocol
- Status = BS->InstallProtocolInterface(&fsw_efi_DriverBinding_table.DriverBindingHandle,
- &PROTO_NAME(ComponentNameProtocol),
+ Status = refit_call4_wrapper(BS->InstallProtocolInterface, &fsw_efi_DriverBinding_table.DriverBindingHandle,
+ &gEfiComponentNameProtocolGuid,
EFI_NATIVE_INTERFACE,
&fsw_efi_ComponentName_table);
if (EFI_ERROR (Status)) {
return EFI_SUCCESS;
}
+#ifdef __MAKEWITH_GNUEFI
+EFI_DRIVER_ENTRY_POINT(fsw_efi_main)
+#endif
+
/**
* Driver Binding EFI protocol, Supported function. This function is called by EFI
* to test if this driver can handle a certain device. Our implementation only checks
// we check for both DiskIO and BlockIO protocols
// first, open DiskIO
- Status = BS->OpenProtocol(ControllerHandle,
+ Status = refit_call6_wrapper(BS->OpenProtocol, ControllerHandle,
&PROTO_NAME(DiskIoProtocol),
(VOID **) &DiskIo,
This->DriverBindingHandle,
return Status;
// we were just checking, close it again
- BS->CloseProtocol(ControllerHandle,
+ refit_call4_wrapper(BS->CloseProtocol, ControllerHandle,
&PROTO_NAME(DiskIoProtocol),
This->DriverBindingHandle,
ControllerHandle);
// next, check BlockIO without actually opening it
- Status = BS->OpenProtocol(ControllerHandle,
+ Status = refit_call6_wrapper(BS->OpenProtocol, ControllerHandle,
&PROTO_NAME(BlockIoProtocol),
NULL,
This->DriverBindingHandle,
#endif
// open consumed protocols
- Status = BS->OpenProtocol(ControllerHandle,
+ Status = refit_call6_wrapper(BS->OpenProtocol, ControllerHandle,
&PROTO_NAME(BlockIoProtocol),
(VOID **) &BlockIo,
This->DriverBindingHandle,
return Status;
}
- Status = BS->OpenProtocol(ControllerHandle,
+ Status = refit_call6_wrapper(BS->OpenProtocol, ControllerHandle,
&PROTO_NAME(DiskIoProtocol),
(VOID **) &DiskIo,
This->DriverBindingHandle,
// register the SimpleFileSystem protocol
Volume->FileSystem.Revision = EFI_FILE_IO_INTERFACE_REVISION;
Volume->FileSystem.OpenVolume = fsw_efi_FileSystem_OpenVolume;
- Status = BS->InstallMultipleProtocolInterfaces(&ControllerHandle,
+ Status = refit_call4_wrapper(BS->InstallMultipleProtocolInterfaces, &ControllerHandle,
&PROTO_NAME(SimpleFileSystemProtocol),
&Volume->FileSystem,
NULL);
fsw_unmount(Volume->vol);
FreePool(Volume);
- BS->CloseProtocol(ControllerHandle,
+ refit_call4_wrapper(BS->CloseProtocol, ControllerHandle,
&PROTO_NAME(DiskIoProtocol),
This->DriverBindingHandle,
ControllerHandle);
#endif
// get the installed SimpleFileSystem interface
- Status = BS->OpenProtocol(ControllerHandle,
+ Status = refit_call6_wrapper(BS->OpenProtocol, ControllerHandle,
&PROTO_NAME(SimpleFileSystemProtocol),
(VOID **) &FileSystem,
This->DriverBindingHandle,
Volume = FSW_VOLUME_FROM_FILE_SYSTEM(FileSystem);
// uninstall Simple File System protocol
- Status = BS->UninstallMultipleProtocolInterfaces(ControllerHandle,
+ Status = refit_call4_wrapper(BS->UninstallMultipleProtocolInterfaces, ControllerHandle,
&PROTO_NAME(SimpleFileSystemProtocol), &Volume->FileSystem,
NULL);
if (EFI_ERROR(Status)) {
FreePool(Volume);
// close the consumed protocols
- Status = BS->CloseProtocol(ControllerHandle,
+ Status = refit_call4_wrapper(BS->CloseProtocol, ControllerHandle,
&PROTO_NAME(DiskIoProtocol),
This->DriverBindingHandle,
ControllerHandle);
// FSW_MSG_DEBUGV((FSW_MSGSTR("fsw_efi_read_block: %d (%d)\n"), phys_bno, vol->phys_blocksize));
// read from disk
- Status = Volume->DiskIo->ReadDisk(Volume->DiskIo, Volume->MediaId,
+ Status = refit_call5_wrapper(Volume->DiskIo->ReadDisk, Volume->DiskIo, Volume->MediaId,
(UINT64)phys_bno * vol->phys_blocksize,
vol->phys_blocksize,
buffer);
{
EFI_STATUS Status;
- Status = This->Close(This);
+ Status = refit_call1_wrapper(This->Close, This);
if (Status == EFI_SUCCESS) {
// this driver is read-only
Status = EFI_WARN_DELETE_FAILURE;
* to be a special value for the end of the file.
*/
-EFI_STATUS fsw_efi_file_setpos(IN FSW_FILE_DATA *File,
- IN UINT64 Position)
+EFI_STATUS fsw_efi_file_setpos(IN FSW_FILE_DATA *File, IN UINT64 Position)
{
if (Position == 0xFFFFFFFFFFFFFFFFULL)
File->shand.pos = File->shand.dnode->size;
lookup_path.data = FileName;
// resolve the path (symlinks along the way are automatically resolved)
- Status = fsw_efi_map_status(fsw_dnode_lookup_path(File->shand.dnode, &lookup_path, '\\', &dno),
- Volume);
+ Status = fsw_efi_map_status(fsw_dnode_lookup_path(File->shand.dnode, &lookup_path, '\\', &dno), Volume);
if (EFI_ERROR(Status))
return Status;
// if the final node is a symlink, also resolve it
- Status = fsw_efi_map_status(fsw_dnode_resolve(dno, &target_dno),
- Volume);
+ Status = fsw_efi_map_status(fsw_dnode_resolve(dno, &target_dno), Volume);
fsw_dnode_release(dno);
if (EFI_ERROR(Status))
return Status;
#endif
// read the next entry
- Status = fsw_efi_map_status(fsw_dnode_dir_read(&File->shand, &dno),
- Volume);
+ Status = fsw_efi_map_status(fsw_dnode_dir_read(&File->shand, &dno), Volume);
if (Status == EFI_NOT_FOUND) {
// end of directory
*BufferSize = 0;
* position to zero.
*/
-EFI_STATUS fsw_efi_dir_setpos(IN FSW_FILE_DATA *File,
- IN UINT64 Position)
+EFI_STATUS fsw_efi_dir_setpos(IN FSW_FILE_DATA *File, IN UINT64 Position)
{
if (Position == 0) {
File->shand.pos = 0;
#include "fsw_core.h"
+#ifdef __MAKEWITH_GNUEFI
+#define CompareGuid(a, b) CompareGuid(a, b)==0
+#endif
+
// extern CHAR8 *msgCursor;
// extern MESSAGE_LOG_PROTOCOL *Msg;
{ FSW_STRING_TYPE_ISO88591, 8, 8, "reiserfs" },
sizeof(struct fsw_reiserfs_volume),
sizeof(struct fsw_reiserfs_dnode),
-
+
fsw_reiserfs_volume_mount,
fsw_reiserfs_volume_free,
fsw_reiserfs_volume_stat,
#ifndef __HFS_FORMAT__
#define __HFS_FORMAT__
-#if !defined(HOST_EFI_EDK2) && !defined(HOST_POSIX)
-// Only available on Mac? and Intel EFI Toolkit?
-#include <sys/types.h>
-#include <sys/appleapiopts.h>
-#endif
+// #if !defined(HOST_EFI_EDK2) && !defined(HOST_POSIX)
+// // Only available on Mac? and Intel EFI Toolkit?
+// #include <sys/types.h>
+// #include <sys/appleapiopts.h>
+// #endif
#ifdef _MSC_VER
# pragma pack(push,2)
SHIM_LOCK *shim_lock;
EFI_GUID ShimLockGuid = SHIM_LOCK_GUID;
- if (refit_call3_wrapper(BS->LocateProtocol, &ShimLockGuid, NULL, (VOID**) &shim_lock) == EFI_SUCCESS) {
+ if ((data != NULL) && (refit_call3_wrapper(BS->LocateProtocol, &ShimLockGuid, NULL, (VOID**) &shim_lock) == EFI_SUCCESS)) {
if (!shim_lock)
return FALSE;
* Install and remove a platform security2 override policy
*/
-// #include <efi.h>
-// #include <efilib.h>
#include <global.h>
#include "guid.h"
-//#include "sha256.h"
-//#include "variables.h"
+#include "../refind/lib.h"
#include "simple_file.h"
-//#include "errors.h"
#include "../include/refit_call_wrapper.h"
#include "mok.h"
typedef struct _EFI_DEVICE_PATH_PROTOCOL EFI_DEVICE_PATH_PROTOCOL;
#endif
-typedef EFI_STATUS (EFIAPI *EFI_SECURITY_FILE_AUTHENTICATION_STATE) (
+#if defined(EFIX64)
+#define MSABI __attribute__((ms_abi))
+#else
+#define MSABI
+#endif
+
+typedef EFI_STATUS (MSABI *EFI_SECURITY_FILE_AUTHENTICATION_STATE) (
const EFI_SECURITY_PROTOCOL *This,
UINT32 AuthenticationStatus,
const EFI_DEVICE_PATH_PROTOCOL *File
);
-typedef EFI_STATUS (EFIAPI *EFI_SECURITY2_FILE_AUTHENTICATION) (
+typedef EFI_STATUS (MSABI *EFI_SECURITY2_FILE_AUTHENTICATION) (
const EFI_SECURITY2_PROTOCOL *This,
const EFI_DEVICE_PATH_PROTOCOL *DevicePath,
VOID *FileBuffer,
};
-static UINT8 *security_policy_esl = NULL;
-static UINTN security_policy_esl_len;
-
static EFI_SECURITY_FILE_AUTHENTICATION_STATE esfas = NULL;
static EFI_SECURITY2_FILE_AUTHENTICATION es2fa = NULL;
-#ifdef __MAKEWITH_GNUEFI
-static EFI_STATUS thunk_security_policy_authentication(
- const EFI_SECURITY_PROTOCOL *This,
- UINT32 AuthenticationStatus,
- const EFI_DEVICE_PATH_PROTOCOL *DevicePath
- )
-__attribute__((unused));
-
-static EFI_STATUS thunk_security2_policy_authentication(
- const EFI_SECURITY2_PROTOCOL *This,
- const EFI_DEVICE_PATH_PROTOCOL *DevicePath,
- VOID *FileBuffer,
- UINTN FileSize,
- BOOLEAN BootPolicy
- )
-__attribute__((unused));
-#endif
-
-#ifdef __MAKEWITH_GNUEFI
-static __attribute__((used)) EFI_STATUS
-#else
-static __attribute__((ms_abi)) EFI_STATUS
-#endif
+// Perform shim/MOK and Secure Boot authentication on a binary that's already been
+// loaded into memory. This function does the platform SB authentication first
+// but preserves its return value in case of its failure, so that it can be
+// returned in case of a shim/MOK authentication failure. This is done because
+// the SB failure code seems to vary from one implementation to another, and I
+// don't want to interfere with that at this time.
+static MSABI EFI_STATUS
security2_policy_authentication (
const EFI_SECURITY2_PROTOCOL *This,
const EFI_DEVICE_PATH_PROTOCOL *DevicePath,
BOOLEAN BootPolicy
)
{
- EFI_STATUS status;
+ EFI_STATUS Status;
/* Chain original security policy */
- status = uefi_call_wrapper(es2fa, 5, This, DevicePath, FileBuffer, FileSize, BootPolicy);
+ Status = uefi_call_wrapper(es2fa, 5, This, DevicePath, FileBuffer, FileSize, BootPolicy);
/* if OK, don't bother with MOK check */
- if (status == EFI_SUCCESS)
- return status;
+ if (Status == EFI_SUCCESS)
+ return Status;
if (ShimValidate(FileBuffer, FileSize)) {
- status = EFI_SUCCESS;
+ return EFI_SUCCESS;
} else {
- status = EFI_ACCESS_DENIED;
+ return Status;
}
-
-// status = security_policy_check_mok(FileBuffer, FileSize);
-
- return status;
-}
-
-#ifdef __MAKEWITH_GNUEFI
-static __attribute__((used)) EFI_STATUS
-#else
-static __attribute__((ms_abi)) EFI_STATUS
-#endif
+} // EFI_STATUS security2_policy_authentication()
+
+// Perform both shim/MOK and platform Secure Boot authentication. This function loads
+// the file and performs shim/MOK authentication first simply to avoid double loads
+// of Linux kernels, which are much more likely to be shim/MOK-signed than platform-signed,
+// since kernels are big and can take several seconds to load on some computers and
+// filesystems. This also has the effect of returning whatever the platform code is for
+// authentication failure, be it EFI_ACCESS_DENIED, EFI_SECURITY_VIOLATION, or something
+// else. (This seems to vary between implementations.)
+static MSABI EFI_STATUS
security_policy_authentication (
const EFI_SECURITY_PROTOCOL *This,
UINT32 AuthenticationStatus,
const EFI_DEVICE_PATH_PROTOCOL *DevicePathConst
)
{
- EFI_STATUS status;
- EFI_DEVICE_PATH *DevPath
- = DuplicateDevicePath((EFI_DEVICE_PATH *)DevicePathConst),
- *OrigDevPath = DevPath;
- EFI_HANDLE h;
- EFI_FILE *f;
- VOID *FileBuffer;
- UINTN FileSize;
- CHAR16* DevPathStr;
-
- /* Chain original security policy */
- status = refit_call3_wrapper(esfas, This, AuthenticationStatus, DevicePathConst);
-
- /* if OK avoid checking MOK: It's a bit expensive to
- * read the whole file in again (esfas already did this) */
- if (status == EFI_SUCCESS)
- goto out;
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH *DevPath, *OrigDevPath;
+ EFI_HANDLE h;
+ EFI_FILE *f;
+ VOID *FileBuffer;
+ UINTN FileSize;
+ CHAR16 *DevPathStr;
+
+ if (DevicePathConst == NULL) {
+ return EFI_INVALID_PARAMETER;
+ } else {
+ DevPath = OrigDevPath = DuplicateDevicePath((EFI_DEVICE_PATH *)DevicePathConst);
+ }
- status = refit_call3_wrapper(BS->LocateDevicePath, &SIMPLE_FS_PROTOCOL, &DevPath, &h);
- if (status != EFI_SUCCESS)
+ Status = refit_call3_wrapper(BS->LocateDevicePath, &SIMPLE_FS_PROTOCOL, &DevPath, &h);
+ if (Status != EFI_SUCCESS)
goto out;
DevPathStr = DevicePathToStr(DevPath);
- status = simple_file_open_by_handle(h, DevPathStr, &f, EFI_FILE_MODE_READ);
- FreePool(DevPathStr);
- if (status != EFI_SUCCESS)
+ Status = simple_file_open_by_handle(h, DevPathStr, &f, EFI_FILE_MODE_READ);
+ MyFreePool(DevPathStr);
+ if (Status != EFI_SUCCESS)
goto out;
- status = simple_file_read_all(f, &FileSize, &FileBuffer);
+ Status = simple_file_read_all(f, &FileSize, &FileBuffer);
simple_file_close(f);
- if (status != EFI_SUCCESS)
+ if (Status != EFI_SUCCESS)
goto out;
if (ShimValidate(FileBuffer, FileSize)) {
- status = EFI_SUCCESS;
+ Status = EFI_SUCCESS;
} else {
- status = EFI_ACCESS_DENIED;
+ // Try using the platform's native policy....
+ Status = uefi_call_wrapper(esfas, 3, This, AuthenticationStatus, DevicePathConst);
}
FreePool(FileBuffer);
out:
- FreePool(OrigDevPath);
- return status;
-}
-
-#ifdef __MAKEWITH_GNUEFI
-/* Nasty: ELF and EFI have different calling conventions. Here is the map for
- * calling ELF -> EFI
- *
- * 1) rdi -> rcx (32 saved)
- * 2) rsi -> rdx (32 saved)
- * 3) rdx -> r8 ( 32 saved)
- * 4) rcx -> r9 (32 saved)
- * 5) r8 -> 32(%rsp) (48 saved)
- * 6) r9 -> 40(%rsp) (48 saved)
- * 7) pad+0(%rsp) -> 48(%rsp) (64 saved)
- * 8) pad+8(%rsp) -> 56(%rsp) (64 saved)
- * 9) pad+16(%rsp) -> 64(%rsp) (80 saved)
- * 10) pad+24(%rsp) -> 72(%rsp) (80 saved)
- * 11) pad+32(%rsp) -> 80(%rsp) (96 saved)
-
- *
- * So for a five argument callback, the map is ignore the first two arguments
- * and then map (EFI -> ELF) assuming pad = 0.
- *
- * ARG4 -> ARG1
- * ARG3 -> ARG2
- * ARG5 -> ARG3
- * ARG6 -> ARG4
- * ARG11 -> ARG5
- *
- * Calling conventions also differ over volatile and preserved registers in
- * MS: RBX, RBP, RDI, RSI, R12, R13, R14, and R15 are considered nonvolatile .
- * In ELF: Registers %rbp, %rbx and %r12 through %r15 “belong” to the calling
- * function and the called function is required to preserve their values.
- *
- * This means when accepting a function callback from MS -> ELF, we have to do
- * separate preservation on %rdi, %rsi before swizzling the arguments and
- * handing off to the ELF function.
- */
-
-asm (
-".type security2_policy_authentication,@function\n"
-"thunk_security2_policy_authentication:\n\t"
- "mov 0x28(%rsp), %r10 # ARG5\n\t"
- "push %rdi\n\t"
- "push %rsi\n\t"
- "mov %r10, %rdi\n\t"
- "subq $8, %rsp # space for storing stack pad\n\t"
- "mov $0x08, %rax\n\t"
- "mov $0x10, %r10\n\t"
- "and %rsp, %rax\n\t"
- "cmovnz %rax, %r11\n\t"
- "cmovz %r10, %r11\n\t"
- "subq %r11, %rsp\n\t"
- "addq $8, %r11\n\t"
- "mov %r11, (%rsp)\n\t"
-"# five argument swizzle\n\t"
- "mov %rdi, %r10\n\t"
- "mov %rcx, %rdi\n\t"
- "mov %rdx, %rsi\n\t"
- "mov %r8, %rdx\n\t"
- "mov %r9, %rcx\n\t"
- "mov %r10, %r8\n\t"
- "callq security2_policy_authentication@PLT\n\t"
- "mov (%rsp), %r11\n\t"
- "addq %r11, %rsp\n\t"
- "pop %rsi\n\t"
- "pop %rdi\n\t"
- "ret\n"
-);
-
-asm (
-".type security_policy_authentication,@function\n"
-"thunk_security_policy_authentication:\n\t"
- "push %rdi\n\t"
- "push %rsi\n\t"
- "subq $8, %rsp # space for storing stack pad\n\t"
- "mov $0x08, %rax\n\t"
- "mov $0x10, %r10\n\t"
- "and %rsp, %rax\n\t"
- "cmovnz %rax, %r11\n\t"
- "cmovz %r10, %r11\n\t"
- "subq %r11, %rsp\n\t"
- "addq $8, %r11\n\t"
- "mov %r11, (%rsp)\n\t"
-"# three argument swizzle\n\t"
- "mov %rcx, %rdi\n\t"
- "mov %rdx, %rsi\n\t"
- "mov %r8, %rdx\n\t"
- "callq security_policy_authentication@PLT\n\t"
- "mov (%rsp), %r11\n\t"
- "addq %r11, %rsp\n\t"
- "pop %rsi\n\t"
- "pop %rdi\n\t"
- "ret\n"
-);
-#endif
+ MyFreePool(OrigDevPath);
+ return Status;
+} // EFI_STATUS security_policy_authentication()
EFI_STATUS
security_policy_install(void)
if (security2_protocol) {
es2fa = security2_protocol->FileAuthentication;
-#ifdef __MAKEWITH_GNUEFI
- security2_protocol->FileAuthentication = thunk_security2_policy_authentication;
-#else
security2_protocol->FileAuthentication = security2_policy_authentication;
-#endif
}
esfas = security_protocol->FileAuthenticationState;
-#ifdef __MAKEWITH_GNUEFI
- security_protocol->FileAuthenticationState = thunk_security_policy_authentication;
-#else
security_protocol->FileAuthenticationState = security_policy_authentication;
-#endif
return EFI_SUCCESS;
}
if (esfas) {
EFI_SECURITY_PROTOCOL *security_protocol;
- status = uefi_call_wrapper(BS->LocateProtocol, 3,
- &SECURITY_PROTOCOL_GUID, NULL,
- (VOID**) &security_protocol);
+ status = uefi_call_wrapper(BS->LocateProtocol, 3, &SECURITY_PROTOCOL_GUID, NULL, (VOID**) &security_protocol);
if (status != EFI_SUCCESS)
return status;
if (es2fa) {
EFI_SECURITY2_PROTOCOL *security2_protocol;
- status = uefi_call_wrapper(BS->LocateProtocol, 3,
- &SECURITY2_PROTOCOL_GUID, NULL,
- (VOID**) &security2_protocol);
+ status = uefi_call_wrapper(BS->LocateProtocol, 3, &SECURITY2_PROTOCOL_GUID, NULL, (VOID**) &security2_protocol);
if (status != EFI_SUCCESS)
return status;
return EFI_SUCCESS;
}
-
-void
-security_protocol_set_hashes(unsigned char *esl, int len)
-{
- security_policy_esl = esl;
- security_policy_esl_len = len;
-}
security_policy_install(void);
EFI_STATUS
security_policy_uninstall(void);
-void
-security_protocol_set_hashes(unsigned char *esl, int len);
+// void
+// security_protocol_set_hashes(unsigned char *esl, int len);
EfiLib/BdsHelper.c\r
EfiLib/BdsTianoCore.c\r
EfiLib/Console.c\r
+ mok/mok.c\r
+ mok/guid.c\r
+ mok/security_policy.c\r
+ mok/simple_file.c\r
refind/main.c\r
refind/config.c\r
refind/icns.c\r
refind/menu.c\r
refind/screen.c\r
refind/driver_support.c\r
- refind/mok.c\r
libeg/image.c\r
libeg/load_bmp.c\r
libeg/load_icns.c\r
\r
[Pcd]\r
\r
-[BuildOptions]\r
+\r
+[BuildOptions.IA32]\r
+ XCODE:*_*_*_CC_FLAGS = -Os \r
+ GCC:*_*_*_CC_FLAGS = -Os -DEFI32 -D__MAKEWITH_TIANO\r
+\r
+[BuildOptions.X64]\r
XCODE:*_*_*_CC_FLAGS = -Os \r
- GCC:*_*_*_CC_FLAGS = -Os\r
+ GCC:*_*_*_CC_FLAGS = -Os -DEFIX64 -D__MAKEWITH_TIANO\r
#define LEGACY_TYPE_MAC 1
#define LEGACY_TYPE_UEFI 2
-#ifndef __MAKEWITH_TIANO
+#ifdef __MAKEWITH_GNUEFI
//
// define BBS Device Types
//
typedef struct {
REFIT_MENU_ENTRY me;
REFIT_VOLUME *Volume;
-#ifdef __MAKEWITH_TIANO
+#ifndef __MAKEWITH_GNUEFI
BDS_COMMON_OPTION *BdsOption;
-#endif // __MAKEWITH_TIANO
+#endif
CHAR16 *LoadOptions;
BOOLEAN Enabled;
} LEGACY_ENTRY;
#include "driver_support.h"
#include "../include/syslinux_mbr.h"
-#ifdef __MAKEWITH_TIANO
-#include "../EfiLib/BdsHelper.h"
-#else
+#ifdef __MAKEWITH_GNUEFI
#define EFI_SECURITY_VIOLATION EFIERR (26)
-#endif // __MAKEWITH_TIANO
+#else
+#include "../EfiLib/BdsHelper.h"
+#endif // __MAKEWITH_GNUEFI
//
// variables
+// #ifdef EFIX64
+// foo
+// #endif
+
#define MACOSX_LOADER_PATH L"System\\Library\\CoreServices\\boot.efi"
#if defined (EFIX64)
#define SHELL_NAMES L"\\EFI\\tools\\shell.efi,\\EFI\\tools\\shellx64.efi,\\shellx64.efi"
if (AboutMenu.EntryCount == 0) {
AboutMenu.TitleImage = BuiltinIcon(BUILTIN_ICON_FUNC_ABOUT);
- AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.6.1.3");
+ AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.6.1.5");
AddMenuInfoLine(&AboutMenu, L"");
AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2006-2010 Christoph Pfisterer");
AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2012 Roderick W. Smith");
// load the image into memory (and execute it, in the case of a shim/MOK image).
ReturnStatus = Status = EFI_NOT_FOUND; // in case the list is empty
for (DevicePathIndex = 0; DevicePaths[DevicePathIndex] != NULL; DevicePathIndex++) {
- // NOTE: Below commented-out line could be more efficient iffile were read ahead of
+ // NOTE: Below commented-out line could be more efficient if file were read ahead of
// time and passed as a pre-loaded image to LoadImage(), but it doesn't work on my
// 32-bit Mac Mini or my 64-bit Intel box when launching a Linux kernel; the
// kernel returns a "Failed to handle fs_proto" error message.
} /* static LEGACY_ENTRY * AddLegacyEntry() */
-#ifdef __MAKEWITH_TIANO
+#ifdef __MAKEWITH_GNUEFI
+static VOID ScanLegacyUEFI(IN UINTN DiskType){}
+#else
// default volume badge icon based on disk kind
static EG_IMAGE * GetDiskBadge(IN UINTN DiskType) {
EG_IMAGE * Badge = NULL;
Index++;
}
} /* static VOID ScanLegacyUEFI() */
-#else
-static VOID ScanLegacyUEFI(IN UINTN DiskType){}
-#endif // __MAKEWITH_TIANO
+#endif // __MAKEWITH_GNUEFI
static VOID ScanLegacyVolume(REFIT_VOLUME *Volume, UINTN VolumeIndex) {
UINTN VolumeIndex2;
GlobalConfig.LegacyType = LEGACY_TYPE_NONE;
// UEFI-style legacy BIOS support is available only with the TianoCore EDK2
- // build environment, and then only with some implementations....
+ // build environment, and then only with some EFI implementations....
#ifdef __MAKEWITH_TIANO
Status = gBS->LocateProtocol (&gEfiLegacyBootProtocolGuid, NULL, (VOID **) &LegacyBios);
if (!EFI_ERROR (Status))
SetupScreen();
} // VOID RescanAll()
-#ifndef __MAKEWITH_GNUEFI
+#ifdef __MAKEWITH_TIANO
// Minimal initialization function
static VOID InitializeLib(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable) {
EFI_STATUS Status;
BOOLEAN Success = FALSE;
- if (secure_mode()) {
+ if (secure_mode() && ShimLoaded()) {
Status = security_policy_install();
if (Status == EFI_SUCCESS) {
Success = TRUE;
} else {
Print(L"Failed to install MOK Secure Boot extensions");
-// PauseForKey();
}
}
return Success;
case TAG_LEGACY_UEFI: // Boot a legacy OS on a non-Mac
StartLegacyUEFI((LEGACY_ENTRY *)ChosenEntry);
break;
-#endif // __MAKEWITH_TIANO
+#endif
case TAG_TOOL: // Start a EFI tool
StartTool((LOADER_ENTRY *)ChosenEntry);