]> code.delx.au - refind/blobdiff - refind/main.c
Fixed bug that caused ASSERT error on some systems if
[refind] / refind / main.c
index 87bd63c99808bf71c43ea6e0a2066fabfdca7378..10349272587df1a6324e177cedfd9e130e367675 100644 (file)
 //
 // variables
 
-// #ifdef EFIX64
-// foo
-// #endif
-
 #define MACOSX_LOADER_PATH      L"System\\Library\\CoreServices\\boot.efi"
 #if defined (EFIX64)
 #define SHELL_NAMES             L"\\EFI\\tools\\shell.efi,\\EFI\\tools\\shellx64.efi,\\shellx64.efi"
@@ -110,8 +106,8 @@ static REFIT_MENU_SCREEN MainMenu       = { L"Main Menu", NULL, 0, NULL, 0, NULL
                                             L"Insert or F2 for more options; Esc to refresh" };
 static REFIT_MENU_SCREEN AboutMenu      = { L"About", NULL, 0, NULL, 0, NULL, 0, NULL, L"Press Enter to return to main menu", L"" };
 
-REFIT_CONFIG GlobalConfig = { FALSE, FALSE, 0, 0, DONT_CHANGE_TEXT_MODE, 20, 0, 0, GRAPHICS_FOR_OSX, LEGACY_TYPE_MAC, 0,
-                              NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+REFIT_CONFIG GlobalConfig = { FALSE, FALSE, 0, 0, 0, DONT_CHANGE_TEXT_MODE, 20, 0, 0, GRAPHICS_FOR_OSX, LEGACY_TYPE_MAC, 0,
+                              NULL, 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
@@ -132,7 +128,7 @@ static VOID AboutrEFInd(VOID)
 
     if (AboutMenu.EntryCount == 0) {
         AboutMenu.TitleImage = BuiltinIcon(BUILTIN_ICON_FUNC_ABOUT);
-        AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.6.2");
+        AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.6.5.4");
         AddMenuInfoLine(&AboutMenu, L"");
         AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2006-2010 Christoph Pfisterer");
         AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2012 Roderick W. Smith");
@@ -572,7 +568,17 @@ VOID GenerateSubScreen(LOADER_ENTRY *Entry, IN REFIT_VOLUME *Volume) {
             SubEntry->LoadOptions     = L"-v -s";
             AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry);
          } // if
-      } // not single-user
+      } // single-user mode allowed
+
+      if (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_SAFEMODE)) {
+         SubEntry = InitializeLoaderEntry(Entry);
+         if (SubEntry != NULL) {
+            SubEntry->me.Title        = L"Boot Mac OS X in safe mode";
+            SubEntry->UseGraphicsMode = FALSE;
+            SubEntry->LoadOptions     = L"-v -x";
+            AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry);
+         } // if
+      } // safe mode allowed
 
       // check for Apple hardware diagnostics
       StrCpy(DiagsFileName, L"System\\Library\\CoreServices\\.diagnostics\\diags.efi");
