*/
/*
- * Modifications copyright (c) 2012-2014 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
#include "config.h"
#include "screen.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;
// 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()
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) {
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);
GlobalConfig.HideUIFlags |= HIDEUI_FLAG_EDITOR;
} else if (StriCmp(FlagName, L"safemode") == 0) {
GlobalConfig.HideUIFlags |= HIDEUI_FLAG_SAFEMODE;
+ } else if (StriCmp(FlagName, L"badges") == 0) {
+ GlobalConfig.HideUIFlags |= HIDEUI_FLAG_BADGES;
} else if (StriCmp(FlagName, L"all") == 0) {
GlobalConfig.HideUIFlags = HIDEUI_FLAG_ALL;
} else {
GlobalConfig.ShowTools[i - 1] = TAG_FIRMWARE;
} else if ((StriCmp(FlagName, L"memtest86") == 0) || (StriCmp(FlagName, L"memtest") == 0)) {
GlobalConfig.ShowTools[i - 1] = TAG_MEMTEST;
+ } else if (StriCmp(FlagName, L"netboot") == 0) {
+ GlobalConfig.ShowTools[i - 1] = TAG_NETBOOT;
} else {
Print(L" unknown showtools flag: '%s'\n", FlagName);
}
} else if (StriCmp(TokenList[0], L"textonly") == 0) {
GlobalConfig.TextOnly = HandleBoolean(TokenList, TokenCount);
-// if ((TokenCount >= 2) && (StriCmp(TokenList[1], L"0") == 0)) {
-// GlobalConfig.TextOnly = FALSE;
-// } else {
-// GlobalConfig.TextOnly = TRUE;
-// }
} else if (StriCmp(TokenList[0], L"textmode") == 0) {
HandleInt(TokenList, TokenCount, &(GlobalConfig.RequestedTextMode));
} else if (StriCmp(TokenList[0], L"scan_all_linux_kernels") == 0) {
GlobalConfig.ScanAllLinux = HandleBoolean(TokenList, TokenCount);
-// if ((TokenCount >= 2) && (StriCmp(TokenList[1], L"0") == 0)) {
-// GlobalConfig.ScanAllLinux = FALSE;
-// } else {
-// GlobalConfig.ScanAllLinux = TRUE;
-// }
+
+ } else if (StriCmp(TokenList[0], L"fold_linux_kernels") == 0) {
+ GlobalConfig.FoldLinuxKernels = HandleBoolean(TokenList, TokenCount);
} else if (StriCmp(TokenList[0], L"max_tags") == 0) {
HandleInt(TokenList, TokenCount, &(GlobalConfig.MaxTags));
+ } else if (StriCmp(TokenList[0], L"enable_and_lock_vmx") == 0) {
+ GlobalConfig.EnableAndLockVMX = HandleBoolean(TokenList, TokenCount);
+
} else if ((StriCmp(TokenList[0], L"include") == 0) && (TokenCount == 2) &&
(StriCmp(FileName, GlobalConfig.ConfigFilename) == 0)) {
if (StriCmp(TokenList[1], FileName) != 0) {
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 filesystem label, a
} else if ((StriCmp(TokenList[0], L"volume") == 0) && (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 ((StriCmp(TokenList[0], L"volume") == 0) && (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)) {
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);
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=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;
+
+ if (GlobalConfig.DiscoveredRoot) {
+ Options = AllocateZeroPool(sizeof(REFIT_FILE));
+ if (Options) {
+ Options->Encoding = ENCODING_UTF16_LE;
+ GuidString = GuidAsString(&(GlobalConfig.DiscoveredRoot->PartGuid));
+ ToLower(GuidString);
+ if (GuidString) {
+ Line = PoolPrint(L"\"Boot with normal options\" \"ro root=/dev/disk/by-partuuid/%s\"\n", GuidString);
+ MergeStrings((CHAR16 **) &(Options->Buffer), Line, 0);
+ MyFreePool(Line);
+ Line = PoolPrint(L"\"Boot into single-user mode\" \"ro root=/dev/disk/by-partuuid/%s single\"\n", 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()