OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
CachelessContext.c
Go to the documentation of this file.
1
16#include <Uefi.h>
17
18#include <Library/BaseLib.h>
19#include <Library/BaseMemoryLib.h>
20#include <Library/BaseOverflowLib.h>
21#include <Library/DebugLib.h>
22#include <Library/MemoryAllocationLib.h>
23#include <Library/PrintLib.h>
25#include <Library/OcFileLib.h>
26#include <Library/OcStringLib.h>
28
29#include "CachelessInternal.h"
30#include "MkextInternal.h"
31#include "PrelinkedInternal.h"
32
33STATIC
34VOID
36 IN BUILTIN_KEXT *BuiltinKext
37 )
38{
39 DEPEND_KEXT *DependKext;
40 LIST_ENTRY *KextLink;
41
42 if (BuiltinKext->PlistPath != NULL) {
43 FreePool (BuiltinKext->PlistPath);
44 }
45
46 if (BuiltinKext->Identifier != NULL) {
47 FreePool (BuiltinKext->Identifier);
48 }
49
50 if (BuiltinKext->BinaryFileName != NULL) {
51 FreePool (BuiltinKext->BinaryFileName);
52 }
53
54 if (BuiltinKext->BinaryPath != NULL) {
55 FreePool (BuiltinKext->BinaryPath);
56 }
57
58 while (!IsListEmpty (&BuiltinKext->Dependencies)) {
59 KextLink = GetFirstNode (&BuiltinKext->Dependencies);
60 DependKext = GET_DEPEND_KEXT_FROM_LINK (KextLink);
61 RemoveEntryList (KextLink);
62
63 if (DependKext->Identifier != NULL) {
64 FreePool (DependKext->Identifier);
65 }
66
67 FreePool (DependKext);
68 }
69
70 FreePool (BuiltinKext);
71}
72
73STATIC
74EFI_STATUS
76 IN OUT LIST_ENTRY *Dependencies,
77 IN CONST CHAR8 *Identifier
78 )
79{
80 DEPEND_KEXT *DependKext;
81 LIST_ENTRY *KextLink;
82
83 KextLink = GetFirstNode (Dependencies);
84 while (!IsNull (Dependencies, KextLink)) {
85 DependKext = GET_DEPEND_KEXT_FROM_LINK (KextLink);
86
87 if (AsciiStrCmp (DependKext->Identifier, Identifier) == 0) {
88 return EFI_SUCCESS;
89 }
90
91 KextLink = GetNextNode (Dependencies, KextLink);
92 }
93
94 DependKext = AllocateZeroPool (sizeof (*DependKext));
95 if (DependKext == NULL) {
96 return EFI_OUT_OF_RESOURCES;
97 }
98
99 DependKext->Signature = DEPEND_KEXT_SIGNATURE;
100 DependKext->Identifier = AllocateCopyPool (AsciiStrSize (Identifier), Identifier);
101 if (DependKext->Identifier == NULL) {
102 FreePool (DependKext);
103 return EFI_OUT_OF_RESOURCES;
104 }
105
106 InsertTailList (Dependencies, &DependKext->Link);
107 return EFI_SUCCESS;
108}
109
110STATIC
111EFI_STATUS
113 IN OUT LIST_ENTRY *Dependencies,
114 IN XML_NODE *InfoPlistLibraries
115 )
116{
117 EFI_STATUS Status;
118 UINT32 ChildCount;
119 UINT32 ChildIndex;
120 CONST CHAR8 *ChildPlistKey;
121
122 ChildCount = PlistDictChildren (InfoPlistLibraries);
123 for (ChildIndex = 0; ChildIndex < ChildCount; ChildIndex++) {
124 ChildPlistKey = PlistKeyValue (PlistDictChild (InfoPlistLibraries, ChildIndex, NULL));
125 if (ChildPlistKey == NULL) {
126 continue;
127 }
128
129 Status = AddKextDependency (Dependencies, ChildPlistKey);
130 if (EFI_ERROR (Status)) {
131 return Status;
132 }
133 }
134
135 return EFI_SUCCESS;
136}
137
138STATIC
139EFI_STATUS
141 IN OUT CACHELESS_CONTEXT *Context,
142 IN EFI_FILE_PROTOCOL *File,
143 IN CONST CHAR16 *FilePath,
144 IN BOOLEAN ReadPlugins
145 )
146{
147 EFI_STATUS Status;
148 EFI_FILE_PROTOCOL *FileKext;
149 EFI_FILE_PROTOCOL *FilePlist;
150 EFI_FILE_PROTOCOL *FilePlugins;
151 EFI_FILE_INFO *FileInfo;
152 UINTN FileInfoSize;
153 BOOLEAN UseContents;
154
155 CHAR8 *InfoPlist;
156 UINT32 InfoPlistSize;
157 XML_DOCUMENT *InfoPlistDocument;
158 XML_NODE *InfoPlistRoot;
159 XML_NODE *InfoPlistValue;
160 XML_NODE *InfoPlistLibraries;
161 XML_NODE *InfoPlistLibraries64;
162 CONST CHAR8 *TmpKeyValue;
163 UINT32 FieldCount;
164 UINT32 FieldIndex;
165
166 BUILTIN_KEXT *BuiltinKext;
167 CHAR16 TmpPath[256];
168
169 DEBUG ((DEBUG_INFO, "OCAK: Scanning %s...\n", FilePath));
170
171 FileInfo = AllocatePool (SIZE_1KB);
172 if (FileInfo == NULL) {
173 return EFI_OUT_OF_RESOURCES;
174 }
175
176 File->SetPosition (File, 0);
177
178 do {
179 //
180 // Apple's HFS+ driver does not adhere to the spec and will return zero for
181 // EFI_BUFFER_TOO_SMALL. EFI_FILE_INFO structures larger than 1KB are
182 // unrealistic as the filename is the only variable.
183 //
184 FileInfoSize = SIZE_1KB - sizeof (CHAR16);
185 Status = File->Read (File, &FileInfoSize, FileInfo);
186 if (EFI_ERROR (Status)) {
187 FileKext->Close (FileKext);
188 File->SetPosition (File, 0);
189 FreePool (FileInfo);
190 return Status;
191 }
192
193 if (FileInfoSize > 0) {
194 if (OcUnicodeEndsWith (FileInfo->FileName, L".kext", FALSE)) {
195 Status = File->Open (File, &FileKext, FileInfo->FileName, EFI_FILE_MODE_READ, EFI_FILE_DIRECTORY);
196 if (EFI_ERROR (Status)) {
197 continue;
198 }
199
200 //
201 // Determine if Contents directory exists.
202 // If not, we'll use the root of the kext.
203 //
204 Status = FileKext->Open (FileKext, &FilePlist, L"Contents", EFI_FILE_MODE_READ, EFI_FILE_DIRECTORY);
205 UseContents = !EFI_ERROR (Status);
206
207 //
208 // There are some kexts that do not have an Info.plist, but do have PlugIns.
209 // This was observed in some versions of 10.4.
210 //
211 Status = FileKext->Open (
212 FileKext,
213 &FilePlist,
214 UseContents ? L"Contents\\Info.plist" : L"Info.plist",
215 EFI_FILE_MODE_READ,
216 0
217 );
218 if (!EFI_ERROR (Status)) {
219 //
220 // Parse Info.plist.
221 //
222 Status = OcAllocateCopyFileData (FilePlist, (UINT8 **)&InfoPlist, &InfoPlistSize);
223 FilePlist->Close (FilePlist);
224 if (EFI_ERROR (Status)) {
225 FileKext->Close (FileKext);
226 File->SetPosition (File, 0);
227 FreePool (FileInfo);
228 return Status;
229 }
230
231 InfoPlistDocument = XmlDocumentParse (InfoPlist, InfoPlistSize, FALSE);
232 if (InfoPlistDocument == NULL) {
233 FreePool (InfoPlist);
234 FileKext->Close (FileKext);
235 File->SetPosition (File, 0);
236 FreePool (FileInfo);
237 return EFI_INVALID_PARAMETER;
238 }
239
240 InfoPlistRoot = PlistNodeCast (PlistDocumentRoot (InfoPlistDocument), PLIST_NODE_TYPE_DICT);
241 if (InfoPlistRoot == NULL) {
242 XmlDocumentFree (InfoPlistDocument);
243 FreePool (InfoPlist);
244 FileKext->Close (FileKext);
245 File->SetPosition (File, 0);
246 FreePool (FileInfo);
247 return EFI_INVALID_PARAMETER;
248 }
249
250 //
251 // Add to built-in kexts list.
252 //
253 BuiltinKext = AllocateZeroPool (sizeof (*BuiltinKext));
254 if (BuiltinKext == NULL) {
255 XmlDocumentFree (InfoPlistDocument);
256 FreePool (InfoPlist);
257 FileKext->Close (FileKext);
258 File->SetPosition (File, 0);
259 FreePool (FileInfo);
260 return EFI_OUT_OF_RESOURCES;
261 }
262
263 BuiltinKext->Signature = BUILTIN_KEXT_SIGNATURE;
264 InitializeListHead (&BuiltinKext->Dependencies);
265
266 //
267 // Search for plist properties.
268 //
269 InfoPlistLibraries = NULL;
270 FieldCount = PlistDictChildren (InfoPlistRoot);
271 for (FieldIndex = 0; FieldIndex < FieldCount; ++FieldIndex) {
272 TmpKeyValue = PlistKeyValue (PlistDictChild (InfoPlistRoot, FieldIndex, &InfoPlistValue));
273 if (TmpKeyValue == NULL) {
274 continue;
275 }
276
277 if (AsciiStrCmp (TmpKeyValue, INFO_BUNDLE_EXECUTABLE_KEY) == 0) {
278 BuiltinKext->BinaryFileName = AsciiStrCopyToUnicode (XmlNodeContent (InfoPlistValue), 0);
279 if (BuiltinKext->BinaryFileName == NULL) {
280 FreeBuiltInKext (BuiltinKext);
281 XmlDocumentFree (InfoPlistDocument);
282 FreePool (InfoPlist);
283 FileKext->Close (FileKext);
284 File->SetPosition (File, 0);
285 FreePool (FileInfo);
286 return EFI_OUT_OF_RESOURCES;
287 }
288 } else if (AsciiStrCmp (TmpKeyValue, INFO_BUNDLE_IDENTIFIER_KEY) == 0) {
289 BuiltinKext->Identifier = AllocateCopyPool (AsciiStrSize (XmlNodeContent (InfoPlistValue)), XmlNodeContent (InfoPlistValue));
290 if (BuiltinKext->Identifier == NULL) {
291 FreeBuiltInKext (BuiltinKext);
292 XmlDocumentFree (InfoPlistDocument);
293 FreePool (InfoPlist);
294 FileKext->Close (FileKext);
295 File->SetPosition (File, 0);
296 FreePool (FileInfo);
297 return EFI_OUT_OF_RESOURCES;
298 }
299 } else if (AsciiStrCmp (TmpKeyValue, INFO_BUNDLE_OS_BUNDLE_REQUIRED_KEY) == 0) {
300 //
301 // If OSBundleRequired is present and is not Safe Boot, no action is required.
302 //
303 if (AsciiStrCmp (XmlNodeContent (InfoPlistValue), OS_BUNDLE_REQUIRED_SAFE_BOOT) != 0) {
305 } else {
307 }
308 } else if (AsciiStrCmp (TmpKeyValue, INFO_BUNDLE_LIBRARIES_KEY) == 0) {
309 if (!Context->Is32Bit && (InfoPlistLibraries64 == NULL)) {
310 InfoPlistLibraries = PlistNodeCast (InfoPlistValue, PLIST_NODE_TYPE_DICT);
311 if (InfoPlistLibraries == NULL) {
312 FreeBuiltInKext (BuiltinKext);
313 XmlDocumentFree (InfoPlistDocument);
314 FreePool (InfoPlist);
315 FileKext->Close (FileKext);
316 File->SetPosition (File, 0);
317 FreePool (FileInfo);
318 return EFI_INVALID_PARAMETER;
319 }
320 }
321 } else if (AsciiStrCmp (TmpKeyValue, INFO_BUNDLE_LIBRARIES_64_KEY) == 0) {
322 InfoPlistLibraries64 = PlistNodeCast (InfoPlistValue, PLIST_NODE_TYPE_DICT);
323 if (InfoPlistLibraries64 == NULL) {
324 FreeBuiltInKext (BuiltinKext);
325 XmlDocumentFree (InfoPlistDocument);
326 FreePool (InfoPlist);
327 FileKext->Close (FileKext);
328 File->SetPosition (File, 0);
329 FreePool (FileInfo);
330 return EFI_INVALID_PARAMETER;
331 }
332
333 if (!Context->Is32Bit) {
334 InfoPlistLibraries = InfoPlistLibraries64;
335 }
336 }
337 }
338
339 if (InfoPlistLibraries != NULL) {
340 Status = AddKextDependencies (&BuiltinKext->Dependencies, InfoPlistLibraries);
341 if (EFI_ERROR (Status)) {
342 FreeBuiltInKext (BuiltinKext);
343 XmlDocumentFree (InfoPlistDocument);
344 FreePool (InfoPlist);
345 FileKext->Close (FileKext);
346 File->SetPosition (File, 0);
347 FreePool (FileInfo);
348 return Status;
349 }
350 }
351
352 XmlDocumentFree (InfoPlistDocument);
353 FreePool (InfoPlist);
354
355 if (BuiltinKext->Identifier == NULL) {
356 FreeBuiltInKext (BuiltinKext);
357 FileKext->Close (FileKext);
358 File->SetPosition (File, 0);
359 FreePool (FileInfo);
360 return EFI_INVALID_PARAMETER;
361 }
362
363 //
364 // Create plist path.
365 //
366 Status = OcUnicodeSafeSPrint (
367 TmpPath,
368 sizeof (TmpPath),
369 L"%s\\%s\\%s",
370 FilePath,
371 FileInfo->FileName,
372 UseContents ? L"Contents\\Info.plist" : L"Info.plist"
373 );
374 if (EFI_ERROR (Status)) {
375 FreeBuiltInKext (BuiltinKext);
376 FileKext->Close (FileKext);
377 File->SetPosition (File, 0);
378 FreePool (FileInfo);
379 return EFI_INVALID_PARAMETER;
380 }
381
382 BuiltinKext->PlistPath = AllocateCopyPool (StrSize (TmpPath), TmpPath);
383 if (BuiltinKext->PlistPath == NULL) {
384 FreeBuiltInKext (BuiltinKext);
385 FileKext->Close (FileKext);
386 File->SetPosition (File, 0);
387 FreePool (FileInfo);
388 return EFI_OUT_OF_RESOURCES;
389 }
390
391 //
392 // Create binary path. If plist is in root of kext, binary is also there.
393 //
394 if (BuiltinKext->BinaryFileName != NULL) {
395 Status = OcUnicodeSafeSPrint (
396 TmpPath,
397 sizeof (TmpPath),
398 L"%s\\%s\\%s%s",
399 FilePath,
400 FileInfo->FileName,
401 UseContents ? L"Contents\\MacOS\\" : L"",
402 BuiltinKext->BinaryFileName
403 );
404 if (EFI_ERROR (Status)) {
405 FreeBuiltInKext (BuiltinKext);
406 FileKext->Close (FileKext);
407 File->SetPosition (File, 0);
408 FreePool (FileInfo);
409 return EFI_INVALID_PARAMETER;
410 }
411
412 BuiltinKext->BinaryPath = AllocateCopyPool (StrSize (TmpPath), TmpPath);
413 if (BuiltinKext->BinaryPath == NULL) {
414 FreeBuiltInKext (BuiltinKext);
415 FileKext->Close (FileKext);
416 File->SetPosition (File, 0);
417 FreePool (FileInfo);
418 return EFI_OUT_OF_RESOURCES;
419 }
420 }
421
422 InsertTailList (&Context->BuiltInKexts, &BuiltinKext->Link);
423 DEBUG ((
424 DEBUG_VERBOSE,
425 "OCAK: Discovered bundle %a %s %s %u\n",
426 BuiltinKext->Identifier,
427 BuiltinKext->PlistPath,
428 BuiltinKext->BinaryPath,
429 BuiltinKext->OSBundleRequiredValue
430 ));
431 }
432
433 //
434 // Scan PlugIns directory.
435 //
436 if (ReadPlugins) {
437 Status = FileKext->Open (FileKext, &FilePlugins, UseContents ? L"Contents\\PlugIns" : L"PlugIns", EFI_FILE_MODE_READ, EFI_FILE_DIRECTORY);
438 if (Status == EFI_SUCCESS) {
439 Status = OcUnicodeSafeSPrint (
440 TmpPath,
441 sizeof (TmpPath),
442 L"%s\\%s\\%s",
443 FilePath,
444 FileInfo->FileName,
445 UseContents ? L"Contents\\PlugIns" : L"PlugIns"
446 );
447
448 Status = ScanExtensions (Context, FilePlugins, TmpPath, FALSE);
449 FilePlugins->Close (FilePlugins);
450 if (EFI_ERROR (Status)) {
451 FileKext->Close (FileKext);
452 File->SetPosition (File, 0);
453 FreePool (FileInfo);
454 return Status;
455 }
456 } else if (Status != EFI_NOT_FOUND) {
457 FileKext->Close (FileKext);
458 File->SetPosition (File, 0);
459 FreePool (FileInfo);
460 return Status;
461 }
462 }
463
464 FileKext->Close (FileKext);
465 }
466 }
467 } while (FileInfoSize > 0);
468
469 File->SetPosition (File, 0);
470 FreePool (FileInfo);
471
472 return EFI_SUCCESS;
473}
474
475STATIC
478 IN OUT CACHELESS_CONTEXT *Context,
479 IN CONST CHAR8 *Identifier
480 )
481{
482 PATCHED_KEXT *PatchedKext;
483 LIST_ENTRY *KextLink;
484
485 KextLink = GetFirstNode (&Context->PatchedKexts);
486 while (!IsNull (&Context->PatchedKexts, KextLink)) {
487 PatchedKext = GET_PATCHED_KEXT_FROM_LINK (KextLink);
488
489 if (AsciiStrCmp (Identifier, PatchedKext->Identifier) == 0) {
490 return PatchedKext;
491 }
492
493 KextLink = GetNextNode (&Context->PatchedKexts, KextLink);
494 }
495
496 return NULL;
497}
498
499STATIC
502 IN OUT CACHELESS_CONTEXT *Context,
503 IN CONST CHAR8 *Identifier
504 )
505{
506 BUILTIN_KEXT *BuiltinKext;
507 LIST_ENTRY *KextLink;
508
509 KextLink = GetFirstNode (&Context->BuiltInKexts);
510 while (!IsNull (&Context->BuiltInKexts, KextLink)) {
511 BuiltinKext = GET_BUILTIN_KEXT_FROM_LINK (KextLink);
512
513 if (AsciiStrCmp (Identifier, BuiltinKext->Identifier) == 0) {
514 return BuiltinKext;
515 }
516
517 KextLink = GetNextNode (&Context->BuiltInKexts, KextLink);
518 }
519
520 return NULL;
521}
522
523STATIC
526 IN OUT CACHELESS_CONTEXT *Context,
527 IN CONST CHAR16 *PlistPath
528 )
529{
530 BUILTIN_KEXT *BuiltinKext;
531 LIST_ENTRY *KextLink;
532
533 KextLink = GetFirstNode (&Context->BuiltInKexts);
534 while (!IsNull (&Context->BuiltInKexts, KextLink)) {
535 BuiltinKext = GET_BUILTIN_KEXT_FROM_LINK (KextLink);
536
537 if (StrCmp (PlistPath, BuiltinKext->PlistPath) == 0) {
538 return BuiltinKext;
539 }
540
541 KextLink = GetNextNode (&Context->BuiltInKexts, KextLink);
542 }
543
544 return NULL;
545}
546
547STATIC
550 IN OUT CACHELESS_CONTEXT *Context,
551 IN CONST CHAR16 *BinaryPath
552 )
553{
554 BUILTIN_KEXT *BuiltinKext;
555 LIST_ENTRY *KextLink;
556
557 KextLink = GetFirstNode (&Context->BuiltInKexts);
558 while (!IsNull (&Context->BuiltInKexts, KextLink)) {
559 BuiltinKext = GET_BUILTIN_KEXT_FROM_LINK (KextLink);
560
561 if ( (BuiltinKext->BinaryPath != NULL)
562 && (StrCmp (BinaryPath, BuiltinKext->BinaryPath) == 0))
563 {
564 return BuiltinKext;
565 }
566
567 KextLink = GetNextNode (&Context->BuiltInKexts, KextLink);
568 }
569
570 return NULL;
571}
572
573STATIC
574EFI_STATUS
576 IN OUT CACHELESS_CONTEXT *Context,
577 IN CHAR8 *Identifier
578 )
579{
580 EFI_STATUS Status;
581 BUILTIN_KEXT *BuiltinKext;
582 DEPEND_KEXT *DependKext;
583 LIST_ENTRY *KextLink;
584
585 DEBUG ((DEBUG_VERBOSE, "OCAK: Scanning dependencies for %a\n", Identifier));
586
587 BuiltinKext = LookupBuiltinKextForIdentifier (Context, Identifier);
588 if ((BuiltinKext == NULL) || (BuiltinKext->OSBundleRequiredValue == KEXT_OSBUNDLE_REQUIRED_VALID)) {
589 //
590 // Injected kexts may have dependencies on other injected kexts, which we do not need to handle.
591 // We should be able to safely assume that any kext with the OSBundleRequired set correctly does not need to be handled either.
592 //
593 return EFI_SUCCESS;
594 }
595
596 BuiltinKext->PatchValidOSBundleRequired = TRUE;
597
598 Status = AddKextDependency (&Context->InjectedDependencies, Identifier);
599 if (EFI_ERROR (Status)) {
600 return Status;
601 }
602
603 KextLink = GetFirstNode (&BuiltinKext->Dependencies);
604 while (!IsNull (&BuiltinKext->Dependencies, KextLink)) {
605 DependKext = GET_DEPEND_KEXT_FROM_LINK (KextLink);
606
607 Status = ScanDependencies (Context, DependKext->Identifier);
608 if (EFI_ERROR (Status)) {
609 return Status;
610 }
611
612 KextLink = GetNextNode (&BuiltinKext->Dependencies, KextLink);
613 }
614
615 return EFI_SUCCESS;
616}
617
618STATIC
619EFI_STATUS
621 IN OUT CACHELESS_CONTEXT *Context,
622 IN CONST CHAR8 *Identifier,
623 OUT PATCHED_KEXT **Kext
624 )
625{
626 PATCHED_KEXT *PatchedKext;
627
628 PatchedKext = AllocateZeroPool (sizeof (*PatchedKext));
629 if (PatchedKext == NULL) {
630 return EFI_OUT_OF_RESOURCES;
631 }
632
633 PatchedKext->Signature = PATCHED_KEXT_SIGNATURE;
634 PatchedKext->Identifier = AllocateCopyPool (AsciiStrSize (Identifier), Identifier);
635 if (PatchedKext->Identifier == NULL) {
636 FreePool (PatchedKext);
637 return EFI_OUT_OF_RESOURCES;
638 }
639
640 InitializeListHead (&PatchedKext->Patches);
641
642 InsertTailList (&Context->PatchedKexts, &PatchedKext->Link);
643
644 *Kext = PatchedKext;
645 return EFI_SUCCESS;
646}
647
648STATIC
649EFI_STATUS
651 IN OUT CACHELESS_CONTEXT *Context,
652 IN CONST CHAR8 *Identifier,
653 IN PATCHER_GENERIC_PATCH *Patch OPTIONAL,
654 IN KERNEL_QUIRK_NAME QuirkName
655 )
656{
657 EFI_STATUS Status;
658 PATCHED_KEXT *PatchedKext;
659 KEXT_PATCH *KextPatch;
660 KERNEL_QUIRK *KernelQuirk;
661
662 if (Patch == NULL) {
663 KernelQuirk = &gKernelQuirks[QuirkName];
664 ASSERT (KernelQuirk->Identifier != NULL);
665
666 Identifier = KernelQuirk->Identifier;
667 }
668
669 //
670 // Check if bundle is already present. If not, add to list.
671 //
672 PatchedKext = LookupPatchedKextForIdentifier (Context, Identifier);
673 if (PatchedKext == NULL) {
674 Status = InternalAddPatchedKext (Context, Identifier, &PatchedKext);
675 if (EFI_ERROR (Status)) {
676 return Status;
677 }
678 }
679
680 //
681 // Add new patch.
682 //
683 KextPatch = AllocateZeroPool (sizeof (*KextPatch));
684 if (KextPatch == NULL) {
685 return EFI_OUT_OF_RESOURCES;
686 }
687
688 KextPatch->Signature = KEXT_PATCH_SIGNATURE;
689
690 if (Patch != NULL) {
691 CopyMem (&KextPatch->Patch, Patch, sizeof (KextPatch->Patch));
692 } else {
693 //
694 // Apply quirk if no Patch.
695 //
696 KextPatch->ApplyQuirk = TRUE;
697 KextPatch->QuirkName = QuirkName;
698 }
699
700 InsertTailList (&PatchedKext->Patches, &KextPatch->Link);
701
702 return EFI_SUCCESS;
703}
704
705EFI_STATUS
707 IN OUT CACHELESS_CONTEXT *Context,
708 IN CONST CHAR16 *FileName,
709 IN EFI_FILE_PROTOCOL *ExtensionsDir,
710 IN UINT32 KernelVersion,
711 IN BOOLEAN Is32Bit
712 )
713{
714 ASSERT (Context != NULL);
715 ASSERT (FileName != NULL);
716 ASSERT (ExtensionsDir != NULL);
717
718 ZeroMem (Context, sizeof (*Context));
719
720 Context->ExtensionsDir = ExtensionsDir;
721 Context->ExtensionsDirFileName = FileName;
722 Context->KernelVersion = KernelVersion;
723 Context->Is32Bit = Is32Bit;
724
725 InitializeListHead (&Context->InjectedKexts);
726 InitializeListHead (&Context->InjectedDependencies);
727 InitializeListHead (&Context->PatchedKexts);
728 InitializeListHead (&Context->BuiltInKexts);
729
730 return EFI_SUCCESS;
731}
732
733VOID
735 IN OUT CACHELESS_CONTEXT *Context
736 )
737{
738 CACHELESS_KEXT *CachelessKext;
739 PATCHED_KEXT *PatchedKext;
740 KEXT_PATCH *KextPatch;
741 BUILTIN_KEXT *BuiltinKext;
742 LIST_ENTRY *KextLink;
743 LIST_ENTRY *PatchLink;
744
745 ASSERT (Context != NULL);
746
747 while (!IsListEmpty (&Context->InjectedKexts)) {
748 KextLink = GetFirstNode (&Context->InjectedKexts);
749 CachelessKext = GET_CACHELESS_KEXT_FROM_LINK (KextLink);
750 RemoveEntryList (KextLink);
751
752 if (CachelessKext->PlistData != NULL) {
753 FreePool (CachelessKext->PlistData);
754 }
755
756 if (CachelessKext->BinaryData != NULL) {
757 FreePool (CachelessKext->BinaryData);
758 }
759
760 if (CachelessKext->BinaryFileName != NULL) {
761 FreePool (CachelessKext->BinaryFileName);
762 }
763
764 FreePool (CachelessKext);
765 }
766
767 while (!IsListEmpty (&Context->PatchedKexts)) {
768 KextLink = GetFirstNode (&Context->PatchedKexts);
769 PatchedKext = GET_PATCHED_KEXT_FROM_LINK (KextLink);
770 RemoveEntryList (KextLink);
771
772 while (!IsListEmpty (&PatchedKext->Patches)) {
773 PatchLink = GetFirstNode (&PatchedKext->Patches);
774 KextPatch = GET_KEXT_PATCH_FROM_LINK (PatchLink);
775 RemoveEntryList (PatchLink);
776
777 FreePool (KextPatch);
778 }
779
780 FreePool (PatchedKext);
781 }
782
783 while (!IsListEmpty (&Context->BuiltInKexts)) {
784 KextLink = GetFirstNode (&Context->BuiltInKexts);
785 BuiltinKext = GET_BUILTIN_KEXT_FROM_LINK (KextLink);
786 RemoveEntryList (KextLink);
787
788 if (BuiltinKext->PlistPath != NULL) {
789 FreePool (BuiltinKext->PlistPath);
790 }
791
792 if (BuiltinKext->Identifier != NULL) {
793 FreePool (BuiltinKext->Identifier);
794 }
795
796 if (BuiltinKext->BinaryFileName != NULL) {
797 FreePool (BuiltinKext->BinaryFileName);
798 }
799
800 FreePool (BuiltinKext);
801 }
802
803 ZeroMem (Context, sizeof (*Context));
804}
805
806EFI_STATUS
808 IN OUT CACHELESS_CONTEXT *Context,
809 IN CONST CHAR8 *InfoPlist,
810 IN UINT32 InfoPlistSize,
811 IN UINT8 *Executable OPTIONAL,
812 IN UINT32 ExecutableSize OPTIONAL,
813 OUT CHAR8 BundleVersion[MAX_INFO_BUNDLE_VERSION_KEY_SIZE] OPTIONAL
814 )
815{
816 EFI_STATUS Status;
817 CACHELESS_KEXT *NewKext;
818
819 XML_DOCUMENT *InfoPlistDocument;
820 XML_NODE *InfoPlistRoot;
821 XML_NODE *InfoPlistValue;
822 XML_NODE *InfoPlistLibraries;
823 XML_NODE *InfoPlistLibraries64;
824 CHAR8 *TmpInfoPlist;
825 CONST CHAR8 *TmpKeyValue;
826 UINT32 FieldCount;
827 UINT32 FieldIndex;
828 CONST CHAR8 *BundleVerStr;
829
830 BOOLEAN Failed;
831 BOOLEAN IsLoadable;
832 BOOLEAN PlistHasChanges;
833 CHAR8 *NewPlistData;
834 UINT32 NewPlistDataSize;
835
836 ASSERT (Context != NULL);
837 ASSERT (InfoPlist != NULL);
838 ASSERT (InfoPlistSize > 0);
839
840 IsLoadable = FALSE;
841 PlistHasChanges = FALSE;
842
843 NewKext = AllocateZeroPool (sizeof (*NewKext));
844 if (NewKext == NULL) {
845 return EFI_OUT_OF_RESOURCES;
846 }
847
849 NewKext->PlistData = AllocateCopyPool (InfoPlistSize, InfoPlist);
850 if (NewKext->PlistData == NULL) {
851 FreePool (NewKext);
852 return EFI_OUT_OF_RESOURCES;
853 }
854
855 NewKext->PlistDataSize = InfoPlistSize;
856
857 //
858 // Allocate Info.plist copy for XML_DOCUMENT.
859 //
860 TmpInfoPlist = AllocateCopyPool (InfoPlistSize, InfoPlist);
861 if (TmpInfoPlist == NULL) {
862 FreePool (NewKext->PlistData);
863 FreePool (NewKext);
864 return EFI_OUT_OF_RESOURCES;
865 }
866
867 InfoPlistDocument = XmlDocumentParse (TmpInfoPlist, InfoPlistSize, FALSE);
868 if (InfoPlistDocument == NULL) {
869 FreePool (TmpInfoPlist);
870 FreePool (NewKext->PlistData);
871 FreePool (NewKext);
872 return EFI_INVALID_PARAMETER;
873 }
874
875 InfoPlistRoot = PlistNodeCast (PlistDocumentRoot (InfoPlistDocument), PLIST_NODE_TYPE_DICT);
876 if (InfoPlistRoot == NULL) {
877 XmlDocumentFree (InfoPlistDocument);
878 FreePool (TmpInfoPlist);
879 FreePool (NewKext->PlistData);
880 FreePool (NewKext);
881 return EFI_INVALID_PARAMETER;
882 }
883
884 //
885 // Search for plist properties.
886 //
887 InfoPlistLibraries = NULL;
888 FieldCount = PlistDictChildren (InfoPlistRoot);
889 for (FieldIndex = 0; FieldIndex < FieldCount; ++FieldIndex) {
890 TmpKeyValue = PlistKeyValue (PlistDictChild (InfoPlistRoot, FieldIndex, &InfoPlistValue));
891 if (TmpKeyValue == NULL) {
892 continue;
893 }
894
895 if (AsciiStrCmp (TmpKeyValue, INFO_BUNDLE_EXECUTABLE_KEY) == 0) {
896 //
897 // We are not supposed to check for this, it is XNU responsibility, which reliably panics.
898 // However, to avoid certain users making this kind of mistake, we still provide some
899 // code in debug mode to diagnose it.
900 //
901 DEBUG_CODE_BEGIN ();
902 if (Executable == NULL) {
903 DEBUG ((DEBUG_ERROR, "OCAK: Plist-only kext has %a key\n", INFO_BUNDLE_EXECUTABLE_KEY));
904 ASSERT (FALSE);
905 CpuDeadLoop ();
906 }
907
908 DEBUG_CODE_END ();
909
910 NewKext->BinaryFileName = AsciiStrCopyToUnicode (XmlNodeContent (InfoPlistValue), 0);
911 if (NewKext->BinaryFileName == NULL) {
912 XmlDocumentFree (InfoPlistDocument);
913 FreePool (TmpInfoPlist);
914 FreePool (NewKext->PlistData);
915 FreePool (NewKext);
916 return EFI_INVALID_PARAMETER;
917 }
918 } else if (AsciiStrCmp (TmpKeyValue, INFO_BUNDLE_OS_BUNDLE_REQUIRED_KEY) == 0) {
919 //
920 // If OSBundleRequired is present and is not Safe Boot, no action is required.
921 //
922 if (AsciiStrCmp (XmlNodeContent (InfoPlistValue), OS_BUNDLE_REQUIRED_SAFE_BOOT) == 0) {
924 PlistHasChanges = TRUE;
925 }
926
927 IsLoadable = TRUE;
928 } else if (AsciiStrCmp (TmpKeyValue, INFO_BUNDLE_LIBRARIES_KEY) == 0) {
929 if (!Context->Is32Bit && (InfoPlistLibraries64 == NULL)) {
930 InfoPlistLibraries = PlistNodeCast (InfoPlistValue, PLIST_NODE_TYPE_DICT);
931 if (InfoPlistLibraries == NULL) {
932 XmlDocumentFree (InfoPlistDocument);
933 FreePool (TmpInfoPlist);
934 FreePool (NewKext->PlistData);
935 FreePool (NewKext);
936 return EFI_INVALID_PARAMETER;
937 }
938 }
939 } else if (AsciiStrCmp (TmpKeyValue, INFO_BUNDLE_LIBRARIES_64_KEY) == 0) {
940 InfoPlistLibraries64 = PlistNodeCast (InfoPlistValue, PLIST_NODE_TYPE_DICT);
941 if (InfoPlistLibraries64 == NULL) {
942 XmlDocumentFree (InfoPlistDocument);
943 FreePool (TmpInfoPlist);
944 FreePool (NewKext->PlistData);
945 FreePool (NewKext);
946 return EFI_INVALID_PARAMETER;
947 }
948
949 if (!Context->Is32Bit) {
950 InfoPlistLibraries = InfoPlistLibraries64;
951 }
952 } else {
953 DEBUG_CODE_BEGIN ();
954 if ((BundleVersion != NULL) && (AsciiStrCmp (TmpKeyValue, INFO_BUNDLE_VERSION_KEY) == 0)) {
955 if (PlistNodeCast (InfoPlistValue, PLIST_NODE_TYPE_STRING) == NULL) {
956 XmlDocumentFree (InfoPlistDocument);
957 FreePool (TmpInfoPlist);
958 FreePool (NewKext->PlistData);
959 FreePool (NewKext);
960 return EFI_INVALID_PARAMETER;
961 }
962
963 BundleVerStr = XmlNodeContent (InfoPlistValue);
964 AsciiStrCpyS (BundleVersion, MAX_INFO_BUNDLE_VERSION_KEY_SIZE, BundleVerStr);
965 }
966
967 DEBUG_CODE_END ();
968 }
969 }
970
971 if (InfoPlistLibraries != NULL) {
972 Status = AddKextDependencies (&Context->InjectedDependencies, InfoPlistLibraries);
973 if (EFI_ERROR (Status)) {
974 XmlDocumentFree (InfoPlistDocument);
975 FreePool (TmpInfoPlist);
976 FreePool (NewKext->PlistData);
977 FreePool (NewKext);
978 return Status;
979 }
980 }
981
982 //
983 // Add OSBundleRequired if not found.
984 //
985 if (!IsLoadable) {
986 Failed = FALSE;
987 Failed |= XmlNodeAppend (InfoPlistRoot, "key", NULL, INFO_BUNDLE_OS_BUNDLE_REQUIRED_KEY) == NULL;
988 Failed |= XmlNodeAppend (InfoPlistRoot, "string", NULL, OS_BUNDLE_REQUIRED_ROOT) == NULL;
989
990 if (Failed) {
991 XmlDocumentFree (InfoPlistDocument);
992 FreePool (TmpInfoPlist);
993 if (NewKext->BinaryFileName != NULL) {
994 FreePool (NewKext->BinaryFileName);
995 }
996
997 FreePool (NewKext->PlistData);
998 FreePool (NewKext);
999 return EFI_OUT_OF_RESOURCES;
1000 }
1001
1002 PlistHasChanges = TRUE;
1003 }
1004
1005 if (PlistHasChanges) {
1006 NewPlistData = XmlDocumentExport (InfoPlistDocument, &NewPlistDataSize, 0, TRUE);
1007 if (NewPlistData == NULL) {
1008 XmlDocumentFree (InfoPlistDocument);
1009 FreePool (TmpInfoPlist);
1010 if (NewKext->BinaryFileName != NULL) {
1011 FreePool (NewKext->BinaryFileName);
1012 }
1013
1014 FreePool (NewKext->PlistData);
1015 FreePool (NewKext);
1016 return EFI_OUT_OF_RESOURCES;
1017 }
1018
1019 FreePool (NewKext->PlistData);
1020 NewKext->PlistData = NewPlistData;
1021 NewKext->PlistDataSize = NewPlistDataSize;
1022 }
1023
1024 XmlDocumentFree (InfoPlistDocument);
1025 FreePool (TmpInfoPlist);
1026
1027 if (Executable != NULL) {
1028 ASSERT (ExecutableSize > 0);
1029
1030 //
1031 // Ensure a binary name was found.
1032 //
1033 ASSERT (NewKext->BinaryFileName != NULL);
1034
1035 //
1036 // Use only the binary for the current arch.
1037 // Some versions of macOS 10.4 may incorrectly chose the 64-bit slice
1038 // despite 32-bit being the only supported Intel architecture.
1039 //
1040 if (!InternalParseKextBinary (&Executable, &ExecutableSize, Context->Is32Bit)) {
1041 FreePool (NewKext->PlistData);
1042 FreePool (NewKext);
1043 return EFI_INVALID_PARAMETER;
1044 }
1045
1046 NewKext->BinaryData = AllocateCopyPool (ExecutableSize, Executable);
1047 if (NewKext->BinaryData == NULL) {
1048 if (NewKext->BinaryFileName != NULL) {
1049 FreePool (NewKext->BinaryFileName);
1050 }
1051
1052 FreePool (NewKext->PlistData);
1053 FreePool (NewKext);
1054 return EFI_OUT_OF_RESOURCES;
1055 }
1056
1057 NewKext->BinaryDataSize = ExecutableSize;
1058 }
1059
1060 InsertTailList (&Context->InjectedKexts, &NewKext->Link);
1061 return EFI_SUCCESS;
1062}
1063
1064EFI_STATUS
1066 IN OUT CACHELESS_CONTEXT *Context,
1067 IN CONST CHAR8 *Identifier
1068 )
1069{
1070 ASSERT (Context != NULL);
1071 ASSERT (Identifier != NULL);
1072
1073 return AddKextDependency (&Context->InjectedDependencies, Identifier);
1074}
1075
1076EFI_STATUS
1078 IN OUT CACHELESS_CONTEXT *Context,
1079 IN CONST CHAR8 *Identifier,
1080 IN PATCHER_GENERIC_PATCH *Patch
1081 )
1082{
1083 ASSERT (Context != NULL);
1084 ASSERT (Identifier != NULL);
1085 ASSERT (Patch != NULL);
1086
1087 return InternalAddKextPatch (Context, Identifier, Patch, 0);
1088}
1089
1090EFI_STATUS
1092 IN OUT CACHELESS_CONTEXT *Context,
1093 IN KERNEL_QUIRK_NAME Quirk
1094 )
1095{
1096 ASSERT (Context != NULL);
1097
1098 return InternalAddKextPatch (Context, NULL, NULL, Quirk);
1099}
1100
1101EFI_STATUS
1103 IN OUT CACHELESS_CONTEXT *Context,
1104 IN CONST CHAR8 *Identifier,
1105 IN BOOLEAN Exclude
1106 )
1107{
1108 EFI_STATUS Status;
1109 PATCHED_KEXT *PatchedKext;
1110
1111 //
1112 // Check if bundle is already present. If not, add to list.
1113 //
1114 PatchedKext = LookupPatchedKextForIdentifier (Context, Identifier);
1115 if (PatchedKext == NULL) {
1116 Status = InternalAddPatchedKext (Context, Identifier, &PatchedKext);
1117 if (EFI_ERROR (Status)) {
1118 return Status;
1119 }
1120 }
1121
1122 PatchedKext->Block = TRUE;
1123
1124 return EFI_SUCCESS;
1125}
1126
1127EFI_STATUS
1129 IN OUT CACHELESS_CONTEXT *Context,
1130 OUT EFI_FILE_PROTOCOL **File
1131 )
1132{
1133 EFI_STATUS Status;
1134 EFI_FILE_PROTOCOL *ExtensionsDirOverlay;
1135
1136 CACHELESS_KEXT *Kext;
1137 LIST_ENTRY *KextLink;
1138 EFI_FILE_INFO *DirectoryEntry;
1139 EFI_FILE_PROTOCOL *NewFile;
1140 EFI_TIME ModificationTime;
1141 UINT32 FileNameIndex;
1142
1143 ASSERT (Context != NULL);
1144 ASSERT (File != NULL);
1145
1146 //
1147 // Create directory overlay.
1148 //
1149 Status = OcGetFileModificationTime (Context->ExtensionsDir, &ModificationTime);
1150 if (EFI_ERROR (Status)) {
1151 ZeroMem (&ModificationTime, sizeof (ModificationTime));
1152 }
1153
1154 Status = VirtualDirCreateOverlayFileNameCopy (Context->ExtensionsDirFileName, &ModificationTime, Context->ExtensionsDir, &ExtensionsDirOverlay);
1155 if (EFI_ERROR (Status)) {
1156 return Status;
1157 }
1158
1159 //
1160 // Inject kexts.
1161 //
1162 FileNameIndex = 0;
1163 KextLink = GetFirstNode (&Context->InjectedKexts);
1164 while (!IsNull (&Context->InjectedKexts, KextLink)) {
1165 Kext = GET_CACHELESS_KEXT_FROM_LINK (KextLink);
1166
1167 //
1168 // Generate next available filename, testing for an existing file to ensure no conflicts.
1169 //
1170 do {
1171 if (FileNameIndex == MAX_UINT32) {
1172 return EFI_DEVICE_ERROR;
1173 }
1174
1175 UnicodeSPrint (Kext->BundleFileName, KEXT_BUNDLE_NAME_SIZE, L"Oc%8X.kext", FileNameIndex++);
1176
1177 Status = Context->ExtensionsDir->Open (Context->ExtensionsDir, &NewFile, Kext->BundleFileName, EFI_FILE_MODE_READ, 0);
1178 if (!EFI_ERROR (Status)) {
1179 NewFile->Close (NewFile);
1180 }
1181 } while (!EFI_ERROR (Status));
1182
1183 DirectoryEntry = AllocateZeroPool (KEXT_BUNDLE_INFO_SIZE);
1184 if (DirectoryEntry == NULL) {
1185 VirtualDirFree (ExtensionsDirOverlay);
1186 return EFI_OUT_OF_RESOURCES;
1187 }
1188
1189 //
1190 // Populate file information.
1191 //
1192 CopyMem (DirectoryEntry->FileName, Kext->BundleFileName, KEXT_BUNDLE_NAME_SIZE);
1193 DirectoryEntry->Size = KEXT_BUNDLE_INFO_SIZE;
1194 DirectoryEntry->Attribute = EFI_FILE_READ_ONLY | EFI_FILE_DIRECTORY;
1195 DirectoryEntry->FileSize = SIZE_OF_EFI_FILE_INFO + L_STR_SIZE (L"Contents");
1196 DirectoryEntry->PhysicalSize = DirectoryEntry->FileSize;
1197
1198 VirtualDirAddEntry (ExtensionsDirOverlay, DirectoryEntry);
1199
1200 KextLink = GetNextNode (&Context->InjectedKexts, KextLink);
1201 }
1202
1203 //
1204 // Return the new handle for the overlayed directory.
1205 //
1206 *File = ExtensionsDirOverlay;
1207 return EFI_SUCCESS;
1208}
1209
1210EFI_STATUS
1212 IN OUT CACHELESS_CONTEXT *Context,
1213 IN CONST CHAR16 *FileName,
1214 OUT EFI_FILE_PROTOCOL **File
1215 )
1216{
1217 EFI_STATUS Status;
1218 EFI_FILE_PROTOCOL *VirtualFileHandle;
1219 CHAR16 *RealFileName;
1220 UINT8 *Buffer;
1221 UINTN BufferSize;
1222
1223 CACHELESS_KEXT *Kext;
1224 LIST_ENTRY *KextLink;
1225
1226 BOOLEAN IsBinaryKext;
1227 CHAR16 *BundleName;
1228 CHAR16 *KextExtension;
1229 CHAR16 *BundlePath;
1230 CHAR16 *BundleBinaryPath;
1231 UINTN BundleBinaryPathSize;
1232 UINTN BundleLength;
1233
1234 EFI_FILE_INFO *ContentsInfo;
1235 EFI_FILE_INFO *ContentsMacOs;
1236 UINTN ContentsInfoEntrySize;
1237 UINTN ContentsMacOsEntrySize;
1238
1239 ASSERT (Context != NULL);
1240 ASSERT (FileName != NULL);
1241 ASSERT (File != NULL);
1242
1243 //
1244 // Only process injected extensions.
1245 //
1246 BundleName = StrStr (FileName, L"Oc");
1247 if (BundleName == NULL) {
1248 return EFI_NOT_FOUND;
1249 }
1250
1251 KextExtension = StrStr (BundleName, L".kext");
1252 if (KextExtension == NULL) {
1253 return EFI_NOT_FOUND;
1254 }
1255
1256 BundlePath = KextExtension + L_STR_LEN (L".kext");
1257 BundleLength = BundlePath - BundleName;
1258
1259 //
1260 // Find matching kext.
1261 //
1262 KextLink = GetFirstNode (&Context->InjectedKexts);
1263 while (!IsNull (&Context->InjectedKexts, KextLink)) {
1264 Kext = GET_CACHELESS_KEXT_FROM_LINK (KextLink);
1265 if (StrnCmp (BundleName, Kext->BundleFileName, BundleLength) == 0) {
1266 IsBinaryKext = Kext->BinaryFileName != NULL;
1267
1268 //
1269 // Contents is being requested.
1270 //
1271 if (StrCmp (BundlePath, L"\\Contents") == 0) {
1272 //
1273 // Create virtual Contents directory.
1274 //
1275 Status = VirtualDirCreateOverlayFileNameCopy (L"Contents", NULL, NULL, &VirtualFileHandle);
1276 if (EFI_ERROR (Status)) {
1277 return Status;
1278 }
1279
1280 //
1281 // Create Info.plist directory entry.
1282 //
1283 ContentsInfoEntrySize = SIZE_OF_EFI_FILE_INFO + L_STR_SIZE (L"Info.plist");
1284 ContentsInfo = AllocateZeroPool (ContentsInfoEntrySize);
1285 if (ContentsInfo == NULL) {
1286 VirtualDirFree (VirtualFileHandle);
1287 return EFI_OUT_OF_RESOURCES;
1288 }
1289
1290 ContentsInfo->Size = ContentsInfoEntrySize;
1291 CopyMem (ContentsInfo->FileName, L"Info.plist", L_STR_SIZE (L"Info.plist"));
1292 ContentsInfo->Attribute = EFI_FILE_READ_ONLY;
1293 ContentsInfo->PhysicalSize = ContentsInfo->FileSize = Kext->PlistDataSize;
1294 VirtualDirAddEntry (VirtualFileHandle, ContentsInfo);
1295
1296 if (IsBinaryKext) {
1297 //
1298 // Create MacOS directory entry.
1299 //
1300 ContentsMacOsEntrySize = SIZE_OF_EFI_FILE_INFO + L_STR_SIZE (L"MacOS");
1301 ContentsMacOs = AllocateZeroPool (ContentsMacOsEntrySize);
1302 if (ContentsMacOs == NULL) {
1303 FreePool (ContentsInfo);
1304 VirtualDirFree (VirtualFileHandle);
1305 return EFI_OUT_OF_RESOURCES;
1306 }
1307
1308 ContentsMacOs->Size = ContentsMacOsEntrySize;
1309 CopyMem (ContentsMacOs->FileName, L"MacOS", L_STR_SIZE (L"MacOS"));
1310 ContentsMacOs->Attribute = EFI_FILE_READ_ONLY | EFI_FILE_DIRECTORY;
1311 if (BaseOverflowAddU64 (SIZE_OF_EFI_FILE_INFO, StrSize (Kext->BinaryFileName), &ContentsMacOs->FileSize)) {
1312 FreePool (ContentsInfo);
1313 VirtualDirFree (VirtualFileHandle);
1314 return EFI_INVALID_PARAMETER;
1315 }
1316
1317 ContentsMacOs->PhysicalSize = ContentsMacOs->FileSize;
1318 VirtualDirAddEntry (VirtualFileHandle, ContentsMacOs);
1319 }
1320 } else {
1321 //
1322 // Contents/Info.plist is being requested.
1323 //
1324 if (StrCmp (BundlePath, L"\\Contents\\Info.plist") == 0) {
1325 RealFileName = L"Info.plist";
1326 BufferSize = Kext->PlistDataSize;
1327 Buffer = AllocateCopyPool (BufferSize, Kext->PlistData);
1328 if (Buffer == NULL) {
1329 return EFI_OUT_OF_RESOURCES;
1330 }
1331
1332 //
1333 // Contents/MacOS/BINARY is being requested.
1334 // It should be safe to assume there will only be one binary ever requested per kext?
1335 //
1336 } else if (IsBinaryKext) {
1337 if (BaseOverflowAddUN (L_STR_SIZE (L"\\Contents\\MacOS\\"), StrSize (Kext->BinaryFileName), &BundleBinaryPathSize)) {
1338 return EFI_OUT_OF_RESOURCES;
1339 }
1340
1341 BundleBinaryPath = AllocateZeroPool (BundleBinaryPathSize);
1342 if (BundleBinaryPath == NULL) {
1343 return EFI_OUT_OF_RESOURCES;
1344 }
1345
1346 StrCatS (BundleBinaryPath, BundleBinaryPathSize / sizeof (CHAR16), L"\\Contents\\MacOS\\");
1347 StrCatS (BundleBinaryPath, BundleBinaryPathSize / sizeof (CHAR16), Kext->BinaryFileName);
1348
1349 if (StrCmp (BundlePath, BundleBinaryPath) == 0) {
1350 FreePool (BundleBinaryPath);
1351
1352 RealFileName = Kext->BinaryFileName;
1353 BufferSize = Kext->BinaryDataSize;
1354 Buffer = AllocateCopyPool (BufferSize, Kext->BinaryData);
1355 if (Buffer == NULL) {
1356 return EFI_OUT_OF_RESOURCES;
1357 }
1358 } else {
1359 FreePool (BundleBinaryPath);
1360 return EFI_NOT_FOUND;
1361 }
1362 } else {
1363 return EFI_NOT_FOUND;
1364 }
1365
1366 //
1367 // Create virtual file.
1368 //
1369 Status = CreateVirtualFileFileNameCopy (RealFileName, Buffer, BufferSize, NULL, &VirtualFileHandle);
1370 if (EFI_ERROR (Status)) {
1371 FreePool (Buffer);
1372 return EFI_OUT_OF_RESOURCES;
1373 }
1374 }
1375
1376 //
1377 // Return our handle.
1378 //
1379 *File = VirtualFileHandle;
1380 return EFI_SUCCESS;
1381 }
1382
1383 KextLink = GetNextNode (&Context->InjectedKexts, KextLink);
1384 }
1385
1386 return EFI_NOT_FOUND;
1387}
1388
1389EFI_STATUS
1391 IN OUT CACHELESS_CONTEXT *Context,
1392 IN CONST CHAR16 *FileName,
1393 IN EFI_FILE_PROTOCOL *File,
1394 OUT EFI_FILE_PROTOCOL **VirtualFile
1395 )
1396{
1397 EFI_STATUS Status;
1398 EFI_TIME ModificationTime;
1399 BUILTIN_KEXT *BuiltinKext;
1400 KEXT_PATCH *KextPatch;
1401 PATCHED_KEXT *PatchedKext;
1402 DEPEND_KEXT *DependKext;
1403 LIST_ENTRY *KextLink;
1404
1405 PATCHER_CONTEXT Patcher;
1406
1407 VOID *Buffer;
1408 UINT32 BufferSize;
1409 XML_DOCUMENT *InfoPlistDocument;
1410 XML_NODE *InfoPlistRoot;
1411 XML_NODE *InfoPlistValue;
1412 CONST CHAR8 *TmpKeyValue;
1413 UINT32 FieldCount;
1414 UINT32 FieldIndex;
1415
1416 BOOLEAN Failed;
1417 CHAR8 *NewPlistData;
1418 UINT32 NewPlistDataSize;
1419
1420 ASSERT (Context != NULL);
1421 ASSERT (FileName != NULL);
1422 ASSERT (File != NULL);
1423 ASSERT (VirtualFile != NULL);
1424
1425 //
1426 // Scan built-in kexts if we have not yet done so.
1427 //
1428 if (!Context->BuiltInKextsValid) {
1429 DEBUG ((DEBUG_INFO, "OCAK: Built-in kext cache is not yet built, building...\n"));
1430
1431 //
1432 // Build list of kexts in system Extensions directory.
1433 //
1434 Status = ScanExtensions (Context, Context->ExtensionsDir, Context->ExtensionsDirFileName, TRUE);
1435 if (EFI_ERROR (Status)) {
1436 return Status;
1437 }
1438
1439 //
1440 // Ensure all kexts to be patched will be loaded.
1441 //
1442 KextLink = GetFirstNode (&Context->PatchedKexts);
1443 while (!IsNull (&Context->PatchedKexts, KextLink)) {
1444 PatchedKext = GET_PATCHED_KEXT_FROM_LINK (KextLink);
1445
1446 BuiltinKext = LookupBuiltinKextForIdentifier (Context, PatchedKext->Identifier);
1447 if (BuiltinKext == NULL) {
1448 //
1449 // Kext is not present, skip.
1450 //
1451 DEBUG ((DEBUG_WARN, "OCAK: Attempted to patch non-existent kext %a\n", PatchedKext->Identifier));
1452 } else {
1453 BuiltinKext->PatchKext = TRUE;
1454 Status = ScanDependencies (Context, PatchedKext->Identifier);
1455 if (EFI_ERROR (Status)) {
1456 return Status;
1457 }
1458 }
1459
1460 KextLink = GetNextNode (&Context->PatchedKexts, KextLink);
1461 }
1462
1463 //
1464 // Scan dependencies, adding any others besides ones being injected.
1465 //
1466 KextLink = GetFirstNode (&Context->InjectedDependencies);
1467 while (!IsNull (&Context->InjectedDependencies, KextLink)) {
1468 DependKext = GET_DEPEND_KEXT_FROM_LINK (KextLink);
1469
1470 Status = ScanDependencies (Context, DependKext->Identifier);
1471 if (EFI_ERROR (Status)) {
1472 return Status;
1473 }
1474
1475 KextLink = GetNextNode (&Context->InjectedDependencies, KextLink);
1476 }
1477
1478 Context->BuiltInKextsValid = TRUE;
1479 DEBUG ((DEBUG_INFO, "OCAK: Built-in kext cache successfully built\n"));
1480 }
1481
1482 //
1483 // Try to get Info.plist.
1484 //
1485 if (OcUnicodeEndsWith (FileName, L"Info.plist", FALSE)) {
1486 BuiltinKext = LookupBuiltinKextForPlistPath (Context, FileName);
1487 if ((BuiltinKext != NULL) && BuiltinKext->PatchValidOSBundleRequired) {
1488 DEBUG ((DEBUG_INFO, "OCAK: Processing plist patches for %s\n", FileName));
1489
1490 //
1491 // Open Info.plist
1492 //
1493 Status = OcAllocateCopyFileData (File, (UINT8 **)&Buffer, &BufferSize);
1494 if (EFI_ERROR (Status)) {
1495 return Status;
1496 }
1497
1498 InfoPlistDocument = XmlDocumentParse (Buffer, BufferSize, FALSE);
1499 if (InfoPlistDocument == NULL) {
1500 FreePool (Buffer);
1501 return EFI_INVALID_PARAMETER;
1502 }
1503
1504 InfoPlistRoot = PlistNodeCast (PlistDocumentRoot (InfoPlistDocument), PLIST_NODE_TYPE_DICT);
1505 if (InfoPlistRoot == NULL) {
1506 XmlDocumentFree (InfoPlistDocument);
1507 FreePool (Buffer);
1508 return EFI_INVALID_PARAMETER;
1509 }
1510
1511 //
1512 // If kext is present but invalid, we need to change it.
1513 // Otherwise add new property.
1514 //
1516 FieldCount = PlistDictChildren (InfoPlistRoot);
1517 for (FieldIndex = 0; FieldIndex < FieldCount; ++FieldIndex) {
1518 TmpKeyValue = PlistKeyValue (PlistDictChild (InfoPlistRoot, FieldIndex, &InfoPlistValue));
1519 if (TmpKeyValue == NULL) {
1520 continue;
1521 }
1522
1523 if (AsciiStrCmp (TmpKeyValue, INFO_BUNDLE_OS_BUNDLE_REQUIRED_KEY) == 0) {
1525 }
1526 }
1527 } else if (BuiltinKext->OSBundleRequiredValue == KEXT_OSBUNDLE_REQUIRED_NONE) {
1528 Failed = FALSE;
1529 Failed |= XmlNodeAppend (InfoPlistRoot, "key", NULL, INFO_BUNDLE_OS_BUNDLE_REQUIRED_KEY) == NULL;
1530 Failed |= XmlNodeAppend (InfoPlistRoot, "string", NULL, OS_BUNDLE_REQUIRED_ROOT) == NULL;
1531 if (Failed) {
1532 XmlDocumentFree (InfoPlistDocument);
1533 FreePool (Buffer);
1534 return EFI_OUT_OF_RESOURCES;
1535 }
1536 }
1537
1538 //
1539 // Export plist.
1540 //
1541 NewPlistData = XmlDocumentExport (InfoPlistDocument, &NewPlistDataSize, 0, TRUE);
1542 if (NewPlistData == NULL) {
1543 XmlDocumentFree (InfoPlistDocument);
1544 FreePool (Buffer);
1545 return EFI_OUT_OF_RESOURCES;
1546 }
1547
1548 XmlDocumentFree (InfoPlistDocument);
1549 FreePool (Buffer);
1550
1551 //
1552 // Virtualize newly created Info.plist.
1553 //
1554 Status = OcGetFileModificationTime (File, &ModificationTime);
1555 if (EFI_ERROR (Status)) {
1556 ZeroMem (&ModificationTime, sizeof (ModificationTime));
1557 }
1558
1559 Status = CreateVirtualFileFileNameCopy (FileName, NewPlistData, NewPlistDataSize, &ModificationTime, VirtualFile);
1560 if (EFI_ERROR (Status)) {
1561 *VirtualFile = NULL;
1562 FreePool (NewPlistData);
1563 }
1564
1565 return Status;
1566 }
1567 } else {
1568 //
1569 // Try to get binary for built-in kext.
1570 //
1571 BuiltinKext = LookupBuiltinKextForBinaryPath (Context, FileName);
1572 if ((BuiltinKext != NULL) && BuiltinKext->PatchKext) {
1573 DEBUG ((DEBUG_INFO, "OCAK: Processing binary patches for %s\n", FileName));
1574
1575 PatchedKext = LookupPatchedKextForIdentifier (Context, BuiltinKext->Identifier);
1576 if (PatchedKext == NULL) {
1577 return EFI_INVALID_PARAMETER;
1578 }
1579
1580 Status = OcAllocateCopyFileData (File, (UINT8 **)&Buffer, &BufferSize);
1581 if (EFI_ERROR (Status)) {
1582 return Status;
1583 }
1584
1585 Status = PatcherInitContextFromBuffer (&Patcher, Buffer, BufferSize, Context->Is32Bit);
1586 if (EFI_ERROR (Status)) {
1587 FreePool (Buffer);
1588 return Status;
1589 }
1590
1591 //
1592 // Apply patches.
1593 //
1594 KextLink = GetFirstNode (&PatchedKext->Patches);
1595 while (!IsNull (&PatchedKext->Patches, KextLink)) {
1596 KextPatch = GET_KEXT_PATCH_FROM_LINK (KextLink);
1597
1598 if (KextPatch->ApplyQuirk) {
1599 Status = KernelApplyQuirk (KextPatch->QuirkName, &Patcher, Context->KernelVersion);
1600 DEBUG ((
1601 EFI_ERROR (Status) ? DEBUG_WARN : DEBUG_INFO,
1602 "OCAK: Cacheless kernel quirk result for %a (%u) - %r\n",
1603 PatchedKext->Identifier,
1604 KextPatch->QuirkName,
1605 Status
1606 ));
1607 } else {
1608 Status = PatcherApplyGenericPatch (&Patcher, &KextPatch->Patch);
1609 DEBUG ((
1610 EFI_ERROR (Status) ? DEBUG_WARN : DEBUG_INFO,
1611 "OCAK: Cacheless patcher result for %a (%a) - %r\n",
1612 PatchedKext->Identifier,
1613 KextPatch->Patch.Comment,
1614 Status
1615 ));
1616 }
1617
1618 KextLink = GetNextNode (&PatchedKext->Patches, KextLink);
1619 }
1620
1621 //
1622 // Block kext if requested.
1623 //
1624 if (PatchedKext->Block) {
1625 Status = PatcherBlockKext (&Patcher);
1626 DEBUG ((
1627 EFI_ERROR (Status) ? DEBUG_WARN : DEBUG_INFO,
1628 "OCAK: Cacheless blocker result for %a - %r\n",
1629 PatchedKext->Identifier,
1630 Status
1631 ));
1632 }
1633
1634 //
1635 // Virtualize patched binary.
1636 //
1637 Status = OcGetFileModificationTime (File, &ModificationTime);
1638 if (EFI_ERROR (Status)) {
1639 ZeroMem (&ModificationTime, sizeof (ModificationTime));
1640 }
1641
1642 Status = CreateVirtualFileFileNameCopy (FileName, Buffer, BufferSize, &ModificationTime, VirtualFile);
1643 if (EFI_ERROR (Status)) {
1644 *VirtualFile = NULL;
1645 FreePool (Buffer);
1646 }
1647
1648 return Status;
1649 }
1650 }
1651
1652 //
1653 // No file hooked.
1654 //
1655 *VirtualFile = NULL;
1656
1657 return EFI_SUCCESS;
1658}
STATIC EFI_STATUS AddKextDependencies(IN OUT LIST_ENTRY *Dependencies, IN XML_NODE *InfoPlistLibraries)
VOID CachelessContextFree(IN OUT CACHELESS_CONTEXT *Context)
STATIC BUILTIN_KEXT * LookupBuiltinKextForPlistPath(IN OUT CACHELESS_CONTEXT *Context, IN CONST CHAR16 *PlistPath)
EFI_STATUS CachelessContextHookBuiltin(IN OUT CACHELESS_CONTEXT *Context, IN CONST CHAR16 *FileName, IN EFI_FILE_PROTOCOL *File, OUT EFI_FILE_PROTOCOL **VirtualFile)
EFI_STATUS CachelessContextPerformInject(IN OUT CACHELESS_CONTEXT *Context, IN CONST CHAR16 *FileName, OUT EFI_FILE_PROTOCOL **File)
STATIC BUILTIN_KEXT * LookupBuiltinKextForIdentifier(IN OUT CACHELESS_CONTEXT *Context, IN CONST CHAR8 *Identifier)
STATIC PATCHED_KEXT * LookupPatchedKextForIdentifier(IN OUT CACHELESS_CONTEXT *Context, IN CONST CHAR8 *Identifier)
STATIC EFI_STATUS ScanExtensions(IN OUT CACHELESS_CONTEXT *Context, IN EFI_FILE_PROTOCOL *File, IN CONST CHAR16 *FilePath, IN BOOLEAN ReadPlugins)
EFI_STATUS CachelessContextInit(IN OUT CACHELESS_CONTEXT *Context, IN CONST CHAR16 *FileName, IN EFI_FILE_PROTOCOL *ExtensionsDir, IN UINT32 KernelVersion, IN BOOLEAN Is32Bit)
EFI_STATUS CachelessContextAddQuirk(IN OUT CACHELESS_CONTEXT *Context, IN KERNEL_QUIRK_NAME Quirk)
EFI_STATUS CachelessContextAddKext(IN OUT CACHELESS_CONTEXT *Context, IN CONST CHAR8 *InfoPlist, IN UINT32 InfoPlistSize, IN UINT8 *Executable OPTIONAL, IN UINT32 ExecutableSize OPTIONAL, OUT CHAR8 BundleVersion[MAX_INFO_BUNDLE_VERSION_KEY_SIZE] OPTIONAL)
EFI_STATUS CachelessContextForceKext(IN OUT CACHELESS_CONTEXT *Context, IN CONST CHAR8 *Identifier)
EFI_STATUS CachelessContextOverlayExtensionsDir(IN OUT CACHELESS_CONTEXT *Context, OUT EFI_FILE_PROTOCOL **File)
STATIC EFI_STATUS InternalAddKextPatch(IN OUT CACHELESS_CONTEXT *Context, IN CONST CHAR8 *Identifier, IN PATCHER_GENERIC_PATCH *Patch OPTIONAL, IN KERNEL_QUIRK_NAME QuirkName)
STATIC EFI_STATUS InternalAddPatchedKext(IN OUT CACHELESS_CONTEXT *Context, IN CONST CHAR8 *Identifier, OUT PATCHED_KEXT **Kext)
STATIC EFI_STATUS ScanDependencies(IN OUT CACHELESS_CONTEXT *Context, IN CHAR8 *Identifier)
STATIC EFI_STATUS AddKextDependency(IN OUT LIST_ENTRY *Dependencies, IN CONST CHAR8 *Identifier)
EFI_STATUS CachelessContextAddPatch(IN OUT CACHELESS_CONTEXT *Context, IN CONST CHAR8 *Identifier, IN PATCHER_GENERIC_PATCH *Patch)
EFI_STATUS CachelessContextBlock(IN OUT CACHELESS_CONTEXT *Context, IN CONST CHAR8 *Identifier, IN BOOLEAN Exclude)
STATIC BUILTIN_KEXT * LookupBuiltinKextForBinaryPath(IN OUT CACHELESS_CONTEXT *Context, IN CONST CHAR16 *BinaryPath)
STATIC VOID FreeBuiltInKext(IN BUILTIN_KEXT *BuiltinKext)
#define GET_DEPEND_KEXT_FROM_LINK(This)
#define PATCHED_KEXT_SIGNATURE
#define KEXT_BUNDLE_INFO_SIZE
#define GET_PATCHED_KEXT_FROM_LINK(This)
#define KEXT_BUNDLE_NAME_SIZE
@ KEXT_OSBUNDLE_REQUIRED_VALID
@ KEXT_OSBUNDLE_REQUIRED_NONE
@ KEXT_OSBUNDLE_REQUIRED_INVALID
#define KEXT_PATCH_SIGNATURE
#define GET_CACHELESS_KEXT_FROM_LINK(This)
#define GET_BUILTIN_KEXT_FROM_LINK(This)
#define DEPEND_KEXT_SIGNATURE
#define GET_KEXT_PATCH_FROM_LINK(This)
#define BUILTIN_KEXT_SIGNATURE
#define CACHELESS_KEXT_SIGNATURE
KERNEL_QUIRK gKernelQuirks[]
STATIC UINT32 KernelVersion
Definition KextInject.c:28
BOOLEAN InternalParseKextBinary(IN OUT UINT8 **Buffer, IN OUT UINT32 *BufferSize, IN BOOLEAN Is32Bit)
DMG_FILEPATH_DEVICE_PATH FilePath
EFI_STATUS PatcherBlockKext(IN OUT PATCHER_CONTEXT *Context)
#define INFO_BUNDLE_LIBRARIES_64_KEY
EFI_STATUS KernelApplyQuirk(IN KERNEL_QUIRK_NAME Name, IN OUT PATCHER_CONTEXT *Patcher OPTIONAL, IN UINT32 KernelVersion)
#define INFO_BUNDLE_OS_BUNDLE_REQUIRED_KEY
#define MAX_INFO_BUNDLE_VERSION_KEY_SIZE
#define OS_BUNDLE_REQUIRED_SAFE_BOOT
#define INFO_BUNDLE_EXECUTABLE_KEY
EFI_STATUS PatcherApplyGenericPatch(IN OUT PATCHER_CONTEXT *Context, IN PATCHER_GENERIC_PATCH *Patch)
#define INFO_BUNDLE_VERSION_KEY
#define INFO_BUNDLE_LIBRARIES_KEY
KERNEL_QUIRK_NAME
EFI_STATUS PatcherInitContextFromBuffer(IN OUT PATCHER_CONTEXT *Context, IN OUT UINT8 *Buffer, IN UINT32 BufferSize, IN BOOLEAN Use32Bit)
#define INFO_BUNDLE_IDENTIFIER_KEY
#define OS_BUNDLE_REQUIRED_ROOT
EFI_STATUS OcGetFileModificationTime(IN EFI_FILE_PROTOCOL *File, OUT EFI_TIME *Time)
EFI_STATUS OcAllocateCopyFileData(IN EFI_FILE_PROTOCOL *File, OUT UINT8 **Buffer, OUT UINT32 *BufferSize)
#define L_STR_LEN(String)
Definition OcStringLib.h:26
#define L_STR_SIZE(String)
Definition OcStringLib.h:35
CHAR16 * AsciiStrCopyToUnicode(IN CONST CHAR8 *String, IN UINTN Length)
Definition OcAsciiLib.c:119
EFI_STATUS EFIAPI OcUnicodeSafeSPrint(OUT CHAR16 *StartOfBuffer, IN UINTN BufferSize, IN CONST CHAR16 *FormatString,...)
BOOLEAN EFIAPI OcUnicodeEndsWith(IN CONST CHAR16 *String, IN CONST CHAR16 *SearchString, IN BOOLEAN CaseInsensitiveMatch)
OC_TYPING_BUFFER_ENTRY Buffer[OC_TYPING_BUFFER_SIZE]
Definition OcTypingLib.h:42
EFI_STATUS VirtualDirAddEntry(IN EFI_FILE_PROTOCOL *This, IN EFI_FILE_INFO *FileInfo)
Definition VirtualDir.c:561
EFI_STATUS VirtualDirCreateOverlayFileNameCopy(IN CONST CHAR16 *FileName, IN CONST EFI_TIME *ModificationTime OPTIONAL, IN EFI_FILE_PROTOCOL *UnderlyingFile OPTIONAL, OUT EFI_FILE_PROTOCOL **File)
Definition VirtualDir.c:531
VOID VirtualDirFree(IN EFI_FILE_PROTOCOL *This)
Definition VirtualDir.c:587
EFI_STATUS CreateVirtualFileFileNameCopy(IN CONST CHAR16 *FileName, IN VOID *FileBuffer, IN UINT64 FileSize, IN CONST EFI_TIME *ModificationTime OPTIONAL, OUT EFI_FILE_PROTOCOL **File)
@ PLIST_NODE_TYPE_DICT
Definition OcXmlLib.h:91
@ PLIST_NODE_TYPE_STRING
Definition OcXmlLib.h:93
XML_DOCUMENT * XmlDocumentParse(IN OUT CHAR8 *Buffer, IN UINT32 Length, IN BOOLEAN WithRefs)
Definition OcXmlLib.c:1308
CONST CHAR8 * PlistKeyValue(IN XML_NODE *Node OPTIONAL)
Definition OcXmlLib.c:1841
CHAR8 * XmlDocumentExport(IN CONST XML_DOCUMENT *Document, OUT UINT32 *Length OPTIONAL, IN UINT32 Skip, IN BOOLEAN PrependPlistInfo)
Definition OcXmlLib.c:1367
CONST CHAR8 * XmlNodeContent(IN CONST XML_NODE *Node)
Definition OcXmlLib.c:1467
UINT32 PlistDictChildren(IN CONST XML_NODE *Node)
Definition OcXmlLib.c:1813
XML_NODE * PlistNodeCast(IN XML_NODE *Node OPTIONAL, IN PLIST_NODE_TYPE Type)
Definition OcXmlLib.c:1760
XML_NODE * XmlNodeAppend(IN OUT XML_NODE *Node, IN CONST CHAR8 *Name, IN CONST CHAR8 *Attributes OPTIONAL, IN CONST CHAR8 *Content OPTIONAL)
Definition OcXmlLib.c:1581
XML_NODE * PlistDocumentRoot(IN CONST XML_DOCUMENT *Document)
Definition OcXmlLib.c:1736
VOID XmlDocumentFree(IN OUT XML_DOCUMENT *Document)
Definition OcXmlLib.c:1435
VOID XmlNodeChangeContent(IN OUT XML_NODE *Node, IN CONST CHAR8 *Content)
Definition OcXmlLib.c:1477
XML_NODE * PlistDictChild(IN CONST XML_NODE *Node, IN UINT32 Child, OUT XML_NODE **Value OPTIONAL)
Definition OcXmlLib.c:1823
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
#define ASSERT(x)
Definition coder.h:55
LIST_ENTRY Dependencies
BOOLEAN PatchValidOSBundleRequired
CHAR16 * BinaryFileName
CHAR16 BundleFileName[KEXT_BUNDLE_NAME_LEN+1]
LIST_ENTRY Link
CONST CHAR8 * Identifier
PATCHER_GENERIC_PATCH Patch
LIST_ENTRY Link
KERNEL_QUIRK_NAME QuirkName