OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
ApplePanic.c
Go to the documentation of this file.
1
15#include <Guid/AppleVariable.h>
16
17#include <Library/MemoryAllocationLib.h>
18#include <Library/BaseMemoryLib.h>
19#include <Library/DevicePathLib.h>
21#include <Library/OcCryptoLib.h>
24#include <Library/OcRtcLib.h>
25#include <Library/PrintLib.h>
26#include <Library/UefiLib.h>
27#include <Library/UefiRuntimeServicesTableLib.h>
28
29STATIC
30VOID *
32 IN CONST VOID *Packed,
33 IN UINTN PackedSize,
34 OUT UINTN *UnpackedSize
35 )
36{
37 VOID *Unpacked;
38 CONST UINT8 *PackedWalker;
39 UINT8 *UnpackedWalker;
40 UINT64 Sequence;
41
42 if (BaseOverflowMulUN (PackedSize, 8, UnpackedSize)) {
43 return NULL;
44 }
45
46 //
47 // Source buffer is required to be 8-byte aligned by Apple,
48 // so we can freely truncate here.
49 //
50 *UnpackedSize /= 7;
51 *UnpackedSize = *UnpackedSize - (*UnpackedSize % 8);
52 if ((*UnpackedSize == 0) || BaseOverflowAddUN (*UnpackedSize, 1, UnpackedSize)) {
53 return NULL;
54 }
55
56 Unpacked = AllocatePool (*UnpackedSize);
57 if (Unpacked == NULL) {
58 return NULL;
59 }
60
61 Sequence = 0;
62 PackedWalker = Packed;
63 UnpackedWalker = Unpacked;
64
65 while (PackedSize >= 7) {
66 CopyMem (&Sequence, PackedWalker, 7);
67 *UnpackedWalker++ = (UINT8)BitFieldRead64 (Sequence, 7 * 0, 7 * 0 + 6);
68 *UnpackedWalker++ = (UINT8)BitFieldRead64 (Sequence, 7 * 1, 7 * 1 + 6);
69 *UnpackedWalker++ = (UINT8)BitFieldRead64 (Sequence, 7 * 2, 7 * 2 + 6);
70 *UnpackedWalker++ = (UINT8)BitFieldRead64 (Sequence, 7 * 3, 7 * 3 + 6);
71 *UnpackedWalker++ = (UINT8)BitFieldRead64 (Sequence, 7 * 4, 7 * 4 + 6);
72 *UnpackedWalker++ = (UINT8)BitFieldRead64 (Sequence, 7 * 5, 7 * 5 + 6);
73 *UnpackedWalker++ = (UINT8)BitFieldRead64 (Sequence, 7 * 6, 7 * 6 + 6);
74 *UnpackedWalker++ = (UINT8)BitFieldRead64 (Sequence, 7 * 7, 7 * 7 + 6);
75 PackedWalker += 7;
76 PackedSize -= 7;
77 }
78
79 //
80 // Ensure null-termination.
81 //
82 *UnpackedWalker++ = '\0';
83
84 return Unpacked;
85}
86
87STATIC
88BOOLEAN
90 IN OUT CHAR8 **Buffer,
91 IN OUT UINTN *AllocatedSize,
92 IN OUT UINTN *CurrentSize,
93 IN CONST CHAR8 *NewData,
94 IN UINTN NewDataSize
95 )
96{
97 CHAR8 *TmpBuffer;
98 UINTN NewSize;
99
100 if (*AllocatedSize - *CurrentSize <= NewDataSize) {
101 if (*AllocatedSize > 0) {
102 NewSize = *AllocatedSize;
103 } else {
104 NewSize = NewDataSize;
105 }
106
107 NewSize = MAX (NewSize, 8192);
108
109 if (BaseOverflowMulUN (NewSize, 2, &NewSize)) {
110 if (*Buffer != NULL) {
111 FreePool (*Buffer);
112 }
113
114 return FALSE;
115 }
116
117 TmpBuffer = ReallocatePool (*AllocatedSize, NewSize, *Buffer);
118 if (TmpBuffer == NULL) {
119 if (*Buffer != NULL) {
120 FreePool (*Buffer);
121 }
122
123 return FALSE;
124 }
125
126 *Buffer = TmpBuffer;
127 *AllocatedSize = NewSize;
128 }
129
130 CopyMem (*Buffer + *CurrentSize, NewData, NewDataSize);
131 *CurrentSize += NewDataSize;
132 return TRUE;
133}
134
135STATIC
136CHAR8 *
138 IN CONST CHAR8 *Encoded,
139 IN UINTN EncodedSize,
140 OUT UINTN *ExpandedSize
141 )
142{
143 CHAR8 *Expanded;
144 UINTN AllocatedSize;
145 UINTN CurrentSize;
146 UINTN TmpSize;
147 CHAR8 *EncodedStart;
148 BOOLEAN Success;
149
150 EncodedStart = AsciiStrStr (Encoded, "loaded kext");
151 if (EncodedStart == NULL) {
152 return NULL;
153 }
154
155 Expanded = NULL;
156 AllocatedSize = 0;
157 CurrentSize = 0;
158
159 TmpSize = EncodedStart - EncodedStart;
160
161 if (!PanicExpandPutBuf (&Expanded, &AllocatedSize, &CurrentSize, Encoded, TmpSize)) {
162 return NULL;
163 }
164
165 Encoded += TmpSize;
166 EncodedSize -= TmpSize;
167
168 while (EncodedSize > 0) {
169 TmpSize = 1;
170
171 switch (Encoded[0]) {
172 case '>':
173 Success = PanicExpandPutBuf (&Expanded, &AllocatedSize, &CurrentSize, "com.apple.driver.", L_STR_LEN ("com.apple.driver."));
174 break;
175 case '|':
176 Success = PanicExpandPutBuf (&Expanded, &AllocatedSize, &CurrentSize, "com.apple.iokit.", L_STR_LEN ("com.apple.iokit."));
177 break;
178 case '$':
179 Success = PanicExpandPutBuf (&Expanded, &AllocatedSize, &CurrentSize, "com.apple.security.", L_STR_LEN ("com.apple.security."));
180 break;
181 case '@':
182 Success = PanicExpandPutBuf (&Expanded, &AllocatedSize, &CurrentSize, "com.apple.", L_STR_LEN ("com.apple."));
183 break;
184 case '!':
185 if (EncodedSize >= 2) {
186 ++TmpSize;
187 switch (Encoded[1]) {
188 case 'U':
189 Success = PanicExpandPutBuf (&Expanded, &AllocatedSize, &CurrentSize, "AppleUSB", L_STR_LEN ("AppleUSB"));
190 break;
191 case 'A':
192 Success = PanicExpandPutBuf (&Expanded, &AllocatedSize, &CurrentSize, "Apple", L_STR_LEN ("Apple"));
193 break;
194 case 'F':
195 Success = PanicExpandPutBuf (&Expanded, &AllocatedSize, &CurrentSize, "Family", L_STR_LEN ("Family"));
196 break;
197 case 'S':
198 Success = PanicExpandPutBuf (&Expanded, &AllocatedSize, &CurrentSize, "Storage", L_STR_LEN ("Storage"));
199 break;
200 case 'C':
201 Success = PanicExpandPutBuf (&Expanded, &AllocatedSize, &CurrentSize, "Controller", L_STR_LEN ("Controller"));
202 break;
203 case 'B':
204 Success = PanicExpandPutBuf (&Expanded, &AllocatedSize, &CurrentSize, "Bluetooth", L_STR_LEN ("Bluetooth"));
205 break;
206 case 'I':
207 Success = PanicExpandPutBuf (&Expanded, &AllocatedSize, &CurrentSize, "Intel", L_STR_LEN ("Intel"));
208 break;
209 default:
210 Success = PanicExpandPutBuf (&Expanded, &AllocatedSize, &CurrentSize, Encoded, 2);
211 break;
212 }
213
214 break;
215 }
216
217 /* Fallthrough */
218 default:
219 Success = PanicExpandPutBuf (&Expanded, &AllocatedSize, &CurrentSize, Encoded, 1);
220 break;
221 }
222
223 if (!Success) {
224 return NULL;
225 }
226
227 Encoded += TmpSize;
228 EncodedSize -= TmpSize;
229 }
230
231 *ExpandedSize = CurrentSize;
232
233 //
234 // One extra byte is always guaranteed.
235 //
236 Expanded[CurrentSize] = '\0';
237
238 return Expanded;
239}
240
241VOID *
243 OUT UINT32 *PanicSize
244 )
245{
246 EFI_STATUS Status;
247 UINT32 Index;
248 VOID *Value;
249 UINTN ValueSize;
250 CHAR16 VariableName[32];
251 VOID *TmpData;
252 UINTN TmpDataSize;
253 VOID *PanicData;
254
255 TmpData = NULL;
256 TmpDataSize = 0;
257
258 for (Index = 0; Index < 1024; ++Index) {
259 UnicodeSPrint (
260 VariableName,
261 sizeof (VariableName),
263 Index
264 );
265 Status = GetVariable2 (VariableName, &gAppleBootVariableGuid, &Value, &ValueSize);
266 if (EFI_ERROR (Status)) {
267 break;
268 }
269
270 if (ValueSize == 0) {
271 FreePool (Value);
272 break;
273 }
274
275 PanicData = ReallocatePool (TmpDataSize, TmpDataSize + ValueSize, TmpData);
276 if (PanicData == NULL) {
277 FreePool (Value);
278 if (TmpData != NULL) {
279 FreePool (TmpData);
280 }
281
282 return NULL;
283 }
284
285 TmpData = PanicData;
286
287 CopyMem (
288 (UINT8 *)TmpData + TmpDataSize,
289 Value,
290 ValueSize
291 );
292
293 FreePool (Value);
294 TmpDataSize += ValueSize;
295 }
296
297 if (Index == 0) {
298 //
299 // We have not advanced past the first variable, there is no panic log.
300 //
301 return NULL;
302 }
303
304 //
305 // We have a kernel panic now.
306 //
307 ASSERT (TmpData != NULL);
308 ASSERT (TmpDataSize > 0);
309
310 PanicData = PanicUnpack (TmpData, TmpDataSize, &TmpDataSize);
311 FreePool (TmpData);
312
313 if (PanicData != NULL) {
314 //
315 // Truncate trailing zeroes.
316 //
317 TmpDataSize = AsciiStrLen (PanicData);
318 TmpData = PanicExpand (PanicData, TmpDataSize, &TmpDataSize);
319 if (TmpData != NULL) {
320 FreePool (PanicData);
321 PanicData = TmpData;
322 }
323 }
324
325 *PanicSize = (UINT32)TmpDataSize;
326
327 return TmpData;
328}
VOID * OcReadApplePanicLog(OUT UINT32 *PanicSize)
Definition ApplePanic.c:242
STATIC CHAR8 * PanicExpand(IN CONST CHAR8 *Encoded, IN UINTN EncodedSize, OUT UINTN *ExpandedSize)
Definition ApplePanic.c:137
STATIC BOOLEAN PanicExpandPutBuf(IN OUT CHAR8 **Buffer, IN OUT UINTN *AllocatedSize, IN OUT UINTN *CurrentSize, IN CONST CHAR8 *NewData, IN UINTN NewDataSize)
Definition ApplePanic.c:89
STATIC VOID * PanicUnpack(IN CONST VOID *Packed, IN UINTN PackedSize, OUT UINTN *UnpackedSize)
Definition ApplePanic.c:31
EFI_GUID gAppleBootVariableGuid
#define APPLE_PANIC_INFO_NO_VARIABLE_NAME
#define L_STR_LEN(String)
Definition OcStringLib.h:26
OC_TYPING_BUFFER_ENTRY Buffer[OC_TYPING_BUFFER_SIZE]
Definition OcTypingLib.h:42
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
#define ASSERT(x)
Definition coder.h:55
#define MAX(a, b)
Definition coder.h:59