]> code.delx.au - refind/commitdiff
Added "volume" token to configuration file boot stanza.
authorsrs5694 <srs5694@users.sourceforge.net>
Sat, 14 Apr 2012 05:39:38 +0000 (01:39 -0400)
committersrs5694 <srs5694@users.sourceforge.net>
Sat, 14 Apr 2012 05:39:38 +0000 (01:39 -0400)
NEWS.txt
docs/refind/configfile.html
docs/refind/todo.html
refind/config.c
refind/lib.c
refind/main.c

index 56cfa9883740678d2828902577d6907436078245..259b03e851b8e9afad12fe1d050ad52a94983b98 100644 (file)
--- a/NEWS.txt
+++ b/NEWS.txt
@@ -1,6 +1,11 @@
 0.2.6 (?/??/2012):
 ------------------
 
+- Added "volume" keyword to configuration file's stanza options. This
+  option changes the volume from which subsequent files (specified by
+  "loader" and "icon") are loaded. You pass "volume" the name/label of the
+  FILESYSTEM you want to use (not the GPT partition name).
+
 - Fixed bug in 0.2.5 that caused failure of Linux initial RAM disk
   mapping on some (but not all) systems. Affected computers include at
   least some Intel motherboards, maybe others.
index 95720e5edbcaed61f2106e531e844a13af558627..25330bbe17b1837f3043588956724a1c16e3b767 100644 (file)
@@ -14,7 +14,7 @@
   <p class="subhead">by Roderick W. Smith, <a
 href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com</a></p>
 
-  <p>Originally written: 3/14/2012; last Web page update: 4/9/2012, referencing rEFInd 0.2.5</p>
+  <p>Originally written: 3/14/2012; last Web page update: 4/14/2012, referencing rEFInd 0.2.6</p>
 
 
 <p>I'm a technical writer and consultant specializing in Linux technologies. This Web page is provided free of charge and with no annoying outside ads; however, I did take time to prepare it, and Web hosting does cost money. If you find this Web page useful, please consider making a small donation to help keep this site up and running. Thanks!</p>
@@ -225,6 +225,11 @@ default_selection elilo
    <td>name for the entry</td>
    <td>Sets the name that's displayed along with the icon for this entry. If the name should contain a space, it <i>must</i> be enclosed in quotes. Following the name, an open curly brace (<tt>{</tt>) ends the <tt>menuentry</tt> line.</td>
 </tr>
+<tr>
+   <td><tt>volume</tt></td>
+   <td>filesystem label</td>
+   <td>Sets the volume that's used for subsequent file accesses (by <tt>icon</tt> and <tt>loader</tt>, and by implication by <tt>initrd</tt> if <tt>loader</tt> follows <tt>volume</tt>). You pass this token a filesystem's name/label, which is typically displayed under the volume's icon in file managers and that rEFInd displays on its menu at the end of the boot prompt string. If this label isn't unique, the first volume with the specified label is used. The matching is nominally case-insensitive, but on some EFIs it's case-sensitive.</td>
+</tr>
 <tr>
    <td><tt>loader</tt></td>
    <td>filename</td>
@@ -276,20 +281,21 @@ menuentry "Ubuntu Linux" {
 }
 
 menuentry Gentoo {
-    loader \EFI\linux\bzImage-3.3.0-rc7
-    initrd \EFI\linux\initrd-3.3.0-rc7.img
-    options "root=/dev/sda3 ro"
     icon \EFI\refind\icons\os_gentoo.icns
+    volume G_KERNELS
+    loader \kernels\bzImage-3.3.0-rc7
+    initrd \kernels\initrd-3.3.0-rc7.img
+    options "root=/dev/sda3 ro"
 }
 </pre>
 
 <p>This example sets up two entries: one for Ubuntu Linux and one for Gentoo Linux. Note that the two entries use different directory separators, simply to demonstrate the fact that it's possible. The Ubuntu entry sets no icon, since rEFInd will note that the boot loader is stored in the <tt>ubuntu</tt> directory, and it will automatically find the appropriate Ubuntu icon (<tt>os_ubuntu.icns</tt>). This option is, however, disabled, so no matching icon will appear when you reboot unless you first comment out or delete the <tt>disabled</tt> line.</p>
 
