#define FALLBACK_BASENAME L"boot.efi" /* Not really correct */
#endif
-#define MOK_NAMES L"\\EFI\\tools\\MokManager.efi,\\EFI\\fedora\\MokManager.efi,\\EFI\\redhat\\MokManager.efi,\\EFI\\ubuntu\\MokManager.efi,\\EFI\\suse\\MokManager"
-
// Filename patterns that identify EFI boot loaders. Note that a single case (either L"*.efi" or
// L"*.EFI") is fine for most systems; but Gigabyte's buggy Hybrid EFI does a case-sensitive
// comparison when it should do a case-insensitive comparison, so I'm doubling this up. It does
if (AboutMenu.EntryCount == 0) {
AboutMenu.TitleImage = BuiltinIcon(BUILTIN_ICON_FUNC_ABOUT);
- AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.6.6.4");
+ AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.6.7.1");
AddMenuInfoLine(&AboutMenu, L"");
AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2006-2010 Christoph Pfisterer");
AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2012 Roderick W. Smith");
RunMenu(&AboutMenu, NULL);
} /* VOID AboutrEFInd() */
+static VOID WarnSecureBootError(CHAR16 *Name, BOOLEAN Verbose) {
+ if (Name == NULL)
+ Name = L"the loader";
+
+ refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_ERROR);
+ Print(L"Secure Boot validation failure loading %s!\n", Name);
+ refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_BASIC);
+ if (Verbose && secure_mode()) {
+ Print(L"\nThis computer is configured with Secure Boot active, but\n%s has failed validation.\n", Name);
+ Print(L"\nYou can:\n * Launch another boot loader\n");
+ Print(L" * Disable Secure Boot in your firmware\n");
+ Print(L" * Sign %s with a machine owner key (MOK)\n", Name);
+ Print(L" * Use a MOK utility (often present on the second row) to add a MOK with which\n");
+ Print(L" %s has already been signed.\n", Name);
+ Print(L" * Use a MOK utility to register %s (\"enroll its hash\") without\n", Name);
+ Print(L" signing it.\n");
+ Print(L"\nSee http://www.rodsbooks.com/refind/secureboot.html for more information\n");
+ PauseForKey();
+ } // if
+} // VOID WarnSecureBootError()
+
// Launch an EFI binary.
static EFI_STATUS StartEFIImageList(IN EFI_DEVICE_PATH **DevicePaths,
IN CHAR16 *LoadOptions, IN CHAR16 *LoadOptionsPrefix,
break;
}
}
+ if ((Status == EFI_ACCESS_DENIED) || (Status == EFI_SECURITY_VIOLATION)) {
+ WarnSecureBootError(ImageTitle, Verbose);
+ goto bailout;
+ }
SPrint(ErrorInfo, 255, L"while loading %s", ImageTitle);
if (CheckError(Status, ErrorInfo)) {
if (ErrorInStep != NULL)
// locate a custom icon for the loader
// Anything found here takes precedence over the "hints" in the OSIconName variable
if (!Entry->me.Image)
- Entry->me.Image = egFindIcon(NoExtension, 128);
+ Entry->me.Image = egLoadIconAnyType(Volume->RootDir, PathOnly, NoExtension, 128);
if (!Entry->me.Image)
- Entry->me.Image = Volume->VolIconImage;
+ Entry->me.Image = egCopyImage(Volume->VolIconImage);
// Begin creating icon "hints" by using last part of directory path leading
// to the loader
// Returns FALSE if the specified file/volume matches the GlobalConfig.DontScanDirs
// or GlobalConfig.DontScanVolumes specification, or if Path points to a volume
-// other than the one specified by Volume. Returns TRUE if none of these conditions
-// is met -- that is, if the path is eligible for scanning. Also reduces *Path to a
-// path alone, with no volume specification.
+// other than the one specified by Volume, or if the specified path is SelfDir.
+// Returns TRUE if none of these conditions is met -- that is, if the path is
+// eligible for scanning.
static BOOLEAN ShouldScan(REFIT_VOLUME *Volume, CHAR16 *Path) {
CHAR16 *VolName = NULL, *DontScanDir;
UINTN i = 0, VolNum;
if (IsIn(Volume->VolName, GlobalConfig.DontScanVolumes))
return FALSE;
+ if ((StriCmp(Path, SelfDirPath) == 0) && (Volume->DeviceHandle == SelfVolume->DeviceHandle))
+ return FALSE;
+
while ((DontScanDir = FindCommaDelimited(GlobalConfig.DontScanDirs, i++)) && ScanIt) {
SplitVolumeAndFilename(&DontScanDir, &VolName);
CleanUpPathNameSlashes(DontScanDir);
// FALSE if the file is not identical to the fallback file OR if the file
// IS the fallback file. Intended for use in excluding the fallback boot
// loader when it's a duplicate of another boot loader.
-BOOLEAN DuplicatesFallback(IN REFIT_VOLUME *Volume, IN CHAR16 *FileName) {
+static BOOLEAN DuplicatesFallback(IN REFIT_VOLUME *Volume, IN CHAR16 *FileName) {
CHAR8 *FileContents, *FallbackContents;
EFI_FILE_HANDLE FileHandle, FallbackHandle;
EFI_FILE_INFO *FileInfo, *FallbackInfo;
struct LOADER_LIST *LoaderList = NULL, *NewLoader;
BOOLEAN FoundFallbackDuplicate = FALSE;
-// Print(L"Entering ScanLoaderDir(), scanning '%s' for pattern '%s'\n", Path, Pattern);
if ((!SelfDirPath || !Path || ((StriCmp(Path, SelfDirPath) == 0) && (Volume->DeviceHandle != SelfVolume->DeviceHandle)) ||
(StriCmp(Path, SelfDirPath) != 0)) &&
(ShouldScan(Volume, Path))) {
CheckError(Status, FileName);
} // if (Status != EFI_NOT_FOUND)
} // if not scanning our own directory
-// PauseForKey();
+
return FoundFallbackDuplicate;
} /* static VOID ScanLoaderDir() */
REFIT_DIR_ITER EfiDirIter;
EFI_FILE_INFO *EfiDirEntry;
CHAR16 FileName[256], *Directory, *MatchPatterns, *VolName = NULL;
- UINTN i, Length, VolNum;
+ UINTN i, Length;
BOOLEAN ScanFallbackLoader = TRUE;
// Print(L"Entering ScanEfiFiles(), GlobalConfig.ScanAllLinux = %s\n", GlobalConfig.ScanAllLinux ? L"TRUE" : L"FALSE");
if ((Volume->RootDir != NULL) && (Volume->VolName != NULL)) {
// check for Mac OS X boot loader
- if (!IsIn(L"System\\Library\\CoreServices", GlobalConfig.DontScanDirs)) {
+ if (ShouldScan(Volume, L"System\\Library\\CoreServices")) {
StrCpy(FileName, MACOSX_LOADER_PATH);
if (FileExists(Volume->RootDir, FileName) && !IsIn(L"boot.efi", GlobalConfig.DontScanFiles)) {
AddLoaderEntry(FileName, L"Mac OS X", Volume);
if (DuplicatesFallback(Volume, FileName))
ScanFallbackLoader = FALSE;
}
- } // if Mac directory not in GlobalConfig.DontScanDirs list
+ } // if should scan Mac directory
// check for Microsoft boot loader/menu
StrCpy(FileName, L"EFI\\Microsoft\\Boot\\Bootmgfw.efi");
- if (FileExists(Volume->RootDir, FileName) && !IsIn(L"EFI\\Microsoft\\Boot", GlobalConfig.DontScanDirs) &&
+ if (FileExists(Volume->RootDir, FileName) && ShouldScan(Volume, L"EFI\\Microsoft\\Boot") &&
!IsIn(L"bootmgfw.efi", GlobalConfig.DontScanFiles)) {
AddLoaderEntry(FileName, L"Microsoft EFI boot", Volume);
if (DuplicatesFallback(Volume, FileName))
// Scan user-specified (or additional default) directories....
i = 0;
while ((Directory = FindCommaDelimited(GlobalConfig.AlsoScan, i++)) != NULL) {
- VolNum = VOL_DONTSCAN;
SplitVolumeAndFilename(&Directory, &VolName);
CleanUpPathNameSlashes(Directory);
Length = StrLen(Directory);
- if (VolName && (Length > 0) && (StrLen(VolName) > 2) && (VolName[0] == L'f') && (VolName[1] == L's') &&
- (VolName[2] >= L'0') && (VolName[2] <= L'9'))
- VolNum = Atoi(VolName + 2);
- if ((Length > 0) && ((VolName == NULL) || (StriCmp(VolName, Volume->VolName) == 0) || (Volume->VolNumber == VolNum)))
- if (ScanLoaderDir(Volume, Directory, MatchPatterns))
- ScanFallbackLoader = FALSE;
+ if ((Length > 0) && ScanLoaderDir(Volume, Directory, MatchPatterns))
+ ScanFallbackLoader = FALSE;
MyFreePool(Directory);
MyFreePool(VolName);
} // while
// If not a duplicate & if it exists & if it's not us, create an entry
// for the fallback boot loader
- if (ScanFallbackLoader && FileExists(Volume->RootDir, FALLBACK_FULLNAME) &&
- ((StriCmp(SelfDirPath, L"EFI\\BOOT") != 0) || (Volume->DeviceHandle != SelfVolume->DeviceHandle))) {
+ if (ScanFallbackLoader && FileExists(Volume->RootDir, FALLBACK_FULLNAME) && ShouldScan(Volume, L"EFI\\BOOT")) {
AddLoaderEntry(FALLBACK_FULLNAME, L"Fallback boot loader", Volume);
}
} // if
CHAR16 ShortcutLetter = 0;
CHAR16 *LegacyDescription = BdsOption->Description;
-// ScanVolume(Volume);
-
// prepare the menu entry
Entry = AllocateZeroPool(sizeof(LEGACY_ENTRY));
Entry->me.Title = AllocateZeroPool(256 * sizeof(CHAR16));
Entry->LoadOptions = (DiskType == BBS_CDROM) ? L"CD" :
((DiskType == BBS_USB) ? L"USB" : L"HD");
Entry->me.BadgeImage = GetDiskBadge(DiskType);
-// Entry->me.BadgeImage = Volume->VolBadgeImage;
Entry->BdsOption = BdsOption;
Entry->Enabled = TRUE;
// check for other bootable entries on the same disk
for (VolumeIndex2 = 0; VolumeIndex2 < VolumesCount; VolumeIndex2++) {
if (VolumeIndex2 != VolumeIndex && Volumes[VolumeIndex2]->HasBootCode &&
- Volumes[VolumeIndex2]->WholeDiskBlockIO == Volume->WholeDiskBlockIO)
+ Volumes[VolumeIndex2]->WholeDiskBlockIO == Volume->WholeDiskBlockIO)
ShowVolume = FALSE;
}
}
// Add the second-row tags containing built-in and external tools (EFI shell,
// reboot, etc.)
static VOID ScanForTools(VOID) {
- CHAR16 *FileName = NULL, Description[256];
+ CHAR16 *FileName = NULL, *MokLocations, *MokName, *PathName, Description[256];
REFIT_MENU_ENTRY *TempMenuEntry;
- UINTN i, j, VolumeIndex;
+ UINTN i, j, k, VolumeIndex;
+
+ MokLocations = StrDuplicate(MOK_LOCATIONS);
+ if (MokLocations != NULL)
+ MergeStrings(&MokLocations, SelfDirPath, L',');
for (i = 0; i < NUM_TOOLS; i++) {
switch(GlobalConfig.ShowTools[i]) {
+ // NOTE: Be sure that FileName is NULL at the end of each case.
case TAG_SHUTDOWN:
TempMenuEntry = CopyMenuEntry(&MenuEntryShutdown);
TempMenuEntry->Image = BuiltinIcon(BUILTIN_ICON_FUNC_SHUTDOWN);
break;
case TAG_SHELL:
j = 0;
- MyFreePool(FileName);
while ((FileName = FindCommaDelimited(SHELL_NAMES, j++)) != NULL) {
if (FileExists(SelfRootDir, FileName)) {
AddToolEntry(SelfLoadedImage->DeviceHandle, FileName, L"EFI Shell", BuiltinIcon(BUILTIN_ICON_TOOL_SHELL),
'S', FALSE);
}
+ MyFreePool(FileName);
} // while
break;
case TAG_GPTSYNC:
- MyFreePool(FileName);
FileName = StrDuplicate(L"\\efi\\tools\\gptsync.efi");
if (FileExists(SelfRootDir, FileName)) {
AddToolEntry(SelfLoadedImage->DeviceHandle, FileName, L"Make Hybrid MBR", BuiltinIcon(BUILTIN_ICON_TOOL_PART), 'P', FALSE);
}
+ MyFreePool(FileName);
+ FileName = NULL;
break;
case TAG_APPLE_RECOVERY:
- MyFreePool(FileName);
FileName = StrDuplicate(L"\\com.apple.recovery.boot\\boot.efi");
for (VolumeIndex = 0; VolumeIndex < VolumesCount; VolumeIndex++) {
if ((Volumes[VolumeIndex]->RootDir != NULL) && (FileExists(Volumes[VolumeIndex]->RootDir, FileName))) {
BuiltinIcon(BUILTIN_ICON_TOOL_APPLE_RESCUE), 'R', TRUE);
}
} // for
+ MyFreePool(FileName);
+ FileName = NULL;
break;
case TAG_MOK_TOOL:
j = 0;
- MyFreePool(FileName);
- while ((FileName = FindCommaDelimited(MOK_NAMES, j++)) != NULL) {
- if (FileExists(SelfRootDir, FileName)) {
- SPrint(Description, 255, L"MOK Key Manager at %s", FileName);
- AddToolEntry(SelfLoadedImage->DeviceHandle, FileName, Description,
- BuiltinIcon(BUILTIN_ICON_TOOL_MOK_TOOL), 'S', FALSE);
- }
- } // while
- if (FileExists(SelfDir, L"MokManager.efi")) {
+ while ((FileName = FindCommaDelimited(MokLocations, j++)) != NULL) {
+ k = 0;
+ while ((MokName = FindCommaDelimited(MOK_NAMES, k++)) != NULL) {
+ PathName = StrDuplicate(FileName);
+ MergeStrings(&PathName, MokName, (StriCmp(PathName, L"\\") == 0) ? 0 : L'\\');
+ for (VolumeIndex = 0; VolumeIndex < VolumesCount; VolumeIndex++) {
+ if ((Volumes[VolumeIndex]->RootDir != NULL) && (FileExists(Volumes[VolumeIndex]->RootDir, PathName))) {
+ SPrint(Description, 255, L"MOK utility at %s on %s", PathName, Volumes[VolumeIndex]->VolName);
+ AddToolEntry(Volumes[VolumeIndex]->DeviceHandle, PathName, Description,
+ BuiltinIcon(BUILTIN_ICON_TOOL_MOK_TOOL), 'S', FALSE);
+ } // if
+ } // for
+ MyFreePool(PathName);
+ MyFreePool(MokName);
+ } // while MOK_NAMES
MyFreePool(FileName);
- FileName = SelfDirPath ? StrDuplicate(SelfDirPath) : NULL;
- MergeStrings(&FileName, L"\\MokManager.efi", 0);
- SPrint(Description, 255, L"MOK Key Manager at %s", FileName);
- AddToolEntry(SelfLoadedImage->DeviceHandle, FileName, Description,
- BuiltinIcon(BUILTIN_ICON_TOOL_MOK_TOOL), 'S', FALSE);
- }
+ } // while MokLocations
+
break;
} // switch()
- MyFreePool(FileName);
- FileName = NULL;
} // for
} // static VOID ScanForTools