OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
AppleHibernate.c
Go to the documentation of this file.
1
15#include <Guid/AppleVariable.h>
16
18
19#include <Library/MemoryAllocationLib.h>
20#include <Library/BaseMemoryLib.h>
21#include <Library/DevicePathLib.h>
23#include <Library/OcCryptoLib.h>
26#include <Library/OcRtcLib.h>
27#include <Library/UefiLib.h>
28#include <Library/UefiRuntimeServicesTableLib.h>
29
30EFI_STATUS
32 IN UINT32 HibernateMask
33 )
34{
35 EFI_STATUS Status;
36 UINTN Size;
37 UINT32 Attributes;
38 VOID *Value;
40 BOOLEAN HasHibernateInfo;
41 BOOLEAN HasHibernateInfoInRTC;
42 UINT8 Index;
43 UINT8 *RtcRawVars;
44 EFI_DEVICE_PATH_PROTOCOL *BootImagePath;
45 EFI_DEVICE_PATH_PROTOCOL *RemainingPath;
46 INTN NumPatchedNodes;
47
48 if (HibernateMask == HIBERNATE_MODE_NONE) {
49 return EFI_INVALID_PARAMETER;
50 }
51
52 HasHibernateInfo = FALSE;
53 HasHibernateInfoInRTC = FALSE;
54
55 //
56 // If legacy boot-switch-vars exists (NVRAM working), then use it.
57 //
58 Status = GetVariable2 (L"boot-switch-vars", &gAppleBootVariableGuid, &Value, &Size);
59 if (!EFI_ERROR (Status)) {
60 //
61 // Leave it as is.
62 //
63 SecureZeroMem (Value, Size);
64 FreePool (Value);
65 DEBUG ((DEBUG_INFO, "OCB: Found legacy boot-switch-vars\n"));
66 return EFI_SUCCESS;
67 }
68
69 Status = GetVariable3 (
70 L"boot-image",
72 (VOID **)&BootImagePath,
73 &Size,
74 &Attributes
75 );
76 if (!EFI_ERROR (Status)) {
77 if (IsDevicePathValid (BootImagePath, Size)) {
79 DEBUG_INFO,
80 "OCB: boot-image pre-fix",
81 BootImagePath
82 );
83
84 //
85 // WARN: BootImagePath must be allocated from pool as it may be reallocated.
86 //
87 NumPatchedNodes = OcFixAppleBootDevicePath (
88 &BootImagePath,
89 &RemainingPath
90 );
91 if (NumPatchedNodes > 0) {
93 DEBUG_INFO,
94 "OCB: boot-image post-fix",
95 BootImagePath
96 );
97
98 //
99 // Updated DevicePath may have different size.
100 //
101 Size = GetDevicePathSize (BootImagePath);
102
103 Status = gRT->SetVariable (
104 L"boot-image",
106 Attributes,
107 Size,
108 BootImagePath
109 );
110 }
111
112 if (NumPatchedNodes >= 0) {
114 DEBUG_INFO,
115 "OCB: boot-image post-fix remainder",
116 RemainingPath
117 );
118 }
119 } else {
120 DEBUG ((DEBUG_INFO, "OCB: Invalid boot-image variable\n"));
121 }
122
123 SecureZeroMem (BootImagePath, Size);
124 FreePool (BootImagePath);
125 }
126
127 DEBUG ((DEBUG_INFO, "OCB: boot-image is %u bytes - %r\n", (UINT32)Size, Status));
128
129 RtcRawVars = (UINT8 *)&RtcVars;
130
131 //
132 // Work with RTC memory if allowed.
133 //
134 if (HibernateMask & HIBERNATE_MODE_RTC) {
135 for (Index = 0; Index < sizeof (AppleRTCHibernateVars); Index++) {
136 RtcRawVars[Index] = OcRtcRead (Index + 128);
137 }
138
139 HasHibernateInfoInRTC = RtcVars.signature[0] == 'A'
140 && RtcVars.signature[1] == 'A'
141 && RtcVars.signature[2] == 'P'
142 && RtcVars.signature[3] == 'L';
143 HasHibernateInfo = HasHibernateInfoInRTC;
144
145 DEBUG ((DEBUG_INFO, "OCB: RTC hibernation is %d\n", HasHibernateInfoInRTC));
146 }
147
148 if (HibernateMask & HIBERNATE_MODE_NVRAM) {
149 //
150 // If RTC variables is still written to NVRAM (and RTC is broken).
151 // Prior to 10.13.6.
152 //
153 Status = GetVariable2 (L"IOHibernateRTCVariables", &gAppleBootVariableGuid, &Value, &Size);
154 if (!HasHibernateInfo && !EFI_ERROR (Status) && (Size == sizeof (RtcVars))) {
155 CopyMem (RtcRawVars, Value, sizeof (RtcVars));
156 HasHibernateInfo = RtcVars.signature[0] == 'A'
157 && RtcVars.signature[1] == 'A'
158 && RtcVars.signature[2] == 'P'
159 && RtcVars.signature[3] == 'L';
160 }
161
162 DEBUG ((
163 DEBUG_INFO,
164 "OCB: NVRAM hibernation is %d / %r / %u\n",
165 HasHibernateInfo,
166 Status,
167 (UINT32)Size
168 ));
169
170 //
171 // Erase RTC variables in NVRAM.
172 //
173 if (!EFI_ERROR (Status)) {
174 Status = gRT->SetVariable (
175 L"IOHibernateRTCVariables",
177 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
178 0,
179 NULL
180 );
181 SecureZeroMem (Value, Size);
182 FreePool (Value);
183 }
184 }
185
186 //
187 // Convert RTC data to boot-key and boot-signature
188 //
189 if (HasHibernateInfo) {
190 gRT->SetVariable (
191 L"boot-image-key",
193 EFI_VARIABLE_BOOTSERVICE_ACCESS,
194 sizeof (RtcVars.wiredCryptKey),
195 RtcVars.wiredCryptKey
196 );
197 gRT->SetVariable (
198 L"boot-signature",
200 EFI_VARIABLE_BOOTSERVICE_ACCESS,
201 sizeof (RtcVars.booterSignature),
202 RtcVars.booterSignature
203 );
204 }
205
206 //
207 // Erase RTC memory similarly to AppleBds.
208 //
209 if (HasHibernateInfoInRTC) {
210 SecureZeroMem (RtcRawVars, sizeof (AppleRTCHibernateVars));
211 RtcVars.signature[0] = 'D';
212 RtcVars.signature[1] = 'E';
213 RtcVars.signature[2] = 'A';
214 RtcVars.signature[3] = 'D';
215
216 for (Index = 0; Index < sizeof (AppleRTCHibernateVars); Index++) {
217 OcRtcWrite (Index + 128, RtcRawVars[Index]);
218 }
219 }
220
221 //
222 // We have everything we need now.
223 //
224 if (HasHibernateInfo) {
225 return EFI_SUCCESS;
226 }
227
228 return EFI_NOT_FOUND;
229}
230
231BOOLEAN
233 VOID
234 )
235{
236 EFI_STATUS Status;
237 UINTN ValueSize;
238
239 //
240 // This is reverse engineered from boot.efi.
241 // To cancel hibernate wake it is enough to delete the variables.
242 // Starting with 10.13.6 boot-switch-vars is no longer supported.
243 //
244 ValueSize = 0;
245 Status = gRT->GetVariable (
246 L"boot-signature",
248 NULL,
249 &ValueSize,
250 NULL
251 );
252
253 if (Status == EFI_BUFFER_TOO_SMALL) {
254 ValueSize = 0;
255 Status = gRT->GetVariable (
256 L"boot-image-key",
258 NULL,
259 &ValueSize,
260 NULL
261 );
262
263 if (Status == EFI_BUFFER_TOO_SMALL) {
264 return TRUE;
265 }
266 } else {
267 ValueSize = 0;
268 Status = gRT->GetVariable (
269 L"boot-switch-vars",
271 NULL,
272 &ValueSize,
273 NULL
274 );
275
276 if (Status == EFI_BUFFER_TOO_SMALL) {
277 return TRUE;
278 }
279 }
280
281 return FALSE;
282}
EFI_STATUS OcActivateHibernateWake(IN UINT32 HibernateMask)
BOOLEAN OcIsAppleHibernateWake(VOID)
EFI_GUID gAppleBootVariableGuid
DMG_SIZE_DEVICE_PATH Size
#define HIBERNATE_MODE_NONE
#define HIBERNATE_MODE_NVRAM
#define HIBERNATE_MODE_RTC
VOID * SecureZeroMem(OUT VOID *Buffer, IN UINTN Length)
Definition SecureMem.c:73
VOID DebugPrintDevicePath(IN UINTN ErrorLevel, IN CONST CHAR8 *Message, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL)
INTN OcFixAppleBootDevicePath(IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, OUT EFI_DEVICE_PATH_PROTOCOL **RemainingDevicePath)
UINT8 OcRtcRead(IN UINT8 Offset)
Definition OcRtcLib.c:25
VOID OcRtcWrite(IN UINT8 Offset, IN UINT8 Value)
Definition OcRtcLib.c:47
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
EFI_RUNTIME_SERVICES * gRT