]> code.delx.au - refind/commitdiff
New config file option: "also_scan_dirs".
authorsrs5694 <srs5694@users.sourceforge.net>
Mon, 16 Apr 2012 16:43:20 +0000 (12:43 -0400)
committersrs5694 <srs5694@users.sourceforge.net>
Mon, 16 Apr 2012 16:43:20 +0000 (12:43 -0400)
NEWS.txt
docs/refind/configfile.html
icons/os_linuxmint.icns [moved from icons/os_mint.icns with 100% similarity]
refind.conf-sample
refind/config.c
refind/global.h
refind/lib.c
refind/lib.h
refind/main.c

index 8723aa573a7eb633ee0e2d881c731829247ae625..6ae3946894da19fc00473c693f84bff9ac8731b6 100644 (file)
--- a/NEWS.txt
+++ b/NEWS.txt
@@ -1,3 +1,15 @@
+0.2.7 (?/??/2012):
+------------------
+
+- Fixed bug that caused rEFInd to show up in its own menu sometimes.
+
+- Added new refind.conf token: also_scan_dirs. When scanning volumes for
+  EFI boot loaders, rEFInd always scans the root directory and every
+  subdirectory of the /EFI directory, but it doesn't recurse into these
+  directories. The also_scan_dirs token adds more directories to the scan
+  list. It defaults to "elilo,boot", but you can set it to any directory or
+  directories you like.
+
 0.2.6 (4/14/2012):
 ------------------
 
index ce7cebeb21dc135cd83478121c8b400d9d5aa263..20e12466a468c66e5d0e471264d1a2fca18950c3 100644 (file)
@@ -177,6 +177,11 @@ timeout 20
    <td><tt>internal</tt>, <tt>external</tt>, <tt>optical</tt>, <tt>hdbios</tt>, <tt>biosexternal</tt>, <tt>cd</tt>, and <tt>manual</tt></td>
    <td>Tells rEFInd what methods to use to locate boot loaders. The <tt>internal</tt>, <tt>external</tt>, and <tt>optical</tt> parameters tell rEFInd to scan for EFI boot loaders on internal, external, and optical (CD, DVD, and Blu-ray) devices, respectively. The <tt>hdbios</tt>, <tt>biosexternal</tt>, and <tt>cd</tt> parameters are similar, but scan for BIOS boot loaders. (Note that the BIOS options are likely to be useless on UEFI PCs.) The <tt>manual</tt> parameter tells rEFInd to scan the configuration file for manual settings. You can specify multiple parameters to have the program scan for multiple boot loader types. When you do so, the order determines the order in which the boot loaders appear in the menu. The default is <tt>internal, external, optical</tt>.</td>
 </tr>
+<tr>
+   <td><tt>also_scan_dirs</tt></td>
+   <td>directory path(s)</td>
+   <td>Adds the specified directory or directories to the directory list that rEFInd scans for EFI boot loaders when <tt>scanfor</tt> includes the <tt>internal</tt>, <tt>external</tt>, or <tt>optical</tt> options. Directories are specified relative to the filesystem's root directory. If this option is used, it's applied to <i>all</i> the filesystems that rEFInd scans. If a specified directory doesn't exist, rEFInd ignores it (no error results).</td>
+</tr>
 <tr>
    <td><tt>default_selection</tt></td>
    <td>A substring of a boot loader's title</td>
similarity index 100%
rename from icons/os_mint.icns
rename to icons/os_linuxmint.icns
index 7e3cb2cdff61ecb28e96d5b219aaa551f7e5a9fd..97a01df15f6f0e137858c391c0bc8d6a6d785ce7 100644 (file)
@@ -55,6 +55,7 @@ timeout 20
 #              systems)
 #  reboot    - a tag to reboot the computer
 # Default is shell,about,shutdown,reboot
+#
 #showtools shell, about, reboot
 
 # Which types of boot loaders to search, and in what order to display them:
@@ -66,7 +67,20 @@ timeout 20
 #  cd            - BIOS optical-disc boot loaders
 #  manual        - use stanzas later in this configuration file
 # Default is internal,external,optical
-scanfor internal,external,optical
+#
+#scanfor internal,external,optical
+
+# When scanning volumes for EFI boot loaders, rEFInd always looks for
+# Mac OS X's and Microsoft Windows' boot loaders in their normal locations,
+# and scans the root directory and every subdirectory of the /EFI directory
+# for additional boot loaders, but it doesn't recurse into these directories.
+# The also_scan_dirs token adds more directories to the scan list.
+# Directories are specified relative to the volume's root directory. This
+# option applies to ALL the volumes that rEFInd scans. If a specified
+# directory doesn't exist, it's ignored (no error condition results).
+# The default is to scan no additional directories.
+#
+#also_scan_dirs boot,EFI/linux/kernels
 
 # Set the maximum number of tags that can be displayed on the screen at
 # any time. If more loaders are discovered than this value, rEFInd shows