-<p>The Gentoo entry passes the filename for an initial RAM disk using the <tt>initrd</tt> line and free-form options using the <tt>option</tt> line. It also sets an icon name, since the path to the kernel doesn't include the distribution's name. Note that the kernel filename does <i>not</i> include a <tt>.efi</tt> extension, which keeps rEFInd from picking up the kernel file in its auto-scans.</p>
+<p class="sidebar"><b>Tip:</b> Under Linux, you can learn a filesystem's label by using <tt>blkid</tt>, as in <tt class="userinput">blkid /dev/sda1</tt>. The filesystem's label, if set, is identified by the keyword <tt>LABEL</tt> in the output.</p>
 
-<p>You can combine these OS stanzas with the global <tt>refind.conf</tt> options presented earlier. The result would contain just one entry on the rEFInd boot menu, unless rEFInd found other boot options on an external or optical disk.</p>
+<p>The Gentoo entry begins with an icon specification to be sure that the icon is loaded from the same volume as rEFInd. (If the icon were stored on the same filesystem as the kernel, you'd place the <tt>icon</tt> line after the <tt>volume</tt> line.) This entry uses the <tt>volume</tt> token to tell rEFInd to load the kernel and initial RAM disk file from the filesystem called <tt>G_KERNELS</tt>. It passes the filename for an initial RAM disk using the <tt>initrd</tt> line and free-form options using the <tt>options</tt> line. Note that the kernel filename does <i>not</i> include a <tt>.efi</tt> extension, which keeps rEFInd from picking up the kernel file in its auto-scans.</p>
 
-<p>Presently, an important limitation of rEFInd is that the manual boot loader definitions can only read files on the partition from which rEFInd launched. rEFInd can, however, auto-detect boot loaders on other disks or partitions via the <tt>internal</tt>, <tt>external</tt>, and similar options.</p>
+<p>You can combine these OS stanzas with the global <tt>refind.conf</tt> options presented earlier. The result would contain just one entry on the rEFInd boot menu, unless rEFInd found other boot options on an external or optical disk.</p>
 
 <h2>Creating Submenu Entries</h2>
 
index a867890de767c324291e6b0d18b5baf05f11bbed..d9908ac6cd1bf4c25b7862a7ed728b5b534eb34e 100644 (file)
@@ -14,7 +14,7 @@
   <p class="subhead">by Roderick W. Smith, <a
 href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com</a></p>
 
-  <p>Originally written: 3/14/2012; last Web page update: 4/9/2012, referencing rEFInd 0.2.5</p>
+  <p>Originally written: 3/14/2012; last Web page update: 4/14/2012, referencing rEFInd 0.2.6</p>
 
 
 <p>I'm a technical writer and consultant specializing in Linux technologies. This Web page is provided free of charge and with no annoying outside ads; however, I did take time to prepare it, and Web hosting does cost money. If you find this Web page useful, please consider making a small donation to help keep this site up and running. Thanks!</p>
@@ -119,7 +119,7 @@ program. I'm not sure what you'd use in Windows to create ICNS files.</li>
 
 <li>Although the ICNS file format used by rEFInd supports multiple image sizes, if a size that rEFInd needs isn't present in the file, rEFInd can't use the icon. The ability to scale images to the desired size would be useful.</li>
 
-<li>I want to be able to specify the volume on which a boot loader resides in <tt>refind.conf</tt>. (As it is, manually-defined options can only launch boot loader files on the same volume as rEFInd.)</li>
+<li>I want to be able to specify the volume on which a boot loader resides using features other than the filesystem's name/label. I used the label because this feature was easily extracted from the data structures that rEFInd maintains (inherited from rEFIt). A number would also be fairly easy to implement, but would be arbitrary and therefore difficult to predict. A partition GUID value would be good, but extracting a GUID from the partition data is harder than extracting the volume's label.</li>
 
 <li>It would be useful to be able to specify paths to boot loaders and/or initial RAM disks relative to the rEFInd directory (or the boot loader's directory, in the case of initrds).</li>
 
index e7ceb17da00c9412952acd76a6cb4fe8c02bdab0..8f955e142cebad0b3f192f6f075cdaca6b49c233 100644 (file)
@@ -419,7 +419,7 @@ static VOID AddSubmenu(LOADER_ENTRY *Entry, REFIT_FILE *File, REFIT_VOLUME *Volu
    if ((SubEntry == NULL) || (SubScreen == NULL))
       return;
    SubEntry->me.Title        = StrDuplicate(Title);
-   
+
    while (((TokenCount = ReadTokenLine(File, &TokenList)) > 0) && (StriCmp(TokenList[0], L"}") != 0)) {
       if ((StriCmp(TokenList[0], L"loader") == 0) && (TokenCount > 1)) { // set the boot loader filename
          if (SubEntry->LoaderPath != NULL)
@@ -461,6 +461,23 @@ static VOID AddSubmenu(LOADER_ENTRY *Entry, REFIT_FILE *File, REFIT_VOLUME *Volu
    Entry->me.SubScreen = SubScreen;
 } // VOID AddSubmenu()
 
+// Finds a volume with the specified Identifier (a volume label, for the moment).
+// If found, sets *Volume to point to that volume. If not, leaves it unchanged.
+// Returns TRUE if a match was found, FALSE if not.
+static BOOLEAN FindVolume(REFIT_VOLUME **Volume, CHAR16 *Identifier) {
+   UINTN     i = 0;
+   BOOLEAN   Found = FALSE;
+
+   while ((i < VolumesCount) && (!Found)) {
+      if (StriCmp(Identifier, Volumes[i]->VolName) == 0) {
+         *Volume = Volumes[i];
+         Found = TRUE;
+      } // if
+      i++;
+   } // while()
+   return (Found);
+} // static VOID FindVolume()
+
 // Adds the options from a SINGLE loaders.conf stanza to a new loader entry and returns
 // that entry. The calling function is then responsible for adding the entry to the
 // list of entries.
@@ -469,6 +486,7 @@ static LOADER_ENTRY * AddStanzaEntries(REFIT_FILE *File, REFIT_VOLUME *Volume, C
    UINTN        TokenCount;
    LOADER_ENTRY *Entry;
    BOOLEAN      DefaultsSet = FALSE, AddedSubmenu = FALSE;
+   REFIT_VOLUME *CurrentVolume = Volume;
 
    // prepare the menu entry
    Entry = InitializeLoaderEntry(NULL);
@@ -476,24 +494,31 @@ static LOADER_ENTRY * AddStanzaEntries(REFIT_FILE *File, REFIT_VOLUME *Volume, C
       return NULL;
 
    Entry->Title           = StrDuplicate(Title);
-   Entry->me.Title        = PoolPrint(L"Boot %s from %s", (Title != NULL) ? Title : L"Unknown", Volume->VolName);
+   Entry->me.Title        = PoolPrint(L"Boot %s from %s", (Title != NULL) ? Title : L"Unknown", CurrentVolume->VolName);
    Entry->me.Row          = 0;
-   Entry->me.BadgeImage   = Volume->VolBadgeImage;
-   Entry->VolName         = Volume->VolName;
+   Entry->me.BadgeImage   = CurrentVolume->VolBadgeImage;
+   Entry->VolName         = CurrentVolume->VolName;
 
    // Parse the config file to add options for a single stanza, terminating when the token
    // is "}" or when the end of file is reached.
    while (((TokenCount = ReadTokenLine(File, &TokenList)) > 0) && (StriCmp(TokenList[0], L"}") != 0)) {
       if ((StriCmp(TokenList[0], L"loader") == 0) && (TokenCount > 1)) { // set the boot loader filename
          Entry->LoaderPath = StrDuplicate(TokenList[1]);
-         Entry->DevicePath = FileDevicePath(Volume->DeviceHandle, Entry->LoaderPath);
-         SetLoaderDefaults(Entry, TokenList[1], Volume);
+         Entry->DevicePath = FileDevicePath(CurrentVolume->DeviceHandle, Entry->LoaderPath);
+         SetLoaderDefaults(Entry, TokenList[1], CurrentVolume);
          FreePool(Entry->LoadOptions);
          Entry->LoadOptions = NULL; // Discard default options, if any
          DefaultsSet = TRUE;
+      } else if ((StriCmp(TokenList[0], L"volume") == 0) && (TokenCount > 1)) {
+         if (FindVolume(&CurrentVolume, TokenList[1])) {
+            FreePool(Entry->me.Title);
+            Entry->me.Title        = PoolPrint(L"Boot %s from %s", (Title != NULL) ? Title : L"Unknown", CurrentVolume->VolName);
+            Entry->me.BadgeImage   = CurrentVolume->VolBadgeImage;
+            Entry->VolName         = CurrentVolume->VolName;
+         } // if match found
       } else if ((StriCmp(TokenList[0], L"icon") == 0) && (TokenCount > 1)) {
          FreePool(Entry->me.Image);
-         Entry->me.Image = LoadIcns(Volume->RootDir, TokenList[1], 128);
+         Entry->me.Image = LoadIcns(CurrentVolume->RootDir, TokenList[1], 128);
          if (Entry->me.Image == NULL) {
             Entry->me.Image = DummyImage(128);
          }
@@ -514,7 +539,7 @@ static LOADER_ENTRY * AddStanzaEntries(REFIT_FILE *File, REFIT_VOLUME *Volume, C
       } else if (StriCmp(TokenList[0], L"disabled") == 0) {
          Entry->Enabled = FALSE;
       } else if ((StriCmp(TokenList[0], L"submenuentry") == 0) && (TokenCount > 1)) {
-         AddSubmenu(Entry, File, Volume, TokenList[1]);
+         AddSubmenu(Entry, File, CurrentVolume, TokenList[1]);
          AddedSubmenu = TRUE;
       } // set options to pass to the loader program
       FreeTokenLine(&TokenList, &TokenCount);
@@ -531,12 +556,12 @@ static LOADER_ENTRY * AddStanzaEntries(REFIT_FILE *File, REFIT_VOLUME *Volume, C
    } // if
 
    if (!DefaultsSet)
-      SetLoaderDefaults(Entry, L"\\EFI\\BOOT\\nemo.efi", Volume); // user included no entry; use bogus one
+      SetLoaderDefaults(Entry, L"\\EFI\\BOOT\\nemo.efi", CurrentVolume); // user included no entry; use bogus one
 
    return(Entry);
 } // static VOID AddStanzaEntries()
 
-// Read the user-configured loaders file, loaders.conf, and add or delete
+// Read the user-configured loaders file, refind_loaders.conf, and add or delete
 // entries based on the contents of that file....
 VOID ScanUserConfigured(VOID)
 {
index 3c61782570ea7777bf587d886b2b1b91bf6f1cb0..18ab99735b892ee361d45993c2541881cd34bc0f 100644 (file)
@@ -293,11 +293,11 @@ VOID ExtractLegacyLoaderPaths(EFI_DEVICE_PATH **PathList, UINTN MaxPaths, EFI_DE
         }
         if (Seen)
             continue;
-        
+
         PathList[PathCount++] = AppendDevicePath(DevicePath, LegacyLoaderMediaPath);
     }
     FreePool(Handles);
-    
+
     if (HardcodedPathList) {
         for (HardcodedIndex = 0; HardcodedPathList[HardcodedIndex] && PathCount < MaxPaths; HardcodedIndex++)
             PathList[PathCount++] = HardcodedPathList[HardcodedIndex];
@@ -316,17 +316,17 @@ static VOID ScanVolumeBootcode(IN OUT REFIT_VOLUME *Volume, OUT BOOLEAN *Bootabl
     UINTN                   i;
     MBR_PARTITION_INFO      *MbrTable;
     BOOLEAN                 MbrTableFound;
-    
+
     Volume->HasBootCode = FALSE;
     Volume->OSIconName = NULL;
     Volume->OSName = NULL;
     *Bootable = FALSE;
-    
+
     if (Volume->BlockIO == NULL)
         return;
     if (Volume->BlockIO->Media->BlockSize > SECTOR_SIZE)
         return;   // our buffer is too small...
-    
+
     // look at the boot sector (this is used for both hard disks and El Torito images!)
     Status = refit_call5_wrapper(Volume->BlockIO->ReadBlocks,
                                  Volume->BlockIO, Volume->BlockIO->Media->MediaId,
index 8c82fa98ff993dde350c1ba93506f1a3f2e17692..e97be6243d758a7a4014b4673533a25ec368444e 100644 (file)
@@ -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.5.1");
+        AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.2.5.2");
         AddMenuInfoLine(&AboutMenu, L"");
         AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2006-2010 Christoph Pfisterer");
         AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2012 Roderick W. Smith");
@@ -619,7 +619,7 @@ LOADER_ENTRY * AddLoaderEntry(IN CHAR16 *LoaderPath, IN CHAR16 *LoaderTitle, IN
       GenerateSubScreen(Entry, Volume);
       AddMenuEntry(&MainMenu, (REFIT_MENU_ENTRY *)Entry);
    }
-   
+
    return(Entry);
 } // LOADER_ENTRY * AddLoaderEntry()
 
@@ -650,8 +650,9 @@ static VOID ScanLoaderDir(IN REFIT_VOLUME *Volume, IN CHAR16 *Path)
                 SPrint(FileName, 255, L"\\%s\\%s", Path, DirEntry->FileName);
           else
                 SPrint(FileName, 255, L"\\%s", DirEntry->FileName);
+          // TODO: Sort loader entries by date/time, most recent first
           AddLoaderEntry(FileName, NULL, Volume);
-       }
+       } // while()
        Status = DirIterClose(&DirIter);
        if (Status != EFI_NOT_FOUND) {
           if (Path)