X-Git-Url: https://code.delx.au/refind/blobdiff_plain/7b006609c81e23ca1c7597776b7ea485932bbe0c..87bc9afcef9d2fc27b8bcff46fa9c88e8962fcae:/refind/main.c diff --git a/refind/main.c b/refind/main.c index 18816e2..ea8c337 100644 --- a/refind/main.c +++ b/refind/main.c @@ -61,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" @@ -96,8 +96,8 @@ 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, LEGACY_TYPE_MAC, 0, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +REFIT_CONFIG GlobalConfig = { FALSE, FALSE, 0, 0, 0, 20, 0, 0, GRAPHICS_FOR_OSX, LEGACY_TYPE_MAC, 0, + NULL, NULL, 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 @@ -118,7 +118,7 @@ static VOID AboutrEFInd(VOID) if (AboutMenu.EntryCount == 0) { AboutMenu.TitleImage = BuiltinIcon(BUILTIN_ICON_FUNC_ABOUT); - AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.5.0"); + AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.6.0.1"); AddMenuInfoLine(&AboutMenu, L""); AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2006-2010 Christoph Pfisterer"); AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2012 Roderick W. Smith"); @@ -186,7 +186,7 @@ static EFI_STATUS StartEFIImageList(IN EFI_DEVICE_PATH **DevicePaths, // set load options if (LoadOptions != NULL) { if (LoadOptionsPrefix != NULL) { - MergeStrings(&FullLoadOptions, LoadOptionsPrefix, 0); +// MergeStrings(&FullLoadOptions, LoadOptionsPrefix, 0); MergeStrings(&FullLoadOptions, LoadOptions, L' '); if (OSType == 'M') { MergeStrings(&FullLoadOptions, L" ", 0); @@ -196,8 +196,12 @@ static EFI_STATUS StartEFIImageList(IN EFI_DEVICE_PATH **DevicePaths, } else { MergeStrings(&FullLoadOptions, LoadOptions, 0); } // if/else - // NOTE: We also include the terminating null in the length for safety. - } // if (LoadOptions != NULL) + } else { // LoadOptions == NULL + // NOTE: We provide a non-null string when no options are specified for safety; + // some systems (at least DUET) can hang when launching some programs (such as + // an EFI shell) without this. + FullLoadOptions = StrDuplicate(L" "); + } if (Verbose) Print(L"Starting %s\nUsing load options '%s'\n", ImageTitle, FullLoadOptions); @@ -451,6 +455,23 @@ LOADER_ENTRY *InitializeLoaderEntry(IN LOADER_ENTRY *Entry) { return (NewEntry); } // LOADER_ENTRY *InitializeLoaderEntry() +// Adds InitrdPath to Options, but only if Options doesn't already include an +// initrd= line. Done to enable overriding the default initrd selection in a +// refind_linux.conf file's options list. +// Returns a pointer to a new string. The calling function is responsible for +// freeing its memory. +static CHAR16 *AddInitrdToOptions(CHAR16 *Options, CHAR16 *InitrdPath) { + CHAR16 *NewOptions = NULL; + + if (Options != NULL) + NewOptions = StrDuplicate(Options); + if ((InitrdPath != NULL) && !StriSubCmp(L"initrd=", Options)) { + MergeStrings(&NewOptions, L"initrd=", L' '); + MergeStrings(&NewOptions, InitrdPath, 0); + } + return NewOptions; +} // CHAR16 *AddInitrdToOptions() + // Prepare a REFIT_MENU_SCREEN data structure for a subscreen entry. This sets up // the default entry that launches the boot loader using the same options as the // main Entry does. Subsequent options can be added by the calling function. @@ -459,7 +480,7 @@ LOADER_ENTRY *InitializeLoaderEntry(IN LOADER_ENTRY *Entry) { // Returns a pointer to the new subscreen data structure, or NULL if there // were problems allocating memory. REFIT_MENU_SCREEN *InitializeSubScreen(IN LOADER_ENTRY *Entry) { - CHAR16 *FileName, *Temp = NULL; + CHAR16 *FileName, *MainOptions = NULL; REFIT_MENU_SCREEN *SubScreen = NULL; LOADER_ENTRY *SubEntry; @@ -474,13 +495,10 @@ REFIT_MENU_SCREEN *InitializeSubScreen(IN LOADER_ENTRY *Entry) { // default entry SubEntry = InitializeLoaderEntry(Entry); if (SubEntry != NULL) { - SubEntry->me.Title = L"Boot using default options"; - if ((SubEntry->InitrdPath != NULL) && (StrLen(SubEntry->InitrdPath) > 0) && (!StriSubCmp(L"initrd", SubEntry->LoadOptions))) { - MergeStrings(&Temp, L"initrd=", 0); - MergeStrings(&Temp, SubEntry->InitrdPath, 0); - MergeStrings(&SubEntry->LoadOptions, Temp, L' '); - MyFreePool(Temp); - } // if + SubEntry->me.Title = StrDuplicate(L"Boot using default options"); + MainOptions = SubEntry->LoadOptions; + SubEntry->LoadOptions = AddInitrdToOptions(MainOptions, SubEntry->InitrdPath); + MyFreePool(MainOptions); AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry); } // if (SubEntry != NULL) } // if (SubScreen != NULL) @@ -493,7 +511,7 @@ REFIT_MENU_SCREEN *InitializeSubScreen(IN LOADER_ENTRY *Entry) { VOID GenerateSubScreen(LOADER_ENTRY *Entry, IN REFIT_VOLUME *Volume) { REFIT_MENU_SCREEN *SubScreen; LOADER_ENTRY *SubEntry; - CHAR16 *InitrdOption = NULL, *Temp; + CHAR16 *InitrdName; CHAR16 DiagsFileName[256]; REFIT_FILE *File; UINTN TokenCount; @@ -563,7 +581,7 @@ VOID GenerateSubScreen(LOADER_ENTRY *Entry, IN REFIT_VOLUME *Volume) { } // not single-user // check for Apple hardware diagnostics - StrCpy(DiagsFileName, L"\\System\\Library\\CoreServices\\.diagnostics\\diags.efi"); + StrCpy(DiagsFileName, L"System\\Library\\CoreServices\\.diagnostics\\diags.efi"); if (FileExists(Volume->RootDir, DiagsFileName) && !(GlobalConfig.HideUIFlags & HIDEUI_FLAG_HWTEST)) { SubEntry = InitializeLoaderEntry(Entry); if (SubEntry != NULL) { @@ -579,24 +597,26 @@ VOID GenerateSubScreen(LOADER_ENTRY *Entry, IN REFIT_VOLUME *Volume) { } else if (Entry->OSType == 'L') { // entries for Linux kernels with EFI stub loaders File = ReadLinuxOptionsFile(Entry->LoaderPath, Volume); if (File != NULL) { - if ((Temp = FindInitrd(Entry->LoaderPath, Volume)) != NULL) { - MergeStrings(&InitrdOption, L"initrd=", 0); - MergeStrings(&InitrdOption, Temp, 0); - } - TokenCount = ReadTokenLine(File, &TokenList); // read and discard first entry, since it's - FreeTokenLine(&TokenList, &TokenCount); // set up by InitializeSubScreen(), earlier.... + InitrdName = FindInitrd(Entry->LoaderPath, Volume); + TokenCount = ReadTokenLine(File, &TokenList); + // first entry requires special processing, since it was initially set + // up with a default title but correct options by InitializeSubScreen(), + // earlier.... + if ((SubScreen->Entries != NULL) && (SubScreen->Entries[0] != NULL)) { + MyFreePool(SubScreen->Entries[0]->Title); + SubScreen->Entries[0]->Title = StrDuplicate(TokenList[0]); + } // if + FreeTokenLine(&TokenList, &TokenCount); while ((TokenCount = ReadTokenLine(File, &TokenList)) > 1) { SubEntry = InitializeLoaderEntry(Entry); SubEntry->me.Title = StrDuplicate(TokenList[0]); MyFreePool(SubEntry->LoadOptions); - SubEntry->LoadOptions = StrDuplicate(TokenList[1]); - MergeStrings(&SubEntry->LoadOptions, InitrdOption, L' '); + SubEntry->LoadOptions = AddInitrdToOptions(TokenList[1], InitrdName); FreeTokenLine(&TokenList, &TokenCount); SubEntry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_LINUX; AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry); } // while - MyFreePool(InitrdOption); - MyFreePool(Temp); + MyFreePool(InitrdName); MyFreePool(File); } // if Linux options file exists @@ -676,18 +696,15 @@ VOID GenerateSubScreen(LOADER_ENTRY *Entry, IN REFIT_VOLUME *Volume) { // kernel's directory; and if present, adds an initrd= option for an initial // RAM disk file with the same version number as the kernel file. static CHAR16 * GetMainLinuxOptions(IN CHAR16 * LoaderPath, IN REFIT_VOLUME *Volume) { - CHAR16 *Options = NULL, *InitrdName, *InitrdOption = NULL; + CHAR16 *Options = NULL, *InitrdName, *FullOptions = NULL; Options = GetFirstOptionsFromFile(LoaderPath, Volume); InitrdName = FindInitrd(LoaderPath, Volume); - if (InitrdName != NULL) { - MergeStrings(&InitrdOption, L"initrd=", 0); - MergeStrings(&InitrdOption, InitrdName, 0); - } // if - MergeStrings(&Options, InitrdOption, ' '); - MyFreePool(InitrdOption); + FullOptions = AddInitrdToOptions(Options, InitrdName); + + MyFreePool(Options); MyFreePool(InitrdName); - return (Options); + return (FullOptions); } // static CHAR16 * GetMainLinuxOptions() // Sets a few defaults for a loader entry -- mainly the icon, but also the OS type @@ -713,6 +730,7 @@ VOID SetLoaderDefaults(LOADER_ENTRY *Entry, CHAR16 *LoaderPath, IN REFIT_VOLUME Temp = FindLastDirName(LoaderPath); MergeStrings(&OSIconName, Temp, L','); MyFreePool(Temp); + Temp = NULL; if (OSIconName != NULL) { ShortcutLetter = OSIconName[0]; } @@ -739,7 +757,7 @@ VOID SetLoaderDefaults(LOADER_ENTRY *Entry, CHAR16 *LoaderPath, IN REFIT_VOLUME Entry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_OSX; } else if (StriCmp(FileName, L"diags.efi") == 0) { MergeStrings(&OSIconName, L"hwtest", L','); - } else if (StriCmp(FileName, L"e.efi") == 0 || StriCmp(FileName, L"elilo.efi") == 0) { + } else if (StriCmp(FileName, L"e.efi") == 0 || StriCmp(FileName, L"elilo.efi") == 0 || StriSubCmp(L"elilo", FileName)) { MergeStrings(&OSIconName, L"elilo,linux", L','); Entry->OSType = 'E'; if (ShortcutLetter == 0) @@ -809,8 +827,7 @@ INTN TimeComp(EFI_TIME *Time1, EFI_TIME *Time2) { INT64 Time1InSeconds, Time2InSeconds; // Following values are overestimates; I'm assuming 31 days in every month. - // This is fine for the purpose of this function, which has a limited - // purpose. + // This is fine for the purpose of this function, which is limited Time1InSeconds = Time1->Second + (Time1->Minute * 60) + (Time1->Hour * 3600) + (Time1->Day * 86400) + (Time1->Month * 2678400) + ((Time1->Year - 1998) * 32140800); Time2InSeconds = Time2->Second + (Time2->Minute * 60) + (Time2->Hour * 3600) + (Time2->Day * 86400) + @@ -869,8 +886,10 @@ static VOID ScanLoaderDir(IN REFIT_VOLUME *Volume, IN CHAR16 *Path, IN CHAR16 *P CHAR16 FileName[256], *Extension; struct LOADER_LIST *LoaderList = NULL, *NewLoader; - if ((!SelfDirPath || !Path || ((StriCmp(Path, SelfDirPath) == 0) && Volume->DeviceHandle != SelfVolume->DeviceHandle) || - (StriCmp(Path, SelfDirPath) != 0)) && (!IsIn(Path, GlobalConfig.DontScanDirs))) { + if ((!SelfDirPath || !Path || ((StriCmp(Path, SelfDirPath) == 0) && (Volume->DeviceHandle != SelfVolume->DeviceHandle)) || + (StriCmp(Path, SelfDirPath) != 0)) && + (!IsIn(Path, GlobalConfig.DontScanDirs)) && + (!IsIn(Volume->VolName, GlobalConfig.DontScanVolumes))) { // look through contents of the directory DirIterOpen(Volume->RootDir, Path, &DirIter); while (DirIterNext(&DirIter, 2, Pattern, &DirEntry)) { @@ -882,9 +901,9 @@ static VOID ScanLoaderDir(IN REFIT_VOLUME *Volume, IN CHAR16 *Path, IN CHAR16 *P continue; // skip this if (Path) - SPrint(FileName, 255, L"\\%s\\%s", Path, DirEntry->FileName); + SPrint(FileName, 255, L"\\%s\\%s", Path, DirEntry->FileName); else - SPrint(FileName, 255, L"\\%s", DirEntry->FileName); + SPrint(FileName, 255, L"\\%s", DirEntry->FileName); CleanUpPathNameSlashes(FileName); NewLoader = AllocateZeroPool(sizeof(struct LOADER_LIST)); if (NewLoader != NULL) { @@ -924,22 +943,22 @@ static VOID ScanEfiFiles(REFIT_VOLUME *Volume) { if ((Volume->RootDir != NULL) && (Volume->VolName != NULL)) { // check for Mac OS X boot loader - if (!IsIn(L"\\System\\Library\\CoreServices", GlobalConfig.DontScanDirs)) { + if (!IsIn(L"System\\Library\\CoreServices", GlobalConfig.DontScanDirs)) { StrCpy(FileName, MACOSX_LOADER_PATH); if (FileExists(Volume->RootDir, FileName) && !IsIn(L"boot.efi", GlobalConfig.DontScanFiles)) { 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) && !IsIn(L"boot.efi", GlobalConfig.DontScanFiles)) { AddLoaderEntry(FileName, L"Windows XP (XoM)", Volume); } } // if Mac directory not in GlobalConfig.DontScanDirs 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.DontScanDirs) && + StrCpy(FileName, L"EFI\\Microsoft\\Boot\\Bootmgfw.efi"); + if (FileExists(Volume->RootDir, FileName) && !IsIn(L"EFI\\Microsoft\\Boot", GlobalConfig.DontScanDirs) && !IsIn(L"bootmgfw.efi", GlobalConfig.DontScanFiles)) { AddLoaderEntry(FileName, L"Microsoft EFI boot", Volume); } @@ -952,7 +971,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); @@ -1794,16 +1813,16 @@ static VOID ScanForTools(VOID) { break; case TAG_GPTSYNC: MyFreePool(FileName); - FileName = NULL; - MergeStrings(&FileName, L"\\efi\\tools\\gptsync.efi", 0); + FileName = StrDuplicate(L"\\efi\\tools\\gptsync.efi"); +// MergeStrings(&FileName, L"\\efi\\tools\\gptsync.efi", 0); if (FileExists(SelfRootDir, FileName)) { 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); + FileName = StrDuplicate(L"\\com.apple.recovery.boot\\boot.efi"); +// 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); @@ -1849,7 +1868,7 @@ VOID RescanAll(VOID) { FreeList((VOID ***) &(MainMenu.Entries), &MainMenu.EntryCount); MainMenu.Entries = NULL; MainMenu.EntryCount = 0; - ReadConfig(); + ReadConfig(CONFIG_FILE_NAME); ConnectAllDriversToAllControllers(); ScanVolumes(); ScanForBootloaders(); @@ -1899,7 +1918,7 @@ efi_main (IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable) FindLegacyBootType(); if (GlobalConfig.LegacyType == LEGACY_TYPE_MAC) CopyMem(GlobalConfig.ScanFor, "ihebocm ", NUM_SCAN_OPTIONS); - ReadConfig(); + ReadConfig(CONFIG_FILE_NAME); WarnIfLegacyProblems(); MainMenu.TimeoutSeconds = GlobalConfig.Timeout;