Modified SIP/CSR feature to work ON MACS when the csr-active-config
[refind] / refind / apple.c
index d9ce975..437b523 100644 (file)
 #include "lib.h"
 #include "screen.h"
 #include "apple.h"
+#include "mystrings.h"
 #include "refit_call_wrapper.h"
 
-CHAR16 *gCsrStatus = NULL;
+CHAR16 gCsrStatus[256];
 
 // 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;
-    }
+// information. If the variable is not present and the firmware is Apple, fake
+// it and claim it's enabled, since that's how OS X 10.11 treats a system with
+// the variable absent.
+EFI_STATUS GetCsrStatus(UINT32 *CsrStatus) {
+    UINT32     *ReturnValue = NULL;
+    UINTN      CsrLength;
+    EFI_GUID   CsrGuid = CSR_GUID;
+    EFI_STATUS Status = EFI_INVALID_PARAMETER;
+
+    if (CsrStatus) {
+        Status = EfivarGetRaw(&CsrGuid, L"csr-active-config", (CHAR8**) &ReturnValue, &CsrLength);
+        if (Status == EFI_SUCCESS) {
+            if (CsrLength == 4) {
+                *CsrStatus = *ReturnValue;
+            } else {
+                Status = EFI_BAD_BUFFER_SIZE;
+                SPrint(gCsrStatus, 255, L" Unknown System Integrity Protection version");
+            }
+            MyFreePool(ReturnValue);
+        } else if ((Status == EFI_NOT_FOUND) && (StriSubCmp(L"Apple", ST->FirmwareVendor))) {
+            *CsrStatus = SIP_ENABLED;
+            Status = EFI_SUCCESS;
+        } // if (Status == EFI_SUCCESS)
+    } // if (CsrStatus)
+    return Status;
 } // 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));
+// Store string describing CSR status value in gCsrStatus variable, which appears
+// on the Info page. If DisplayMessage is TRUE, displays the new value of
+// gCsrStatus on the screen for three seconds.
+VOID RecordgCsrStatus(UINT32 CsrStatus, BOOLEAN DisplayMessage) {
+    EG_PIXEL    BGColor;
+
+    BGColor.b = 255;
+    BGColor.g = 175;
+    BGColor.r = 100;
+    BGColor.a = 0;
 
     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;
@@ -76,64 +78,38 @@ VOID RecordgCsrStatus(INTN CsrStatus) {
         default:
             SPrint(gCsrStatus, 255, L" System Integrity Protection status: 0x%02x", CsrStatus);
     } // switch
-} // VOID RecordgCsrStatus
+    if (DisplayMessage) {
+        egDisplayMessage(gCsrStatus, &BGColor);
+        PauseSeconds(3);
+    } // if
+} // 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]);
+VOID RotateCsrValue(VOID) {
+    UINT32       CurrentValue, TargetCsr;
+    UINT32_LIST  *ListItem;
+    EFI_GUID     CsrGuid = CSR_GUID;
+    EFI_STATUS   Status;
+
+    Status = GetCsrStatus(&CurrentValue);
+    if ((Status == EFI_SUCCESS) && GlobalConfig.CsrValues) {
+        ListItem = GlobalConfig.CsrValues;
+        while ((ListItem != NULL) && (ListItem->Value != CurrentValue))
+            ListItem = ListItem->Next;
+        if (ListItem == NULL || ListItem->Next == NULL) {
+            TargetCsr = GlobalConfig.CsrValues->Value;
         } else {
-            egDisplayMessage(L"Error setting System Integrity Protection status", &BGColor);
+            TargetCsr = ListItem->Next->Value;
         }
-        PauseSeconds(3);
+        Status = EfivarSetRaw(&CsrGuid, L"csr-active-config", (CHAR8 *) &TargetCsr, 4, TRUE);
+        if (Status == EFI_SUCCESS)
+            RecordgCsrStatus(TargetCsr, TRUE);
+        else
+            SPrint(gCsrStatus, 255, L" Error setting System Integrity Protection code.");
     } // if
-    return (INTN) TargetCsr[0];
-} // INTN RotateCsrValue()
+} // VOID RotateCsrValue()
 
 
 /*
@@ -166,7 +142,7 @@ EFI_STATUS SetAppleOSInfo() {
 
     Status = refit_call3_wrapper(BS->LocateProtocol, &apple_set_os_guid, NULL, (VOID**) &SetOs);
 
-    // Not a Mac, so ignore the call....
+    // If not a Mac, ignore the call....
     if ((Status != EFI_SUCCESS) || (!SetOs))
         return EFI_SUCCESS;
 
@@ -186,7 +162,7 @@ EFI_STATUS SetAppleOSInfo() {
                 Print(L"Out of resources in SetAppleOSInfo!\n");
             }
             if ((Status == EFI_SUCCESS) && (SetOs->Version == 2))
-                Status = refit_call1_wrapper (SetOs->SetOsVendor, "Apple Inc.");
+                Status = refit_call1_wrapper (SetOs->SetOsVendor, (CHAR8 *) "Apple Inc.");
             MyFreePool(AppleOSVersion);
         } // if (AppleOSVersion)
     } // if