From a8046e5f1429d856cfaa202e2271c7db5b6a106f Mon Sep 17 00:00:00 2001 From: srs5694 Date: Sat, 14 Apr 2012 01:39:38 -0400 Subject: [PATCH] Added "volume" token to configuration file boot stanza. --- NEWS.txt | 5 +++++ docs/refind/configfile.html | 20 +++++++++++------ docs/refind/todo.html | 4 ++-- refind/config.c | 45 ++++++++++++++++++++++++++++--------- refind/lib.c | 10 ++++----- refind/main.c | 7 +++--- 6 files changed, 64 insertions(+), 27 deletions(-) diff --git a/NEWS.txt b/NEWS.txt index 56cfa98..259b03e 100644 --- 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. diff --git a/docs/refind/configfile.html b/docs/refind/configfile.html index 95720e5..25330bb 100644 --- a/docs/refind/configfile.html +++ b/docs/refind/configfile.html @@ -14,7 +14,7 @@

by Roderick W. Smith, rodsmith@rodsbooks.com

-

Originally written: 3/14/2012; last Web page update: 4/9/2012, referencing rEFInd 0.2.5

+

Originally written: 3/14/2012; last Web page update: 4/14/2012, referencing rEFInd 0.2.6

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!

@@ -225,6 +225,11 @@ default_selection elilo name for the entry Sets the name that's displayed along with the icon for this entry. If the name should contain a space, it must be enclosed in quotes. Following the name, an open curly brace ({) ends the menuentry line. + + volume + filesystem label + Sets the volume that's used for subsequent file accesses (by icon and loader, and by implication by initrd if loader follows volume). 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. + loader filename @@ -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" }

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 ubuntu directory, and it will automatically find the appropriate Ubuntu icon (os_ubuntu.icns). This option is, however, disabled, so no matching icon will appear when you reboot unless you first comment out or delete the disabled line.

-

The Gentoo entry passes the filename for an initial RAM disk using the initrd line and free-form options using the option 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 not include a .efi extension, which keeps rEFInd from picking up the kernel file in its auto-scans.

+ -

You can combine these OS stanzas with the global refind.conf 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.

+

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 icon line after the volume line.) This entry uses the volume token to tell rEFInd to load the kernel and initial RAM disk file from the filesystem called G_KERNELS. It passes the filename for an initial RAM disk using the initrd line and free-form options using the options line. Note that the kernel filename does not include a .efi extension, which keeps rEFInd from picking up the kernel file in its auto-scans.

-

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 internal, external, and similar options.

+

You can combine these OS stanzas with the global refind.conf 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.

Creating Submenu Entries

diff --git a/docs/refind/todo.html b/docs/refind/todo.html index a867890..d9908ac 100644 --- a/docs/refind/todo.html +++ b/docs/refind/todo.html @@ -14,7 +14,7 @@

by Roderick W. Smith, rodsmith@rodsbooks.com

-

Originally written: 3/14/2012; last Web page update: 4/9/2012, referencing rEFInd 0.2.5

+

Originally written: 3/14/2012; last Web page update: 4/14/2012, referencing rEFInd 0.2.6

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!

@@ -119,7 +119,7 @@ program. I'm not sure what you'd use in Windows to create ICNS files.
  • 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.
  • -
  • I want to be able to specify the volume on which a boot loader resides in refind.conf. (As it is, manually-defined options can only launch boot loader files on the same volume as rEFInd.)
  • +
  • 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.
  • 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).
  • diff --git a/refind/config.c b/refind/config.c index e7ceb17..8f955e1 100644 --- a/refind/config.c +++ b/refind/config.c @@ -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) { diff --git a/refind/lib.c b/refind/lib.c index 3c61782..18ab997 100644 --- a/refind/lib.c +++ b/refind/lib.c @@ -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, diff --git a/refind/main.c b/refind/main.c index 8c82fa9..e97be62 100644 --- a/refind/main.c +++ b/refind/main.c @@ -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) -- 2.39.2