3 * Functions specific to Apple computers
5 * Copyright (c) 2015 Roderick W. Smith
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
27 #include "refit_call_wrapper.h"
29 CHAR16
*gCsrStatus
= NULL
;
31 // Get CSR (Apple's System Integrity Protection [SIP], or "rootless") status
32 // byte. Return values:
33 // -2 = Call succeeded but returned value of unexpected length, so result
35 // -1 = Call failed; likely not an Apple, or an Apple running OS X version
36 // that doesn't support CSR/SIP
37 // 0-127 = Valid values (as of 11/2015)
38 // 128-255 = High bit set unexpectedly, but value still returned
39 INTN
GetCsrStatus(VOID
) {
42 EFI_GUID CsrGuid
= CSR_GUID
;
45 Status
= EfivarGetRaw(&CsrGuid
, L
"csr-active-config", &CsrValues
, &CsrLength
);
46 if (Status
== EFI_SUCCESS
) {
55 } // INTN GetCsrStatus()
57 // Store string describing CSR status byte in gCsrStatus variable, which appears
59 VOID
RecordgCsrStatus(INTN CsrStatus
) {
60 if (gCsrStatus
== NULL
)
61 gCsrStatus
= AllocateZeroPool(256 * sizeof(CHAR16
));
65 SPrint(gCsrStatus
, 255, L
" System Integrity Protection status is unrecognized");
68 SPrint(gCsrStatus
, 255, L
"System Integrity Protection status is unrecorded");
71 SPrint(gCsrStatus
, 255, L
" System Integrity Protection is enabled (0x%02x)", CsrStatus
);
74 SPrint(gCsrStatus
, 255, L
" System Integrity Protection is disabled (0x%02x)", CsrStatus
);
77 SPrint(gCsrStatus
, 255, L
" System Integrity Protection status: 0x%02x", CsrStatus
);
79 } // VOID RecordgCsrStatus
81 // Find the current CSR status and reset it to the next one in the
82 // GlobalConfig.CsrValues list, or to the first value if the current
83 // value is not on the list.
84 // Returns the value to which the CSR is being set.
85 INTN
RotateCsrValue(VOID
) {
88 CHAR16
*CurrentValueAsString
= NULL
;
89 CHAR16
*TargetValueAsString
= NULL
;
92 EFI_GUID CsrGuid
= CSR_GUID
;
100 CurrentValue
= GetCsrStatus();
101 if ((CurrentValue
>= 0) && GlobalConfig
.CsrValues
) {
102 CurrentValueAsString
= PoolPrint(L
"%02x", CurrentValue
);
103 while (TargetValueAsString
== NULL
) {
104 ListItem
= FindCommaDelimited(GlobalConfig
.CsrValues
, Index
++);
106 if (MyStriCmp(ListItem
, CurrentValueAsString
)) {
107 TargetValueAsString
= FindCommaDelimited(GlobalConfig
.CsrValues
, Index
);
108 if (TargetValueAsString
== NULL
)
109 TargetValueAsString
= FindCommaDelimited(GlobalConfig
.CsrValues
, 0);
112 TargetValueAsString
= FindCommaDelimited(GlobalConfig
.CsrValues
, 0);
114 MyFreePool(ListItem
);
116 TargetCsr
[0] = (CHAR8
) StrToHex(TargetValueAsString
, 0, 2);
117 Status
= EfivarSetRaw(&CsrGuid
, L
"csr-active-config", TargetCsr
, 4, TRUE
);
118 if (Status
== EFI_SUCCESS
) {
119 switch (TargetCsr
[0]) {
121 egDisplayMessage(PoolPrint(L
"Set System Integrity Protection to enabled (0x%x)", (UINTN
) TargetCsr
[0]), &BGColor
);
124 egDisplayMessage(PoolPrint(L
"Set System Integrity Protection status to disabled (0x%x)", (UINTN
) TargetCsr
[0]), &BGColor
);
127 egDisplayMessage(PoolPrint(L
"Set System Integrity Protection status to 0x%x", (UINTN
) TargetCsr
[0]), &BGColor
);
129 RecordgCsrStatus((INTN
) TargetCsr
[0]);
131 egDisplayMessage(L
"Error setting System Integrity Protection status", &BGColor
);
135 return (INTN
) TargetCsr
[0];
136 } // INTN RotateCsrValue()
140 * The below definitions and SetAppleOSInfo() function are based on a GRUB patch
142 * https://lists.gnu.org/archive/html/grub-devel/2013-12/msg00442.html
145 #define EFI_APPLE_SET_OS_PROTOCOL_GUID \
146 { 0xc5c5da95, 0x7d5c, 0x45e6, \
147 { 0xb2, 0xf1, 0x3f, 0xd5, 0x2b, 0xb1, 0x00, 0x77 } \
150 typedef struct EfiAppleSetOsInterface
{
152 EFI_STATUS
EFIAPI (*SetOsVersion
) (IN CHAR8
*Version
);
153 EFI_STATUS
EFIAPI (*SetOsVendor
) (IN CHAR8
*Vendor
);
154 } EfiAppleSetOsInterface
;
156 // Function to tell the firmware that OS X is being launched. This is
157 // required to work around problems on some Macs that don't fully
158 // initialize some hardware (especially video displays) when third-party
159 // OSes are launched in EFI mode.
160 EFI_STATUS
SetAppleOSInfo() {
161 CHAR16
*AppleOSVersion
= NULL
;
162 CHAR8
*AppleOSVersion8
= NULL
;
164 EFI_GUID apple_set_os_guid
= EFI_APPLE_SET_OS_PROTOCOL_GUID
;
165 EfiAppleSetOsInterface
*SetOs
= NULL
;
167 Status
= refit_call3_wrapper(BS
->LocateProtocol
, &apple_set_os_guid
, NULL
, (VOID
**) &SetOs
);
169 // Not a Mac, so ignore the call....
170 if ((Status
!= EFI_SUCCESS
) || (!SetOs
))
173 if ((SetOs
->Version
!= 0) && GlobalConfig
.SpoofOSXVersion
) {
174 AppleOSVersion
= StrDuplicate(L
"Mac OS X");
175 MergeStrings(&AppleOSVersion
, GlobalConfig
.SpoofOSXVersion
, ' ');
176 if (AppleOSVersion
) {
177 AppleOSVersion8
= AllocateZeroPool((StrLen(AppleOSVersion
) + 1) * sizeof(CHAR8
));
178 UnicodeStrToAsciiStr(AppleOSVersion
, AppleOSVersion8
);
179 if (AppleOSVersion8
) {
180 Status
= refit_call1_wrapper (SetOs
->SetOsVersion
, AppleOSVersion8
);
181 if (!EFI_ERROR(Status
))
182 Status
= EFI_SUCCESS
;
183 MyFreePool(AppleOSVersion8
);
185 Status
= EFI_OUT_OF_RESOURCES
;
186 Print(L
"Out of resources in SetAppleOSInfo!\n");
188 if ((Status
== EFI_SUCCESS
) && (SetOs
->Version
== 2))
189 Status
= refit_call1_wrapper (SetOs
->SetOsVendor
, "Apple Inc.");
190 MyFreePool(AppleOSVersion
);
191 } // if (AppleOSVersion)
193 if (Status
!= EFI_SUCCESS
)
194 Print(L
"Unable to set firmware boot type!\n");
197 } // EFI_STATUS SetAppleOSInfo()