]> code.delx.au - refind/commitdiff
Added new "csr_rotate" option for "showtools", and matching
authorsrs5694 <srs5694@users.sourceforge.net>
Wed, 4 Nov 2015 01:37:50 +0000 (20:37 -0500)
committersrs5694 <srs5694@users.sourceforge.net>
Wed, 4 Nov 2015 01:37:50 +0000 (20:37 -0500)
"csr_values" token to specify values through which to rotate, for
setting Apple's System Integrity Protection feature on or off.

12 files changed:
NEWS.txt
refind.conf-sample
refind/Make.tiano
refind/Makefile
refind/apple.c [new file with mode: 0644]
refind/apple.h [new file with mode: 0644]
refind/config.c
refind/global.h
refind/icns.c
refind/icns.h
refind/lib.h
refind/main.c

index f1222876c0859ef6c94f68af8909339578733126..b9898dd8a99deb0ada7ca3256fcd3b45e53013d3 100644 (file)
--- a/NEWS.txt
+++ b/NEWS.txt
@@ -1,6 +1,22 @@
 0.9.3 (??/??/2015):
 -------------------
 
+- Added new System Integrity Protection (SIP) rotation feature for Macs
+  running OS X 10.11 or later. This feature is disabled by default. To
+  enable it, you must make TWO changes to refind.conf: Uncomment the new
+  "csr_values" item and add "csr_rotate" to the "showtools" line
+  (uncommenting it, too, if it's commented out). If desired, you can set
+  more values on "csr_values"; these are comma-delimited one-byte
+  hexadecimal values that define various SIP states.  When SIP/CSR rotation
+  is activated, a new shield icon appears among the tools. Selecting it
+  causes the next defined value to be set and a confirmation message to
+  appear for three seconds.
+
+- Added display of current System Integrity Protection (SIP) mode to
+  "About" display.
+
+- Added mountesp script for OS X to (you guessed it!) mount the ESP.
+
 - Renamed support scripts: install.sh to refind-install, mvrefind.sh to
   mvrefind, and mkrlconf.sh to mkrlconf.
 
index 5ace75def229d1f58dbec68de5eb6a2de22ac62e..2f6c38afb8abc04e50ff8c1edf4729fc5c9f2b93 100644 (file)
@@ -171,6 +171,8 @@ timeout 20
 #                     (see also the windows_recovery_files option)
 #  mok_tool         - makes available the Machine Owner Key (MOK) maintenance
 #                     tool, MokManager.efi, used on Secure Boot systems
+#  csr_rotate       - adjusts Apple System Integrity Protection (SIP)
+#                     policy. Requires "csr_values" to be set.
 #  about            - an "about this program" option
 #  exit             - a tag to exit from rEFInd
 #  shutdown         - shuts down the computer (a bug causes this to reboot
@@ -386,6 +388,22 @@ timeout 20
 #
 #spoof_osx_version "10.9"
 
+# Set the CSR values for Apple's System Integrity Protection (SIP) feature.
+# Values are one-byte (two-character) hexadecimal numbers. These values
+# define which specific security features are enabled. Below are the codes
+# for what the values mean. Add them up (in hexadecimal!) to set new values.
+# Apple's "csrutil enable" and "csrutil disable" commands set values of 10
+# and 77, respectively.
+#   CSR_ALLOW_UNTRUSTED_KEXTS       0x01
+#   CSR_ALLOW_UNRESTRICTED_FS       0x02
+#   CSR_ALLOW_TASK_FOR_PID          0x04
+#   CSR_ALLOW_KERNEL_DEBUGGER       0x08
+#   CSR_ALLOW_APPLE_INTERNAL        0x10
+#   CSR_ALLOW_UNRESTRICTED_DTRACE   0x20
+#   CSR_ALLOW_UNRESTRICTED_NVRAM    0x40
+#
+#csr_values 10,77
+
 # Include a secondary configuration file within this one. This secondary
 # file is loaded as if its options appeared at the point of the "include"
 # token itself, so if you want to override a setting in the main file,
index 4cc17834b2712cba8739c7e56aa4519d7b48c3fa..bda28cfea6e455679420ab5127255f5b473e04ca 100644 (file)
@@ -35,7 +35,7 @@ ALL_EFILIBS     = $(EFILIB)/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevel
 #                /usr/local/UDK2010/MyWorkSpace/Build/MdeModule/RELEASE_GCC46/X64/MdeModulePkg/Core/Dxe/DxeMain/OUTPUT/DxeMain/DxeMain.obj
 
 
-SOURCE_NAMES     = config line_edit driver_support icns lib main menu screen gpt crc32 legacy AutoGen
+SOURCE_NAMES     = apple config line_edit driver_support icns lib main menu screen gpt crc32 legacy AutoGen
 OBJS             = $(SOURCE_NAMES:=.obj)
 
 all: $(BUILDME)
index fe5c247d469c23992f3c835b1b0eb84d289ff453..00735fe9746ad28e77cebe09b8ef36264ba7a8df 100644 (file)
@@ -25,7 +25,7 @@ LOCAL_CPPFLAGS  = -I$(SRCDIR) -I$(SRCDIR)/../include -I$(SRCDIR)/../libeg -I$(SR
 LOCAL_LDFLAGS   = -L$(SRCDIR)/../libeg/ -L$(SRCDIR)/../mok/ -L$(SRCDIR)/../EfiLib/
 LOCAL_LIBS      = -leg -lmok -lEfiLib
 
-OBJS            = main.o line_edit.o config.o menu.o screen.o icns.o gpt.o crc32.o lib.o driver_support.o legacy.o
+OBJS            = main.o apple.o line_edit.o config.o menu.o screen.o icns.o gpt.o crc32.o lib.o driver_support.o legacy.o
 #OBJS            = main.o line_edit.o config.o menu.o screen.o icns.o lib.o mok.o driver_support.o variables.o sha256.o pecoff.o simple_file.o security_policy.o guid.o
 
 all: $(TARGET)
diff --git a/refind/apple.c b/refind/apple.c
new file mode 100644 (file)
index 0000000..d9ce975
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * refind/apple.c
+ * Functions specific to Apple computers
+ * 
+ * Copyright (c) 2015 Roderick W. Smith
+ * 
+ * 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 "config.h"
+#include "lib.h"
+#include "screen.h"
+#include "apple.h"
+#include "refit_call_wrapper.h"
+
+CHAR16 *gCsrStatus = NULL;
+
+// Get CSR (Apple's System Integrity Protection [SIP], or "rootless") status
+// byte. Return values:
+// -2      = Call succeeded but returned value of unexpected length, so result
+//           is suspect
+// -1      = Call failed; likely not an Apple, or an Apple running OS X version
+//           that doesn't support CSR/SIP
+// 0-127   = Valid values (as of 11/2015)
+// 128-255 = High bit set unexpectedly, but value still returned
+INTN GetCsrStatus(VOID) {
+    CHAR8 *CsrValues;
+    UINTN CsrLength;
+    EFI_GUID CsrGuid = CSR_GUID;
+    EFI_STATUS Status;
+
+    Status = EfivarGetRaw(&CsrGuid, L"csr-active-config", &CsrValues, &CsrLength);
+    if (Status == EFI_SUCCESS) {
+        if (CsrLength == 4) {
+            return CsrValues[0];
+        } else {
+            return -2;
+        }
+    } else {
+        return -1;
+    }
+} // INTN GetCsrStatus()
+
+// Store string describing CSR status byte in gCsrStatus variable, which appears
+// on the Info page.
+VOID RecordgCsrStatus(INTN CsrStatus) {
+    if (gCsrStatus == NULL)
+        gCsrStatus = AllocateZeroPool(256 * sizeof(CHAR16));
+
+    switch (CsrStatus) {
+        case -2:
+            SPrint(gCsrStatus, 255, L" System Integrity Protection status is unrecognized");
+            break;
+        case -1:
+            SPrint(gCsrStatus, 255, L"System Integrity Protection status is unrecorded");
+            break;
+        case SIP_ENABLED:
+            SPrint(gCsrStatus, 255, L" System Integrity Protection is enabled (0x%02x)", CsrStatus);
+            break;
+        case SIP_DISABLED:
+            SPrint(gCsrStatus, 255, L" System Integrity Protection is disabled (0x%02x)", CsrStatus);
+            break;
+        default:
+            SPrint(gCsrStatus, 255, L" System Integrity Protection status: 0x%02x", CsrStatus);
+    } // switch
+} // VOID RecordgCsrStatus
+
+// Find the current CSR status and reset it to the next one in the
+// GlobalConfig.CsrValues list, or to the first value if the current
+// value is not on the list.
+// Returns the value to which the CSR is being set.
+INTN RotateCsrValue(VOID) {
+    INTN        CurrentValue;
+    UINTN       Index = 0;
+    CHAR16      *CurrentValueAsString = NULL;
+    CHAR16      *TargetValueAsString = NULL;
+    CHAR16      *ListItem;
+    CHAR8       TargetCsr[4];
+    EFI_GUID    CsrGuid = CSR_GUID;
+    EFI_STATUS  Status;
+    EG_PIXEL    BGColor;
+
+    BGColor.b = 255;
+    BGColor.g = 175;
+    BGColor.r = 100;
+    BGColor.a = 0;
+    CurrentValue = GetCsrStatus();
+    if ((CurrentValue >= 0) && GlobalConfig.CsrValues) {
+        CurrentValueAsString = PoolPrint(L"%02x", CurrentValue);
+        while (TargetValueAsString == NULL) {
+            ListItem = FindCommaDelimited(GlobalConfig.CsrValues, Index++);
+            if (ListItem) {
+                if (MyStriCmp(ListItem, CurrentValueAsString)) {
+                    TargetValueAsString = FindCommaDelimited(GlobalConfig.CsrValues, Index);
+                    if (TargetValueAsString == NULL)
+                        TargetValueAsString = FindCommaDelimited(GlobalConfig.CsrValues, 0);
+                }
+            } else {
+                TargetValueAsString = FindCommaDelimited(GlobalConfig.CsrValues, 0);
+            } // if/else
+            MyFreePool(ListItem);
+        } // while
+        TargetCsr[0] = (CHAR8) StrToHex(TargetValueAsString, 0, 2);
+        Status = EfivarSetRaw(&CsrGuid, L"csr-active-config", TargetCsr, 4, TRUE);
+        if (Status == EFI_SUCCESS) {
+            switch (TargetCsr[0]) {
+                case SIP_ENABLED:
+                    egDisplayMessage(PoolPrint(L"Set System Integrity Protection to enabled (0x%x)", (UINTN) TargetCsr[0]), &BGColor);
+                    break;
+                case SIP_DISABLED:
+                    egDisplayMessage(PoolPrint(L"Set System Integrity Protection status to disabled (0x%x)", (UINTN) TargetCsr[0]), &BGColor);
+                    break;
+                default:
+                    egDisplayMessage(PoolPrint(L"Set System Integrity Protection status to 0x%x", (UINTN) TargetCsr[0]), &BGColor);
+            }
+            RecordgCsrStatus((INTN) TargetCsr[0]);
+        } else {
+            egDisplayMessage(L"Error setting System Integrity Protection status", &BGColor);
+        }
+        PauseSeconds(3);
+    } // if
+    return (INTN) TargetCsr[0];
+} // INTN RotateCsrValue()
+
+
+/*
+ * The below definitions and SetAppleOSInfo() function are based on a GRUB patch
+ * by Andreas Heider:
+ * https://lists.gnu.org/archive/html/grub-devel/2013-12/msg00442.html
+ */
+
+#define EFI_APPLE_SET_OS_PROTOCOL_GUID  \
+  { 0xc5c5da95, 0x7d5c, 0x45e6, \
+    { 0xb2, 0xf1, 0x3f, 0xd5, 0x2b, 0xb1, 0x00, 0x77 } \
+  }
+
+typedef struct EfiAppleSetOsInterface {
+    UINT64 Version;
+    EFI_STATUS EFIAPI (*SetOsVersion) (IN CHAR8 *Version);
+    EFI_STATUS EFIAPI (*SetOsVendor) (IN CHAR8 *Vendor);
+} EfiAppleSetOsInterface;
+
+// Function to tell the firmware that OS X is being launched. This is
+// required to work around problems on some Macs that don't fully
+// initialize some hardware (especially video displays) when third-party
+// OSes are launched in EFI mode.
+EFI_STATUS SetAppleOSInfo() {
+    CHAR16 *AppleOSVersion = NULL;
+    CHAR8 *AppleOSVersion8 = NULL;
+    EFI_STATUS Status;
+    EFI_GUID apple_set_os_guid = EFI_APPLE_SET_OS_PROTOCOL_GUID;
+    EfiAppleSetOsInterface *SetOs = NULL;
+
+    Status = refit_call3_wrapper(BS->LocateProtocol, &apple_set_os_guid, NULL, (VOID**) &SetOs);
+
+    // Not a Mac, so ignore the call....
+    if ((Status != EFI_SUCCESS) || (!SetOs))
+        return EFI_SUCCESS;
+
+    if ((SetOs->Version != 0) && GlobalConfig.SpoofOSXVersion) {
+        AppleOSVersion = StrDuplicate(L"Mac OS X");
+        MergeStrings(&AppleOSVersion, GlobalConfig.SpoofOSXVersion, ' ');
+        if (AppleOSVersion) {
+            AppleOSVersion8 = AllocateZeroPool((StrLen(AppleOSVersion) + 1) * sizeof(CHAR8));
+            UnicodeStrToAsciiStr(AppleOSVersion, AppleOSVersion8);
+            if (AppleOSVersion8) {
+                Status = refit_call1_wrapper (SetOs->SetOsVersion, AppleOSVersion8);
+                if (!EFI_ERROR(Status))
+                    Status = EFI_SUCCESS;
+                MyFreePool(AppleOSVersion8);
+            } else {
+                Status = EFI_OUT_OF_RESOURCES;
+                Print(L"Out of resources in SetAppleOSInfo!\n");
+            }
+            if ((Status == EFI_SUCCESS) && (SetOs->Version == 2))
+                Status = refit_call1_wrapper (SetOs->SetOsVendor, "Apple Inc.");
+            MyFreePool(AppleOSVersion);
+        } // if (AppleOSVersion)
+    } // if
+    if (Status != EFI_SUCCESS)
+        Print(L"Unable to set firmware boot type!\n");
+
+    return (Status);
+} // EFI_STATUS SetAppleOSInfo()
\ No newline at end of file
diff --git a/refind/apple.h b/refind/apple.h
new file mode 100644 (file)
index 0000000..33fd5b2
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * refind/apple.h
+ * 
+ * Copyright (c) 2015 Roderick W. Smith
+ * 
+ * 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/>.
+ *
+ */
+
+extern CHAR16 *gCsrStatus;
+
+INTN GetCsrStatus(VOID);
+VOID RecordgCsrStatus(INTN CsrStatus);
+INTN RotateCsrValue(VOID);
+EFI_STATUS SetAppleOSInfo();
index 2ee92779d2c9e6f05f7d5528bfbd9d7dd121d328..e54e56bc0cf8a0516a96fb9a8e65b4bf873f2a14 100644 (file)
@@ -605,6 +605,8 @@ VOID ReadConfig(CHAR16 *FileName)
                    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")) {
@@ -704,6 +706,9 @@ VOID ReadConfig(CHAR16 *FileName)
         } else if (MyStriCmp(TokenList[0], L"spoof_osx_version")) {
             HandleString(TokenList, TokenCount, &(GlobalConfig.SpoofOSXVersion));
 
+        } else if (MyStriCmp(TokenList[0], L"csr_values")) {
+            HandleStrings(TokenList, TokenCount, &(GlobalConfig.CsrValues));
+
         } else if (MyStriCmp(TokenList[0], L"include") && (TokenCount == 2) && MyStriCmp(FileName, GlobalConfig.ConfigFilename)) {
            if (!MyStriCmp(TokenList[1], FileName)) {
               ReadConfig(TokenList[1]);
index d7a8821d3d754bfc797085f612fb664706c1b72a..a07e0c90d74f4815e00dcecf942f8fdb77f49de7 100644 (file)
@@ -75,7 +75,8 @@
 #define TAG_MEMTEST          (15)
 #define TAG_GDISK            (16)
 #define TAG_NETBOOT          (17)
-#define NUM_TOOLS            (18)
+#define TAG_CSR_ROTATE       (18)
+#define NUM_TOOLS            (19)
 
 #define NUM_SCAN_OPTIONS 10
 
@@ -325,6 +326,7 @@ typedef struct {
    CHAR16           *DriverDirs;
    CHAR16           *IconsDir;
    CHAR16           *SpoofOSXVersion;
+   CHAR16           *CsrValues;
    UINTN            ShowTools[NUM_TOOLS];
    CHAR8            ScanFor[NUM_SCAN_OPTIONS]; // codes of types of loaders for which to scan
 } REFIT_CONFIG;
index 5438afdc49908b3517cca3cdfd26e59b770b307a..f091e41366fc1c17b8b04aa581c463efbb2e51fc 100644 (file)
@@ -56,6 +56,7 @@ BUILTIN_ICON BuiltinIconTable[BUILTIN_ICON_COUNT] = {
    { NULL, L"func_shutdown", ICON_SIZE_SMALL },
    { NULL, L"func_exit", ICON_SIZE_SMALL },
    { NULL, L"func_firmware", ICON_SIZE_SMALL },
+   { NULL, L"func_csr_rotate", ICON_SIZE_SMALL },
    { NULL, L"tool_shell", ICON_SIZE_SMALL },
    { NULL, L"tool_part", ICON_SIZE_SMALL },
    { NULL, L"tool_rescue", ICON_SIZE_SMALL },
index 17e91ee468bea32d94868c2432ba08bb1971ca3d..2a6f92bdec5eb8018b8cf1558759e3459691fca0 100644 (file)
@@ -60,19 +60,20 @@ EG_IMAGE * BuiltinIcon(IN UINTN Id);
 #define BUILTIN_ICON_FUNC_SHUTDOWN         (2)
 #define BUILTIN_ICON_FUNC_EXIT             (3)
 #define BUILTIN_ICON_FUNC_FIRMWARE         (4)
-#define BUILTIN_ICON_TOOL_SHELL            (5)
-#define BUILTIN_ICON_TOOL_PART             (6)
-#define BUILTIN_ICON_TOOL_RESCUE           (7)
-#define BUILTIN_ICON_TOOL_APPLE_RESCUE     (8)
-#define BUILTIN_ICON_TOOL_WINDOWS_RESCUE   (9)
-#define BUILTIN_ICON_TOOL_MOK_TOOL         (10)
-#define BUILTIN_ICON_TOOL_MEMTEST          (11)
-#define BUILTIN_ICON_TOOL_NETBOOT          (12)
-#define BUILTIN_ICON_VOL_INTERNAL          (13)
-#define BUILTIN_ICON_VOL_EXTERNAL          (14)
-#define BUILTIN_ICON_VOL_OPTICAL           (15)
-#define BUILTIN_ICON_VOL_NET               (16)
-#define BUILTIN_ICON_COUNT                 (17)
+#define BUILTIN_ICON_FUNC_CSR_ROTATE       (5)
+#define BUILTIN_ICON_TOOL_SHELL            (6)
+#define BUILTIN_ICON_TOOL_PART             (7)
+#define BUILTIN_ICON_TOOL_RESCUE           (8)
+#define BUILTIN_ICON_TOOL_APPLE_RESCUE     (9)
+#define BUILTIN_ICON_TOOL_WINDOWS_RESCUE   (10)
+#define BUILTIN_ICON_TOOL_MOK_TOOL         (11)
+#define BUILTIN_ICON_TOOL_MEMTEST          (12)
+#define BUILTIN_ICON_TOOL_NETBOOT          (13)
+#define BUILTIN_ICON_VOL_INTERNAL          (14)
+#define BUILTIN_ICON_VOL_EXTERNAL          (15)
+#define BUILTIN_ICON_VOL_OPTICAL           (16)
+#define BUILTIN_ICON_VOL_NET               (17)
+#define BUILTIN_ICON_COUNT                 (18)
 
 #endif
 
index 2da1e21fd32ac63947a720deb76a77054a32d71b..376efd7604440e5409873098a2a59697f18f860c 100644 (file)
@@ -133,7 +133,7 @@ BOOLEAN SplitVolumeAndFilename(IN OUT CHAR16 **Path, OUT CHAR16 **VolName);
 CHAR16 *FindNumbers(IN CHAR16 *InString);
 CHAR16 *FindCommaDelimited(IN CHAR16 *InString, IN UINTN Index);
 VOID SplitPathName(CHAR16 *InPath, CHAR16 **VolName, CHAR16 **Path, CHAR16 **Filename);
-BOOLEAN IsIn(IN CHAR16 *Filename, IN CHAR16 *List);
+BOOLEAN IsIn(IN CHAR16 *SmallString, IN CHAR16 *List);
 BOOLEAN IsInSubstring(IN CHAR16 *BigString, IN CHAR16 *List);
 BOOLEAN FilenameIn(IN REFIT_VOLUME *Volume, IN CHAR16 *Directory, IN CHAR16 *Filename, IN CHAR16 *List);
 BOOLEAN VolumeNumberToName(REFIT_VOLUME *Volume, CHAR16 **VolName);
index 690816996b2e4a93b0eb475225448710166a0dcb..f16908609db6940cdf45da3be38f02acb056d117 100644 (file)
@@ -64,6 +64,7 @@
 #include "menu.h"
 #include "mok.h"
 #include "gpt.h"
+#include "apple.h"
 #include "security_policy.h"
 #include "driver_support.h"
 #include "../include/Handle.h"
@@ -150,6 +151,7 @@ static REFIT_MENU_ENTRY MenuEntryShutdown = { L"Shut Down Computer", TAG_SHUTDOW
 REFIT_MENU_ENTRY MenuEntryReturn   = { L"Return to Main Menu", TAG_RETURN, 1, 0, 0, NULL, NULL, NULL };
 static REFIT_MENU_ENTRY MenuEntryExit     = { L"Exit rEFInd", TAG_EXIT, 1, 0, 0, NULL, NULL, NULL };
 static REFIT_MENU_ENTRY MenuEntryFirmware = { L"Reboot to Computer Setup Utility", TAG_FIRMWARE, 1, 0, 0, NULL, NULL, NULL };
+static REFIT_MENU_ENTRY MenuEntryRotateCsr = { L"Change SIP Policy", TAG_CSR_ROTATE, 1, 0, 0, NULL, NULL, NULL };
 
 REFIT_MENU_SCREEN MainMenu       = { L"Main Menu", NULL, 0, NULL, 0, NULL, 0, L"Automatic boot",
                                      L"Use arrow keys to move cursor; Enter to boot;",
@@ -160,7 +162,7 @@ REFIT_CONFIG GlobalConfig = { FALSE, TRUE, FALSE, FALSE, TRUE, 0, 0, 0, DONT_CHA
                               20, 0, 0, GRAPHICS_FOR_OSX, LEGACY_TYPE_MAC,
                               0, 0, { DEFAULT_BIG_ICON_SIZE / 4, DEFAULT_SMALL_ICON_SIZE, DEFAULT_BIG_ICON_SIZE },
                               BANNER_NOSCALE, NULL, NULL, NULL, NULL, CONFIG_FILE_NAME, NULL, NULL, NULL, NULL,
-                              NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                              NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                               { TAG_SHELL, TAG_MEMTEST, TAG_GDISK, TAG_APPLE_RECOVERY, TAG_WINDOWS_RECOVERY,
                                 TAG_MOK_TOOL, TAG_ABOUT, TAG_SHUTDOWN, TAG_REBOOT, TAG_FIRMWARE,
                                 0, 0, 0, 0, 0, 0, 0, 0 }
@@ -183,26 +185,14 @@ struct LOADER_LIST {
 // misc functions
 //
 
-static INTN GetCsrStatus(VOID) {
-    CHAR8 *CsrValues;
-    UINTN CsrLength;
-    EFI_GUID CsrGuid = CSR_GUID;
-    EFI_STATUS Status;
-
-    Status = EfivarGetRaw(&CsrGuid, L"csr-active-config", &CsrValues, &CsrLength);
-    if ((Status == EFI_SUCCESS) && (CsrLength == 4))
-        return CsrValues[0];
-    else
-        return -1;
-} // INTN GetCsrStatus()
-
 static VOID AboutrEFInd(VOID)
 {
     CHAR16 *FirmwareVendor;
+    INTN   CsrStatus;
 
     if (AboutMenu.EntryCount == 0) {
         AboutMenu.TitleImage = BuiltinIcon(BUILTIN_ICON_FUNC_ABOUT);
-        AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.9.2.5");
+        AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.9.2.6");
         AddMenuInfoLine(&AboutMenu, L"");
         AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2006-2010 Christoph Pfisterer");
         AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2012-2015 Roderick W. Smith");
@@ -220,18 +210,10 @@ static VOID AboutrEFInd(VOID)
 #else
         AddMenuInfoLine(&AboutMenu, L" Platform: unknown");
 #endif
-        if (StriSubCmp(L"Apple", ST->FirmwareVendor)) {
-            switch (GetCsrStatus()) {
-                case SIP_ENABLED:
-                    AddMenuInfoLine(&AboutMenu, L" System Integrity Protection is enabled");
-                    break;
-                case SIP_DISABLED:
-                    AddMenuInfoLine(&AboutMenu, L" System Integrity Protection is disabled");
-                    break;
-                default:
-                    AddMenuInfoLine(&AboutMenu, L" System Integrity Protection status is unrecognized");
-            } // switch
-        } // if
+        CsrStatus = GetCsrStatus();
+        RecordgCsrStatus(CsrStatus);
+        if ((CsrStatus == -2) || (CsrStatus >= 0))
+            AddMenuInfoLine(&AboutMenu, gCsrStatus);
         FirmwareVendor = StrDuplicate(ST->FirmwareVendor);
         LimitStringLength(FirmwareVendor, MAX_LINE_LENGTH); // More than ~65 causes empty info page on 800x600 display
         AddMenuInfoLine(&AboutMenu, PoolPrint(L" Firmware: %s %d.%02d", FirmwareVendor, ST->FirmwareRevision >> 16,
@@ -2060,6 +2042,14 @@ static VOID ScanForTools(VOID) {
                 FindTool(MokLocations, MOK_NAMES, L"MOK utility", BUILTIN_ICON_TOOL_MOK_TOOL);
                 break;
 
+            case TAG_CSR_ROTATE:
+                if ((GetCsrStatus() >= 0) && (GlobalConfig.CsrValues)) {
+                    TempMenuEntry = CopyMenuEntry(&MenuEntryRotateCsr);
+                    TempMenuEntry->Image = BuiltinIcon(BUILTIN_ICON_FUNC_CSR_ROTATE);
+                    AddMenuEntry(&MainMenu, TempMenuEntry);
+                } // if
+                break;
+
             case TAG_MEMTEST:
                 FindTool(MEMTEST_LOCATIONS, MEMTEST_NAMES, L"Memory test utility", BUILTIN_ICON_TOOL_MEMTEST);
                 break;
@@ -2169,66 +2159,6 @@ static VOID SetConfigFilename(EFI_HANDLE ImageHandle) {
     } // if
 } // VOID SetConfigFilename()
 
-/*
- * The below definitions and SetAppleOSInfo() function are based on a GRUB patch
- * by Andreas Heider:
- * https://lists.gnu.org/archive/html/grub-devel/2013-12/msg00442.html
- */
-
-#define EFI_APPLE_SET_OS_PROTOCOL_GUID  \
-  { 0xc5c5da95, 0x7d5c, 0x45e6, \
-    { 0xb2, 0xf1, 0x3f, 0xd5, 0x2b, 0xb1, 0x00, 0x77 } \
-  }
-
-typedef struct EfiAppleSetOsInterface {
-    UINT64 Version;
-    EFI_STATUS EFIAPI (*SetOsVersion) (IN CHAR8 *Version);
-    EFI_STATUS EFIAPI (*SetOsVendor) (IN CHAR8 *Vendor);
-} EfiAppleSetOsInterface;
-
-// Function to tell the firmware that OS X is being launched. This is
-// required to work around problems on some Macs that don't fully
-// initialize some hardware (especially video displays) when third-party
-// OSes are launched in EFI mode.
-static EFI_STATUS SetAppleOSInfo() {
-    CHAR16 *AppleOSVersion = NULL;
-    CHAR8 *AppleOSVersion8 = NULL;
-    EFI_STATUS Status;
-    EFI_GUID apple_set_os_guid = EFI_APPLE_SET_OS_PROTOCOL_GUID;
-    EfiAppleSetOsInterface *SetOs = NULL;
-
-    Status = refit_call3_wrapper(BS->LocateProtocol, &apple_set_os_guid, NULL, (VOID**) &SetOs);
-
-    // Not a Mac, so ignore the call....
-    if ((Status != EFI_SUCCESS) || (!SetOs))
-        return EFI_SUCCESS;
-
-    if ((SetOs->Version != 0) && GlobalConfig.SpoofOSXVersion) {
-        AppleOSVersion = StrDuplicate(L"Mac OS X");
-        MergeStrings(&AppleOSVersion, GlobalConfig.SpoofOSXVersion, ' ');
-        if (AppleOSVersion) {
-            AppleOSVersion8 = AllocateZeroPool((StrLen(AppleOSVersion) + 1) * sizeof(CHAR8));
-            UnicodeStrToAsciiStr(AppleOSVersion, AppleOSVersion8);
-            if (AppleOSVersion8) {
-                Status = refit_call1_wrapper (SetOs->SetOsVersion, AppleOSVersion8);
-                if (!EFI_ERROR(Status))
-                    Status = EFI_SUCCESS;
-                MyFreePool(AppleOSVersion8);
-            } else {
-                Status = EFI_OUT_OF_RESOURCES;
-                Print(L"Out of resources in SetAppleOSInfo!\n");
-            }
-            if ((Status == EFI_SUCCESS) && (SetOs->Version == 2))
-                Status = refit_call1_wrapper (SetOs->SetOsVendor, "Apple Inc.");
-            MyFreePool(AppleOSVersion);
-        } // if (AppleOSVersion)
-    } // if
-    if (Status != EFI_SUCCESS)
-        Print(L"Unable to set firmware boot type!\n");
-
-    return (Status);
-} // EFI_STATUS SetAppleOSInfo()
-
 //
 // main entry point
 //
@@ -2348,6 +2278,10 @@ efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
                 RebootIntoFirmware();
                 break;
 
+            case TAG_CSR_ROTATE:
+                RotateCsrValue();
+                break;
+
         } // switch()
     } // while()