From 26d86fa4b6c17ae9d5afce77e18909d10ba19d90 Mon Sep 17 00:00:00 2001
From: srs5694
Date: Sun, 29 Dec 2013 19:04:28 -0500
Subject: [PATCH] Added support for "-c" command-line parameter to rEFInd, to
specify configuration file to use.
---
NEWS.txt | 11 ++++++++-
docs/refind/configfile.html | 4 +++-
docs/refind/features.html | 4 ++++
refind/config.c | 8 ++++---
refind/global.h | 1 +
refind/lib.c | 27 +++++++++++++++++++++-
refind/lib.h | 1 +
refind/main.c | 46 ++++++++++++++++++++++++++++++++-----
8 files changed, 90 insertions(+), 12 deletions(-)
diff --git a/NEWS.txt b/NEWS.txt
index dd45319..52c57d8 100644
--- a/NEWS.txt
+++ b/NEWS.txt
@@ -1,6 +1,15 @@
-0.7.7 (??/??/201?):
+0.7.7 (12/??/2013):
-------------------
+- Added support for specifying the configuration file at program launch,
+ via the "-c" parameter, as in "refind_x64.efi -c foo.conf" to use the
+ foo.conf file as the main configuration file.
+
+- Scans of ext2/3/4fs and ReiserFS partitions now omit partitions with
+ duplicate filesystem UUIDs. These are likely parts of RAID arrays and so
+ would have the same boot loaders or kernels as the first one with a given
+ UUID.
+
- Added feature in install.sh: Script now tries to locate and mount an ESP
in Linux, if it's currently unmounted.
diff --git a/docs/refind/configfile.html b/docs/refind/configfile.html
index 8516a57..664c4d5 100644
--- a/docs/refind/configfile.html
+++ b/docs/refind/configfile.html
@@ -190,7 +190,9 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com
Adjusting the Global Configuration
-You can adjust many of rEFInd's options by editing its refind.conf file. You can use any text editor you like for the job, but be sure it saves the file in plain ASCII text, not in a word processing format. (In theory, a UTF-16 encoding should also work, but I've not tried that myself.) Note that the EFI shell includes its own editor. If you need to make a change before you launch an OS, you can launch a shell, change to the rEFInd directory, and type edit refind.conf to edit the file. This EFI editor is quite primitive, but it gets the job done. After editing, you'll need to reboot for rEFInd to read the changed configuration file.
+You can adjust many of rEFInd's options by editing its configuration file. This file is called refind.conf by default; but you can use another filename by passing -c filename as an option, as in refind_x64.efi -c myrefind.conf to use myrefind.conf in rEFInd's main directory. You can specify a configuration file in another directory, but to do so, you must use backslashes as directory separators, as in -c \EFI\other\refind.conf. This feature is intended for users who want to have rEFInd appear in its own menu, with the version launched in this way behaving differently from the original—for instance, to have a secondary rEFInd that provides boot options hidden by the main one. In this scenario, the default refind.conf would have a manual boot stanza defining the new rEFInd instance, including its -c option.
+
+You can use any text editor you like to edit refind.conf, but be sure it saves the file in plain ASCII text, not in a word processing format. (In theory, a UTF-16 encoding should also work, but this has been poorly tested.) Note that the EFI shell includes its own editor. If you need to make a change before you launch an OS, you can launch a shell, change to the rEFInd directory, and type edit refind.conf to edit the file. This EFI editor is quite primitive, but it gets the job done. After editing, you'll need to reboot or re-launch rEFInd for rEFInd to read the changed configuration file.
Global configuration file options consist of a name token followed by one or more parameters, as in:
diff --git a/docs/refind/features.html b/docs/refind/features.html
index 1c19a3d..27f81cd 100644
--- a/docs/refind/features.html
+++ b/docs/refind/features.html
@@ -161,6 +161,10 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com
Bug fixes, focusing on those that have bothered me personally.
+The ability to specify a configuration file to use at program launch
+ time via the -c filename
+ command-line option.
+
User-configurable methods of detecting boot loaders:
diff --git a/refind/config.c b/refind/config.c
index 26eeeff..a3e3900 100644
--- a/refind/config.c
+++ b/refind/config.c
@@ -411,7 +411,7 @@ VOID ReadConfig(CHAR16 *FileName)
UINTN TokenCount, i;
// Set a few defaults only if we're loading the default file.
- if (StriCmp(FileName, CONFIG_FILE_NAME) == 0) {
+ if (StriCmp(FileName, GlobalConfig.ConfigFilename) == 0) {
MyFreePool(GlobalConfig.AlsoScan);
GlobalConfig.AlsoScan = StrDuplicate(ALSO_SCAN_DIRS);
MyFreePool(GlobalConfig.DontScanDirs);
@@ -605,7 +605,8 @@ VOID ReadConfig(CHAR16 *FileName)
} else if (StriCmp(TokenList[0], L"max_tags") == 0) {
HandleInt(TokenList, TokenCount, &(GlobalConfig.MaxTags));
- } else if ((StriCmp(TokenList[0], L"include") == 0) && (TokenCount == 2) && (StriCmp(FileName, CONFIG_FILE_NAME) == 0)) {
+ } else if ((StriCmp(TokenList[0], L"include") == 0) && (TokenCount == 2) &&
+ (StriCmp(FileName, GlobalConfig.ConfigFilename) == 0)) {
if (StriCmp(TokenList[1], FileName) != 0) {
ReadConfig(TokenList[1]);
}
@@ -844,7 +845,8 @@ VOID ScanUserConfigured(CHAR16 *FileName)
} // if/else
MyFreePool(Title);
- } else if ((StriCmp(TokenList[0], L"include") == 0) && (TokenCount == 2) && (StriCmp(FileName, CONFIG_FILE_NAME) == 0)) {
+ } else if ((StriCmp(TokenList[0], L"include") == 0) && (TokenCount == 2) &&
+ (StriCmp(FileName, GlobalConfig.ConfigFilename) == 0)) {
if (StriCmp(TokenList[1], FileName) != 0) {
ScanUserConfigured(TokenList[1]);
}
diff --git a/refind/global.h b/refind/global.h
index e6d4b4b..8dc6d59 100644
--- a/refind/global.h
+++ b/refind/global.h
@@ -238,6 +238,7 @@ typedef struct {
UINTN ScreensaverTime;
CHAR16 *BannerFileName;
EG_IMAGE *ScreenBackground;
+ CHAR16 *ConfigFilename;
CHAR16 *SelectionSmallFileName;
CHAR16 *SelectionBigFileName;
CHAR16 *DefaultSelection;
diff --git a/refind/lib.c b/refind/lib.c
index 49c0b99..c6a9257 100644
--- a/refind/lib.c
+++ b/refind/lib.c
@@ -471,7 +471,7 @@ static VOID SetFilesystemData(IN UINT8 *Buffer, IN UINTN BufferSize, IN OUT REFI
}
} // search for ext2/3/4 magic
- if (BufferSize >= (65536 + 62)) {
+ if (BufferSize >= (65536 + 100)) {
MagicString = (char*) (Buffer + 65536 + 52);
if ((CompareMem(MagicString, REISERFS_SUPER_MAGIC_STRING, 8) == 0) ||
(CompareMem(MagicString, REISER2FS_SUPER_MAGIC_STRING, 9) == 0) ||
@@ -1681,6 +1681,31 @@ CHAR16 *FindCommaDelimited(IN CHAR16 *InString, IN UINTN Index) {
return (FoundString);
} // CHAR16 *FindCommaDelimited()
+// Return the position of SmallString within BigString, or -1 if
+// not found.
+INTN FindSubString(IN CHAR16 *SmallString, IN CHAR16 *BigString) {
+ INTN Position = -1;
+ UINTN i = 0, SmallSize, BigSize;
+ BOOLEAN Found = FALSE;
+
+ if ((SmallString == NULL) || (BigString == NULL))
+ return -1;
+
+ SmallSize = StrLen(SmallString);
+ BigSize = StrLen(BigString);
+ if ((SmallSize > BigSize) || (SmallSize == 0) || (BigSize == 0))
+ return -1;
+
+ while ((i <= (BigSize - SmallSize) && !Found)) {
+ if (CompareMem(BigString + i, SmallString, SmallSize) == 0) {
+ Found = TRUE;
+ Position = i;
+ } // if
+ i++;
+ } // while()
+ return Position;
+} // INTN FindSubString()
+
// Returns TRUE if SmallString is an element in the comma-delimited List,
// FALSE otherwise. Performs comparison case-insensitively (except on
// buggy EFIs with case-sensitive StriCmp() functions).
diff --git a/refind/lib.h b/refind/lib.h
index d0a4022..bc3f870 100644
--- a/refind/lib.h
+++ b/refind/lib.h
@@ -114,6 +114,7 @@ VOID FindVolumeAndFilename(IN EFI_DEVICE_PATH *loadpath, OUT REFIT_VOLUME **Devi
BOOLEAN SplitVolumeAndFilename(IN OUT CHAR16 **Path, OUT CHAR16 **VolName);
CHAR16 *FindNumbers(IN CHAR16 *InString);
CHAR16 *FindCommaDelimited(IN CHAR16 *InString, IN UINTN Index);
+INTN FindSubString(IN CHAR16 *SmallString, IN CHAR16 *BigString);
BOOLEAN IsIn(IN CHAR16 *SmallString, IN CHAR16 *List);
VOID MyFreePool(IN OUT VOID *Pointer);
diff --git a/refind/main.c b/refind/main.c
index be3dca4..31fd886 100644
--- a/refind/main.c
+++ b/refind/main.c
@@ -56,7 +56,9 @@
#include "../include/syslinux_mbr.h"
#ifdef __MAKEWITH_GNUEFI
+#ifndef EFI_SECURITY_VIOLATION
#define EFI_SECURITY_VIOLATION EFIERR (26)
+#endif
#else
#include "../EfiLib/BdsHelper.h"
#include "../EfiLib/legacy.h"
@@ -130,7 +132,7 @@ static REFIT_MENU_SCREEN MainMenu = { L"Main Menu", NULL, 0, NULL, 0, NULL
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, 0, DONT_CHANGE_TEXT_MODE, 20, 0, 0, GRAPHICS_FOR_OSX, LEGACY_TYPE_MAC, 0, 0,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, CONFIG_FILE_NAME, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
{ TAG_SHELL, TAG_MEMTEST, TAG_APPLE_RECOVERY, TAG_MOK_TOOL, TAG_ABOUT, TAG_SHUTDOWN,
TAG_REBOOT, TAG_FIRMWARE, 0, 0, 0, 0, 0, 0 }
};
@@ -153,7 +155,7 @@ static VOID AboutrEFInd(VOID)
{
if (AboutMenu.EntryCount == 0) {
AboutMenu.TitleImage = BuiltinIcon(BUILTIN_ICON_FUNC_ABOUT);
- AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.7.6.1");
+ AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.7.6.2");
AddMenuInfoLine(&AboutMenu, L"");
AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2006-2010 Christoph Pfisterer");
AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2012-2013 Roderick W. Smith");
@@ -930,7 +932,7 @@ VOID SetLoaderDefaults(LOADER_ENTRY *Entry, CHAR16 *LoaderPath, REFIT_VOLUME *Vo
} // if
// detect specific loaders
- if (StriSubCmp(L"bzImage", LoaderPath) || StriSubCmp(L"vmlinuz", LoaderPath)) {
+ if (StriSubCmp(L"bzImage", FileName) || StriSubCmp(L"vmlinuz", FileName)) {
GuessLinuxDistribution(&OSIconName, Volume, LoaderPath);
MergeStrings(&OSIconName, L"linux", L',');
Entry->OSType = 'L';
@@ -2184,7 +2186,7 @@ static VOID ScanForBootloaders(VOID) {
ScanLegacyExternal();
break;
case 'm': case 'M':
- ScanUserConfigured(CONFIG_FILE_NAME);
+ ScanUserConfigured(GlobalConfig.ConfigFilename);
break;
case 'e': case 'E':
ScanExternal();
@@ -2341,7 +2343,7 @@ VOID RescanAll(VOID) {
FreeList((VOID ***) &(MainMenu.Entries), &MainMenu.EntryCount);
MainMenu.Entries = NULL;
MainMenu.EntryCount = 0;
- ReadConfig(CONFIG_FILE_NAME);
+ ReadConfig(GlobalConfig.ConfigFilename);
ConnectAllDriversToAllControllers();
ScanVolumes();
ScanForBootloaders();
@@ -2401,6 +2403,37 @@ static BOOLEAN SecureBootUninstall(VOID) {
return Success;
} // VOID SecureBootUninstall
+// Sets the global configuration filename; will be CONFIG_FILE_NAME unless the
+// "-c" command-line option is set, in which case that takes precedence.
+// If an error is encountered, leaves the value alone (it should be set to
+// CONFIG_FILE_NAME when GlobalConfig is initialized).
+static VOID SetConfigFilename(EFI_HANDLE ImageHandle) {
+ EFI_LOADED_IMAGE *Info;
+ CHAR16 *Options, *FileName;
+ EFI_STATUS Status;
+ INTN Where;
+
+ Status = uefi_call_wrapper(BS->HandleProtocol, 3, ImageHandle,
+ &LoadedImageProtocol, (VOID **) &Info);
+ if ((Status == EFI_SUCCESS) && (Info->LoadOptionsSize > 0)) {
+ Options = (CHAR16 *) Info->LoadOptions;
+ Where = FindSubString(L" -c ", Options);
+ if (Where >= 0) {
+ FileName = StrDuplicate(&Options[Where + 4]);
+ Where = FindSubString(L" ", FileName);
+ if (Where > 0)
+ FileName[Where] = L'\0';
+
+ if (FileExists(SelfDir, FileName)) {
+ GlobalConfig.ConfigFilename = FileName;
+ } else {
+ Print(L"Specified configuration file (%s) doesn't exist; using\n'refind.conf' default\n", FileName);
+ MyFreePool(FileName);
+ } // if/else
+ } // if
+ } // if
+} // VOID SetConfigFilename()
+
//
// main entry point
//
@@ -2427,7 +2460,8 @@ efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
FindLegacyBootType();
if (GlobalConfig.LegacyType == LEGACY_TYPE_MAC)
CopyMem(GlobalConfig.ScanFor, "ihebocm ", NUM_SCAN_OPTIONS);
- ReadConfig(CONFIG_FILE_NAME);
+ SetConfigFilename(ImageHandle);
+ ReadConfig(GlobalConfig.ConfigFilename);
ScanVolumes();
InitScreen();
--
2.39.2