#include "icns.h"
#include "menu.h"
#include "refit_call_wrapper.h"
+#include "driver_support.h"
#include "../include/syslinux_mbr.h"
//
// variables
-#define MACOSX_LOADER_PATH L"\\System\\Library\\CoreServices\\boot.efi"
+#define MACOSX_LOADER_PATH L"System\\Library\\CoreServices\\boot.efi"
+#if defined (EFIX64)
+#define SHELL_NAMES L"\\EFI\\tools\\shell.efi,\\shellx64.efi"
+#elif defined (EFI32)
+#define SHELL_NAMES L"\\EFI\\tools\\shell.efi,\\shellia32.efi"
+#else
+#define SHELL_NAMES L"\\EFI\\tools\\shell.efi"
+#endif
+
+// 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
+// no harm on other computers, AFAIK. In theory, every case variation should be done for
+// completeness, but that's ridiculous....
+#define LOADER_MATCH_PATTERNS L"*.efi,*.EFI"
+
+// Patterns that identify Linux kernels. Added to the loader match pattern when the
+// scan_all_linux_kernels option is set in the configuration file. Causes kernels WITHOUT
+// a ".efi" extension to be found when scanning for boot loaders.
+#define LINUX_MATCH_PATTERNS L"vmlinuz*,bzImage*"
static REFIT_MENU_ENTRY MenuEntryAbout = { L"About rEFInd", TAG_ABOUT, 1, 0, 'A', NULL, NULL, NULL };
-static REFIT_MENU_ENTRY MenuEntryReset = { L"Restart Computer", TAG_RESET, 1, 0, 'R', NULL, NULL, NULL };
+static REFIT_MENU_ENTRY MenuEntryReset = { L"Reboot Computer", TAG_REBOOT, 1, 0, 'R', NULL, NULL, NULL };
static REFIT_MENU_ENTRY MenuEntryShutdown = { L"Shut Down Computer", TAG_SHUTDOWN, 1, 0, 'U', NULL, NULL, NULL };
static REFIT_MENU_ENTRY MenuEntryReturn = { L"Return to Main Menu", TAG_RETURN, 0, 0, 0, NULL, NULL, NULL };
+static REFIT_MENU_ENTRY MenuEntryExit = { L"Exit rEFInd", TAG_EXIT, 1, 0, 0, NULL, NULL, NULL };
static REFIT_MENU_SCREEN MainMenu = { L"Main Menu", NULL, 0, NULL, 0, NULL, 0, L"Automatic boot" };
static REFIT_MENU_SCREEN AboutMenu = { L"About", NULL, 0, NULL, 0, NULL, 0, NULL };
-REFIT_CONFIG GlobalConfig = { FALSE, 20, 0, 0, FALSE, NULL, NULL, NULL, NULL };
+REFIT_CONFIG GlobalConfig = { FALSE, FALSE, 20, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL,
+ {TAG_SHELL, TAG_ABOUT, TAG_SHUTDOWN, TAG_REBOOT, 0, 0, 0, 0, 0 }};
//
// misc functions
{
if (AboutMenu.EntryCount == 0) {
AboutMenu.TitleImage = BuiltinIcon(BUILTIN_ICON_FUNC_ABOUT);
- AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.2.2");
+ AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.2.7.3");
AddMenuInfoLine(&AboutMenu, L"");
AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2006-2010 Christoph Pfisterer");
AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2012 Roderick W. Smith");
AddMenuInfoLine(&AboutMenu, L"Portions Copyright (c) Intel Corporation and others");
+ AddMenuInfoLine(&AboutMenu, L"Distributed under the terms of the GNU GPLv3 license");
AddMenuInfoLine(&AboutMenu, L"");
AddMenuInfoLine(&AboutMenu, L"Running on:");
AddMenuInfoLine(&AboutMenu, PoolPrint(L" EFI Revision %d.%02d",
- ST->Hdr.Revision >> 16, ST->Hdr.Revision & ((1 << 16) - 1)));
+ ST->Hdr.Revision >> 16, ST->Hdr.Revision & ((1 << 16) - 1)));
#if defined(EFI32)
AddMenuInfoLine(&AboutMenu, L" Platform: x86 (32 bit)");
#elif defined(EFIX64)
static EFI_STATUS StartEFIImageList(IN EFI_DEVICE_PATH **DevicePaths,
IN CHAR16 *LoadOptions, IN CHAR16 *LoadOptionsPrefix,
IN CHAR16 *ImageTitle,
- OUT UINTN *ErrorInStep)
+ OUT UINTN *ErrorInStep,
+ IN BOOLEAN Verbose)
{
EFI_STATUS Status, ReturnStatus;
EFI_HANDLE ChildImageHandle;
CHAR16 ErrorInfo[256];
CHAR16 *FullLoadOptions = NULL;
- Print(L"Starting %s\n", ImageTitle);
+ if (Verbose)
+ Print(L"Starting %s\n", ImageTitle);
if (ErrorInStep != NULL)
*ErrorInStep = 0;
// set load options
if (LoadOptions != NULL) {
- ReturnStatus = Status = refit_call3_wrapper(BS->HandleProtocol, ChildImageHandle, &LoadedImageProtocol, (VOID **) &ChildLoadedImage);
+ 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;
}
-
+
if (LoadOptionsPrefix != NULL) {
FullLoadOptions = PoolPrint(L"%s %s ", LoadOptionsPrefix, LoadOptions);
// NOTE: That last space is also added by the EFI shell and seems to be significant
// NOTE: We also include the terminating null in the length for safety.
ChildLoadedImage->LoadOptions = (VOID *)LoadOptions;
ChildLoadedImage->LoadOptionsSize = ((UINT32)StrLen(LoadOptions) + 1) * sizeof(CHAR16);
- Print(L"Using load options '%s'\n", LoadOptions);
+ if (Verbose)
+ Print(L"Using load options '%s'\n", LoadOptions);
}
// close open file handles
if (ErrorInStep != NULL)
*ErrorInStep = 3;
}
-
+
// re-open file handles
ReinitRefitLib();
static EFI_STATUS StartEFIImage(IN EFI_DEVICE_PATH *DevicePath,
IN CHAR16 *LoadOptions, IN CHAR16 *LoadOptionsPrefix,
IN CHAR16 *ImageTitle,
- OUT UINTN *ErrorInStep)
+ OUT UINTN *ErrorInStep,
+ IN BOOLEAN Verbose)
{
EFI_DEVICE_PATH *DevicePaths[2];
-
+
DevicePaths[0] = DevicePath;
DevicePaths[1] = NULL;
- return StartEFIImageList(DevicePaths, LoadOptions, LoadOptionsPrefix, ImageTitle, ErrorInStep);
+ return StartEFIImageList(DevicePaths, LoadOptions, LoadOptionsPrefix, ImageTitle, ErrorInStep, Verbose);
} /* static EFI_STATUS StartEFIImage() */
//
static VOID StartLoader(IN LOADER_ENTRY *Entry)
{
+ UINTN ErrorInStep = 0;
+
BeginExternalScreen(Entry->UseGraphicsMode, L"Booting OS");
StartEFIImage(Entry->DevicePath, Entry->LoadOptions,
- Basename(Entry->LoaderPath), Basename(Entry->LoaderPath), NULL);
+ Basename(Entry->LoaderPath), Basename(Entry->LoaderPath), &ErrorInStep, TRUE);
FinishExternalScreen();
}
KernelVersion = FindNumbers(FileName);
Path = FindPath(LoaderPath);
+ // Add trailing backslash for root directory; necessary on some systems, but must
+ // NOT be added to all directories, since on other systems, a trailing backslash on
+ // anything but the root directory causes them to flake out!
+ if (StrLen(Path) == 0) {
+ MergeStrings(&Path, L"\\", 0);
+ } // if
DirIterOpen(Volume->RootDir, Path, &DirIter);
+ // Now add a trailing backslash if it was NOT added earlier, for consistency in
+ // building the InitrdName later....
+ if ((StrLen(Path) > 0) && (Path[StrLen(Path) - 1] != L'\\'))
+ MergeStrings(&Path, L"\\", 0);
while ((DirIterNext(&DirIter, 2, L"init*", &DirEntry)) && (InitrdName == NULL)) {
InitrdVersion = FindNumbers(DirEntry->FileName);
if (KernelVersion != NULL) {
-// if (StriSubCmp(KernelVersion, DirEntry->FileName)) {
if (StriCmp(InitrdVersion, KernelVersion) == 0)
- InitrdName = PoolPrint(L"%s\\%s", Path, DirEntry->FileName);
-// } // if match found
+ InitrdName = PoolPrint(L"%s%s", Path, DirEntry->FileName);
} else {
if (InitrdVersion == NULL)
- InitrdName = PoolPrint(L"%s\\%s", Path, DirEntry->FileName);
+ InitrdName = PoolPrint(L"%s%s", Path, DirEntry->FileName);
} // if/else
if (InitrdVersion != NULL)
FreePool(InitrdVersion);
SubEntry = InitializeLoaderEntry(Entry);
if (SubEntry != NULL) {
SubEntry->me.Title = L"Boot using default options";
-// SubEntry->me.Title = (Entry->OSType == 'M') ? L"Boot Mac OS X" : PoolPrint(L"Run %s", FileName);
if ((SubEntry->InitrdPath != NULL) && (StrLen(SubEntry->InitrdPath) > 0) && (!StriSubCmp(L"initrd", SubEntry->LoadOptions))) {
Temp = PoolPrint(L"initrd=%s", SubEntry->InitrdPath);
MergeStrings(&SubEntry->LoadOptions, Temp, L' ');
Entry->Title = NULL;
}
SubScreen = InitializeSubScreen(Entry);
-
+
// loader-specific submenu entries
if (Entry->OSType == 'M') { // entries for Mac OS X
#if defined(EFIX64)
} // if
#endif
- if (!(GlobalConfig.DisableFlags & DISABLE_FLAG_SINGLEUSER)) {
+ if (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_SINGLEUSER)) {
SubEntry = InitializeLoaderEntry(Entry);
if (SubEntry != NULL) {
SubEntry->me.Title = L"Boot Mac OS X in verbose mode";
SubEntry->LoadOptions = L"-v";
AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry);
} // if
-
+
#if defined(EFIX64)
SubEntry = InitializeLoaderEntry(Entry);
if (SubEntry != NULL) {
AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry);
}
#endif
-
+
SubEntry = InitializeLoaderEntry(Entry);
if (SubEntry != NULL) {
SubEntry->me.Title = L"Boot Mac OS X in single user mode";
// check for Apple hardware diagnostics
StrCpy(DiagsFileName, L"\\System\\Library\\CoreServices\\.diagnostics\\diags.efi");
- if (FileExists(Volume->RootDir, DiagsFileName) && !(GlobalConfig.DisableFlags & DISABLE_FLAG_HWTEST)) {
+ if (FileExists(Volume->RootDir, DiagsFileName) && !(GlobalConfig.HideUIFlags & HIDEUI_FLAG_HWTEST)) {
SubEntry = InitializeLoaderEntry(Entry);
if (SubEntry != NULL) {
SubEntry->me.Title = L"Run Apple Hardware Test";
AddMenuInfoLine(SubScreen, L"NOTE: This is an example. Entries");
AddMenuInfoLine(SubScreen, L"marked with (*) may not work.");
-
+
} else if (Entry->OSType == 'X') { // entries for xom.efi
// by default, skip the built-in selection and boot from hard disk only
Entry->LoadOptions = L"-s -h";
// that will (with luck) work fairly automatically.
VOID SetLoaderDefaults(LOADER_ENTRY *Entry, CHAR16 *LoaderPath, IN REFIT_VOLUME *Volume) {
CHAR16 IconFileName[256];
- CHAR16 *FileName, *OSIconName = NULL, *Temp;
+ CHAR16 *FileName, *PathOnly, *OSIconName = NULL, *Temp;
CHAR16 ShortcutLetter = 0;
FileName = Basename(LoaderPath);
-
+ PathOnly = FindPath(LoaderPath);
+
// locate a custom icon for the loader
StrCpy(IconFileName, LoaderPath);
ReplaceExtension(IconFileName, L".icns");
if (FileExists(Volume->RootDir, IconFileName)) {
Entry->me.Image = LoadIcns(Volume->RootDir, IconFileName, 128);
- } // if
-
+ } else if ((StrLen(PathOnly) == 0) && (Volume->VolIconImage != NULL)) {
+ Entry->me.Image = Volume->VolIconImage;
+ } // icon matched to loader or volume
+
Temp = FindLastDirName(LoaderPath);
MergeStrings(&OSIconName, Temp, L',');
FreePool(Temp);
Entry->OSType = 'R';
ShortcutLetter = 'R';
} else if (StriCmp(LoaderPath, MACOSX_LOADER_PATH) == 0) {
+ if (Volume->VolIconImage != NULL) { // custom icon file found
+ Entry->me.Image = Volume->VolIconImage;
+ }
MergeStrings(&OSIconName, L"mac", L',');
Entry->UseGraphicsMode = TRUE;
Entry->OSType = 'M';
Entry->me.ShortcutLetter = ShortcutLetter;
if (Entry->me.Image == NULL)
Entry->me.Image = LoadOSIcon(OSIconName, L"unknown", FALSE);
+ if (PathOnly != NULL)
+ FreePool(PathOnly);
} // VOID SetLoaderDefaults()
-
+
// Add a specified EFI boot loader to the list, using automatic settings
// for icons, options, etc.
LOADER_ENTRY * AddLoaderEntry(IN CHAR16 *LoaderPath, IN CHAR16 *LoaderTitle, IN REFIT_VOLUME *Volume) {
LOADER_ENTRY *Entry;
+ CleanUpPathNameSlashes(LoaderPath);
Entry = InitializeLoaderEntry(NULL);
if (Entry != NULL) {
Entry->Title = StrDuplicate(LoaderTitle);
- Entry->me.Title = PoolPrint(L"Boot %s from %s", (LoaderTitle != NULL) ? LoaderTitle : LoaderPath + 1, Volume->VolName);
+ Entry->me.Title = PoolPrint(L"Boot %s from %s", (LoaderTitle != NULL) ? LoaderTitle : LoaderPath, Volume->VolName);
Entry->me.Row = 0;
Entry->me.BadgeImage = Volume->VolBadgeImage;
Entry->LoaderPath = StrDuplicate(LoaderPath);
GenerateSubScreen(Entry, Volume);
AddMenuEntry(&MainMenu, (REFIT_MENU_ENTRY *)Entry);
}
-
+
return(Entry);
} // LOADER_ENTRY * AddLoaderEntry()
// Scan an individual directory for EFI boot loader files and, if found,
// add them to the list.
-static VOID ScanLoaderDir(IN REFIT_VOLUME *Volume, IN CHAR16 *Path)
+static VOID ScanLoaderDir(IN REFIT_VOLUME *Volume, IN CHAR16 *Path, IN CHAR16 *Pattern)
{
EFI_STATUS Status;
REFIT_DIR_ITER DirIter;
EFI_FILE_INFO *DirEntry;
CHAR16 FileName[256];
- // Note: SelfDirPath includes a leading backslash ('\'), but Path
- // doesn't, so we rejigger the string to compensate....
- if (!SelfDirPath || !Path || ((StriCmp(Path, &SelfDirPath[1]) == 0) && Volume != SelfVolume) ||
- (StriCmp(Path, &SelfDirPath[1]) != 0)) {
+ if (!SelfDirPath || !Path || ((StriCmp(Path, SelfDirPath) == 0) && Volume != SelfVolume) ||
+ (StriCmp(Path, SelfDirPath) != 0)) {
// look through contents of the directory
DirIterOpen(Volume->RootDir, Path, &DirIter);
- while (DirIterNext(&DirIter, 2, L"*.efi", &DirEntry)) {
+ while (DirIterNext(&DirIter, 2, Pattern, &DirEntry)) {
if (DirEntry->FileName[0] == '.' ||
StriCmp(DirEntry->FileName, L"TextMode.efi") == 0 ||
StriCmp(DirEntry->FileName, L"ebounce.efi") == 0 ||
- StriCmp(DirEntry->FileName, L"GraphicsConsole.efi") == 0)
+ StriCmp(DirEntry->FileName, L"GraphicsConsole.efi") == 0 ||
+ StriSubCmp(L"shell", DirEntry->FileName))
continue; // skip this
if (Path)
EFI_STATUS Status;
REFIT_DIR_ITER EfiDirIter;
EFI_FILE_INFO *EfiDirEntry;
- CHAR16 FileName[256];
-// LOADER_ENTRY *Entry;
+ CHAR16 FileName[256], *Directory, *MatchPatterns;
+ UINTN i, Length;
+
+ MatchPatterns = StrDuplicate(LOADER_MATCH_PATTERNS);
+ if (GlobalConfig.ScanAllLinux)
+ MergeStrings(&MatchPatterns, LINUX_MATCH_PATTERNS, L',');
if ((Volume->RootDir != NULL) && (Volume->VolName != NULL)) {
// check for Mac OS X boot loader
}
// check for XOM
- StrCpy(FileName, L"\\System\\Library\\CoreServices\\xom.efi");
+ StrCpy(FileName, L"System\\Library\\CoreServices\\xom.efi");
if (FileExists(Volume->RootDir, FileName)) {
AddLoaderEntry(FileName, L"Windows XP (XoM)", Volume);
}
// check for Microsoft boot loader/menu
- StrCpy(FileName, L"\\EFI\\Microsoft\\Boot\\Bootmgfw.efi");
+ StrCpy(FileName, L"EFI\\Microsoft\\Boot\\Bootmgfw.efi");
if (FileExists(Volume->RootDir, FileName)) {
AddLoaderEntry(FileName, L"Microsoft EFI boot", Volume);
}
// scan the root directory for EFI executables
- ScanLoaderDir(Volume, NULL);
- // scan the elilo directory (as used on gimli's first Live CD)
- ScanLoaderDir(Volume, L"elilo");
- // scan the boot directory
- ScanLoaderDir(Volume, L"boot");
+ ScanLoaderDir(Volume, NULL, MatchPatterns);
// scan subdirectories of the EFI directory (as per the standard)
DirIterOpen(Volume->RootDir, L"EFI", &EfiDirIter);
while (DirIterNext(&EfiDirIter, 1, NULL, &EfiDirEntry)) {
- if (StriCmp(EfiDirEntry->FileName, L"TOOLS") == 0 || EfiDirEntry->FileName[0] == '.')
+ if (StriCmp(EfiDirEntry->FileName, L"tools") == 0 || EfiDirEntry->FileName[0] == '.')
continue; // skip this, doesn't contain boot loaders
SPrint(FileName, 255, L"EFI\\%s", EfiDirEntry->FileName);
- ScanLoaderDir(Volume, FileName);
+ ScanLoaderDir(Volume, FileName, MatchPatterns);
} // while()
Status = DirIterClose(&EfiDirIter);
if (Status != EFI_NOT_FOUND)
CheckError(Status, L"while scanning the EFI directory");
+
+ // Scan user-specified (or additional default) directories....
+ i = 0;
+ while ((Directory = FindCommaDelimited(GlobalConfig.AlsoScan, i++)) != NULL) {
+ Length = StrLen(Directory);
+ // Some EFI implementations won't read a directory if the path ends in
+ // a backslash, so eliminate this character, if it's present....
+ while ((Length > 0) && (Directory[Length - 1] == L'\\')) {
+ Directory[--Length] = 0;
+ } // while
+ if (Length > 0)
+ ScanLoaderDir(Volume, Directory, MatchPatterns);
+ FreePool(Directory);
+ } // while
} // if
} // static VOID ScanEfiFiles()
if (PartitionIndex < LogicalPartitionIndex)
break; // stop the loop, no need to touch further EMBRs
}
-
+
}
return EFI_SUCCESS;
ExtractLegacyLoaderPaths(DiscoveredPathList, MAX_DISCOVERED_PATHS, LegacyLoaderList);
- Status = StartEFIImageList(DiscoveredPathList, Entry->LoadOptions, NULL, L"legacy loader", &ErrorInStep);
+ Status = StartEFIImageList(DiscoveredPathList, Entry->LoadOptions, NULL, L"legacy loader", &ErrorInStep, TRUE);
if (Status == EFI_NOT_FOUND) {
if (ErrorInStep == 1) {
Print(L"\nPlease make sure that you have the latest firmware update installed.\n");
SubEntry->Volume = Entry->Volume;
SubEntry->LoadOptions = Entry->LoadOptions;
AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry);
-
+
AddMenuEntry(SubScreen, &MenuEntryReturn);
Entry->me.SubScreen = SubScreen;
AddMenuEntry(&MainMenu, (REFIT_MENU_ENTRY *)Entry);
{
BeginExternalScreen(Entry->UseGraphicsMode, Entry->me.Title + 6); // assumes "Start <title>" as assigned below
StartEFIImage(Entry->DevicePath, Entry->LoadOptions, Basename(Entry->LoaderPath),
- Basename(Entry->LoaderPath), NULL);
+ Basename(Entry->LoaderPath), NULL, TRUE);
FinishExternalScreen();
} /* static VOID StartTool() */
return Entry;
} /* static LOADER_ENTRY * AddToolEntry() */
-static VOID ScanTool(VOID)
-{
- CHAR16 FileName[256];
- LOADER_ENTRY *Entry;
-
- if (GlobalConfig.DisableFlags & DISABLE_FLAG_TOOLS)
- return;
-
- // look for the EFI shell
- if (!(GlobalConfig.DisableFlags & DISABLE_FLAG_SHELL)) {
- SPrint(FileName, 255, L"%s\\apps\\shell.efi", SelfDirPath);
- if (FileExists(SelfRootDir, FileName)) {
- AddToolEntry(FileName, L"EFI Shell", BuiltinIcon(BUILTIN_ICON_TOOL_SHELL), 'E', FALSE);
- } else {
- StrCpy(FileName, L"\\efi\\tools\\shell.efi");
- if (FileExists(SelfRootDir, FileName)) {
- AddToolEntry(FileName, L"EFI Shell", BuiltinIcon(BUILTIN_ICON_TOOL_SHELL), 'E', FALSE);
- }
- }
- }
-
- // look for the GPT/MBR sync tool
- StrCpy(FileName, L"\\efi\\tools\\gptsync.efi");
- if (FileExists(SelfRootDir, FileName)) {
- AddToolEntry(FileName, L"Make Hybrid MBR", BuiltinIcon(BUILTIN_ICON_TOOL_PART), 'P', FALSE);
- }
-
- // look for rescue Linux
- StrCpy(FileName, L"\\efi\\rescue\\elilo.efi");
- if (SelfVolume != NULL && FileExists(SelfRootDir, FileName)) {
- Entry = AddToolEntry(FileName, L"Rescue Linux", BuiltinIcon(BUILTIN_ICON_TOOL_RESCUE), '0', FALSE);
-
- if (UGAWidth == 1440 && UGAHeight == 900)
- Entry->LoadOptions = L"-d 0 i17";
- else if (UGAWidth == 1680 && UGAHeight == 1050)
- Entry->LoadOptions = L"-d 0 i20";
- else
- Entry->LoadOptions = L"-d 0 mini";
- }
-}
-
-
-#ifdef DEBIAN_ENABLE_EFI110
//
// pre-boot driver functions
//
-static VOID ScanDriverDir(IN CHAR16 *Path)
+static UINTN ScanDriverDir(IN CHAR16 *Path)
{
EFI_STATUS Status;
REFIT_DIR_ITER DirIter;
+ UINTN NumFound = 0;
EFI_FILE_INFO *DirEntry;
CHAR16 FileName[256];
-
+
// look through contents of the directory
DirIterOpen(SelfRootDir, Path, &DirIter);
- while (DirIterNext(&DirIter, 2, L"*.EFI", &DirEntry)) {
+ while (DirIterNext(&DirIter, 2, LOADER_MATCH_PATTERNS, &DirEntry)) {
if (DirEntry->FileName[0] == '.')
continue; // skip this
-
+
SPrint(FileName, 255, L"%s\\%s", Path, DirEntry->FileName);
+ NumFound++;
Status = StartEFIImage(FileDevicePath(SelfLoadedImage->DeviceHandle, FileName),
- L"", DirEntry->FileName, DirEntry->FileName, NULL);
+ L"", DirEntry->FileName, DirEntry->FileName, NULL, FALSE);
}
Status = DirIterClose(&DirIter);
if (Status != EFI_NOT_FOUND) {
SPrint(FileName, 255, L"while scanning the %s directory", Path);
CheckError(Status, FileName);
}
+ return (NumFound);
}
static EFI_STATUS ConnectAllDriversToAllControllers(VOID)
{
- EFI_STATUS Status;
- UINTN AllHandleCount;
- EFI_HANDLE *AllHandleBuffer;
- UINTN Index;
- UINTN HandleCount;
- EFI_HANDLE *HandleBuffer;
- UINT32 *HandleType;
- UINTN HandleIndex;
- BOOLEAN Parent;
- BOOLEAN Device;
-
+ EFI_STATUS Status;
+ UINTN AllHandleCount;
+ EFI_HANDLE *AllHandleBuffer;
+ UINTN Index;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ UINT32 *HandleType;
+ UINTN HandleIndex;
+ BOOLEAN Parent;
+ BOOLEAN Device;
+
Status = LibLocateHandle(AllHandles,
NULL,
NULL,
&AllHandleBuffer);
if (EFI_ERROR(Status))
return Status;
-
+
for (Index = 0; Index < AllHandleCount; Index++) {
//
// Scan the handle database
&HandleType);
if (EFI_ERROR (Status))
goto Done;
-
+
Device = TRUE;
if (HandleType[Index] & EFI_HANDLE_TYPE_DRIVER_BINDING_HANDLE)
Device = FALSE;
if (HandleType[Index] & EFI_HANDLE_TYPE_IMAGE_HANDLE)
Device = FALSE;
-
+
if (Device) {
Parent = FALSE;
for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
if (HandleType[HandleIndex] & EFI_HANDLE_TYPE_PARENT_HANDLE)
Parent = TRUE;
- }
-
+ } // for
+
if (!Parent) {
if (HandleType[Index] & EFI_HANDLE_TYPE_DEVICE_HANDLE) {
- Status = refit_call4_wrapper(BS->ConnectController,
- AllHandleBuffer[Index],
- NULL,
- NULL,
- TRUE);
+ Status = refit_call4_wrapper(BS->ConnectController,
+ AllHandleBuffer[Index],
+ NULL,
+ NULL,
+ TRUE);
}
}
}
-
+
FreePool (HandleBuffer);
FreePool (HandleType);
}
-
+
Done:
FreePool (AllHandleBuffer);
return Status;
-}
+} /* EFI_STATUS ConnectAllDriversToAllControllers() */
static VOID LoadDrivers(VOID)
{
- CHAR16 DirName[256];
-
- // load drivers from /efi/refind/drivers
- SPrint(DirName, 255, L"%s\\drivers", SelfDirPath);
- ScanDriverDir(DirName);
-
- // load drivers from /efi/tools/drivers
- ScanDriverDir(L"\\efi\\tools\\drivers");
+ CHAR16 *Directory;
+ UINTN i = 0, Length, NumFound = 0;
+
+ // load drivers from the "drivers" subdirectory of rEFInd's home directory
+ Directory = StrDuplicate(SelfDirPath);
+ MergeStrings(&Directory, L"drivers", L'\\');
+ NumFound += ScanDriverDir(Directory);
+
+ // Scan additional user-specified driver directories....
+ while ((Directory = FindCommaDelimited(GlobalConfig.DriverDirs, i++)) != NULL) {
+ Length = StrLen(Directory);
+ // Some EFI implementations won't read a directory if the path ends in
+ // a backslash, so eliminate this character, if it's present....
+ while ((Length > 0) && (Directory[Length - 1] == L'\\')) {
+ Directory[--Length] = 0;
+ } // while
+ if (Length > 0)
+ NumFound += ScanDriverDir(Directory);
+ FreePool(Directory);
+ } // while
// connect all devices
- ConnectAllDriversToAllControllers();
+ if (NumFound > 0)
+ ConnectAllDriversToAllControllers();
}
-#endif /* DEBIAN_ENABLE_EFI110 */
static VOID ScanForBootloaders(VOID) {
UINTN i;
break;
} // switch()
} // for
- ScanTool();
- // fixed other menu entries
- if (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_FUNCS)) {
- MenuEntryAbout.Image = BuiltinIcon(BUILTIN_ICON_FUNC_ABOUT);
- AddMenuEntry(&MainMenu, &MenuEntryAbout);
- }
- if (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_FUNCS) || MainMenu.EntryCount == 0) {
- MenuEntryShutdown.Image = BuiltinIcon(BUILTIN_ICON_FUNC_SHUTDOWN);
- AddMenuEntry(&MainMenu, &MenuEntryShutdown);
- MenuEntryReset.Image = BuiltinIcon(BUILTIN_ICON_FUNC_RESET);
- AddMenuEntry(&MainMenu, &MenuEntryReset);
- }
-
// assign shortcut keys
for (i = 0; i < MainMenu.EntryCount && MainMenu.Entries[i]->Row == 0 && i < 9; i++)
MainMenu.Entries[i]->ShortcutDigit = (CHAR16)('1' + i);
-
+
// wait for user ACK when there were errors
FinishTextScreen(FALSE);
} // static VOID ScanForBootloaders()
+// Add the second-row tags containing built-in and external tools (EFI shell,
+// reboot, etc.)
+static VOID ScanForTools(VOID) {
+ CHAR16 *FileName = NULL;
+ UINTN i, j;
+
+ for (i = 0; i < NUM_TOOLS; i++) {
+ switch(GlobalConfig.ShowTools[i]) {
+ case TAG_SHUTDOWN:
+ MenuEntryShutdown.Image = BuiltinIcon(BUILTIN_ICON_FUNC_SHUTDOWN);
+ AddMenuEntry(&MainMenu, &MenuEntryShutdown);
+ break;
+ case TAG_REBOOT:
+ MenuEntryReset.Image = BuiltinIcon(BUILTIN_ICON_FUNC_RESET);
+ AddMenuEntry(&MainMenu, &MenuEntryReset);
+ break;
+ case TAG_ABOUT:
+ MenuEntryAbout.Image = BuiltinIcon(BUILTIN_ICON_FUNC_ABOUT);
+ AddMenuEntry(&MainMenu, &MenuEntryAbout);
+ break;
+ case TAG_EXIT:
+ MenuEntryExit.Image = BuiltinIcon(BUILTIN_ICON_FUNC_EXIT);
+ AddMenuEntry(&MainMenu, &MenuEntryExit);
+ break;
+ case TAG_SHELL:
+ j = 0;
+ while ((FileName = FindCommaDelimited(SHELL_NAMES, j++)) != NULL) {
+ if (FileExists(SelfRootDir, FileName)) {
+ AddToolEntry(FileName, L"EFI Shell", BuiltinIcon(BUILTIN_ICON_TOOL_SHELL), 'E', FALSE);
+ }
+ } // while
+ break;
+ case TAG_GPTSYNC:
+ MergeStrings(&FileName, L"\\efi\\tools\\gptsync.efi", 0);
+ if (FileExists(SelfRootDir, FileName)) {
+ AddToolEntry(FileName, L"Make Hybrid MBR", BuiltinIcon(BUILTIN_ICON_TOOL_PART), 'P', FALSE);
+ }
+ break;
+ } // switch()
+ if (FileName != NULL) {
+ FreePool(FileName);
+ FileName = NULL;
+ }
+ } // for
+} // static VOID ScanForTools
+
//
// main entry point
//
// further bootstrap (now with config available)
SetupScreen();
-#ifdef DEBIAN_ENABLE_EFI110
LoadDrivers();
-#endif /* DEBIAN_ENABLE_EFI110 */
ScanForBootloaders();
+ ScanForTools();
while (MainLoopRunning) {
MenuExit = RunMainMenu(&MainMenu, GlobalConfig.DefaultSelection, &ChosenEntry);
-
+
// We don't allow exiting the main menu with the Escape key.
if (MenuExit == MENU_EXIT_ESCAPE) {
// Commented-out below: Was part of an attempt to get rEFInd to
// SetupScreen();
continue;
}
-
+
switch (ChosenEntry->Tag) {
-
- case TAG_RESET: // Restart
+
+ case TAG_REBOOT: // Reboot
TerminateScreen();
refit_call4_wrapper(RT->ResetSystem, EfiResetCold, EFI_SUCCESS, 0, NULL);
MainLoopRunning = FALSE; // just in case we get this far
break;
-
+
case TAG_SHUTDOWN: // Shut Down
TerminateScreen();
refit_call4_wrapper(RT->ResetSystem, EfiResetShutdown, EFI_SUCCESS, 0, NULL);
MainLoopRunning = FALSE; // just in case we get this far
break;
-
+
case TAG_ABOUT: // About rEFInd
AboutrEFInd();
break;
-
+
case TAG_LOADER: // Boot OS via .EFI loader
StartLoader((LOADER_ENTRY *)ChosenEntry);
break;
-
+
case TAG_LEGACY: // Boot legacy OS
StartLegacy((LEGACY_ENTRY *)ChosenEntry);
break;
-
+
case TAG_TOOL: // Start a EFI tool
StartTool((LOADER_ENTRY *)ChosenEntry);
break;
-
+
+ case TAG_EXIT: // Terminate rEFInd
+ BeginTextScreen(L" ");
+ return EFI_SUCCESS;
+ break;
+
}
}
// fails, go into an endless loop.
refit_call4_wrapper(RT->ResetSystem, EfiResetCold, EFI_SUCCESS, 0, NULL);
EndlessIdleLoop();
-
+
return EFI_SUCCESS;
} /* efi_main() */