X-Git-Url: https://code.delx.au/refind/blobdiff_plain/0be6e6f2e72a4b7a1146b6a7bdf9d85d58a93e2c..e0f6b77e5692ec112bb803202ae27f8c5d55de50:/refind/main.c diff --git a/refind/main.c b/refind/main.c index a228096..acc37cb 100644 --- a/refind/main.c +++ b/refind/main.c @@ -35,11 +35,11 @@ */ /* * Modifications copyright (c) 2012 Roderick W. Smith - * + * * Modifications distributed under the terms of the GNU General Public * License (GPL) version 3 (GPLv3), a copy of which must be distributed * with this source code or binaries made from it. - * + * */ #include "global.h" @@ -48,6 +48,7 @@ #include "lib.h" #include "icns.h" #include "menu.h" +#include "mok2.h" #include "../include/Handle.h" #include "../include/refit_call_wrapper.h" #include "driver_support.h" @@ -60,7 +61,7 @@ // // 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" #define DRIVER_DIRS L"drivers,drivers_x64" @@ -72,6 +73,8 @@ #define DRIVER_DIRS L"drivers" #endif +#define MOK_NAMES L"\\EFI\\tools\\MokManager.efi,\\EFI\\redhat\\MokManager.efi" + // 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 @@ -93,8 +96,9 @@ static REFIT_MENU_ENTRY MenuEntryExit = { L"Exit rEFInd", TAG_EXIT, 1, 0, 0, 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, FALSE, 0, 0, 20, 0, 0, GRAPHICS_FOR_OSX, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - {TAG_SHELL, TAG_ABOUT, TAG_SHUTDOWN, TAG_REBOOT, 0, 0, 0, 0, 0 }}; +REFIT_CONFIG GlobalConfig = { FALSE, FALSE, 0, 0, 20, 0, 0, GRAPHICS_FOR_OSX, LEGACY_TYPE_MAC, 0, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + {TAG_SHELL, TAG_APPLE_RECOVERY, TAG_MOK_TOOL, TAG_ABOUT, TAG_SHUTDOWN, TAG_REBOOT, 0, 0, 0, 0, 0 }}; // Structure used to hold boot loader filenames and time stamps in // a linked list; used to sort entries within a directory. @@ -114,7 +118,7 @@ static VOID AboutrEFInd(VOID) if (AboutMenu.EntryCount == 0) { AboutMenu.TitleImage = BuiltinIcon(BUILTIN_ICON_FUNC_ABOUT); - AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.4.5.2"); + AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.4.7.7"); AddMenuInfoLine(&AboutMenu, L""); AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2006-2010 Christoph Pfisterer"); AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2012 Roderick W. Smith"); @@ -156,29 +160,74 @@ static VOID AboutrEFInd(VOID) static EFI_STATUS StartEFIImageList(IN EFI_DEVICE_PATH **DevicePaths, IN CHAR16 *LoadOptions, IN CHAR16 *LoadOptionsPrefix, - IN CHAR16 *ImageTitle, + IN CHAR16 *ImageTitle, IN CHAR8 OSType, OUT UINTN *ErrorInStep, IN BOOLEAN Verbose) { EFI_STATUS Status, ReturnStatus; EFI_HANDLE ChildImageHandle; - EFI_LOADED_IMAGE *ChildLoadedImage; + 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 (Verbose) - Print(L"Starting %s\n", ImageTitle); if (ErrorInStep != NULL) *ErrorInStep = 0; - // load the image into memory + // set load options + if (LoadOptions != NULL) { + if (LoadOptionsPrefix != NULL) { + MergeStrings(&FullLoadOptions, LoadOptionsPrefix, 0); + MergeStrings(&FullLoadOptions, LoadOptions, L' '); + if (OSType == 'M') { + MergeStrings(&FullLoadOptions, L" ", 0); + // NOTE: That last space is also added by the EFI shell and seems to be significant + // when passing options to Apple's boot.efi... + } // if + } else { + MergeStrings(&FullLoadOptions, LoadOptions, 0); + } // if/else + // NOTE: We also include the terminating null in the length for safety. + } // if (LoadOptions != NULL) + if (Verbose) + Print(L"Starting %s\nUsing load options '%s'\n", ImageTitle, FullLoadOptions); + + // load the image into memory (and execute it, in the case of a MOK image). ReturnStatus = Status = EFI_NOT_FOUND; // in case the list is empty for (DevicePathIndex = 0; DevicePaths[DevicePathIndex] != NULL; DevicePathIndex++) { - ReturnStatus = Status = refit_call6_wrapper(BS->LoadImage, FALSE, SelfImageHandle, DevicePaths[DevicePathIndex], NULL, 0, &ChildImageHandle); - if (ReturnStatus != EFI_NOT_FOUND) { - break; - } + ReturnStatus = Status = refit_call6_wrapper(BS->LoadImage, FALSE, SelfImageHandle, DevicePaths[DevicePathIndex], + NULL, 0, &ChildImageHandle); + // ReturnStatus = Status = refit_call6_wrapper(BS->LoadImage, FALSE, SelfImageHandle, DevicePaths[DevicePathIndex], + // ImageData, ImageSize, &ChildImageHandle); + // TODO: Commented-out version above is more efficient if the below FindVolumeAndFilename() + // and ReadFile() calls (and surrounding logic) are moved earlier; however, this causes + // some computers, including my 32-bit Mac Mini and 64-bit Intel machine, to fail when + // launching a Linux kernel, with a "Failed to handle fs_proto" error message from the + // kernel. Find out what's causing this and fix it. + if (ReturnStatus == EFI_ACCESS_DENIED) { + // TODO: I originally had the next few lines a + 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 + ReturnStatus = Status = start_image(SelfImageHandle, loader, ImageData, ImageSize, FullLoadOptions, DeviceVolume); + if (ReturnStatus == EFI_SUCCESS) { + UseMok = TRUE; + } // if + } + if (ReturnStatus != EFI_NOT_FOUND) { + break; + } } SPrint(ErrorInfo, 255, L"while loading %s", ImageTitle); if (CheckError(Status, ErrorInfo)) { @@ -187,59 +236,48 @@ static EFI_STATUS StartEFIImageList(IN EFI_DEVICE_PATH **DevicePaths, goto bailout; } - // set load options - if (LoadOptions != NULL) { - ReturnStatus = Status = refit_call3_wrapper(BS->HandleProtocol, ChildImageHandle, &LoadedImageProtocol, (VOID **) &ChildLoadedImage); + 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; + if (ErrorInStep != NULL) + *ErrorInStep = 2; + goto bailout_unload; } + } - if (LoadOptionsPrefix != NULL) { - MergeStrings(&FullLoadOptions, LoadOptionsPrefix, 0); - MergeStrings(&FullLoadOptions, LoadOptions, L' '); - MergeStrings(&FullLoadOptions, L" ", 0); - // NOTE: That last space is also added by the EFI shell and seems to be significant - // when passing options to Apple's boot.efi... - } else { - MergeStrings(&FullLoadOptions, LoadOptions, 0); - } // if/else - // NOTE: We also include the terminating null in the length for safety. + if (!UseMok) { ChildLoadedImage->LoadOptions = (VOID *)FullLoadOptions; ChildLoadedImage->LoadOptionsSize = ((UINT32)StrLen(FullLoadOptions) + 1) * sizeof(CHAR16); - if (Verbose) - Print(L"Using load options '%s'\n", FullLoadOptions); - } - - // close open file handles - UninitRefitLib(); - - // turn control over to the image - // TODO: (optionally) re-enable the EFI watchdog timer! - 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; - } + // 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; + } - // re-open file handles - ReinitRefitLib(); + // re-open file handles + ReinitRefitLib(); + } // if bailout_unload: // unload the image, we don't care if it works or not... - Status = refit_call1_wrapper(BS->UnloadImage, ChildImageHandle); + if (!UseMok) + Status = refit_call1_wrapper(BS->UnloadImage, ChildImageHandle); bailout: - if (FullLoadOptions != NULL) - FreePool(FullLoadOptions); + MyFreePool(FullLoadOptions); return ReturnStatus; } /* static EFI_STATUS StartEFIImageList() */ static EFI_STATUS StartEFIImage(IN EFI_DEVICE_PATH *DevicePath, IN CHAR16 *LoadOptions, IN CHAR16 *LoadOptionsPrefix, - IN CHAR16 *ImageTitle, + IN CHAR16 *ImageTitle, IN CHAR8 OSType, OUT UINTN *ErrorInStep, IN BOOLEAN Verbose) { @@ -247,7 +285,7 @@ static EFI_STATUS StartEFIImage(IN EFI_DEVICE_PATH *DevicePath, DevicePaths[0] = DevicePath; DevicePaths[1] = NULL; - return StartEFIImageList(DevicePaths, LoadOptions, LoadOptionsPrefix, ImageTitle, ErrorInStep, Verbose); + return StartEFIImageList(DevicePaths, LoadOptions, LoadOptionsPrefix, ImageTitle, OSType, ErrorInStep, Verbose); } /* static EFI_STATUS StartEFIImage() */ // @@ -259,8 +297,8 @@ 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), &ErrorInStep, !Entry->UseGraphicsMode); + StartEFIImage(Entry->DevicePath, Entry->LoadOptions, Basename(Entry->LoaderPath), + Basename(Entry->LoaderPath), Entry->OSType, &ErrorInStep, !Entry->UseGraphicsMode); FinishExternalScreen(); } @@ -308,14 +346,13 @@ static CHAR16 * FindInitrd(IN CHAR16 *LoaderPath, IN REFIT_VOLUME *Volume) { MergeStrings(&InitrdName, DirEntry->FileName, 0); } // if } // if/else - if (InitrdVersion != NULL) - FreePool(InitrdVersion); + MyFreePool(InitrdVersion); } // while DirIterClose(&DirIter); // Note: Don't FreePool(FileName), since Basename returns a pointer WITHIN the string it's passed. - FreePool(KernelVersion); - FreePool(Path); + MyFreePool(KernelVersion); + MyFreePool(Path); return (InitrdName); } // static CHAR16 * FindInitrd() @@ -334,8 +371,8 @@ static REFIT_MENU_SCREEN* CopyMenuScreen(REFIT_MENU_SCREEN *Entry) { NewEntry = AllocateZeroPool(sizeof(REFIT_MENU_SCREEN)); if ((Entry != NULL) && (NewEntry != NULL)) { CopyMem(NewEntry, Entry, sizeof(REFIT_MENU_SCREEN)); - NewEntry->Title = StrDuplicate(Entry->Title); - NewEntry->TimeoutText = StrDuplicate(Entry->TimeoutText); + NewEntry->Title = (Entry->Title) ? StrDuplicate(Entry->Title) : NULL; + NewEntry->TimeoutText = (Entry->TimeoutText) ? StrDuplicate(Entry->TimeoutText) : NULL; if (Entry->TitleImage != NULL) { NewEntry->TitleImage = AllocatePool(sizeof(EG_IMAGE)); if (NewEntry->TitleImage != NULL) @@ -343,7 +380,7 @@ static REFIT_MENU_SCREEN* CopyMenuScreen(REFIT_MENU_SCREEN *Entry) { } // if NewEntry->InfoLines = (CHAR16**) AllocateZeroPool(Entry->InfoLineCount * (sizeof(CHAR16*))); for (i = 0; i < Entry->InfoLineCount && NewEntry->InfoLines; i++) { - NewEntry->InfoLines[i] = StrDuplicate(Entry->InfoLines[i]); + NewEntry->InfoLines[i] = (Entry->InfoLines[i]) ? StrDuplicate(Entry->InfoLines[i]) : NULL; } // for NewEntry->Entries = (REFIT_MENU_ENTRY**) AllocateZeroPool(Entry->EntryCount * (sizeof (REFIT_MENU_ENTRY*))); for (i = 0; i < Entry->EntryCount && NewEntry->Entries; i++) { @@ -364,7 +401,7 @@ static REFIT_MENU_ENTRY* CopyMenuEntry(REFIT_MENU_ENTRY *Entry) { NewEntry = AllocateZeroPool(sizeof(REFIT_MENU_ENTRY)); if ((Entry != NULL) && (NewEntry != NULL)) { CopyMem(NewEntry, Entry, sizeof(REFIT_MENU_ENTRY)); - NewEntry->Title = StrDuplicate(Entry->Title); + NewEntry->Title = (Entry->Title) ? StrDuplicate(Entry->Title) : NULL; if (Entry->BadgeImage != NULL) { NewEntry->BadgeImage = AllocatePool(sizeof(EG_IMAGE)); if (NewEntry->BadgeImage != NULL) @@ -398,12 +435,12 @@ LOADER_ENTRY *InitializeLoaderEntry(IN LOADER_ENTRY *Entry) { NewEntry->UseGraphicsMode = FALSE; NewEntry->OSType = 0; if (Entry != NULL) { - NewEntry->LoaderPath = StrDuplicate(Entry->LoaderPath); - NewEntry->VolName = StrDuplicate(Entry->VolName); + NewEntry->LoaderPath = (Entry->LoaderPath) ? StrDuplicate(Entry->LoaderPath) : NULL; + NewEntry->VolName = (Entry->VolName) ? StrDuplicate(Entry->VolName) : NULL; NewEntry->DevicePath = Entry->DevicePath; NewEntry->UseGraphicsMode = Entry->UseGraphicsMode; - NewEntry->LoadOptions = StrDuplicate(Entry->LoadOptions); - NewEntry->InitrdPath = StrDuplicate(Entry->InitrdPath); + NewEntry->LoadOptions = (Entry->LoadOptions) ? StrDuplicate(Entry->LoadOptions) : NULL; + NewEntry->InitrdPath = (Entry->InitrdPath) ? StrDuplicate(Entry->InitrdPath) : NULL; } } // if return (NewEntry); @@ -437,7 +474,7 @@ REFIT_MENU_SCREEN *InitializeSubScreen(IN LOADER_ENTRY *Entry) { MergeStrings(&Temp, L"initrd=", 0); MergeStrings(&Temp, SubEntry->InitrdPath, 0); MergeStrings(&SubEntry->LoadOptions, Temp, L' '); - FreePool(Temp); + MyFreePool(Temp); } // if AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry); } // if (SubEntry != NULL) @@ -459,7 +496,7 @@ VOID GenerateSubScreen(LOADER_ENTRY *Entry, IN REFIT_VOLUME *Volume) { // create the submenu if (StrLen(Entry->Title) == 0) { - FreePool(Entry->Title); + MyFreePool(Entry->Title); Entry->Title = NULL; } SubScreen = InitializeSubScreen(Entry); @@ -526,7 +563,7 @@ VOID GenerateSubScreen(LOADER_ENTRY *Entry, IN REFIT_VOLUME *Volume) { SubEntry = InitializeLoaderEntry(Entry); if (SubEntry != NULL) { SubEntry->me.Title = L"Run Apple Hardware Test"; - FreePool(SubEntry->LoaderPath); + MyFreePool(SubEntry->LoaderPath); SubEntry->LoaderPath = StrDuplicate(DiagsFileName); SubEntry->DevicePath = FileDevicePath(Volume->DeviceHandle, SubEntry->LoaderPath); SubEntry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_OSX; @@ -546,19 +583,16 @@ VOID GenerateSubScreen(LOADER_ENTRY *Entry, IN REFIT_VOLUME *Volume) { while ((TokenCount = ReadTokenLine(File, &TokenList)) > 1) { SubEntry = InitializeLoaderEntry(Entry); SubEntry->me.Title = StrDuplicate(TokenList[0]); - if (SubEntry->LoadOptions != NULL) - FreePool(SubEntry->LoadOptions); + MyFreePool(SubEntry->LoadOptions); SubEntry->LoadOptions = StrDuplicate(TokenList[1]); MergeStrings(&SubEntry->LoadOptions, InitrdOption, L' '); FreeTokenLine(&TokenList, &TokenCount); SubEntry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_LINUX; AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry); } // while - if (InitrdOption) - FreePool(InitrdOption); - if (Temp) - FreePool(Temp); - FreePool(File); + MyFreePool(InitrdOption); + MyFreePool(Temp); + MyFreePool(File); } // if Linux options file exists } else if (Entry->OSType == 'E') { // entries for ELILO @@ -646,10 +680,8 @@ static CHAR16 * GetMainLinuxOptions(IN CHAR16 * LoaderPath, IN REFIT_VOLUME *Vol MergeStrings(&InitrdOption, InitrdName, 0); } // if MergeStrings(&Options, InitrdOption, ' '); - if (InitrdOption != NULL) - FreePool(InitrdOption); - if (InitrdName != NULL) - FreePool(InitrdName); + MyFreePool(InitrdOption); + MyFreePool(InitrdName); return (Options); } // static CHAR16 * GetMainLinuxOptions() @@ -675,7 +707,7 @@ VOID SetLoaderDefaults(LOADER_ENTRY *Entry, CHAR16 *LoaderPath, IN REFIT_VOLUME Temp = FindLastDirName(LoaderPath); MergeStrings(&OSIconName, Temp, L','); - FreePool(Temp); + MyFreePool(Temp); if (OSIconName != NULL) { ShortcutLetter = OSIconName[0]; } @@ -732,8 +764,7 @@ VOID SetLoaderDefaults(LOADER_ENTRY *Entry, CHAR16 *LoaderPath, IN REFIT_VOLUME Entry->me.ShortcutLetter = ShortcutLetter; if (Entry->me.Image == NULL) Entry->me.Image = LoadOSIcon(OSIconName, L"unknown", FALSE); - if (PathOnly != NULL) - FreePool(PathOnly); + MyFreePool(PathOnly); } // VOID SetLoaderDefaults() // Add a specified EFI boot loader to the list, using automatic settings @@ -817,8 +848,8 @@ static VOID CleanUpLoaderList(struct LOADER_LIST *LoaderList) { while (LoaderList != NULL) { Temp = LoaderList; LoaderList = LoaderList->NextEntry; - FreePool(Temp->FileName); - FreePool(Temp); + MyFreePool(Temp->FileName); + MyFreePool(Temp); } // while } // static VOID CleanUpLoaderList() @@ -858,7 +889,7 @@ static VOID ScanLoaderDir(IN REFIT_VOLUME *Volume, IN CHAR16 *Path, IN CHAR16 *P NewLoader->TimeStamp = DirEntry->ModificationTime; LoaderList = AddLoaderListEntry(LoaderList, NewLoader); } // if - FreePool(Extension); + MyFreePool(Extension); } // while NewLoader = LoaderList; while (NewLoader != NULL) { @@ -869,9 +900,9 @@ static VOID ScanLoaderDir(IN REFIT_VOLUME *Volume, IN CHAR16 *Path, IN CHAR16 *P Status = DirIterClose(&DirIter); if (Status != EFI_NOT_FOUND) { if (Path) - SPrint(FileName, 255, L"while scanning the %s directory", Path); + SPrint(FileName, 255, L"while scanning the %s directory", Path); else - StrCpy(FileName, L"while scanning the root directory"); + StrCpy(FileName, L"while scanning the root directory"); CheckError(Status, FileName); } // if (Status != EFI_NOT_FOUND) } // if not scanning our own directory @@ -884,28 +915,28 @@ static VOID ScanEfiFiles(REFIT_VOLUME *Volume) { CHAR16 FileName[256], *Directory, *MatchPatterns; UINTN i, Length; - MatchPatterns = StrDuplicate(LOADER_MATCH_PATTERNS); - if (GlobalConfig.ScanAllLinux) - MergeStrings(&MatchPatterns, LINUX_MATCH_PATTERNS, L','); + 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 - if (!IsIn(L"System\\Library\\CoreServices", GlobalConfig.DontScan)) { + if (!IsIn(L"\\System\\Library\\CoreServices", GlobalConfig.DontScan)) { StrCpy(FileName, MACOSX_LOADER_PATH); if (FileExists(Volume->RootDir, FileName)) { AddLoaderEntry(FileName, L"Mac OS X", Volume); } // 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); } } // if Mac directory not in GlobalConfig.DontScan list // 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.DontScan)) { + StrCpy(FileName, L"\\EFI\\Microsoft\\Boot\\Bootmgfw.efi"); + if (FileExists(Volume->RootDir, FileName) && !IsIn(L"\\EFI\\Microsoft\\Boot", GlobalConfig.DontScan)) { AddLoaderEntry(FileName, L"Microsoft EFI boot", Volume); } @@ -917,7 +948,7 @@ static VOID ScanEfiFiles(REFIT_VOLUME *Volume) { while (DirIterNext(&EfiDirIter, 1, NULL, &EfiDirEntry)) { 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); + SPrint(FileName, 255, L"\\EFI\\%s", EfiDirEntry->FileName); ScanLoaderDir(Volume, FileName, MatchPatterns); } // while() Status = DirIterClose(&EfiDirIter); @@ -931,7 +962,7 @@ static VOID ScanEfiFiles(REFIT_VOLUME *Volume) { Length = StrLen(Directory); if (Length > 0) ScanLoaderDir(Volume, Directory, MatchPatterns); - FreePool(Directory); + MyFreePool(Directory); } // while } // if } // static VOID ScanEfiFiles() @@ -1134,7 +1165,7 @@ static VOID StartLegacy(IN LEGACY_ENTRY *Entry) UINTN ErrorInStep = 0; EFI_DEVICE_PATH *DiscoveredPathList[MAX_DISCOVERED_PATHS]; - BeginExternalScreen(TRUE, L"Booting Legacy OS"); + BeginExternalScreen(TRUE, L"Booting Legacy OS (Mac mode)"); BootLogoImage = LoadOSIcon(Entry->Volume->OSIconName, L"legacy", TRUE); if (BootLogoImage != NULL) @@ -1149,7 +1180,7 @@ static VOID StartLegacy(IN LEGACY_ENTRY *Entry) ExtractLegacyLoaderPaths(DiscoveredPathList, MAX_DISCOVERED_PATHS, LegacyLoaderList); - Status = StartEFIImageList(DiscoveredPathList, Entry->LoadOptions, NULL, L"legacy loader", &ErrorInStep, TRUE); + Status = StartEFIImageList(DiscoveredPathList, Entry->LoadOptions, NULL, L"legacy loader", 0, &ErrorInStep, TRUE); if (Status == EFI_NOT_FOUND) { if (ErrorInStep == 1) { Print(L"\nPlease make sure that you have the latest firmware update installed.\n"); @@ -1163,11 +1194,18 @@ static VOID StartLegacy(IN LEGACY_ENTRY *Entry) // Start a device on a non-Mac using the EFI_LEGACY_BIOS_PROTOCOL #ifdef __MAKEWITH_TIANO -static VOID StartLegacyNonMac(IN LEGACY_ENTRY *Entry) +static VOID StartLegacyUEFI(IN LEGACY_ENTRY *Entry) { + BeginExternalScreen(TRUE, L"Booting Legacy OS (UEFI mode)"); + BdsLibConnectDevicePath (Entry->BdsOption->DevicePath); BdsLibDoLegacyBoot(Entry->BdsOption); -} + + // If we get here, it means that there was a failure.... + Print(L"Failure booting legacy (BIOS) OS."); + PauseForKey(); + FinishExternalScreen(); +} // static VOID StartLegacyUEFI() #endif // __MAKEWITH_TIANO static LEGACY_ENTRY * AddLegacyEntry(IN CHAR16 *LoaderTitle, IN REFIT_VOLUME *Volume) @@ -1227,28 +1265,49 @@ static LEGACY_ENTRY * AddLegacyEntry(IN CHAR16 *LoaderTitle, IN REFIT_VOLUME *Vo #ifdef __MAKEWITH_TIANO +// default volume badge icon based on disk kind +static EG_IMAGE * GetDiskBadge(IN UINTN DiskType) { + EG_IMAGE * Badge = NULL; + + switch (DiskType) { + case BBS_HARDDISK: + Badge = BuiltinIcon(BUILTIN_ICON_VOL_INTERNAL); + break; + case BBS_USB: + Badge = BuiltinIcon(BUILTIN_ICON_VOL_EXTERNAL); + break; + case BBS_CDROM: + Badge = BuiltinIcon(BUILTIN_ICON_VOL_OPTICAL); + break; + } // switch() + return Badge; +} // static EG_IMAGE * GetDiskBadge() + /** Create a rEFInd boot option from a Legacy BIOS protocol option. */ -static LEGACY_ENTRY * AddLegacyEntryNonMac(BDS_COMMON_OPTION *BdsOption, IN UINT16 DiskType) +static LEGACY_ENTRY * AddLegacyEntryUEFI(BDS_COMMON_OPTION *BdsOption, IN UINT16 DiskType) { LEGACY_ENTRY *Entry, *SubEntry; REFIT_MENU_SCREEN *SubScreen; 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)); SPrint(Entry->me.Title, 255, L"Boot legacy target %s", LegacyDescription); - Entry->me.Tag = TAG_LEGACY_NON_MAC; + Entry->me.Tag = TAG_LEGACY_UEFI; Entry->me.Row = 0; Entry->me.ShortcutLetter = ShortcutLetter; Entry->me.Image = LoadOSIcon(L"legacy", L"legacy", TRUE); Entry->LoadOptions = (DiskType == BBS_CDROM) ? L"CD" : ((DiskType == BBS_USB) ? L"USB" : L"HD"); - Entry->me.BadgeImage = NULL; - Entry->BdsOption = BdsOption; + Entry->me.BadgeImage = GetDiskBadge(DiskType); +// Entry->me.BadgeImage = Volume->VolBadgeImage; + Entry->BdsOption = BdsOption; Entry->Enabled = TRUE; // create the submenu @@ -1261,7 +1320,7 @@ static LEGACY_ENTRY * AddLegacyEntryNonMac(BDS_COMMON_OPTION *BdsOption, IN UINT SubEntry = AllocateZeroPool(sizeof(LEGACY_ENTRY)); SubEntry->me.Title = AllocateZeroPool(256 * sizeof(CHAR16)); SPrint(SubEntry->me.Title, 255, L"Boot %s", LegacyDescription); - SubEntry->me.Tag = TAG_LEGACY_NON_MAC; + SubEntry->me.Tag = TAG_LEGACY_UEFI; Entry->BdsOption = BdsOption; AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry); @@ -1269,39 +1328,39 @@ static LEGACY_ENTRY * AddLegacyEntryNonMac(BDS_COMMON_OPTION *BdsOption, IN UINT Entry->me.SubScreen = SubScreen; AddMenuEntry(&MainMenu, (REFIT_MENU_ENTRY *)Entry); return Entry; -} /* static LEGACY_ENTRY * AddLegacyEntryNonMac() */ +} /* static LEGACY_ENTRY * AddLegacyEntryUEFI() */ /** Scan for legacy BIOS targets on machines that implement EFI_LEGACY_BIOS_PROTOCOL. In testing, protocol has not been implemented on Macs but has been - implemented on several Dell PCs. + implemented on several Dell PCs and an ASUS motherboard. + Restricts output to disks of the specified DiskType. */ -static VOID ScanLegacyNonMac() +static VOID ScanLegacyUEFI(IN UINTN DiskType) { EFI_STATUS Status; EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; - EFI_GUID EfiLegacyBootProtocolGuid = { 0xdb9a1e3d, 0x45cb, 0x4abb, { 0x85, 0x3b, 0xe5, 0x38, 0x7f, 0xdb, 0x2e, 0x2d }}; - EFI_GUID EfiGlobalVariableGuid = { 0x8BE4DF61, 0x93CA, 0x11D2, { 0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C }}; UINT16 *BootOrder = NULL; UINTN Index = 0; - UINT16 BootOption[10]; + CHAR16 BootOption[10]; UINTN BootOrderSize = 0; CHAR16 Buffer[20]; BDS_COMMON_OPTION *BdsOption; LIST_ENTRY TempList; BBS_BBS_DEVICE_PATH * BbsDevicePath = NULL; +// REFIT_VOLUME Volume; InitializeListHead (&TempList); ZeroMem (Buffer, sizeof (Buffer)); // If LegacyBios protocol is not implemented on this platform, then //we do not support this type of legacy boot on this machine. - Status = gBS->LocateProtocol (&EfiLegacyBootProtocolGuid, NULL, (VOID **) &LegacyBios); + Status = gBS->LocateProtocol(&gEfiLegacyBootProtocolGuid, NULL, (VOID **) &LegacyBios); if (EFI_ERROR (Status)) return; // Grab the boot order - BootOrder = BdsLibGetVariableAndSize (L"BootOrder", &EfiGlobalVariableGuid, &BootOrderSize); + BootOrder = BdsLibGetVariableAndSize(L"BootOrder", &gEfiGlobalVariableGuid, &BootOrderSize); if (BootOrder == NULL) { BootOrderSize = 0; } @@ -1314,21 +1373,23 @@ static VOID ScanLegacyNonMac() UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]); BdsOption = BdsLibVariableToOption (&TempList, BootOption); - //Print(L"Option description = '%s'\n", BdsOption->Description); - BbsDevicePath = (BBS_BBS_DEVICE_PATH *)BdsOption->DevicePath; + if (BdsOption != NULL) { + BbsDevicePath = (BBS_BBS_DEVICE_PATH *)BdsOption->DevicePath; - // Only add the entry if it is of a supported type (e.g. USB, HD) - // See BdsHelper.c for currently supported types - if(IsBbsDeviceTypeSupported(BbsDevicePath->DeviceType)) - { - // TODO: Find/build REFIT_VOLUME structure for volume and pass instead of NULL - AddLegacyEntryNonMac(BdsOption, BbsDevicePath->DeviceType); + // Only add the entry if it is of a requested type (e.g. USB, HD) + + // Two checks necessary because some systems return EFI boot loaders + // with a DeviceType value that would inappropriately include them + // as legacy loaders.... + if ((BbsDevicePath->DeviceType == DiskType) && (BdsOption->DevicePath->Type == DEVICE_TYPE_BIOS)) { + AddLegacyEntryUEFI(BdsOption, BbsDevicePath->DeviceType); + } } Index++; } -} /* static VOID ScanLegacyNonMac() */ +} /* static VOID ScanLegacyUEFI() */ #else -static VOID ScanLegacyNonMac(){} +static VOID ScanLegacyUEFI(IN UINTN DiskType){} #endif // __MAKEWITH_TIANO static VOID ScanLegacyVolume(REFIT_VOLUME *Volume, UINTN VolumeIndex) { @@ -1368,11 +1429,15 @@ static VOID ScanLegacyDisc(VOID) UINTN VolumeIndex; REFIT_VOLUME *Volume; - for (VolumeIndex = 0; VolumeIndex < VolumesCount; VolumeIndex++) { - Volume = Volumes[VolumeIndex]; - if (Volume->DiskKind == DISK_KIND_OPTICAL) - ScanLegacyVolume(Volume, VolumeIndex); - } // for + if (GlobalConfig.LegacyType == LEGACY_TYPE_MAC) { + for (VolumeIndex = 0; VolumeIndex < VolumesCount; VolumeIndex++) { + Volume = Volumes[VolumeIndex]; + if (Volume->DiskKind == DISK_KIND_OPTICAL) + ScanLegacyVolume(Volume, VolumeIndex); + } // for + } else if (GlobalConfig.LegacyType == LEGACY_TYPE_UEFI) { + ScanLegacyUEFI(BBS_CDROM); + } } /* static VOID ScanLegacyDisc() */ // Scan internal hard disks for legacy (BIOS) boot code @@ -1382,11 +1447,15 @@ static VOID ScanLegacyInternal(VOID) UINTN VolumeIndex; REFIT_VOLUME *Volume; - for (VolumeIndex = 0; VolumeIndex < VolumesCount; VolumeIndex++) { - Volume = Volumes[VolumeIndex]; - if (Volume->DiskKind == DISK_KIND_INTERNAL) - ScanLegacyVolume(Volume, VolumeIndex); - } // for + if (GlobalConfig.LegacyType == LEGACY_TYPE_MAC) { + for (VolumeIndex = 0; VolumeIndex < VolumesCount; VolumeIndex++) { + Volume = Volumes[VolumeIndex]; + if (Volume->DiskKind == DISK_KIND_INTERNAL) + ScanLegacyVolume(Volume, VolumeIndex); + } // for + } else if (GlobalConfig.LegacyType == LEGACY_TYPE_UEFI) { + ScanLegacyUEFI(BBS_HARDDISK); + } } /* static VOID ScanLegacyInternal() */ // Scan external disks for legacy (BIOS) boot code @@ -1396,11 +1465,15 @@ static VOID ScanLegacyExternal(VOID) UINTN VolumeIndex; REFIT_VOLUME *Volume; - for (VolumeIndex = 0; VolumeIndex < VolumesCount; VolumeIndex++) { - Volume = Volumes[VolumeIndex]; - if (Volume->DiskKind == DISK_KIND_EXTERNAL) - ScanLegacyVolume(Volume, VolumeIndex); - } // for + if (GlobalConfig.LegacyType == LEGACY_TYPE_MAC) { + for (VolumeIndex = 0; VolumeIndex < VolumesCount; VolumeIndex++) { + Volume = Volumes[VolumeIndex]; + if (Volume->DiskKind == DISK_KIND_EXTERNAL) + ScanLegacyVolume(Volume, VolumeIndex); + } // for + } else if (GlobalConfig.LegacyType == LEGACY_TYPE_UEFI) { + ScanLegacyUEFI(BBS_USB); + } } /* static VOID ScanLegacyExternal() */ // @@ -1411,11 +1484,11 @@ static VOID StartTool(IN LOADER_ENTRY *Entry) { BeginExternalScreen(Entry->UseGraphicsMode, Entry->me.Title + 6); // assumes "Start " as assigned below StartEFIImage(Entry->DevicePath, Entry->LoadOptions, Basename(Entry->LoaderPath), - Basename(Entry->LoaderPath), NULL, TRUE); + Basename(Entry->LoaderPath), Entry->OSType, NULL, TRUE); FinishExternalScreen(); } /* static VOID StartTool() */ -static LOADER_ENTRY * AddToolEntry(IN CHAR16 *LoaderPath, IN CHAR16 *LoaderTitle, IN EG_IMAGE *Image, +static LOADER_ENTRY * AddToolEntry(EFI_HANDLE DeviceHandle, IN CHAR16 *LoaderPath, IN CHAR16 *LoaderTitle, IN EG_IMAGE *Image, IN CHAR16 ShortcutLetter, IN BOOLEAN UseGraphicsMode) { LOADER_ENTRY *Entry; @@ -1430,8 +1503,8 @@ static LOADER_ENTRY * AddToolEntry(IN CHAR16 *LoaderPath, IN CHAR16 *LoaderTitle Entry->me.Row = 1; Entry->me.ShortcutLetter = ShortcutLetter; Entry->me.Image = Image; - Entry->LoaderPath = StrDuplicate(LoaderPath); - Entry->DevicePath = FileDevicePath(SelfLoadedImage->DeviceHandle, Entry->LoaderPath); + Entry->LoaderPath = (LoaderPath) ? StrDuplicate(LoaderPath) : NULL; + Entry->DevicePath = FileDevicePath(DeviceHandle, Entry->LoaderPath); Entry->UseGraphicsMode = UseGraphicsMode; AddMenuEntry(&MainMenu, (REFIT_MENU_ENTRY *)Entry); @@ -1460,7 +1533,7 @@ static UINTN ScanDriverDir(IN CHAR16 *Path) SPrint(FileName, 255, L"%s\\%s", Path, DirEntry->FileName); NumFound++; Status = StartEFIImage(FileDevicePath(SelfLoadedImage->DeviceHandle, FileName), - L"", DirEntry->FileName, DirEntry->FileName, NULL, FALSE); + L"", DirEntry->FileName, DirEntry->FileName, 0, NULL, FALSE); } Status = DirIterClose(&DirIter); if (Status != EFI_NOT_FOUND) { @@ -1530,12 +1603,12 @@ static EFI_STATUS ConnectAllDriversToAllControllers(VOID) } } - FreePool (HandleBuffer); - FreePool (HandleType); + MyFreePool (HandleBuffer); + MyFreePool (HandleType); } Done: - FreePool (AllHandleBuffer); + MyFreePool (AllHandleBuffer); return Status; } /* EFI_STATUS ConnectAllDriversToAllControllers() */ #else @@ -1556,12 +1629,12 @@ static VOID LoadDrivers(VOID) // load drivers from the subdirectories of rEFInd's home directory specified // in the DRIVER_DIRS constant. while ((Directory = FindCommaDelimited(DRIVER_DIRS, i++)) != NULL) { - SelfDirectory = StrDuplicate(SelfDirPath); + SelfDirectory = SelfDirPath ? StrDuplicate(SelfDirPath) : NULL; CleanUpPathNameSlashes(SelfDirectory); MergeStrings(&SelfDirectory, Directory, L'\\'); NumFound += ScanDriverDir(SelfDirectory); - FreePool(Directory); - FreePool(SelfDirectory); + MyFreePool(Directory); + MyFreePool(SelfDirectory); } // Scan additional user-specified driver directories.... @@ -1569,9 +1642,10 @@ static VOID LoadDrivers(VOID) while ((Directory = FindCommaDelimited(GlobalConfig.DriverDirs, i++)) != NULL) { CleanUpPathNameSlashes(Directory); Length = StrLen(Directory); - if (Length > 0) + if (Length > 0) { NumFound += ScanDriverDir(Directory); - FreePool(Directory); + } // if + MyFreePool(Directory); } // while // connect all devices @@ -1579,9 +1653,64 @@ static VOID LoadDrivers(VOID) ConnectAllDriversToAllControllers(); } /* static VOID LoadDrivers() */ +// Determine what (if any) type of legacy (BIOS) boot support is available +static VOID FindLegacyBootType(VOID) { +#ifdef __MAKEWITH_TIANO + EFI_STATUS Status; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; +#endif + + 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.... +#ifdef __MAKEWITH_TIANO + Status = gBS->LocateProtocol (&gEfiLegacyBootProtocolGuid, NULL, (VOID **) &LegacyBios); + if (!EFI_ERROR (Status)) + GlobalConfig.LegacyType = LEGACY_TYPE_UEFI; +#endif + + // Macs have their own system. If the firmware vendor code contains the + // string "Apple", assume it's available. Note that this overrides the + // UEFI type, and might yield false positives if the vendor string + // contains "Apple" as part of something bigger, so this isn't 100% + // perfect. + if (StriSubCmp(L"Apple", ST->FirmwareVendor)) + GlobalConfig.LegacyType = LEGACY_TYPE_MAC; +} // static VOID FindLegacyBootType + +// Warn the user if legacy OS scans are enabled but the firmware or this +// application can't support them.... +static VOID WarnIfLegacyProblems() { + BOOLEAN found = FALSE; + UINTN i = 0; + + if (GlobalConfig.LegacyType == LEGACY_TYPE_NONE) { + do { + if (GlobalConfig.ScanFor[i] == 'h' || GlobalConfig.ScanFor[i] == 'b' || GlobalConfig.ScanFor[i] == 'c') + found = TRUE; + i++; + } while ((i < NUM_SCAN_OPTIONS) && (!found)); + if (found) { + Print(L"NOTE: refind.conf's 'scanfor' line specifies scanning for one or more legacy\n"); + Print(L"(BIOS) boot options; however, this is not possible because "); +#ifdef __MAKEWITH_TIANO + Print(L"your computer lacks\n"); + Print(L"the necessary Compatibility Support Module (CSM) support.\n"); +#else + Print(L"this program was\n"); + Print(L"compiled without the necessary support. Please visit\n"); + Print(L"http://www.rodsbooks.com/refind/getting.html and download and install a rEFInd\n"); + Print(L"binary built with the TianoCore EDK2 to enable legacy boot support.\n"); +#endif + PauseForKey(); + } // if (found) + } // if no legacy support +} // static VOID WarnIfLegacyProblems() +// Locates boot loaders. NOTE: This assumes that GlobalConfig.LegacyType is set correctly. static VOID ScanForBootloaders(VOID) { - UINTN i; + UINTN i; ScanVolumes(); @@ -1609,9 +1738,6 @@ static VOID ScanForBootloaders(VOID) { case 'o': case 'O': ScanOptical(); break; - case 'l': case 'L': - ScanLegacyNonMac(); - break; } // switch() } // for @@ -1626,9 +1752,9 @@ static VOID ScanForBootloaders(VOID) { // Add the second-row tags containing built-in and external tools (EFI shell, // reboot, etc.) static VOID ScanForTools(VOID) { - CHAR16 *FileName = NULL; + CHAR16 *FileName = NULL, Description[256]; REFIT_MENU_ENTRY *TempMenuEntry; - UINTN i, j; + UINTN i, j, VolumeIndex; for (i = 0; i < NUM_TOOLS; i++) { switch(GlobalConfig.ShowTools[i]) { @@ -1654,23 +1780,56 @@ static VOID ScanForTools(VOID) { break; case TAG_SHELL: j = 0; + MyFreePool(FileName); while ((FileName = FindCommaDelimited(SHELL_NAMES, j++)) != NULL) { if (FileExists(SelfRootDir, FileName)) { - AddToolEntry(FileName, L"EFI Shell", BuiltinIcon(BUILTIN_ICON_TOOL_SHELL), 'S', FALSE); + AddToolEntry(SelfLoadedImage->DeviceHandle, FileName, L"EFI Shell", BuiltinIcon(BUILTIN_ICON_TOOL_SHELL), + 'S', FALSE); } } // while break; case TAG_GPTSYNC: + MyFreePool(FileName); + FileName = NULL; 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); + AddToolEntry(SelfLoadedImage->DeviceHandle, FileName, L"Make Hybrid MBR", BuiltinIcon(BUILTIN_ICON_TOOL_PART), 'P', FALSE); + } + break; + case TAG_APPLE_RECOVERY: + MyFreePool(FileName); + FileName = NULL; + MergeStrings(&FileName, L"\\com.apple.recovery.boot\\boot.efi", 0); + for (VolumeIndex = 0; VolumeIndex < VolumesCount; VolumeIndex++) { + if ((Volumes[VolumeIndex]->RootDir != NULL) && (FileExists(Volumes[VolumeIndex]->RootDir, FileName))) { + SPrint(Description, 255, L"Apple Recovery on %s", Volumes[VolumeIndex]->VolName); + AddToolEntry(Volumes[VolumeIndex]->DeviceHandle, FileName, Description, + BuiltinIcon(BUILTIN_ICON_TOOL_APPLE_RESCUE), 'R', TRUE); + } + } // for + 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")) { + MyFreePool(FileName); + FileName = StrDuplicate(SelfDirPath); + 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); } break; } // switch() - if (FileName != NULL) { - FreePool(FileName); - FileName = NULL; - } + MyFreePool(FileName); + FileName = NULL; } // for } // static VOID ScanForTools @@ -1688,6 +1847,7 @@ VOID RescanAll(VOID) { MainMenu.EntryCount = 0; ReadConfig(); ConnectAllDriversToAllControllers(); + ScanVolumes(); ScanForBootloaders(); ScanForTools(); SetupScreen(); @@ -1719,8 +1879,9 @@ efi_main (IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable) EFI_STATUS Status; BOOLEAN MainLoopRunning = TRUE; REFIT_MENU_ENTRY *ChosenEntry; - UINTN MenuExit; + UINTN MenuExit, i; CHAR16 *Selection; + EG_PIXEL BGColor; // bootstrap InitializeLib(ImageHandle, SystemTable); @@ -1730,8 +1891,12 @@ efi_main (IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable) return Status; // read configuration - CopyMem(GlobalConfig.ScanFor, "ieo ", NUM_SCAN_OPTIONS); + CopyMem(GlobalConfig.ScanFor, "ieom ", NUM_SCAN_OPTIONS); + FindLegacyBootType(); + if (GlobalConfig.LegacyType == LEGACY_TYPE_MAC) + CopyMem(GlobalConfig.ScanFor, "ihebocm ", NUM_SCAN_OPTIONS); ReadConfig(); + WarnIfLegacyProblems(); MainMenu.TimeoutSeconds = GlobalConfig.Timeout; // disable EFI watchdog timer @@ -1739,10 +1904,22 @@ efi_main (IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable) // further bootstrap (now with config available) SetupScreen(); + ScanVolumes(); LoadDrivers(); ScanForBootloaders(); ScanForTools(); + if (GlobalConfig.ScanDelay > 0) { + BGColor.b = 255; + BGColor.g = 175; + BGColor.r = 100; + BGColor.a = 0; + egDisplayMessage(L"Pausing before disk scan; please wait....", &BGColor); + for (i = 0; i < GlobalConfig.ScanDelay; i++) + refit_call1_wrapper(BS->Stall, 1000000); + RescanAll(); + } // if + Selection = StrDuplicate(GlobalConfig.DefaultSelection); while (MainLoopRunning) { MenuExit = RunMainMenu(&MainMenu, Selection, &ChosenEntry); @@ -1780,8 +1957,8 @@ efi_main (IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable) break; #ifdef __MAKEWITH_TIANO - case TAG_LEGACY_NON_MAC: // Boot a legacy OS on a non-Mac - StartLegacyNonMac((LEGACY_ENTRY *)ChosenEntry); + case TAG_LEGACY_UEFI: // Boot a legacy OS on a non-Mac + StartLegacyUEFI((LEGACY_ENTRY *)ChosenEntry); break; #endif // __MAKEWITH_TIANO @@ -1795,8 +1972,8 @@ efi_main (IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable) break; } // switch() - FreePool(Selection); - Selection = StrDuplicate(ChosenEntry->Title); + MyFreePool(Selection); + Selection = (ChosenEntry->Title) ? StrDuplicate(ChosenEntry->Title) : NULL; } // while() // If we end up here, things have gone wrong. Try to reboot, and if that