index 8016931c5f5bb83d454a414e3c6a080ab6876fed..7ad8f91b423e8642e7c3611378ff9034c6ae5fbb 100644 (file)
@@ -357,7 +357,16 @@ VOID ReadConfig(VOID)
               else
                  GlobalConfig.ScanFor[i] = ' ';
            }
-        } else if (StriCmp(TokenList[0], L"showtools") == 0) {
+
+        } else if (StriCmp(TokenList[0], L"also_scan_dirs") == 0) {
+           if (GlobalConfig.AlsoScan != NULL) {
+              FreePool(GlobalConfig.AlsoScan);
+              GlobalConfig.AlsoScan = NULL;
+           } // if
+           for (i = 1; i < TokenCount; i++)
+              MergeStrings(&GlobalConfig.AlsoScan, TokenList[i], L',');
+
+      } else if (StriCmp(TokenList[0], L"showtools") == 0) {
             SetMem(GlobalConfig.ShowTools, NUM_TOOLS * sizeof(UINTN), 0);
             for (i = 1; (i < TokenCount) && (i < NUM_TOOLS); i++) {
                 FlagName = TokenList[i];
index 9489beee85b5e8514dd95a500cd61402c0c70cd0..d61676b419b235e160ae688781e80dfbc018a48a 100644 (file)
@@ -159,6 +159,7 @@ typedef struct {
    CHAR16      *SelectionSmallFileName;
    CHAR16      *SelectionBigFileName;
    CHAR16      *DefaultSelection;
+   CHAR16      *AlsoScan;
    UINTN       ShowTools[NUM_TOOLS];
    CHAR8       ScanFor[NUM_SCAN_OPTIONS]; // codes of types of loaders for which to scan
 } REFIT_CONFIG;
index e78ae6a341edfbfa2adaaffeb223e84a9e433e97..f5037c5f65f7dd8d41709b24142118b98216d99f 100644 (file)
@@ -79,8 +79,9 @@ static VOID UninitVolumes(VOID);
 
 // Converts forward slashes to backslashes and removes duplicate slashes.
 // Necessary because some (buggy?) EFI implementations produce "\/" strings
-// in pathnames.
-static VOID CleanUpPathNameSlashes(IN OUT CHAR16 *PathName) {
+// in pathnames and because some user inputs can produce duplicate directory
+// separators
+VOID CleanUpPathNameSlashes(IN OUT CHAR16 *PathName) {
    CHAR16   *NewName;
    UINTN    i, j = 0;
    BOOLEAN  LastWasSlash = FALSE;
@@ -1076,8 +1077,8 @@ VOID MergeStrings(IN OUT CHAR16 **First, IN CHAR16 *Second, CHAR16 AddChar) {
    if (Second != NULL)
       Length2 = StrLen(Second);
    NewString = AllocatePool(sizeof(CHAR16) * (Length1 + Length2 + 2));
-   NewString[0] = L'\0';
    if (NewString != NULL) {
+      NewString[0] = L'\0';
       if (*First != NULL) {
          StrCat(NewString, *First);
          if (AddChar) {
@@ -1085,7 +1086,7 @@ VOID MergeStrings(IN OUT CHAR16 **First, IN CHAR16 *Second, CHAR16 AddChar) {
             NewString[Length1 + 1] = 0;
          } // if (AddChar)
       } // if (*First != NULL)
-      if (First != NULL)
+      if (Second != NULL)
          StrCat(NewString, Second);
       FreePool(*First);
       *First = NewString;
@@ -1174,7 +1175,7 @@ CHAR16 *FindNumbers(IN CHAR16 *InString) {
 
 // Find the #Index element (numbered from 0) in a comma-delimited string
 // of elements.
-// Returns the found element, or NULL if Index is out of range of InString
+// Returns the found element, or NULL if Index is out of range or InString
 // is NULL.
 CHAR16 *FindCommaDelimited(IN CHAR16 *InString, IN UINTN Index) {
    UINTN    StartPos = 0, CurPos = 0;
@@ -1197,10 +1198,10 @@ CHAR16 *FindCommaDelimited(IN CHAR16 *InString, IN UINTN Index) {
          else
             CurPos++;
       } // while
+      if (Index == 0)
+         FoundString = StrDuplicate(&InString[StartPos]);
+      if (FoundString != NULL)
+         FoundString[CurPos - StartPos] = 0;
    } // if
-   if (Index == 0)
-      FoundString = StrDuplicate(&InString[StartPos]);
-   if (FoundString != NULL)
-      FoundString[CurPos - StartPos] = 0;
    return (FoundString);
 } // CHAR16 *FindCommaDelimited()
index 374fecb4360210238db4ddbc17131b0a3e7b3457..d888b989de14dd57980d18d7da730fc681e8e879 100644 (file)
@@ -73,6 +73,7 @@ EFI_STATUS InitRefitLib(IN EFI_HANDLE ImageHandle);
 VOID UninitRefitLib(VOID);
 EFI_STATUS ReinitRefitLib(VOID);
 
+VOID CleanUpPathNameSlashes(IN OUT CHAR16 *PathName);
 VOID CreateList(OUT VOID ***ListPtr, OUT UINTN *ElementCount, IN UINTN InitialElementCount);
 VOID AddListElement(IN OUT VOID ***ListPtr, IN OUT UINTN *ElementCount, IN VOID *NewElement);
 VOID FreeList(IN OUT VOID ***ListPtr, IN OUT UINTN *ElementCount /*, IN Callback*/);
index 5e8496e0156f4f1b72f8216b9f7a99ec2d849f88..058728cfa181d0f7a2675e7722d10f222c036dbe 100644 (file)
@@ -72,7 +72,7 @@ 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, 20, 0, 0, NULL, NULL, NULL, NULL,
+REFIT_CONFIG GlobalConfig = { FALSE, 20, 0, 0, NULL, NULL, NULL, NULL, NULL,
                               {TAG_SHELL, TAG_ABOUT, TAG_SHUTDOWN, TAG_REBOOT, 0, 0, 0, 0, 0 }};
 
 //
@@ -83,7 +83,7 @@ static VOID AboutrEFInd(VOID)
 {
     if (AboutMenu.EntryCount == 0) {
         AboutMenu.TitleImage = BuiltinIcon(BUILTIN_ICON_FUNC_ABOUT);
-        AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.2.6");
+        AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.2.6.1");
         AddMenuInfoLine(&AboutMenu, L"");
         AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2006-2010 Christoph Pfisterer");
         AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2012 Roderick W. Smith");
@@ -606,6 +606,7 @@ VOID SetLoaderDefaults(LOADER_ENTRY *Entry, CHAR16 *LoaderPath, IN REFIT_VOLUME
 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);
@@ -630,12 +631,18 @@ static VOID ScanLoaderDir(IN REFIT_VOLUME *Volume, IN CHAR16 *Path)
     EFI_STATUS              Status;
     REFIT_DIR_ITER          DirIter;
     EFI_FILE_INFO           *DirEntry;
-    CHAR16                  FileName[256];
+    CHAR16                  FileName[256], *SelfPath;
+    UINTN                   i = 0;
+
+    // Skip past leading slashes, which are sometimes (but not always) included
+    // in SelfDirPath, to get a path that's known to never include this feature.
+    while ((SelfDirPath != NULL) && (SelfDirPath[i] == L'\\')) {
+       i++;
+    }
+    SelfPath = &SelfDirPath[i]; // NOTE: *DO NOT* call FreePool() on SelfPath!!!
 
-    // 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 (!SelfPath || !Path || ((StriCmp(Path, SelfPath) == 0) && Volume != SelfVolume) ||
+        (StriCmp(Path, SelfPath) != 0)) {
        // look through contents of the directory
        DirIterOpen(Volume->RootDir, Path, &DirIter);
        while (DirIterNext(&DirIter, 2, L"*.efi", &DirEntry)) {
@@ -667,7 +674,8 @@ static VOID ScanEfiFiles(REFIT_VOLUME *Volume) {
    EFI_STATUS              Status;
    REFIT_DIR_ITER          EfiDirIter;
    EFI_FILE_INFO           *EfiDirEntry;
-   CHAR16                  FileName[256];
+   CHAR16                  FileName[256], *Directory;
+   UINTN                   i, Length;
 
    if ((Volume->RootDir != NULL) && (Volume->VolName != NULL)) {
       // check for Mac OS X boot loader
@@ -690,10 +698,6 @@ static VOID ScanEfiFiles(REFIT_VOLUME *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");
 
       // scan subdirectories of the EFI directory (as per the standard)
       DirIterOpen(Volume->RootDir, L"EFI", &EfiDirIter);
@@ -706,6 +710,20 @@ static VOID ScanEfiFiles(REFIT_VOLUME *Volume) {
       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);
+         FreePool(Directory);
+      } // while
    } // if
 } // static VOID ScanEfiFiles()