* 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"
} // 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
GlobalConfig.ShowTools[i - 1] = TAG_WINDOWS_RECOVERY;
} else if (MyStriCmp(FlagName, L"mok_tool")) {
GlobalConfig.ShowTools[i - 1] = TAG_MOK_TOOL;
+ } 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 (MyStriCmp(FlagName, L"memtest86") || MyStriCmp(FlagName, L"memtest")) {
} else if (MyStriCmp(TokenList[0], L"max_tags")) {
HandleInt(TokenList, TokenCount, &(GlobalConfig.MaxTags));
- } else if (MyStriCmp(TokenList[0], L"enable_and_lock_vmx")) {
- GlobalConfig.EnableAndLockVMX = HandleBoolean(TokenList, TokenCount);
+ } 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)) {
// 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".
+// "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;
+ 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\" \"ro root=/dev/disk/by-partuuid/%s\"\n", 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\" \"ro root=/dev/disk/by-partuuid/%s single\"\n", GuidString);
+ 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);