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 "mystrings.h"
28 #include "refit_call_wrapper.h"
30 CHAR16 gCsrStatus
[256];
32 // Get CSR (Apple's System Integrity Protection [SIP], or "rootless") status
33 // information. If the variable is not present and the firmware is Apple, fake
34 // it and claim it's enabled, since that's how OS X 10.11 treats a system with
35 // the variable absent.
36 EFI_STATUS
GetCsrStatus(UINT32
*CsrStatus
) {
37 UINT32
*ReturnValue
= NULL
;
39 EFI_GUID CsrGuid
= CSR_GUID
;
40 EFI_STATUS Status
= EFI_INVALID_PARAMETER
;
43 Status
= EfivarGetRaw(&CsrGuid
, L
"csr-active-config", (CHAR8
**) &ReturnValue
, &CsrLength
);
44 if (Status
== EFI_SUCCESS
) {
46 *CsrStatus
= *ReturnValue
;
48 Status
= EFI_BAD_BUFFER_SIZE
;
49 SPrint(gCsrStatus
, 255, L
" Unknown System Integrity Protection version");
51 MyFreePool(ReturnValue
);
52 } else if ((Status
== EFI_NOT_FOUND
) && (StriSubCmp(L
"Apple", ST
->FirmwareVendor
))) {
53 *CsrStatus
= SIP_ENABLED
;
55 } // if (Status == EFI_SUCCESS)
58 } // INTN GetCsrStatus()
60 // Store string describing CSR status value in gCsrStatus variable, which appears
61 // on the Info page. If DisplayMessage is TRUE, displays the new value of
62 // gCsrStatus on the screen for three seconds.
63 VOID
RecordgCsrStatus(UINT32 CsrStatus
, BOOLEAN DisplayMessage
) {
73 SPrint(gCsrStatus
, 255, L
" System Integrity Protection is enabled (0x%02x)", CsrStatus
);
76 SPrint(gCsrStatus
, 255, L
" System Integrity Protection is disabled (0x%02x)", CsrStatus
);
79 SPrint(gCsrStatus
, 255, L
" System Integrity Protection status: 0x%02x", CsrStatus
);
82 egDisplayMessage(gCsrStatus
, &BGColor
);
85 } // VOID RecordgCsrStatus()
87 // Find the current CSR status and reset it to the next one in the
88 // GlobalConfig.CsrValues list, or to the first value if the current
89 // value is not on the list.
90 VOID
RotateCsrValue(VOID
) {
91 UINT32 CurrentValue
, TargetCsr
;
92 UINT32_LIST
*ListItem
;
93 EFI_GUID CsrGuid
= CSR_GUID
;
96 Status
= GetCsrStatus(&CurrentValue
);
97 if ((Status
== EFI_SUCCESS
) && GlobalConfig
.CsrValues
) {
98 ListItem
= GlobalConfig
.CsrValues
;
99 while ((ListItem
!= NULL
) && (ListItem
->Value
!= CurrentValue
))
100 ListItem
= ListItem
->Next
;
101 if (ListItem
== NULL
|| ListItem
->Next
== NULL
) {
102 TargetCsr
= GlobalConfig
.CsrValues
->Value
;
104 TargetCsr
= ListItem
->Next
->Value
;
106 Status
= EfivarSetRaw(&CsrGuid
, L
"csr-active-config", (CHAR8
*) &TargetCsr
, 4, TRUE
);
107 if (Status
== EFI_SUCCESS
)
108 RecordgCsrStatus(TargetCsr
, TRUE
);
110 SPrint(gCsrStatus
, 255, L
" Error setting System Integrity Protection code.");
112 } // VOID RotateCsrValue()
116 * The below definitions and SetAppleOSInfo() function are based on a GRUB patch
118 * https://lists.gnu.org/archive/html/grub-devel/2013-12/msg00442.html
121 #define EFI_APPLE_SET_OS_PROTOCOL_GUID \
122 { 0xc5c5da95, 0x7d5c, 0x45e6, \
123 { 0xb2, 0xf1, 0x3f, 0xd5, 0x2b, 0xb1, 0x00, 0x77 } \
126 typedef struct EfiAppleSetOsInterface
{
128 EFI_STATUS
EFIAPI (*SetOsVersion
) (IN CHAR8
*Version
);
129 EFI_STATUS
EFIAPI (*SetOsVendor
) (IN CHAR8
*Vendor
);
130 } EfiAppleSetOsInterface
;
132 // Function to tell the firmware that OS X is being launched. This is
133 // required to work around problems on some Macs that don't fully
134 // initialize some hardware (especially video displays) when third-party
135 // OSes are launched in EFI mode.
136 EFI_STATUS
SetAppleOSInfo() {
137 CHAR16
*AppleOSVersion
= NULL
;
138 CHAR8
*AppleOSVersion8
= NULL
;
140 EFI_GUID apple_set_os_guid
= EFI_APPLE_SET_OS_PROTOCOL_GUID
;
141 EfiAppleSetOsInterface
*SetOs
= NULL
;
143 Status
= refit_call3_wrapper(BS
->LocateProtocol
, &apple_set_os_guid
, NULL
, (VOID
**) &SetOs
);
145 // If not a Mac, ignore the call....
146 if ((Status
!= EFI_SUCCESS
) || (!SetOs
))
149 if ((SetOs
->Version
!= 0) && GlobalConfig
.SpoofOSXVersion
) {
150 AppleOSVersion
= StrDuplicate(L
"Mac OS X");
151 MergeStrings(&AppleOSVersion
, GlobalConfig
.SpoofOSXVersion
, ' ');
152 if (AppleOSVersion
) {
153 AppleOSVersion8
= AllocateZeroPool((StrLen(AppleOSVersion
) + 1) * sizeof(CHAR8
));
154 UnicodeStrToAsciiStr(AppleOSVersion
, AppleOSVersion8
);
155 if (AppleOSVersion8
) {
156 Status
= refit_call1_wrapper (SetOs
->SetOsVersion
, AppleOSVersion8
);
157 if (!EFI_ERROR(Status
))
158 Status
= EFI_SUCCESS
;
159 MyFreePool(AppleOSVersion8
);
161 Status
= EFI_OUT_OF_RESOURCES
;
162 Print(L
"Out of resources in SetAppleOSInfo!\n");
164 if ((Status
== EFI_SUCCESS
) && (SetOs
->Version
== 2))
165 Status
= refit_call1_wrapper (SetOs
->SetOsVendor
, (CHAR8
*) "Apple Inc.");
166 MyFreePool(AppleOSVersion
);
167 } // if (AppleOSVersion)
169 if (Status
!= EFI_SUCCESS
)
170 Print(L
"Unable to set firmware boot type!\n");
173 } // EFI_STATUS SetAppleOSInfo()