*/
/*
- * Modifications copyright (c) 2012-2013 Roderick W. Smith
+ * Modifications copyright (c) 2012-2015 Roderick W. Smith
*
* Modifications distributed under the terms of the GNU General Public
- * License (GPL) version 3 (GPLv3), a copy of which must be distributed
- * with this source code or binaries made from it.
+ * License (GPL) version 3 (GPLv3) or (at your option) any later version.
*
*/
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
#include "global.h"
#include "lib.h"
#include "menu.h"
#include "config.h"
#include "screen.h"
+#include "apple.h"
+#include "mystrings.h"
#include "../include/refit_call_wrapper.h"
+#include "../mok/mok.h"
// constants
#define GetTime ST->RuntimeServices->GetTime
#define LAST_MINUTE 1439 /* Last minute of a day */
-static REFIT_MENU_ENTRY MenuEntryReturn = { L"Return to Main Menu", TAG_RETURN, 0, 0, 0, NULL, NULL, NULL };
+extern REFIT_MENU_ENTRY MenuEntryReturn;
+//static REFIT_MENU_ENTRY MenuEntryReturn = { L"Return to Main Menu", TAG_RETURN, 0, 0, 0, NULL, NULL, NULL };
//
// read a file into a buffer
Line = ReadLine(File);
if (Line == NULL)
return(0);
+ if (Line[0] == L'\0') {
+ MyFreePool(Line);
+ return(0);
+ } // if
p = Line;
LineFinished = FALSE;
static VOID HandleInt(IN CHAR16 **TokenList, IN UINTN TokenCount, OUT UINTN *Value)
{
if (TokenCount == 2) {
- if (StriCmp(TokenList[1], L"-1") == 0)
+ if (StrCmp(TokenList[1], L"-1") == 0)
*Value = -1;
else
*Value = Atoi(TokenList[1]);
// handle a parameter with a single string argument
static VOID HandleString(IN CHAR16 **TokenList, IN UINTN TokenCount, OUT CHAR16 **Target) {
- if (TokenCount == 2) {
- MyFreePool(*Target);
- *Target = StrDuplicate(TokenList[1]);
+ if ((TokenCount == 2) && Target) {
+ if ((StrLen(TokenList[1]) > 1) && (TokenList[1][0] == L'+') &&
+ ((TokenList[1][1] == L',') || (TokenList[1][1] == L' '))) {
+ if (*Target) {
+ MergeStrings(Target, TokenList[1] + 2, L',');
+ } else {
+ *Target = StrDuplicate(TokenList[1] + 2);
+ } // if/else
+ } else {
+ MyFreePool(*Target);
+ *Target = StrDuplicate(TokenList[1]);
+ } // if/else
} // if
} // static VOID HandleString()
-// Handle a parameter with a series of string arguments, to be added to a comma-delimited
-// list. Passes each token through the CleanUpPathNameSlashes() function to ensure
-// consistency in subsequent comparisons of filenames.
+// Handle a parameter with a series of string arguments, to replace or be added to a
+// comma-delimited list. Passes each token through the CleanUpPathNameSlashes() function
+// to ensure consistency in subsequent comparisons of filenames. If the first
+// non-keyword token is "+", the list is added to the existing target string; otherwise,
+// the tokens replace the current string.
static VOID HandleStrings(IN CHAR16 **TokenList, IN UINTN TokenCount, OUT CHAR16 **Target) {
UINTN i;
+ BOOLEAN AddMode = FALSE;
+
+ if ((TokenCount > 2) && (StrCmp(TokenList[1], L"+") == 0)) {
+ AddMode = TRUE;
+ }
- if (*Target != NULL) {
+ if ((*Target != NULL) && !AddMode) {
FreePool(*Target);
*Target = NULL;
} // if
for (i = 1; i < TokenCount; i++) {
- CleanUpPathNameSlashes(TokenList[i]);
- MergeStrings(Target, TokenList[i], L',');
- }
+ if ((i != 1) || !AddMode) {
+ CleanUpPathNameSlashes(TokenList[i]);
+ MergeStrings(Target, TokenList[i], L',');
+ } // if
+ } // for
} // static VOID HandleStrings()
+// Handle a parameter with a series of hexadecimal arguments, to replace or be added to a
+// linked list of UINT32 values. Any item with a non-hexadecimal value is discarded, as is
+// any value that exceeds MaxValue. If the first non-keyword token is "+", the new list is
+// added to the existing Target; otherwise, the interpreted tokens replace the current
+// Target.
+static VOID HandleHexes(IN CHAR16 **TokenList, IN UINTN TokenCount, IN UINTN MaxValue, OUT UINT32_LIST **Target) {
+ UINTN InputIndex = 1, i;
+ UINT32 Value;
+ UINT32_LIST *EndOfList = NULL;
+ UINT32_LIST *NewEntry;
+
+ if ((TokenCount > 2) && (StrCmp(TokenList[1], L"+") == 0)) {
+ InputIndex = 2;
+ EndOfList = *Target;
+ while (EndOfList && (EndOfList->Next != NULL)) {
+ EndOfList = EndOfList->Next;
+ }
+ } else {
+ EraseUint32List(Target);
+ }
+
+ for (i = InputIndex; i < TokenCount; i++) {
+ if (IsValidHex(TokenList[i])) {
+ Value = (UINT32) StrToHex(TokenList[i], 0, 8);
+ if (Value <= MaxValue) {
+ NewEntry = AllocatePool(sizeof(UINT32_LIST));
+ if (NewEntry) {
+ NewEntry->Value = Value;
+ NewEntry->Next = NULL;
+ if (EndOfList == NULL) {
+ EndOfList = NewEntry;
+ *Target = NewEntry;
+ } else {
+ EndOfList->Next = NewEntry;
+ EndOfList = NewEntry;
+ } // if/else
+ } // if allocated memory for NewEntry
+ } // if (Value < MaxValue)
+ } // if is valid hex value
+ } // for
+} // static VOID HandleHexes()
+
// Convert TimeString (in "HH:MM" format) to a pure-minute format. Values should be
// in the range from 0 (for 00:00, or midnight) to 1439 (for 23:59; aka LAST_MINUTE).
// Any value outside that range denotes an error in the specification. Note that if
return (Hour * 60 + Minute);
} // BOOLEAN HandleTime()
+static BOOLEAN HandleBoolean(IN CHAR16 **TokenList, IN UINTN TokenCount) {
+ BOOLEAN TruthValue = TRUE;
+
+ if ((TokenCount >= 2) && ((StrCmp(TokenList[1], L"0") == 0) ||
+ MyStriCmp(TokenList[1], L"false") ||
+ MyStriCmp(TokenList[1], L"off"))) {
+ TruthValue = FALSE;
+ } // if
+
+ return TruthValue;
+} // BOOLEAN HandleBoolean
+
// Sets the default boot loader IF the current time is within the bounds
// defined by the third and fourth tokens in the TokenList.
static VOID SetDefaultByTime(IN CHAR16 **TokenList, OUT CHAR16 **Default) {
EFI_STATUS Status;
EFI_TIME CurrentTime;
- UINTN StartTime = LAST_MINUTE + 1, EndTime = LAST_MINUTE + 1, Now;
+ UINTN StartTime, EndTime, Now;
BOOLEAN SetIt = FALSE;
StartTime = HandleTime(TokenList[2]);
CHAR16 *FlagName;
CHAR16 *TempStr = NULL;
UINTN TokenCount, i;
+ EFI_GUID RefindGuid = REFIND_GUID_VALUE;
// Set a few defaults only if we're loading the default file.
- if (StriCmp(FileName, GlobalConfig.ConfigFilename) == 0) {
+ if (MyStriCmp(FileName, GlobalConfig.ConfigFilename)) {
MyFreePool(GlobalConfig.AlsoScan);
GlobalConfig.AlsoScan = StrDuplicate(ALSO_SCAN_DIRS);
MyFreePool(GlobalConfig.DontScanDirs);
MergeStrings(&(GlobalConfig.DontScanFiles), MOK_NAMES, L',');
MyFreePool(GlobalConfig.DontScanVolumes);
GlobalConfig.DontScanVolumes = StrDuplicate(DONT_SCAN_VOLUMES);
+ GlobalConfig.WindowsRecoveryFiles = StrDuplicate(WINDOWS_RECOVERY_FILES);
+ if (GlobalConfig.DefaultSelection != NULL) {
+ MyFreePool(GlobalConfig.DefaultSelection);
+ GlobalConfig.DefaultSelection = NULL;
+ }
+ Status = EfivarGetRaw(&RefindGuid, L"PreviousBoot", (CHAR8**) &(GlobalConfig.DefaultSelection), &i);
+ if (Status != EFI_SUCCESS)
+ GlobalConfig.DefaultSelection = NULL;
} // if
if (!FileExists(SelfDir, FileName)) {
- Print(L"Configuration file '%s' missing!\n", FileName);
- return;
+ Print(L"Configuration file '%s' missing!\n", FileName);
+ if (!FileExists(SelfDir, L"icons")) {
+ Print(L"Icons directory doesn't exist; setting textonly = TRUE!\n");
+ GlobalConfig.TextOnly = TRUE;
+ }
+ return;
}
Status = ReadFile(SelfDir, FileName, &File, &i);
if (TokenCount == 0)
break;
- if (StriCmp(TokenList[0], L"timeout") == 0) {
+ if (MyStriCmp(TokenList[0], L"timeout")) {
HandleInt(TokenList, TokenCount, &(GlobalConfig.Timeout));
- } else if (StriCmp(TokenList[0], L"hideui") == 0) {
+ } else if (MyStriCmp(TokenList[0], L"hideui")) {
for (i = 1; i < TokenCount; i++) {
FlagName = TokenList[i];
- if (StriCmp(FlagName, L"banner") == 0) {
+ if (MyStriCmp(FlagName, L"banner")) {
GlobalConfig.HideUIFlags |= HIDEUI_FLAG_BANNER;
- } else if (StriCmp(FlagName, L"label") == 0) {
+ } else if (MyStriCmp(FlagName, L"label")) {
GlobalConfig.HideUIFlags |= HIDEUI_FLAG_LABEL;
- } else if (StriCmp(FlagName, L"singleuser") == 0) {
+ } else if (MyStriCmp(FlagName, L"singleuser")) {
GlobalConfig.HideUIFlags |= HIDEUI_FLAG_SINGLEUSER;
- } else if (StriCmp(FlagName, L"hwtest") == 0) {
+ } else if (MyStriCmp(FlagName, L"hwtest")) {
GlobalConfig.HideUIFlags |= HIDEUI_FLAG_HWTEST;
- } else if (StriCmp(FlagName, L"arrows") == 0) {
+ } else if (MyStriCmp(FlagName, L"arrows")) {
GlobalConfig.HideUIFlags |= HIDEUI_FLAG_ARROWS;
- } else if (StriCmp(FlagName, L"hints") == 0) {
+ } else if (MyStriCmp(FlagName, L"hints")) {
GlobalConfig.HideUIFlags |= HIDEUI_FLAG_HINTS;
- } else if (StriCmp(FlagName, L"editor") == 0) {
+ } else if (MyStriCmp(FlagName, L"editor")) {
GlobalConfig.HideUIFlags |= HIDEUI_FLAG_EDITOR;
- } else if (StriCmp(FlagName, L"safemode") == 0) {
+ } else if (MyStriCmp(FlagName, L"safemode")) {
GlobalConfig.HideUIFlags |= HIDEUI_FLAG_SAFEMODE;
- } else if (StriCmp(FlagName, L"all") == 0) {
+ } else if (MyStriCmp(FlagName, L"badges")) {
+ GlobalConfig.HideUIFlags |= HIDEUI_FLAG_BADGES;
+ } else if (MyStriCmp(FlagName, L"all")) {
GlobalConfig.HideUIFlags = HIDEUI_FLAG_ALL;
} else {
Print(L" unknown hideui flag: '%s'\n", FlagName);
}
}
- } else if (StriCmp(TokenList[0], L"icons_dir") == 0) {
+ } else if (MyStriCmp(TokenList[0], L"icons_dir")) {
HandleString(TokenList, TokenCount, &(GlobalConfig.IconsDir));
- } else if (StriCmp(TokenList[0], L"scanfor") == 0) {
+ } else if (MyStriCmp(TokenList[0], L"scanfor")) {
for (i = 0; i < NUM_SCAN_OPTIONS; i++) {
if (i < TokenCount)
GlobalConfig.ScanFor[i] = TokenList[i][0];
GlobalConfig.ScanFor[i] = ' ';
}
- } else if ((StriCmp(TokenList[0], L"scan_delay") == 0) && (TokenCount == 2)) {
+ } else if (MyStriCmp(TokenList[0], L"uefi_deep_legacy_scan")) {
+ GlobalConfig.DeepLegacyScan = HandleBoolean(TokenList, TokenCount);
+
+ } else if (MyStriCmp(TokenList[0], L"scan_delay") && (TokenCount == 2)) {
HandleInt(TokenList, TokenCount, &(GlobalConfig.ScanDelay));
- } else if (StriCmp(TokenList[0], L"also_scan_dirs") == 0) {
+ } else if (MyStriCmp(TokenList[0], L"also_scan_dirs")) {
HandleStrings(TokenList, TokenCount, &(GlobalConfig.AlsoScan));
- } else if ((StriCmp(TokenList[0], L"don't_scan_volumes") == 0) || (StriCmp(TokenList[0], L"dont_scan_volumes") == 0)) {
+ } else if (MyStriCmp(TokenList[0], L"don't_scan_volumes") || MyStriCmp(TokenList[0], L"dont_scan_volumes")) {
// Note: Don't use HandleStrings() because it modifies slashes, which might be present in volume name
MyFreePool(GlobalConfig.DontScanVolumes);
GlobalConfig.DontScanVolumes = NULL;
MergeStrings(&GlobalConfig.DontScanVolumes, TokenList[i], L',');
}
- } else if ((StriCmp(TokenList[0], L"don't_scan_dirs") == 0) || (StriCmp(TokenList[0], L"dont_scan_dirs") == 0)) {
+ } else if (MyStriCmp(TokenList[0], L"don't_scan_dirs") || MyStriCmp(TokenList[0], L"dont_scan_dirs")) {
HandleStrings(TokenList, TokenCount, &(GlobalConfig.DontScanDirs));
- } else if ((StriCmp(TokenList[0], L"don't_scan_files") == 0) || (StriCmp(TokenList[0], L"dont_scan_files") == 0)) {
+ } else if (MyStriCmp(TokenList[0], L"don't_scan_files") || MyStriCmp(TokenList[0], L"dont_scan_files")) {
HandleStrings(TokenList, TokenCount, &(GlobalConfig.DontScanFiles));
- } else if (StriCmp(TokenList[0], L"scan_driver_dirs") == 0) {
+ } else if (MyStriCmp(TokenList[0], L"windows_recovery_files")) {
+ HandleStrings(TokenList, TokenCount, &(GlobalConfig.WindowsRecoveryFiles));
+
+ } else if (MyStriCmp(TokenList[0], L"scan_driver_dirs")) {
HandleStrings(TokenList, TokenCount, &(GlobalConfig.DriverDirs));
- } else if (StriCmp(TokenList[0], L"showtools") == 0) {
+ } else if (MyStriCmp(TokenList[0], L"showtools")) {
SetMem(GlobalConfig.ShowTools, NUM_TOOLS * sizeof(UINTN), 0);
for (i = 1; (i < TokenCount) && (i < NUM_TOOLS); i++) {
FlagName = TokenList[i];
- if (StriCmp(FlagName, L"shell") == 0) {
+ if (MyStriCmp(FlagName, L"shell")) {
GlobalConfig.ShowTools[i - 1] = TAG_SHELL;
- } else if (StriCmp(FlagName, L"gptsync") == 0) {
+ } else if (MyStriCmp(FlagName, L"gptsync")) {
GlobalConfig.ShowTools[i - 1] = TAG_GPTSYNC;
- } else if (StriCmp(FlagName, L"about") == 0) {
+ } else if (MyStriCmp(FlagName, L"gdisk")) {
+ GlobalConfig.ShowTools[i - 1] = TAG_GDISK;
+ } else if (MyStriCmp(FlagName, L"about")) {
GlobalConfig.ShowTools[i - 1] = TAG_ABOUT;
- } else if (StriCmp(FlagName, L"exit") == 0) {
+ } else if (MyStriCmp(FlagName, L"exit")) {
GlobalConfig.ShowTools[i - 1] = TAG_EXIT;
- } else if (StriCmp(FlagName, L"reboot") == 0) {
+ } else if (MyStriCmp(FlagName, L"reboot")) {
GlobalConfig.ShowTools[i - 1] = TAG_REBOOT;
- } else if (StriCmp(FlagName, L"shutdown") == 0) {
+ } else if (MyStriCmp(FlagName, L"shutdown")) {
GlobalConfig.ShowTools[i - 1] = TAG_SHUTDOWN;
- } else if (StriCmp(FlagName, L"apple_recovery") == 0) {
+ } else if (MyStriCmp(FlagName, L"apple_recovery")) {
GlobalConfig.ShowTools[i - 1] = TAG_APPLE_RECOVERY;
- } else if (StriCmp(FlagName, L"mok_tool") == 0) {
+ } else if (MyStriCmp(FlagName, L"windows_recovery")) {
+ GlobalConfig.ShowTools[i - 1] = TAG_WINDOWS_RECOVERY;
+ } else if (MyStriCmp(FlagName, L"mok_tool")) {
GlobalConfig.ShowTools[i - 1] = TAG_MOK_TOOL;
- } else if (StriCmp(FlagName, L"firmware") == 0) {
+ } else if (MyStriCmp(FlagName, L"csr_rotate")) {
+ GlobalConfig.ShowTools[i - 1] = TAG_CSR_ROTATE;
+ } else if (MyStriCmp(FlagName, L"firmware")) {
GlobalConfig.ShowTools[i - 1] = TAG_FIRMWARE;
- } else if ((StriCmp(FlagName, L"memtest86") == 0) || (StriCmp(FlagName, L"memtest") == 0)) {
+ } else if (MyStriCmp(FlagName, L"memtest86") || MyStriCmp(FlagName, L"memtest")) {
GlobalConfig.ShowTools[i - 1] = TAG_MEMTEST;
+ } else if (MyStriCmp(FlagName, L"netboot")) {
+ GlobalConfig.ShowTools[i - 1] = TAG_NETBOOT;
} else {
Print(L" unknown showtools flag: '%s'\n", FlagName);
}
} // showtools options
- } else if (StriCmp(TokenList[0], L"banner") == 0) {
+ } else if (MyStriCmp(TokenList[0], L"banner")) {
HandleString(TokenList, TokenCount, &(GlobalConfig.BannerFileName));
- } else if (StriCmp(TokenList[0], L"selection_small") == 0) {
+ } else if (MyStriCmp(TokenList[0], L"banner_scale") && (TokenCount == 2)) {
+ if (MyStriCmp(TokenList[1], L"noscale")) {
+ GlobalConfig.BannerScale = BANNER_NOSCALE;
+ } else if (MyStriCmp(TokenList[1], L"fillscreen") || MyStriCmp(TokenList[1], L"fullscreen")) {
+ GlobalConfig.BannerScale = BANNER_FILLSCREEN;
+ } else {
+ Print(L" unknown banner_type flag: '%s'\n", TokenList[1]);
+ } // if/else
+
+ } else if (MyStriCmp(TokenList[0], L"small_icon_size") && (TokenCount == 2)) {
+ HandleInt(TokenList, TokenCount, &i);
+ if (i >= 32)
+ GlobalConfig.IconSizes[ICON_SIZE_SMALL] = i;
+
+ } else if (MyStriCmp(TokenList[0], L"big_icon_size") && (TokenCount == 2)) {
+ HandleInt(TokenList, TokenCount, &i);
+ if (i >= 32) {
+ GlobalConfig.IconSizes[ICON_SIZE_BIG] = i;
+ GlobalConfig.IconSizes[ICON_SIZE_BADGE] = i / 4;
+ }
+
+ } else if (MyStriCmp(TokenList[0], L"selection_small")) {
HandleString(TokenList, TokenCount, &(GlobalConfig.SelectionSmallFileName));
- } else if (StriCmp(TokenList[0], L"selection_big") == 0) {
+ } else if (MyStriCmp(TokenList[0], L"selection_big")) {
HandleString(TokenList, TokenCount, &(GlobalConfig.SelectionBigFileName));
- } else if (StriCmp(TokenList[0], L"default_selection") == 0) {
+ } else if (MyStriCmp(TokenList[0], L"default_selection")) {
if (TokenCount == 4) {
SetDefaultByTime(TokenList, &(GlobalConfig.DefaultSelection));
} else {
HandleString(TokenList, TokenCount, &(GlobalConfig.DefaultSelection));
}
- } else if (StriCmp(TokenList[0], L"textonly") == 0) {
- if ((TokenCount >= 2) && (StriCmp(TokenList[1], L"0") == 0)) {
- GlobalConfig.TextOnly = FALSE;
- } else {
- GlobalConfig.TextOnly = TRUE;
- }
+ } else if (MyStriCmp(TokenList[0], L"textonly")) {
+ GlobalConfig.TextOnly = HandleBoolean(TokenList, TokenCount);
- } else if (StriCmp(TokenList[0], L"textmode") == 0) {
+ } else if (MyStriCmp(TokenList[0], L"textmode")) {
HandleInt(TokenList, TokenCount, &(GlobalConfig.RequestedTextMode));
- } else if ((StriCmp(TokenList[0], L"resolution") == 0) && ((TokenCount == 2) || (TokenCount == 3))) {
+ } else if (MyStriCmp(TokenList[0], L"resolution") && ((TokenCount == 2) || (TokenCount == 3))) {
GlobalConfig.RequestedScreenWidth = Atoi(TokenList[1]);
if (TokenCount == 3)
GlobalConfig.RequestedScreenHeight = Atoi(TokenList[2]);
else
GlobalConfig.RequestedScreenHeight = 0;
- } else if (StriCmp(TokenList[0], L"screensaver") == 0) {
+ } else if (MyStriCmp(TokenList[0], L"screensaver")) {
HandleInt(TokenList, TokenCount, &(GlobalConfig.ScreensaverTime));
- } else if (StriCmp(TokenList[0], L"use_graphics_for") == 0) {
- GlobalConfig.GraphicsFor = 0;
+ } else if (MyStriCmp(TokenList[0], L"use_graphics_for")) {
+ if ((TokenCount == 2) || ((TokenCount > 2) && (!MyStriCmp(TokenList[1], L"+"))))
+ GlobalConfig.GraphicsFor = 0;
for (i = 1; i < TokenCount; i++) {
- if (StriCmp(TokenList[i], L"osx") == 0) {
+ if (MyStriCmp(TokenList[i], L"osx")) {
GlobalConfig.GraphicsFor |= GRAPHICS_FOR_OSX;
- } else if (StriCmp(TokenList[i], L"linux") == 0) {
+ } else if (MyStriCmp(TokenList[i], L"linux")) {
GlobalConfig.GraphicsFor |= GRAPHICS_FOR_LINUX;
- } else if (StriCmp(TokenList[i], L"elilo") == 0) {
+ } else if (MyStriCmp(TokenList[i], L"elilo")) {
GlobalConfig.GraphicsFor |= GRAPHICS_FOR_ELILO;
- } else if (StriCmp(TokenList[i], L"grub") == 0) {
+ } else if (MyStriCmp(TokenList[i], L"grub")) {
GlobalConfig.GraphicsFor |= GRAPHICS_FOR_GRUB;
- } else if (StriCmp(TokenList[i], L"windows") == 0) {
+ } else if (MyStriCmp(TokenList[i], L"windows")) {
GlobalConfig.GraphicsFor |= GRAPHICS_FOR_WINDOWS;
}
} // for (graphics_on tokens)
- } else if ((StriCmp(TokenList[0], L"font") == 0) && (TokenCount == 2)) {
+ } else if (MyStriCmp(TokenList[0], L"font") && (TokenCount == 2)) {
egLoadFont(TokenList[1]);
- } else if (StriCmp(TokenList[0], L"scan_all_linux_kernels") == 0) {
- if ((TokenCount >= 2) && (StriCmp(TokenList[1], L"0") == 0)) {
- GlobalConfig.ScanAllLinux = FALSE;
- } else {
- GlobalConfig.ScanAllLinux = TRUE;
- }
+ } else if (MyStriCmp(TokenList[0], L"scan_all_linux_kernels")) {
+ GlobalConfig.ScanAllLinux = HandleBoolean(TokenList, TokenCount);
+
+ } else if (MyStriCmp(TokenList[0], L"fold_linux_kernels")) {
+ GlobalConfig.FoldLinuxKernels = HandleBoolean(TokenList, TokenCount);
- } else if (StriCmp(TokenList[0], L"max_tags") == 0) {
+ } else if (MyStriCmp(TokenList[0], L"max_tags")) {
HandleInt(TokenList, TokenCount, &(GlobalConfig.MaxTags));
- } else if ((StriCmp(TokenList[0], L"include") == 0) && (TokenCount == 2) &&
- (StriCmp(FileName, GlobalConfig.ConfigFilename) == 0)) {
- if (StriCmp(TokenList[1], FileName) != 0) {
+ } else if (MyStriCmp(TokenList[0], L"enable_and_lock_vmx")) {
+ GlobalConfig.EnableAndLockVMX = HandleBoolean(TokenList, TokenCount);
+
+ } else if (MyStriCmp(TokenList[0], L"spoof_osx_version")) {
+ HandleString(TokenList, TokenCount, &(GlobalConfig.SpoofOSXVersion));
+
+ } else if (MyStriCmp(TokenList[0], L"csr_values")) {
+ HandleHexes(TokenList, TokenCount, CSR_MAX_LEGAL_VALUE, &(GlobalConfig.CsrValues));
+
+ } else if (MyStriCmp(TokenList[0], L"include") && (TokenCount == 2) && MyStriCmp(FileName, GlobalConfig.ConfigFilename)) {
+ if (!MyStriCmp(TokenList[1], FileName)) {
ReadConfig(TokenList[1]);
}
FreeTokenLine(&TokenList, &TokenCount);
}
+ if ((GlobalConfig.DontScanFiles) && (GlobalConfig.WindowsRecoveryFiles))
+ MergeStrings(&(GlobalConfig.DontScanFiles), GlobalConfig.WindowsRecoveryFiles, L',');
MyFreePool(File.Buffer);
+
+ if (!FileExists(SelfDir, L"icons") && !FileExists(SelfDir, GlobalConfig.IconsDir)) {
+ Print(L"Icons directory doesn't exist; setting textonly = TRUE!\n");
+ GlobalConfig.TextOnly = TRUE;
+ }
} /* VOID ReadConfig() */
-// Finds a volume with the specified Identifier (a volume label or a number
-// followed by a colon, for the moment). If found, sets *Volume to point to
-// that volume. If not, leaves it unchanged.
+// Finds a volume with the specified Identifier (a filesystem label, a
+// partition name, a partition GUID, or a number followed by a colon). 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, CountedVolumes = 0;
+ UINTN i = 0, CountedVolumes = 0, Length;
INTN Number = -1;
- BOOLEAN Found = FALSE;
+ BOOLEAN Found = FALSE, IdIsGuid = FALSE;
+ EFI_GUID VolGuid, NullGuid = NULL_GUID_VALUE;
- if ((StrLen(Identifier) >= 2) && (Identifier[StrLen(Identifier) - 1] == L':') &&
+ VolGuid = StringAsGuid(Identifier);
+ Length = StrLen(Identifier);
+ if ((Length >= 2) && (Identifier[Length - 1] == L':') &&
(Identifier[0] >= L'0') && (Identifier[0] <= L'9')) {
Number = (INTN) Atoi(Identifier);
+ } else if (IsGuid(Identifier)) {
+ IdIsGuid = TRUE;
}
while ((i < VolumesCount) && (!Found)) {
if (Number >= 0) { // User specified a volume by number
}
CountedVolumes++;
} // if
- } else { // User specified a volume by label
- if (StriCmp(Identifier, Volumes[i]->VolName) == 0) {
+ } else { // User specified a volume by label or GUID
+ if (MyStriCmp(Identifier, Volumes[i]->VolName) || MyStriCmp(Identifier, Volumes[i]->PartName)) {
*Volume = Volumes[i];
Found = TRUE;
} // if
+ if (IdIsGuid && !Found) {
+ if (GuidsAreEqual(&VolGuid, &(Volumes[i]->PartGuid)) && !GuidsAreEqual(&NullGuid, &(Volumes[i]->PartGuid))) {
+ *Volume = Volumes[i];
+ Found = TRUE;
+ } // if
+ } // if
} // if/else
i++;
} // while()
return;
SubEntry->me.Title = StrDuplicate(Title);
- while (((TokenCount = ReadTokenLine(File, &TokenList)) > 0) && (StriCmp(TokenList[0], L"}") != 0)) {
+ while (((TokenCount = ReadTokenLine(File, &TokenList)) > 0) && (StrCmp(TokenList[0], L"}") != 0)) {
- if ((StriCmp(TokenList[0], L"loader") == 0) && (TokenCount > 1)) { // set the boot loader filename
+ if (MyStriCmp(TokenList[0], L"loader") && (TokenCount > 1)) { // set the boot loader filename
MyFreePool(SubEntry->LoaderPath);
SubEntry->LoaderPath = StrDuplicate(TokenList[1]);
SubEntry->DevicePath = FileDevicePath(Volume->DeviceHandle, SubEntry->LoaderPath);
- } else if ((StriCmp(TokenList[0], L"volume") == 0) && (TokenCount > 1)) {
+ } else if (MyStriCmp(TokenList[0], L"volume") && (TokenCount > 1)) {
if (FindVolume(&Volume, TokenList[1])) {
- MyFreePool(SubEntry->me.Title);
- SubEntry->me.Title = AllocateZeroPool(256 * sizeof(CHAR16));
- SPrint(SubEntry->me.Title, 255, L"Boot %s from %s", (Title != NULL) ? Title : L"Unknown", Volume->VolName);
- SubEntry->me.BadgeImage = Volume->VolBadgeImage;
- SubEntry->VolName = Volume->VolName;
+ if ((Volume != NULL) && (Volume->IsReadable) && (Volume->RootDir)) {
+ MyFreePool(SubEntry->me.Title);
+ SubEntry->me.Title = AllocateZeroPool(256 * sizeof(CHAR16));
+ SPrint(SubEntry->me.Title, 255, L"Boot %s from %s", (Title != NULL) ? Title : L"Unknown", Volume->VolName);
+ SubEntry->me.BadgeImage = Volume->VolBadgeImage;
+ SubEntry->VolName = Volume->VolName;
+ } // if volume is readable
} // if match found
- } else if (StriCmp(TokenList[0], L"initrd") == 0) {
+ } else if (MyStriCmp(TokenList[0], L"initrd")) {
MyFreePool(SubEntry->InitrdPath);
SubEntry->InitrdPath = NULL;
if (TokenCount > 1) {
SubEntry->InitrdPath = StrDuplicate(TokenList[1]);
}
- } else if (StriCmp(TokenList[0], L"options") == 0) {
+ } else if (MyStriCmp(TokenList[0], L"options")) {
MyFreePool(SubEntry->LoadOptions);
SubEntry->LoadOptions = NULL;
if (TokenCount > 1) {
SubEntry->LoadOptions = StrDuplicate(TokenList[1]);
} // if/else
- } else if ((StriCmp(TokenList[0], L"add_options") == 0) && (TokenCount > 1)) {
+ } else if (MyStriCmp(TokenList[0], L"add_options") && (TokenCount > 1)) {
MergeStrings(&SubEntry->LoadOptions, TokenList[1], L' ');
- } else if ((StriCmp(TokenList[0], L"graphics") == 0) && (TokenCount > 1)) {
- SubEntry->UseGraphicsMode = (StriCmp(TokenList[1], L"on") == 0);
+ } else if (MyStriCmp(TokenList[0], L"graphics") && (TokenCount > 1)) {
+ SubEntry->UseGraphicsMode = MyStriCmp(TokenList[1], L"on");
- } else if (StriCmp(TokenList[0], L"disabled") == 0) {
+ } else if (MyStriCmp(TokenList[0], L"disabled")) {
SubEntry->Enabled = FALSE;
} // ief/elseif
// 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
+ while (((TokenCount = ReadTokenLine(File, &TokenList)) > 0) && (StrCmp(TokenList[0], L"}") != 0)) {
+ if (MyStriCmp(TokenList[0], L"loader") && (TokenCount > 1)) { // set the boot loader filename
Entry->LoaderPath = StrDuplicate(TokenList[1]);
Entry->DevicePath = FileDevicePath(CurrentVolume->DeviceHandle, Entry->LoaderPath);
SetLoaderDefaults(Entry, TokenList[1], CurrentVolume);
Entry->LoadOptions = NULL; // Discard default options, if any
DefaultsSet = TRUE;
- } else if ((StriCmp(TokenList[0], L"volume") == 0) && (TokenCount > 1)) {
+ } else if (MyStriCmp(TokenList[0], L"volume") && (TokenCount > 1)) {
if (FindVolume(&CurrentVolume, TokenList[1])) {
- MyFreePool(Entry->me.Title);
- Entry->me.Title = AllocateZeroPool(256 * sizeof(CHAR16));
- SPrint(Entry->me.Title, 255, L"Boot %s from %s", (Title != NULL) ? Title : L"Unknown", CurrentVolume->VolName);
- Entry->me.BadgeImage = CurrentVolume->VolBadgeImage;
- Entry->VolName = CurrentVolume->VolName;
+ if ((CurrentVolume != NULL) && (CurrentVolume->IsReadable) && (CurrentVolume->RootDir)) {
+ MyFreePool(Entry->me.Title);
+ Entry->me.Title = AllocateZeroPool(256 * sizeof(CHAR16));
+ SPrint(Entry->me.Title, 255, L"Boot %s from %s", (Title != NULL) ? Title : L"Unknown", CurrentVolume->VolName);
+ Entry->me.BadgeImage = CurrentVolume->VolBadgeImage;
+ Entry->VolName = CurrentVolume->VolName;
+ } // if volume is readable
} // if match found
- } else if ((StriCmp(TokenList[0], L"icon") == 0) && (TokenCount > 1)) {
+ } else if (MyStriCmp(TokenList[0], L"icon") && (TokenCount > 1)) {
MyFreePool(Entry->me.Image);
- Entry->me.Image = egLoadIcon(CurrentVolume->RootDir, TokenList[1], 128);
+ Entry->me.Image = egLoadIcon(CurrentVolume->RootDir, TokenList[1], GlobalConfig.IconSizes[ICON_SIZE_BIG]);
if (Entry->me.Image == NULL) {
- Entry->me.Image = DummyImage(128);
+ Entry->me.Image = DummyImage(GlobalConfig.IconSizes[ICON_SIZE_BIG]);
}
- } else if ((StriCmp(TokenList[0], L"initrd") == 0) && (TokenCount > 1)) {
+ } else if (MyStriCmp(TokenList[0], L"initrd") && (TokenCount > 1)) {
MyFreePool(Entry->InitrdPath);
Entry->InitrdPath = StrDuplicate(TokenList[1]);
- } else if ((StriCmp(TokenList[0], L"options") == 0) && (TokenCount > 1)) {
+ } else if (MyStriCmp(TokenList[0], L"options") && (TokenCount > 1)) {
MyFreePool(Entry->LoadOptions);
Entry->LoadOptions = StrDuplicate(TokenList[1]);
- } else if ((StriCmp(TokenList[0], L"ostype") == 0) && (TokenCount > 1)) {
+ } else if (MyStriCmp(TokenList[0], L"ostype") && (TokenCount > 1)) {
if (TokenCount > 1) {
Entry->OSType = TokenList[1][0];
}
- } else if ((StriCmp(TokenList[0], L"graphics") == 0) && (TokenCount > 1)) {
- Entry->UseGraphicsMode = (StriCmp(TokenList[1], L"on") == 0);
+ } else if (MyStriCmp(TokenList[0], L"graphics") && (TokenCount > 1)) {
+ Entry->UseGraphicsMode = MyStriCmp(TokenList[1], L"on");
- } else if (StriCmp(TokenList[0], L"disabled") == 0) {
+ } else if (MyStriCmp(TokenList[0], L"disabled")) {
Entry->Enabled = FALSE;
- } else if ((StriCmp(TokenList[0], L"submenuentry") == 0) && (TokenCount > 1)) {
+ } else if (MyStriCmp(TokenList[0], L"submenuentry") && (TokenCount > 1)) {
AddSubmenu(Entry, File, CurrentVolume, TokenList[1]);
AddedSubmenu = TRUE;
Volume = SelfVolume;
while ((TokenCount = ReadTokenLine(&File, &TokenList)) > 0) {
- if ((StriCmp(TokenList[0], L"menuentry") == 0) && (TokenCount > 1)) {
+ if (MyStriCmp(TokenList[0], L"menuentry") && (TokenCount > 1)) {
Title = StrDuplicate(TokenList[1]);
Entry = AddStanzaEntries(&File, Volume, TokenList[1]);
if (Entry->Enabled) {
if (Entry->me.SubScreen == NULL)
- GenerateSubScreen(Entry, Volume);
+ GenerateSubScreen(Entry, Volume, TRUE);
AddPreparedLoaderEntry(Entry);
} else {
MyFreePool(Entry);
} // if/else
MyFreePool(Title);
- } else if ((StriCmp(TokenList[0], L"include") == 0) && (TokenCount == 2) &&
- (StriCmp(FileName, GlobalConfig.ConfigFilename) == 0)) {
- if (StriCmp(TokenList[1], FileName) != 0) {
+ } else if (MyStriCmp(TokenList[0], L"include") && (TokenCount == 2) &&
+ MyStriCmp(FileName, GlobalConfig.ConfigFilename)) {
+ if (!MyStriCmp(TokenList[1], FileName)) {
ScanUserConfigured(TokenList[1]);
}
while ((TokenCount = ReadTokenLine(Fstab, &TokenList)) > 0) {
if (TokenCount > 2) {
Root[0] = '\0';
- if (StriCmp(TokenList[1], L"\\") == 0) {
+ if (StrCmp(TokenList[1], L"\\") == 0) {
SPrint(Root, 99, L"%s", TokenList[0]);
- } else if (StriCmp(TokenList[2], L"\\") == 0) {
+ } else if (StrCmp(TokenList[2], L"\\") == 0) {
SPrint(Root, 99, L"%s=%s", TokenList[0], TokenList[1]);
} // if/elseif/elseif
if (Root[0] != L'\0') {
FreeTokenLine(&TokenList, &TokenCount);
} // while
- Options->Current8Ptr = (CHAR8 *)Options->Buffer;
- Options->End8Ptr = Options->Current8Ptr + Options->BufferSize;
- Options->Current16Ptr = (CHAR16 *)Options->Buffer;
- Options->End16Ptr = Options->Current16Ptr + (Options->BufferSize >> 1);
+ if (Options->Buffer) {
+ Options->Current8Ptr = (CHAR8 *)Options->Buffer;
+ Options->End8Ptr = Options->Current8Ptr + Options->BufferSize;
+ Options->Current16Ptr = (CHAR16 *)Options->Buffer;
+ Options->End16Ptr = Options->Current16Ptr + (Options->BufferSize >> 1);
+ } else {
+ MyFreePool(Options);
+ Options = NULL;
+ }
MyFreePool(Fstab->Buffer);
MyFreePool(Fstab);
return Options;
} // GenerateOptionsFromEtcFstab()
+// Create options from partition type codes. Specifically, if the earlier
+// partition scan found a partition with a type code corresponding to a root
+// filesystem according to the Freedesktop.org Discoverable Partitions Spec
+// (http://www.freedesktop.org/wiki/Specifications/DiscoverablePartitionsSpec/),
+// this function returns an appropriate file with two lines, one with
+// "ro root=/dev/disk/by-partuuid/{GUID}" and the other with that plus "single".
+// Note that this function returns the LAST partition found with the
+// appropriate type code, so this will work poorly on dual-boot systems or
+// if the type code is set incorrectly.
+static REFIT_FILE * GenerateOptionsFromPartTypes(VOID) {
+ REFIT_FILE *Options = NULL;
+ CHAR16 *Line, *GuidString, *WriteStatus;
+
+ if (GlobalConfig.DiscoveredRoot) {
+ Options = AllocateZeroPool(sizeof(REFIT_FILE));
+ if (Options) {
+ Options->Encoding = ENCODING_UTF16_LE;
+ GuidString = GuidAsString(&(GlobalConfig.DiscoveredRoot->PartGuid));
+ WriteStatus = GlobalConfig.DiscoveredRoot->IsMarkedReadOnly ? L"ro" : L"rw";
+ ToLower(GuidString);
+ if (GuidString) {
+ Line = PoolPrint(L"\"Boot with normal options\" \"%s root=/dev/disk/by-partuuid/%s\"\n", WriteStatus, GuidString);
+ MergeStrings((CHAR16 **) &(Options->Buffer), Line, 0);
+ MyFreePool(Line);
+ Line = PoolPrint(L"\"Boot into single-user mode\" \"%s root=/dev/disk/by-partuuid/%s single\"\n", WriteStatus, GuidString);
+ MergeStrings((CHAR16**) &(Options->Buffer), Line, 0);
+ MyFreePool(Line);
+ MyFreePool(GuidString);
+ } // if (GuidString)
+ Options->BufferSize = StrLen((CHAR16*) Options->Buffer) * sizeof(CHAR16);
+
+ Options->Current8Ptr = (CHAR8 *)Options->Buffer;
+ Options->End8Ptr = Options->Current8Ptr + Options->BufferSize;
+ Options->Current16Ptr = (CHAR16 *)Options->Buffer;
+ Options->End16Ptr = Options->Current16Ptr + (Options->BufferSize >> 1);
+ } // if (Options allocated OK)
+ } // if (partition has root GUID)
+ return Options;
+} // REFIT_FILE * GenerateOptionsFromPartTypes()
// Read a Linux kernel options file for a Linux boot loader into memory. The LoaderPath
// and Volume variables identify the location of the options file, but not its name --
} else { // a filename string is NULL
GoOn = FALSE;
} // if/else
- if (!FileFound)
- File = GenerateOptionsFromEtcFstab(Volume);
MyFreePool(OptionsFilename);
MyFreePool(FullFilename);
OptionsFilename = FullFilename = NULL;
} while (GoOn);
+ if (!FileFound) {
+ // No refind_linux.conf file; look for /etc/fstab and try to pull values from there....
+ File = GenerateOptionsFromEtcFstab(Volume);
+ // If still no joy, try to use Freedesktop.org Discoverable Partitions Spec....
+ if (!File)
+ File = GenerateOptionsFromPartTypes();
+ } // if
return (File);
} // static REFIT_FILE * ReadLinuxOptionsFile()