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 is 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.
+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
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.
- As of 5/2012, most Linux distributions seem to deliver rather elderly
- versions of GNU-EFI, so you may need to download the latest source
- code, compile it, and install it locally. Since rEFInd version 0.2.7,
- the Makefiles assume this (see below). 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.
+ 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.
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
file for your system. (The main Makefile controls the process for both
toolkits, while Make.common holds GNU-EFI options and Make.tiano holds
TianoCore options.) The most likely thing you'll need to change is the path
-to the various GNU-EFI include files and libraries. Since rEFInd 0.2.7, the
+to the various GNU-EFI include files and libraries. Since rEFInd 0.6.2, the
default Make.common file includes the following definitions:
-EFIINC = /usr/local/include/efi
-GNUEFILIB = /usr/local/lib
-EFILIB = /usr/local/lib
-EFICRT0 = /usr/local/lib
+EFIINC = /usr/include/efi
+GNUEFILIB = /usr/lib
+EFILIB = /usr/lib
+EFICRT0 = /usr/lib
-If you've installed GNU-EFI from a distribution's package, you may need to
-remove "local" from those paths, and perhaps change references to "lib" to
-"lib64". As noted earlier, though, as of 5/2012, most distributions provide
-out-of-date GNU-EFI implementations that will not work with rEFInd 0.2.7
-and later.
+If you've installed GNU-EFI from source code, you may need to add "local"
+to those paths, as in "/usr/local/include/efi". You might need to change
+references to "lib" to "lib64" on some systems. Recall that you need at
+least GNU-EFI version 3.0l to build rEFInd, and until very recently, most
+distributions provided out-of-date versions of this package.
If you're using TianoCore's EDK2, as noted earlier, you may need to adjust
the EDK2BASE variable in Make.tiano and filesystems/Make.tiano.
# Common make rules for building with gnu-efi
#
-EFIINC = /usr/local/include/efi
-GNUEFILIB = /usr/local/lib
-EFILIB = /usr/local/lib
-EFICRT0 = /usr/local/lib
+EFIINC = /usr/include/efi
+GNUEFILIB = /usr/lib
+EFILIB = /usr/lib
+EFICRT0 = /usr/lib
HOSTARCH = $(shell uname -m | sed s,i[3456789]86,ia32,)
ARCH := $(HOSTARCH)
OS = $(shell uname -s)
-CPPFLAGS = -I$(EFIINC) -I$(EFIINC)/$(ARCH) -I$(EFIINC)/protocol -DCONFIG_$(ARCH) -D__MAKEWITH_GNUEFI
+CPPFLAGS = -I$(EFIINC) -I$(EFIINC)/$(ARCH) -I$(EFIINC)/protocol -I../include -I../refind -I../libeg -DCONFIG_$(ARCH) -D__MAKEWITH_GNUEFI
OPTIMFLAGS = -O2 -fno-strict-aliasing
DEBUGFLAGS = -Wall
-I $(EDK2BASE)/MdePkg/Include/$(ARCHDIR) \
-I .. \
-I ../refind \
- -I ../libeg
+ -I ../libeg \
+ -I ../mok
OPTIMFLAGS = -fno-strict-aliasing -mno-red-zone -Wno-address -Os
DEBUGFLAGS = -Wall -Wno-missing-braces -Wno-array-bounds -ffunction-sections -fdata-sections
LOADER_DIR=refind
FS_DIR=filesystems
LIBEG_DIR=libeg
+MOK_DIR=mok
EFILIB_DIR=EfiLib
# Build rEFInd, including libeg
gnuefi:
make -C $(LIBEG_DIR)
+ make -C $(MOK_DIR)
make -C $(LOADER_DIR)
# make -C $(FS_DIR)
tiano:
make AR_TARGET=EfiLib -C $(EFILIB_DIR) -f Make.tiano
make AR_TARGET=libeg -C $(LIBEG_DIR) -f Make.tiano
+ make AR_TARGET=mok -C $(MOK_DIR) -f Make.tiano
make BUILDME=refind DLL_TARGET=refind -C $(LOADER_DIR) -f Make.tiano
clean:
make -C $(LIBEG_DIR) clean
+ make -C $(MOK_DIR) clean
make -C $(LOADER_DIR) clean
make -C $(EFILIB_DIR) clean -f Make.tiano
make -C $(FS_DIR) clean
-0.6.2 (??/??/201?):
+0.6.2 (12/??/2012):
-------------------
+- 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.)
</tr>
<tr>
<td><tt>textonly</tt></td>
- <td>None or <tt>0</tt></td>
+ <td>none or <tt>0</tt></td>
<td>rEFInd defaults to a graphical mode; however, if you prefer to do without the flashy graphics, you can run it in text mode by including this option. Passing any option but <tt>0</tt> causes text mode to be used; passing a <tt>0</tt> causes graphics mode to be used. (This could be useful if you want to override a text-mode setting in an included secondary configuration file.)</td>
</tr>
<tr>
</tr>
<tr>
<td><tt>dont_scan_files</tt> or <tt>don't_scan_files</tt></td>
- <td>Filename(s)</td>
+ <td>filename(s)</td>
<td>Adds the specified filename or filenames to a filename "blacklist"—these files are <i>not</i> included as boot loader options even if they're found on the disk. This is useful to exclude support programs (such as <tt>shim.efi</tt> and <tt>MokManager.efi</tt>) and drivers from your OS list. The default value is <tt>shim.efi, MokManager.efi, TextMode.efi, ebounce.efi, GraphicsConsole.efi</tt>.</td>
</tr>
<tr>
<td><tt>scan_all_linux_kernels</tt></td>
- <td>None or <tt>0</tt></td>
+ <td>none or <tt>0</tt></td>
<td>When set, causes rEFInd to add Linux kernels (files with names that begin with <tt>vmlinuz</tt> or <tt>bzImage</tt>) to the list of EFI boot loaders, even if they lack <tt>.efi</tt> filename extensions. The hope is that this will simplify use of rEFInd on distributions that provide kernels with EFI stub loader support but that don't give those kernels names that end in <tt>.efi</tt>. Of course, the kernels must still be stored on a filesystem that rEFInd can read, and in a directory that it scans. (<a href="drivers.html">Drivers</a> and the <tt>also_scan_dirs</tt> options can help with those issues.) Note that this option can cause unwanted files to be improperly detected and given loader tags, such as older kernels without EFI stub loader support. Versions of rEFInd prior to 0.5.0 left this option commented out in the <tt>refind.conf-sample</tt> file, but as of version 0.5.0, this option is enabled in the default configuration file. The program default remains to not scan for such kernels, though, so you can delete or uncomment this option to keep them from appearing in your boot menu. Passing any option but <tt>0</tt> causes scans for all kernels to occur; passing a <tt>0</tt> causes these kernels to not be scanned. (This could be useful if you want to override a setting of <tt>scan_all_linux_kernels</tt> in an included secondary configuration file.)</td>
</tr>
<tr>
<td><tt>default_selection</tt></td>
- <td>A substring of a boot loader's title; or a numeric position</td>
+ <td>a substring of a boot loader's title; or a numeric position</td>
<td>Sets the default boot OS based on the loader's title, which appears in the main menu beneath the icons when you select the loader. You can enter any substring of the title as the <tt>default_selection</tt>, so long as it's two or more characters in length. It's best to use a unique substring, since rEFInd stops searching when it finds the first match. Because rEFInd sorts entries within a directory in descending order by file modification time, if you specify a directory (or volume name, for loaders in a partition's root directory) as the <tt>default_selection</tt>, the most recent loader in that directory will be the default. One-character entries are matched against the first character of the title, except for digits, which refer to the numeric order of the boot loader entries.</td>
</tr>
<tr>
</tr>
<tr>
<td><tt>disabled</tt></td>
- <td>None</td>
+ <td>none</td>
<td>Disable an entry. This is often easier than commenting out an entire entry if you want to temporarily disable it.</td>
</tr>
<tr>
</tr>
<tr>
<td><tt>disabled</tt></td>
- <td>None</td>
+ <td>none</td>
<td>Disable a submenu entry. This is often easier than commenting out an entire entry if you want to temporarily disable it.</td>
</tr>
</table>
EFI_STATUS Status;
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info = NULL;
- Status = refit_call4_wrapper(GraphicsOutput->QueryMode, GraphicsOutput, *ModeWidth, &Size, &Info);
- if ((Status == EFI_SUCCESS) && (Info != NULL)) {
- *ModeWidth = Info->HorizontalResolution;
- *Height = Info->VerticalResolution;
- return TRUE;
+ if ((ModeWidth != NULL) && (Height != NULL)) {
+ Status = refit_call4_wrapper(GraphicsOutput->QueryMode, GraphicsOutput, *ModeWidth, &Size, &Info);
+ if ((Status == EFI_SUCCESS) && (Info != NULL)) {
+ *ModeWidth = Info->HorizontalResolution;
+ *Height = Info->VerticalResolution;
+ return TRUE;
+ }
}
return FALSE;
} // BOOLEAN egGetResFromMode()
BOOLEAN egSetScreenSize(IN OUT UINTN *ScreenWidth, IN OUT UINTN *ScreenHeight) {
EFI_STATUS Status = EFI_SUCCESS;
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
- UINT32 ModeNum = 0;
UINTN Size;
- BOOLEAN ModeSet = FALSE;
+ UINT32 ModeNum = 0;
UINT32 UGAWidth, UGAHeight, UGADepth, UGARefreshRate;
+ BOOLEAN ModeSet = FALSE;
+
+ if ((ScreenWidth == NULL) || (ScreenHeight == NULL))
+ return FALSE;
if (GraphicsOutput != NULL) { // GOP mode (UEFI)
if (*ScreenHeight == 0) { // User specified a mode number (stored in *ScreenWidth); use it directly
// and if so, switch to it....
do {
Status = refit_call4_wrapper(GraphicsOutput->QueryMode, GraphicsOutput, ModeNum, &Size, &Info);
- if ((Status == EFI_SUCCESS) && (Size >= sizeof(*Info)) &&
+ if ((Status == EFI_SUCCESS) && (Size >= sizeof(*Info) && (Info != NULL)) &&
(Info->HorizontalResolution == *ScreenWidth) && (Info->VerticalResolution == *ScreenHeight)) {
Status = refit_call2_wrapper(GraphicsOutput->SetMode, GraphicsOutput, ModeNum);
ModeSet = (Status == EFI_SUCCESS);
EFI_STATUS Status;
BOOLEAN ChangedIt = FALSE;
- if ((RequestedMode != ST->ConOut->Mode->Mode) && (RequestedMode != DONT_CHANGE_TEXT_MODE)) {
+ if ((RequestedMode != DONT_CHANGE_TEXT_MODE) && (RequestedMode != ST->ConOut->Mode->Mode)) {
// SwitchToGraphics();
Status = refit_call2_wrapper(ST->ConOut->SetMode, ST->ConOut, RequestedMode);
if (Status == EFI_SUCCESS) {
ChangedIt = TRUE;
} else {
SwitchToText(FALSE);
- Print(L"Error setting text mode %d; available modes are:\n", RequestedMode);
+ Print(L"\nError setting text mode %d; available modes are:\n", RequestedMode);
do {
Status = refit_call4_wrapper(ST->ConOut->QueryMode, ST->ConOut, i, &Width, &Height);
if (Status == EFI_SUCCESS)
Print(L"Mode %d: %d x %d\n", i, Width, Height);
} while (++i < ST->ConOut->Mode->MaxMode);
+ Print(L"Mode %d: Use default mode\n", DONT_CHANGE_TEXT_MODE);
PauseForKey();
SwitchToGraphics();
# Prepare a place and copy files there....
mkdir -p ../snapshots/$1/refind-$1/icons
cp --preserve=timestamps icons/*icns ../snapshots/$1/refind-$1/icons/
-cp -a docs images keys include EfiLib libeg refind filesystems install.sh mkrlconf.sh CREDITS.txt NEWS.txt BUILDING.txt COPYING.txt LICENSE.txt README.txt refind.inf Make.tiano Make.common Makefile refind.conf-sample ../snapshots/$1/refind-$1
+cp -a docs images keys include EfiLib libeg mok refind filesystems install.sh mkrlconf.sh CREDITS.txt NEWS.txt BUILDING.txt COPYING.txt LICENSE.txt README.txt refind.inf Make.tiano Make.common Makefile refind.conf-sample ../snapshots/$1/refind-$1
# Go there and prepare a souce code zip file....
cd ../snapshots/$1/
#
# refind/Make.tiano
# Build control file for rEFInd, using TianoCore EDK2
-# Requires that EfiLib and libeg subdirectories be built before this
+# Requires that EfiLib, mok, and libeg subdirectories be built before this
# file is used.
#
# /usr/local/UDK2010/MyWorkSpace/Build/MdeModule/RELEASE_GCC46/X64/MdeModulePkg/Core/Dxe/DxeMain/OUTPUT/DxeMain/DxeMain.obj
-SOURCE_NAMES = config driver_support icns lib main menu screen mok AutoGen
+SOURCE_NAMES = config driver_support icns lib main menu screen AutoGen
OBJS = $(SOURCE_NAMES:=.obj)
all: $(BUILDME)
$(AR_TARGET): $(OBJS)
$(AR) -cr $(AR_TARGET).lib $(OBJS)
-$(DLL_TARGET)_$(FILENAME_CODE).dll: $(OBJS) ../libeg/libeg.lib ../EfiLib/EfiLib.lib
- $(LD) -o $(DLL_TARGET)_$(FILENAME_CODE).dll $(LDFLAGS) --start-group $(ALL_EFILIBS) $(OBJS) ../libeg/libeg.lib ../EfiLib/EfiLib.lib --end-group
+$(DLL_TARGET)_$(FILENAME_CODE).dll: $(OBJS) ../libeg/libeg.lib ../EfiLib/EfiLib.lib ../mok/mok.lib
+ $(LD) -o $(DLL_TARGET)_$(FILENAME_CODE).dll $(LDFLAGS) --start-group $(ALL_EFILIBS) $(OBJS) ../libeg/libeg.lib ../EfiLib/EfiLib.lib ../mok/mok.lib --end-group
$(BUILDME): $(DLL_TARGET)_$(FILENAME_CODE).dll
$(OBJCOPY) --strip-unneeded $(DLL_TARGET)_$(FILENAME_CODE).dll
TARGET = refind_x64.efi
endif
-LOCAL_CPPFLAGS = -I$(SRCDIR) -I$(SRCDIR)/../include -I$(SRCDIR)/../libeg
-#LOCAL_LDFLAGS = -L$(SRCDIR)/../libeg/$(LIBEG)
-LOCAL_LDFLAGS = -L$(SRCDIR)/../libeg/
-LOCAL_LIBS = -leg
+LOCAL_CPPFLAGS = -I$(SRCDIR) -I$(SRCDIR)/../include -I$(SRCDIR)/../libeg -I$(SRCDIR)/../mok
+LOCAL_LDFLAGS = -L$(SRCDIR)/../libeg/ -L$(SRCDIR)/../mok/
+LOCAL_LIBS = -leg -lmok
-OBJS = main.o config.o menu.o screen.o icns.o lib.o mok.o driver_support.o
+OBJS = main.o config.o menu.o screen.o icns.o lib.o driver_support.o
+#OBJS = main.o config.o menu.o screen.o icns.o lib.o mok.o driver_support.o variables.o sha256.o pecoff.o simple_file.o security_policy.o guid.o
all: $(TARGET)
} // VOID EjectMedia()
-// // Return the GUID as a string, suitable for display to the user. Note that the calling
-// // function is responsible for freeing the allocated memory.
-// CHAR16 * GuidAsString(EFI_GUID *GuidData) {
-// CHAR16 *TheString;
-//
-// TheString = AllocateZeroPool(42 * sizeof(CHAR16));
-// if (TheString != 0) {
-// SPrint (TheString, 82, L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
-// (UINTN)GuidData->Data1, (UINTN)GuidData->Data2, (UINTN)GuidData->Data3,
-// (UINTN)GuidData->Data4[0], (UINTN)GuidData->Data4[1], (UINTN)GuidData->Data4[2],
-// (UINTN)GuidData->Data4[3], (UINTN)GuidData->Data4[4], (UINTN)GuidData->Data4[5],
-// (UINTN)GuidData->Data4[6], (UINTN)GuidData->Data4[7]);
-// }
-// return TheString;
-// } // GuidAsString(EFI_GUID *GuidData)
+// Return the GUID as a string, suitable for display to the user. Note that the calling
+// function is responsible for freeing the allocated memory.
+CHAR16 * GuidAsString(EFI_GUID *GuidData) {
+ CHAR16 *TheString;
+
+ TheString = AllocateZeroPool(42 * sizeof(CHAR16));
+ if (TheString != 0) {
+ SPrint (TheString, 82, L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ (UINTN)GuidData->Data1, (UINTN)GuidData->Data2, (UINTN)GuidData->Data3,
+ (UINTN)GuidData->Data4[0], (UINTN)GuidData->Data4[1], (UINTN)GuidData->Data4[2],
+ (UINTN)GuidData->Data4[3], (UINTN)GuidData->Data4[4], (UINTN)GuidData->Data4[5],
+ (UINTN)GuidData->Data4[6], (UINTN)GuidData->Data4[7]);
+ }
+ return TheString;
+} // GuidAsString(EFI_GUID *GuidData)
BOOLEAN EjectMedia(VOID);
-//CHAR16 * GuidAsString(EFI_GUID *GuidData);
+CHAR16 * GuidAsString(EFI_GUID *GuidData);
#endif
\ No newline at end of file
#include "icns.h"
#include "menu.h"
#include "mok.h"
+#include "security_policy.h"
#include "../include/Handle.h"
#include "../include/refit_call_wrapper.h"
#include "driver_support.h"
if (AboutMenu.EntryCount == 0) {
AboutMenu.TitleImage = BuiltinIcon(BUILTIN_ICON_FUNC_ABOUT);
- AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.6.1.1");
+ AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.6.1.3");
AddMenuInfoLine(&AboutMenu, L"");
AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2006-2010 Christoph Pfisterer");
AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2012 Roderick W. Smith");
EFI_STATUS Status, ReturnStatus;
EFI_HANDLE ChildImageHandle;
EFI_LOADED_IMAGE *ChildLoadedImage = NULL;
- REFIT_FILE File;
- VOID *ImageData = NULL;
- UINTN ImageSize;
- REFIT_VOLUME *DeviceVolume = NULL;
UINTN DevicePathIndex;
CHAR16 ErrorInfo[256];
CHAR16 *FullLoadOptions = NULL;
- CHAR16 *loader = NULL;
- BOOLEAN UseMok = FALSE;
if (ErrorInStep != NULL)
*ErrorInStep = 0;
// set load options
if (LoadOptions != NULL) {
if (LoadOptionsPrefix != NULL) {
-// MergeStrings(&FullLoadOptions, LoadOptionsPrefix, 0);
MergeStrings(&FullLoadOptions, LoadOptions, L' ');
if (OSType == 'M') {
MergeStrings(&FullLoadOptions, L" ", 0);
// 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 if the ReadFile() and
- // FindVolumeAndFilename() calls were moved earlier, but it doesn't work on my
+ // NOTE: Below commented-out line could be more efficient iffile 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.
// TODO: Track down the cause of this error and fix it, if possible.
// ImageData, ImageSize, &ChildImageHandle);
ReturnStatus = Status = refit_call6_wrapper(BS->LoadImage, FALSE, SelfImageHandle, DevicePaths[DevicePathIndex],
NULL, 0, &ChildImageHandle);
- if (((Status == EFI_ACCESS_DENIED) || (Status == EFI_SECURITY_VIOLATION)) && (ShimLoaded())) {
- FindVolumeAndFilename(DevicePaths[DevicePathIndex], &DeviceVolume, &loader);
- if (DeviceVolume != NULL) {
- Status = ReadFile(DeviceVolume->RootDir, loader, &File, &ImageSize);
- ImageData = File.Buffer;
- } else {
- Status = EFI_NOT_FOUND;
- Print(L"Error: device volume not found!\n");
- } // if/else
- if (Status != EFI_NOT_FOUND) {
- ReturnStatus = Status = start_image(SelfImageHandle, loader, ImageData, ImageSize, FullLoadOptions,
- DeviceVolume, FileDevicePath(DeviceVolume->DeviceHandle, loader));
-// ReturnStatus = Status = start_image(SelfImageHandle, loader, ImageData, ImageSize, FullLoadOptions,
-// DeviceVolume, DevicePaths[DevicePathIndex]);
- }
- if (ReturnStatus == EFI_SUCCESS) {
- UseMok = TRUE;
- } // if
- } // if (UEFI SB failed; use shim)
if (ReturnStatus != EFI_NOT_FOUND) {
break;
}
goto bailout;
}
- if (!UseMok) {
- ReturnStatus = Status = refit_call3_wrapper(BS->HandleProtocol, ChildImageHandle, &LoadedImageProtocol,
- (VOID **) &ChildLoadedImage);
- if (CheckError(Status, L"while getting a LoadedImageProtocol handle")) {
- if (ErrorInStep != NULL)
- *ErrorInStep = 2;
- goto bailout_unload;
- }
- ChildLoadedImage->LoadOptions = (VOID *)FullLoadOptions;
- ChildLoadedImage->LoadOptionsSize = ((UINT32)StrLen(FullLoadOptions) + 1) * sizeof(CHAR16);
- // turn control over to the image
- // TODO: (optionally) re-enable the EFI watchdog timer!
-
- // close open file handles
- UninitRefitLib();
- ReturnStatus = Status = refit_call3_wrapper(BS->StartImage, ChildImageHandle, NULL, NULL);
- // control returns here when the child image calls Exit()
- SPrint(ErrorInfo, 255, L"returned from %s", ImageTitle);
- if (CheckError(Status, ErrorInfo)) {
- if (ErrorInStep != NULL)
- *ErrorInStep = 3;
- }
+ ReturnStatus = Status = refit_call3_wrapper(BS->HandleProtocol, ChildImageHandle, &LoadedImageProtocol,
+ (VOID **) &ChildLoadedImage);
+ if (CheckError(Status, L"while getting a LoadedImageProtocol handle")) {
+ if (ErrorInStep != NULL)
+ *ErrorInStep = 2;
+ goto bailout_unload;
+ }
+ ChildLoadedImage->LoadOptions = (VOID *)FullLoadOptions;
+ ChildLoadedImage->LoadOptionsSize = ((UINT32)StrLen(FullLoadOptions) + 1) * sizeof(CHAR16);
+ // turn control over to the image
+ // TODO: (optionally) re-enable the EFI watchdog timer!
- // re-open file handles
- ReinitRefitLib();
- } // if
+ // close open file handles
+ UninitRefitLib();
+ ReturnStatus = Status = refit_call3_wrapper(BS->StartImage, ChildImageHandle, NULL, NULL);
+
+ // control returns here when the child image calls Exit()
+ SPrint(ErrorInfo, 255, L"returned from %s", ImageTitle);
+ if (CheckError(Status, ErrorInfo)) {
+ if (ErrorInStep != NULL)
+ *ErrorInStep = 3;
+ }
+
+ // re-open file handles
+ ReinitRefitLib();
bailout_unload:
// unload the image, we don't care if it works or not...
- if (!UseMok)
- Status = refit_call1_wrapper(BS->UnloadImage, ChildImageHandle);
+ Status = refit_call1_wrapper(BS->UnloadImage, ChildImageHandle);
bailout:
MyFreePool(FullLoadOptions);
#endif
+// Set up our own Secure Boot extensions....
+// Returns TRUE on success, FALSE otherwise
+static BOOLEAN SecureBootSetup(VOID) {
+ EFI_STATUS Status;
+ BOOLEAN Success = FALSE;
+
+ if (secure_mode()) {
+ Status = security_policy_install();
+ if (Status == EFI_SUCCESS) {
+ Success = TRUE;
+ } else {
+ Print(L"Failed to install MOK Secure Boot extensions");
+// PauseForKey();
+ }
+ }
+ return Success;
+} // VOID SecureBootSetup()
+
+// Remove our own Secure Boot extensions....
+// Returns TRUE on success, FALSE otherwise
+static BOOLEAN SecureBootUninstall(VOID) {
+ EFI_STATUS Status;
+ BOOLEAN Success = TRUE;
+
+ if (secure_mode()) {
+ Status = security_policy_uninstall();
+ if (Status != EFI_SUCCESS) {
+ Success = FALSE;
+ BeginTextScreen(L"Secure Boot Policy Failure");
+ Print(L"Failed to uninstall MOK Secure Boot extensions; forcing a reboot.");
+ PauseForKey();
+ refit_call4_wrapper(RT->ResetSystem, EfiResetCold, EFI_SUCCESS, 0, NULL);
+ }
+ }
+ return Success;
+} // VOID SecureBootUninstall
+
//
// main entry point
//
{
EFI_STATUS Status;
BOOLEAN MainLoopRunning = TRUE;
+ BOOLEAN MokProtocol;
REFIT_MENU_ENTRY *ChosenEntry;
UINTN MenuExit, i;
CHAR16 *Selection;
// further bootstrap (now with config available)
SetupScreen();
+ MokProtocol = SecureBootSetup();
ScanVolumes();
LoadDrivers();
+ PauseForKey();
ScanForBootloaders();
ScanForTools();
break;
case TAG_EXIT: // Terminate rEFInd
- BeginTextScreen(L" ");
- return EFI_SUCCESS;
+ if ((MokProtocol) && !SecureBootUninstall()) {
+ MainLoopRunning = FALSE; // just in case we get this far
+ } else {
+ BeginTextScreen(L" ");
+ return EFI_SUCCESS;
+ }
break;
} // switch()