@@ -598,12 +604,12 @@ VOID GenerateSubScreen(LOADER_ENTRY *Entry, IN REFIT_VOLUME *Volume) {
          // earlier....
          if ((SubScreen->Entries != NULL) && (SubScreen->Entries[0] != NULL)) {
             MyFreePool(SubScreen->Entries[0]->Title);
-            SubScreen->Entries[0]->Title = StrDuplicate(TokenList[0]);
+            SubScreen->Entries[0]->Title = TokenList[0] ? StrDuplicate(TokenList[0]) : StrDuplicate(L"Boot Linux");
          } // if
          FreeTokenLine(&TokenList, &TokenCount);
          while ((TokenCount = ReadTokenLine(File, &TokenList)) > 1) {
             SubEntry = InitializeLoaderEntry(Entry);
-            SubEntry->me.Title = StrDuplicate(TokenList[0]);
+            SubEntry->me.Title = TokenList[0] ? StrDuplicate(TokenList[0]) : StrDuplicate(L"Boot Linux");
             MyFreePool(SubEntry->LoadOptions);
             SubEntry->LoadOptions = AddInitrdToOptions(TokenList[1], InitrdName);
             FreeTokenLine(&TokenList, &TokenCount);
@@ -705,23 +711,26 @@ static CHAR16 * GetMainLinuxOptions(IN CHAR16 * LoaderPath, IN REFIT_VOLUME *Vol
 // code and shortcut letter. For Linux EFI stub loaders, also sets kernel options
 // that will (with luck) work fairly automatically.
 VOID SetLoaderDefaults(LOADER_ENTRY *Entry, CHAR16 *LoaderPath, REFIT_VOLUME *Volume) {
-   CHAR16      IconFileName[256];
-   CHAR16      *FileName, *PathOnly, *OSIconName = NULL, *Temp, *SubString;
+   CHAR16      *FileName, *PathOnly, *IconNames = NULL, *NoExtension, *OSIconName = NULL, *Temp, *SubString;
    CHAR16      ShortcutLetter = 0;
-   UINTN       i, Length;
+   UINTN       i = 0, Length;
 
    FileName = Basename(LoaderPath);
    PathOnly = FindPath(LoaderPath);
+   NoExtension = StripEfiExtension(FileName);
 
    // locate a custom icon for the loader
    // Anything found here takes precedence over the "hints" in the OSIconName variable
-   StrCpy(IconFileName, LoaderPath);
-   ReplaceEfiExtension(IconFileName, L".icns");
-   if (FileExists(Volume->RootDir, IconFileName)) {
-      Entry->me.Image = LoadIcns(Volume->RootDir, IconFileName, 128);
-   } else if ((StrLen(PathOnly) == 0) && (Volume->VolIconImage != NULL)) {
+   while ((Temp = FindCommaDelimited(ICON_EXTENSIONS, i++)) != NULL) {
+      MergeStrings(&IconNames, NoExtension, L',');
+      MergeStrings(&IconNames, Temp, L'.');
+      MyFreePool(Temp);
+   }
+   if (!Entry->me.Image)
+      Entry->me.Image = LoadIcns(Volume->RootDir, IconNames, 128);
+   if (!Entry->me.Image)
       Entry->me.Image = Volume->VolIconImage;
-   } // icon matched to loader or volume
+   MyFreePool(IconNames);
 
    // Begin creating icon "hints" by using last part of directory path leading
    // to the loader
@@ -893,6 +902,40 @@ static VOID CleanUpLoaderList(struct LOADER_LIST *LoaderList) {
    } // while
 } // static VOID CleanUpLoaderList()
 
+// 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.
+static BOOLEAN ShouldScan(REFIT_VOLUME *Volume, CHAR16 *Path) {
+   CHAR16   *VolName = NULL, *DontScanDir;
+   UINTN    i = 0, VolNum;
+   BOOLEAN  ScanIt = TRUE;
+
+   if (IsIn(Volume->VolName, GlobalConfig.DontScanVolumes))
+      return FALSE;
+
+   while ((DontScanDir = FindCommaDelimited(GlobalConfig.DontScanDirs, i++)) && ScanIt) {
+      SplitVolumeAndFilename(&DontScanDir, &VolName);
+      CleanUpPathNameSlashes(DontScanDir);
+      if (VolName != NULL) {
+         if ((StriCmp(VolName, Volume->VolName) == 0) && (StriCmp(DontScanDir, Path) == 0))
+            ScanIt = FALSE;
+         if ((StrLen(VolName) > 2) && (VolName[0] == L'f') && (VolName[1] == L's') && (VolName[2] >= L'0') && (VolName[2] <= L'9')) {
+            VolNum = Atoi(VolName + 2);
+            if ((VolNum == Volume->VolNumber) && (StriCmp(DontScanDir, Path) == 0))
+               ScanIt = FALSE;
+         }
+      } else {
+         if (StriCmp(DontScanDir, Path) == 0)
+            ScanIt = FALSE;
+      }
+      MyFreePool(DontScanDir);
+      DontScanDir = NULL;
+   }
+   return ScanIt;
+} // BOOLEAN ShouldScan()
+
 // Scan an individual directory for EFI boot loader files and, if found,
 // add them to the list. Sorts the entries within the loader directory
 // so that the most recent one appears first in the list.
@@ -906,14 +949,14 @@ static VOID ScanLoaderDir(IN REFIT_VOLUME *Volume, IN CHAR16 *Path, IN CHAR16 *P
 
     if ((!SelfDirPath || !Path || ((StriCmp(Path, SelfDirPath) == 0) && (Volume->DeviceHandle != SelfVolume->DeviceHandle)) ||
            (StriCmp(Path, SelfDirPath) != 0)) &&
-         (!IsIn(Path, GlobalConfig.DontScanDirs)) &&
-         (!IsIn(Volume->VolName, GlobalConfig.DontScanVolumes))) {
+           (ShouldScan(Volume, Path))) {
        // look through contents of the directory
        DirIterOpen(Volume->RootDir, Path, &DirIter);
        while (DirIterNext(&DirIter, 2, Pattern, &DirEntry)) {
           Extension = FindExtension(DirEntry->FileName);
           if (DirEntry->FileName[0] == '.' ||
               StriCmp(Extension, L".icns") == 0 ||
+              StriCmp(Extension, L".png") == 0 ||
               StriSubCmp(L"shell", DirEntry->FileName) ||
               IsIn(DirEntry->FileName, GlobalConfig.DontScanFiles))
                 continue;   // skip this
@@ -952,8 +995,8 @@ static VOID ScanEfiFiles(REFIT_VOLUME *Volume) {
    EFI_STATUS              Status;
    REFIT_DIR_ITER          EfiDirIter;
    EFI_FILE_INFO           *EfiDirEntry;
-   CHAR16                  FileName[256], *Directory, *MatchPatterns;
-   UINTN                   i, Length;
+   CHAR16                  FileName[256], *Directory, *MatchPatterns, *VolName = NULL;
+   UINTN                   i, Length, VolNum;
 
    MatchPatterns = StrDuplicate(LOADER_MATCH_PATTERNS);
    if (GlobalConfig.ScanAllLinux)
@@ -999,11 +1042,17 @@ static VOID ScanEfiFiles(REFIT_VOLUME *Volume) {
       // 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 (Length > 0)
+         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)))
             ScanLoaderDir(Volume, Directory, MatchPatterns);
          MyFreePool(Directory);
+         MyFreePool(VolName);
       } // while
    } // if
 } // static VOID ScanEfiFiles()
@@ -1872,7 +1921,7 @@ static VOID ScanForTools(VOID) {
             } // while
             if (FileExists(SelfDir, L"MokManager.efi")) {
                MyFreePool(FileName);
-               FileName = StrDuplicate(SelfDirPath);
+               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,
@@ -1969,7 +2018,7 @@ efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
     BOOLEAN            MokProtocol;
     REFIT_MENU_ENTRY   *ChosenEntry;
     UINTN              MenuExit, i;
-    CHAR16             *Selection;
+    CHAR16             *Selection = NULL;
     EG_PIXEL           BGColor;
 
     // bootstrap
@@ -1983,6 +2032,7 @@ efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
     FindLegacyBootType();
     if (GlobalConfig.LegacyType == LEGACY_TYPE_MAC)
        CopyMem(GlobalConfig.ScanFor, "ihebocm   ", NUM_SCAN_OPTIONS);
+    ScanVolumes();
     ReadConfig(CONFIG_FILE_NAME);
 
     InitScreen();
@@ -1993,12 +2043,12 @@ efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
     refit_call4_wrapper(BS->SetWatchdogTimer, 0x0000, 0x0000, 0x0000, NULL);
 
     // further bootstrap (now with config available)
-    SetupScreen();
     MokProtocol = SecureBootSetup();
-    ScanVolumes();
+//    ScanVolumes();
     LoadDrivers();
     ScanForBootloaders();
     ScanForTools();
+    SetupScreen();
 
     if (GlobalConfig.ScanDelay > 0) {
        BGColor.b = 255;
@@ -2011,7 +2061,9 @@ efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
        RescanAll();
     } // if
 
-    Selection = StrDuplicate(GlobalConfig.DefaultSelection);
+    if (GlobalConfig.DefaultSelection)
+       Selection = StrDuplicate(GlobalConfig.DefaultSelection);
+
     while (MainLoopRunning) {
         MenuExit = RunMainMenu(&MainMenu, Selection, &ChosenEntry);