19#include <Library/BaseLib.h>
20#include <Library/BaseMemoryLib.h>
21#include <Library/DebugLib.h>
22#include <Library/MemoryAllocationLib.h>
40 CONST CHAR8 *KextPlistKey;
54 for (KextIndex = 1; KextIndex <= KextCount; ++KextIndex) {
56 if (LastKext == NULL) {
64 for (FieldIndex = 0; FieldIndex < FieldCount; ++FieldIndex) {
66 if (KextPlistKey == NULL) {
71 if (!
PlistIntegerValue (KextPlistValue, &LoadAddress,
sizeof (LoadAddress), TRUE)) {
80 if ((LoadSize != 0) && (LoadAddress != 0)) {
85 if (BaseOverflowAddU64 (LoadAddress, LoadSize, &LoadAddress)) {
89 if (LoadAddress != 0) {
109 if (*PrelinkedInfoSegment == NULL) {
110 return EFI_NOT_FOUND;
113 if ((MachoContext->Is32Bit ? (*PrelinkedInfoSegment)->Segment32.FileOffset : (*PrelinkedInfoSegment)->Segment64.FileOffset) > MAX_UINT32) {
114 return EFI_UNSUPPORTED;
119 *PrelinkedInfoSegment,
122 if (*PrelinkedInfoSection == NULL) {
123 return EFI_NOT_FOUND;
126 if ((MachoContext->Is32Bit ? (*PrelinkedInfoSection)->Section32.Size : (*PrelinkedInfoSection)->Section64.Size) > MAX_UINT32) {
127 return EFI_UNSUPPORTED;
138 IN UINT32 BufferSize,
139 OUT BOOLEAN *KernelCollection OPTIONAL
144 BOOLEAN IsKernelCollection;
150 IsKernelCollection = (Context->Is32Bit ?
153 if (KernelCollection != NULL) {
154 *KernelCollection = IsKernelCollection;
160 if (IsKernelCollection) {
168 "OCAK: KC symtab failed locating inner %Lx %Lx (%d)\n",
173 return EFI_INVALID_PARAMETER;
186 "OCAK: KC symtab failed initialising inner %Lx %x\n",
190 return EFI_INVALID_PARAMETER;
196 "OCAK: KC symtab failed getting symtab from inner %Lx %x\n",
200 return EFI_INVALID_PARAMETER;
210 IN OUT UINT8 *Prelinked,
211 IN UINT32 PrelinkedSize,
212 IN UINT32 PrelinkedAllocSize,
219 CONST CHAR8 *PrelinkedInfoRootKey;
220 UINT64 SegmentEndOffset;
221 UINT32 PrelinkedInfoRootIndex;
222 UINT32 PrelinkedInfoRootCount;
226 ASSERT (Prelinked != NULL);
227 ASSERT (PrelinkedSize > 0);
228 ASSERT (PrelinkedAllocSize >= PrelinkedSize);
230 ZeroMem (Context,
sizeof (*Context));
232 Context->Prelinked = Prelinked;
233 Context->PrelinkedSize =
MACHO_ALIGN (PrelinkedSize);
234 Context->PrelinkedAllocSize = PrelinkedAllocSize;
235 Context->Is32Bit = Is32Bit;
240 if (Context->PrelinkedSize != PrelinkedSize) {
241 if (Context->PrelinkedSize > PrelinkedAllocSize) {
242 return EFI_BUFFER_TOO_SMALL;
245 ZeroMem (&Prelinked[PrelinkedSize], Context->PrelinkedSize - PrelinkedSize);
251 if (!
MachoInitializeContext (&Context->PrelinkedMachContext, Prelinked, PrelinkedSize, 0, PrelinkedSize, Context->Is32Bit)) {
252 return EFI_INVALID_PARAMETER;
256 &Context->PrelinkedMachContext,
257 &Context->InnerMachContext,
259 Context->PrelinkedSize,
260 &Context->IsKernelCollection
262 if (EFI_ERROR (Status)) {
269 InitializeListHead (&Context->PrelinkedKexts);
270 InitializeListHead (&Context->InjectedKexts);
272 if (PrelinkedKext == NULL) {
273 return EFI_INVALID_PARAMETER;
279 if (Context->PrelinkedLastAddress == 0) {
280 return EFI_INVALID_PARAMETER;
287 &Context->PrelinkedMachContext,
288 &Context->PrelinkedInfoSegment,
289 &Context->PrelinkedInfoSection
291 if (EFI_ERROR (Status)) {
295 if (Context->IsKernelCollection) {
300 &Context->InnerMachContext,
304 if (EFI_ERROR (Status)) {
309 &Context->PrelinkedMachContext,
312 if (Context->RegionSegment == NULL) {
313 return EFI_NOT_FOUND;
317 &Context->PrelinkedMachContext,
320 if (Context->LinkEditSegment == NULL) {
321 return EFI_NOT_FOUND;
325 &Context->PrelinkedMachContext,
328 if (Context->PrelinkedTextSegment == NULL) {
329 return EFI_NOT_FOUND;
333 &Context->PrelinkedMachContext,
334 Context->PrelinkedTextSegment,
337 if (Context->PrelinkedTextSection == NULL) {
338 return EFI_NOT_FOUND;
342 Context->PrelinkedInfo = Context->Is32Bit ?
344 Context->PrelinkedInfoSection->Section32.Size,
345 &Context->Prelinked[Context->PrelinkedInfoSection->Section32.Offset]
348 (UINTN)Context->PrelinkedInfoSection->Section64.Size,
349 &Context->Prelinked[Context->PrelinkedInfoSection->Section64.Offset]
351 if (Context->PrelinkedInfo == NULL) {
353 return EFI_OUT_OF_RESOURCES;
357 Context->PrelinkedInfo,
358 (UINT32)(Context->Is32Bit ?
359 Context->PrelinkedInfoSection->Section32.Size : Context->PrelinkedInfoSection->Section64.Size),
362 if (Context->PrelinkedInfoDocument == NULL) {
364 return EFI_INVALID_PARAMETER;
371 if (Context->IsKernelCollection) {
378 if (PrelinkedInfoRoot == NULL) {
380 return EFI_INVALID_PARAMETER;
383 if (Context->IsKernelCollection) {
387 SegmentEndOffset = Context->LinkEditSegment->Segment64.FileOffset + Context->LinkEditSegment->Segment64.FileSize;
389 if (
MACHO_ALIGN (SegmentEndOffset) != Context->PrelinkedSize) {
391 return EFI_INVALID_PARAMETER;
394 Context->PrelinkedLastLoadAddress = Context->LinkEditSegment->Segment64.VirtualAddress + Context->LinkEditSegment->Segment64.Size;
401 for (PrelinkedInfoRootIndex = 0; PrelinkedInfoRootIndex < PrelinkedInfoRootCount; ++PrelinkedInfoRootIndex) {
403 if (PrelinkedInfoRootKey == NULL) {
409 if (Context->PrelinkedLastLoadAddress == 0) {
413 if (Context->PrelinkedLastLoadAddress != 0) {
423 return EFI_INVALID_PARAMETER;
435 if (Context->PrelinkedInfoDocument != NULL) {
437 Context->PrelinkedInfoDocument = NULL;
440 if (Context->KextScratchBuffer != NULL) {
441 FreePool (Context->KextScratchBuffer);
442 Context->KextScratchBuffer = NULL;
445 if (Context->PrelinkedInfo != NULL) {
446 FreePool (Context->PrelinkedInfo);
447 Context->PrelinkedInfo = NULL;
450 if (Context->PooledBuffers != NULL) {
451 for (Index = 0; Index < Context->PooledBuffersCount; ++Index) {
452 FreePool (Context->PooledBuffers[Index]);
455 FreePool (Context->PooledBuffers);
456 Context->PooledBuffers = NULL;
459 if (Context->LinkBuffer != NULL) {
460 ZeroMem (Context->LinkBuffer, Context->LinkBufferSize);
461 FreePool (Context->LinkBuffer);
462 Context->LinkBuffer = NULL;
465 if (Context->PrelinkedStateKernel != NULL) {
466 FreePool (Context->PrelinkedStateKernel);
467 Context->PrelinkedStateKernel = NULL;
470 if (Context->PrelinkedStateKexts != NULL) {
471 FreePool (Context->PrelinkedStateKexts);
472 Context->PrelinkedStateKexts = NULL;
475 while (!IsListEmpty (&Context->PrelinkedKexts)) {
476 Link = GetFirstNode (&Context->PrelinkedKexts);
478 RemoveEntryList (Link);
482 ZeroMem (&Context->PrelinkedKexts, sizeof (Context->PrelinkedKexts));
487 ZeroMem (&Context->InjectedKexts, sizeof (Context->InjectedKexts));
496 VOID **NewPooledBuffers;
498 if (Context->PooledBuffersCount == Context->PooledBuffersAllocCount) {
499 NewPooledBuffers = AllocatePool (
500 2 * (Context->PooledBuffersAllocCount + 1) * sizeof (NewPooledBuffers[0])
502 if (NewPooledBuffers == NULL) {
503 return EFI_OUT_OF_RESOURCES;
506 if (Context->PooledBuffers != NULL) {
508 &NewPooledBuffers[0],
509 &Context->PooledBuffers[0],
510 Context->PooledBuffersCount * sizeof (NewPooledBuffers[0])
512 FreePool (Context->PooledBuffers);
515 Context->PooledBuffers = NewPooledBuffers;
516 Context->PooledBuffersAllocCount = 2 * (Context->PooledBuffersAllocCount + 1);
519 Context->PooledBuffers[Context->PooledBuffersCount] =
Buffer;
520 Context->PooledBuffersCount++;
528 IN UINT32 LinkedExpansion,
529 IN UINT32 ReservedExeSize
533 UINT64 SegmentEndOffset;
534 UINT32 AlignedExpansion;
536 if (Context->IsKernelCollection) {
541 if ( (Context->PrelinkedAllocSize < LinkedExpansion)
542 || (Context->PrelinkedAllocSize - LinkedExpansion < Context->PrelinkedSize))
544 return EFI_OUT_OF_RESOURCES;
547 ASSERT (Context->PrelinkedLastAddress == Context->PrelinkedLastLoadAddress);
554 "KextsFixupChains may be unaligned"
557 Context->KextsFixupChains = (VOID *)(Context->Prelinked + Context->PrelinkedSize);
564 Context->Prelinked + Context->PrelinkedSize,
568 Context->PrelinkedSize += AlignedExpansion;
569 Context->PrelinkedLastAddress += AlignedExpansion;
570 Context->PrelinkedLastLoadAddress += AlignedExpansion;
571 Context->LinkEditSegment->Segment64.Size += AlignedExpansion;
572 Context->LinkEditSegment->Segment64.FileSize += AlignedExpansion;
613 SegmentEndOffset = Context->Is32Bit ?
614 Context->PrelinkedInfoSegment->Segment32.FileOffset + Context->PrelinkedInfoSegment->Segment32.FileSize :
615 Context->PrelinkedInfoSegment->Segment64.FileOffset + Context->PrelinkedInfoSegment->Segment64.FileSize;
617 if (
MACHO_ALIGN (SegmentEndOffset) == Context->PrelinkedSize) {
620 "OCAK: Reducing %a-bit prelink size from %X to %X via plist\n",
621 Context->Is32Bit ?
"32" :
"64",
622 Context->PrelinkedSize,
625 Context->PrelinkedInfoSegment->Segment32.FileOffset : Context->PrelinkedInfoSegment->Segment64.FileOffset
630 Context->PrelinkedInfoSegment->Segment32.FileOffset : Context->PrelinkedInfoSegment->Segment64.FileOffset
635 "OCAK: Leaving unchanged %a-bit prelink size %X due to %LX plist\n",
636 Context->Is32Bit ?
"32" :
"64",
637 Context->PrelinkedSize,
642 if (Context->PrelinkedStateSegment != NULL) {
643 SegmentEndOffset = Context->Is32Bit ?
644 Context->PrelinkedStateSegment->Segment32.FileOffset + Context->PrelinkedStateSegment->Segment32.FileSize :
645 Context->PrelinkedStateSegment->Segment64.FileOffset + Context->PrelinkedStateSegment->Segment64.FileSize;
647 if (
MACHO_ALIGN (SegmentEndOffset) == Context->PrelinkedSize) {
650 "OCAK: Reducing %a-bit prelink size from %X to %X via state\n",
651 Context->Is32Bit ?
"32" :
"64",
652 Context->PrelinkedSize,
655 Context->PrelinkedStateSegment->Segment32.FileOffset : Context->PrelinkedStateSegment->Segment64.FileOffset
660 Context->PrelinkedStateSegment->Segment32.FileOffset : Context->PrelinkedStateSegment->Segment64.FileOffset
667 if (Context->Is32Bit) {
668 Context->PrelinkedStateSegment->Segment32.VirtualAddress = 0;
669 Context->PrelinkedStateSegment->Segment32.Size = 0;
670 Context->PrelinkedStateSegment->Segment32.FileOffset = 0;
671 Context->PrelinkedStateSegment->Segment32.FileSize = 0;
672 Context->PrelinkedStateSectionKernel->Section32.Address = 0;
673 Context->PrelinkedStateSectionKernel->Section32.Size = 0;
674 Context->PrelinkedStateSectionKernel->Section32.Offset = 0;
675 Context->PrelinkedStateSectionKexts->Section32.Address = 0;
676 Context->PrelinkedStateSectionKexts->Section32.Size = 0;
677 Context->PrelinkedStateSectionKexts->Section32.Offset = 0;
679 Context->PrelinkedStateSegment->Segment64.VirtualAddress = 0;
680 Context->PrelinkedStateSegment->Segment64.Size = 0;
681 Context->PrelinkedStateSegment->Segment64.FileOffset = 0;
682 Context->PrelinkedStateSegment->Segment64.FileSize = 0;
683 Context->PrelinkedStateSectionKernel->Section64.Address = 0;
684 Context->PrelinkedStateSectionKernel->Section64.Size = 0;
685 Context->PrelinkedStateSectionKernel->Section64.Offset = 0;
686 Context->PrelinkedStateSectionKexts->Section64.Address = 0;
687 Context->PrelinkedStateSectionKexts->Section64.Size = 0;
688 Context->PrelinkedStateSectionKexts->Section64.Offset = 0;
693 "OCAK: Leaving unchanged %a-bit prelink size %X due to %LX state\n",
694 Context->Is32Bit ?
"32" :
"64",
695 Context->PrelinkedSize,
701 if (Context->Is32Bit) {
702 Context->PrelinkedInfoSegment->Segment32.VirtualAddress = 0;
703 Context->PrelinkedInfoSegment->Segment32.Size = 0;
704 Context->PrelinkedInfoSegment->Segment32.FileOffset = 0;
705 Context->PrelinkedInfoSegment->Segment32.FileSize = 0;
706 Context->PrelinkedInfoSection->Section32.Address = 0;
707 Context->PrelinkedInfoSection->Section32.Size = 0;
708 Context->PrelinkedInfoSection->Section32.Offset = 0;
710 Context->PrelinkedInfoSegment->Segment64.VirtualAddress = 0;
711 Context->PrelinkedInfoSegment->Segment64.Size = 0;
712 Context->PrelinkedInfoSegment->Segment64.FileOffset = 0;
713 Context->PrelinkedInfoSegment->Segment64.FileSize = 0;
714 Context->PrelinkedInfoSection->Section64.Address = 0;
715 Context->PrelinkedInfoSection->Section64.Size = 0;
716 Context->PrelinkedInfoSection->Section64.Offset = 0;
720 if (Context->PrelinkedLastAddress == 0) {
721 return EFI_INVALID_PARAMETER;
727 SegmentEndOffset = Context->Is32Bit ?
728 Context->PrelinkedTextSegment->Segment32.FileOffset + Context->PrelinkedTextSegment->Segment32.FileSize :
729 Context->PrelinkedTextSegment->Segment64.FileOffset + Context->PrelinkedTextSegment->Segment64.FileSize;
731 if (
MACHO_ALIGN (SegmentEndOffset) != Context->PrelinkedSize) {
736 return EFI_UNSUPPORTED;
743 Context->KextsFileOffset = Context->PrelinkedSize;
744 Context->KextsVmAddress = Context->PrelinkedLastAddress;
746 if (Context->IsKernelCollection) {
748 if (EFI_ERROR (Status)) {
763 UINT32 ExportedInfoSize;
768 if (Context->IsKernelCollection) {
773 KextsSize = Context->PrelinkedSize - Context->KextsFileOffset;
777 ASSERT (ChainSize <= Context->KextsFixupChains->Size);
779 Context->KextsFixupChains->Size = ChainSize;
780 Context->KextsFixupChains->PageCount = (UINT16)(KextsSize /
MACHO_PAGE_SIZE);
783 if (EFI_ERROR (Status)) {
786 }
else if ((Context->PrelinkedStateSegment != NULL) && ((Context->Is32Bit ?
787 Context->PrelinkedStateSegment->Segment32.VirtualAddress : Context->PrelinkedStateSegment->Segment64.VirtualAddress)
791 if (EFI_ERROR (Status)) {
796 ExportedInfo =
XmlDocumentExport (Context->PrelinkedInfoDocument, &ExportedInfoSize, 0, FALSE);
797 if (ExportedInfo == NULL) {
798 return EFI_OUT_OF_RESOURCES;
806 if ( BaseOverflowAddU32 (Context->PrelinkedSize,
MACHO_ALIGN (ExportedInfoSize), &NewSize)
807 || (NewSize > Context->PrelinkedAllocSize))
809 FreePool (ExportedInfo);
810 return EFI_BUFFER_TOO_SMALL;
818 if (Context->IsKernelCollection && (
MACHO_ALIGN (ExportedInfoSize) <= Context->PrelinkedInfoSegment->Size)) {
820 &Context->Prelinked[Context->PrelinkedInfoSegment->FileOffset],
826 &Context->Prelinked[Context->PrelinkedInfoSegment->FileOffset + ExportedInfoSize],
827 Context->PrelinkedInfoSegment->FileSize - ExportedInfoSize
830 FreePool (ExportedInfo);
837 if (Context->Is32Bit) {
838 Context->PrelinkedInfoSegment->Segment32.VirtualAddress = (UINT32)Context->PrelinkedLastAddress;
839 Context->PrelinkedInfoSegment->Segment32.Size =
MACHO_ALIGN (ExportedInfoSize);
840 Context->PrelinkedInfoSegment->Segment32.FileOffset = Context->PrelinkedSize;
841 Context->PrelinkedInfoSegment->Segment32.FileSize =
MACHO_ALIGN (ExportedInfoSize);
842 Context->PrelinkedInfoSection->Section32.Address = (UINT32)Context->PrelinkedLastAddress;
843 Context->PrelinkedInfoSection->Section32.Size =
MACHO_ALIGN (ExportedInfoSize);
844 Context->PrelinkedInfoSection->Section32.Offset = Context->PrelinkedSize;
846 Context->PrelinkedInfoSegment->Segment64.VirtualAddress = Context->PrelinkedLastAddress;
847 Context->PrelinkedInfoSegment->Segment64.Size =
MACHO_ALIGN (ExportedInfoSize);
848 Context->PrelinkedInfoSegment->Segment64.FileOffset = Context->PrelinkedSize;
849 Context->PrelinkedInfoSegment->Segment64.FileSize =
MACHO_ALIGN (ExportedInfoSize);
850 Context->PrelinkedInfoSection->Section64.Address = Context->PrelinkedLastAddress;
851 Context->PrelinkedInfoSection->Section64.Size =
MACHO_ALIGN (ExportedInfoSize);
852 Context->PrelinkedInfoSection->Section64.Offset = Context->PrelinkedSize;
855 if (Context->IsKernelCollection) {
860 Context->InnerInfoSegment->VirtualAddress = Context->PrelinkedLastAddress;
861 Context->InnerInfoSegment->Size =
MACHO_ALIGN (ExportedInfoSize);
862 Context->InnerInfoSegment->FileOffset = Context->PrelinkedSize;
863 Context->InnerInfoSegment->FileSize =
MACHO_ALIGN (ExportedInfoSize);
864 Context->InnerInfoSection->Address = Context->PrelinkedLastAddress;
865 Context->InnerInfoSection->Size =
MACHO_ALIGN (ExportedInfoSize);
866 Context->InnerInfoSection->Offset = Context->PrelinkedSize;
870 &Context->Prelinked[Context->PrelinkedSize],
876 &Context->Prelinked[Context->PrelinkedSize + ExportedInfoSize],
880 Context->PrelinkedLastAddress +=
MACHO_ALIGN (ExportedInfoSize);
881 Context->PrelinkedSize +=
MACHO_ALIGN (ExportedInfoSize);
883 Context->PrelinkedMachContext.FileSize = Context->PrelinkedSize;
885 if (Context->IsKernelCollection) {
892 &Context->PrelinkedMachContext,
897 FreePool (ExportedInfo);
904 IN OUT UINT32 *ReservedInfoSize,
905 IN OUT UINT32 *ReservedExeSize,
906 IN UINT32 InfoPlistSize,
907 IN UINT8 *Executable OPTIONAL,
908 IN UINT32 ExecutableSize OPTIONAL,
918 return EFI_INVALID_PARAMETER;
923 if (Executable != NULL) {
924 ASSERT (ExecutableSize > 0);
926 return EFI_INVALID_PARAMETER;
930 if (ExecutableSize == 0) {
931 return EFI_INVALID_PARAMETER;
935 if ( BaseOverflowAddU32 (*ReservedInfoSize, InfoPlistSize, &InfoPlistSize)
936 || BaseOverflowAddU32 (*ReservedExeSize, ExecutableSize, &ExecutableSize))
938 return EFI_INVALID_PARAMETER;
941 *ReservedInfoSize = InfoPlistSize;
942 *ReservedExeSize = ExecutableSize;
950 IN CONST CHAR8 *Identifier OPTIONAL,
951 IN CONST CHAR8 *BundlePath,
952 IN CONST CHAR8 *InfoPlist,
953 IN UINT32 InfoPlistSize,
954 IN CONST CHAR8 *ExecutablePath OPTIONAL,
955 IN CONST UINT8 *Executable OPTIONAL,
956 IN UINT32 ExecutableSize OPTIONAL,
969 CONST CHAR8 *TmpKeyValue;
972 UINT32 NewInfoPlistSize;
973 UINT32 NewPrelinkedSize;
974 UINT32 AlignedExecutableSize;
978 CHAR8 ExecutableSourceAddrStr[24];
979 CHAR8 ExecutableSizeStr[24];
980 CHAR8 ExecutableLoadAddrStr[24];
981 CHAR8 KmodInfoStr[24];
984 UINT64 LoadAddressOffset;
985 CONST CHAR8 *BundleVerStr;
987 PrelinkedKext = NULL;
990 ASSERT (BundlePath != NULL);
991 ASSERT (InfoPlist != NULL);
992 ASSERT (InfoPlistSize > 0);
995 AlignedExecutableSize = 0;
1001 if (Identifier != NULL) {
1003 DEBUG ((DEBUG_INFO,
"OCAK: Bundle %a is already present in prelinked\n", Identifier));
1004 return EFI_ALREADY_STARTED;
1011 if (Executable != NULL) {
1012 ASSERT (ExecutableSize > 0);
1014 DEBUG ((DEBUG_INFO,
"OCAK: Injected kext %a/%a is not a supported executable\n", BundlePath, ExecutablePath));
1015 return EFI_INVALID_PARAMETER;
1021 KextOffset = Context->PrelinkedSize;
1025 &Context->Prelinked[KextOffset],
1026 Context->PrelinkedAllocSize - KextOffset,
1031 AlignedExecutableSize =
MACHO_ALIGN (ExecutableSize);
1033 if ( BaseOverflowAddU32 (KextOffset, AlignedExecutableSize, &NewPrelinkedSize)
1034 || (NewPrelinkedSize > Context->PrelinkedAllocSize)
1035 || (ExecutableSize == 0))
1037 return EFI_BUFFER_TOO_SMALL;
1041 &Context->Prelinked[KextOffset + ExecutableSize],
1042 AlignedExecutableSize - ExecutableSize
1046 || BaseOverflowAddU64 (Context->PrelinkedLastLoadAddress, FileOffset, &LoadAddressOffset))
1048 return EFI_INVALID_PARAMETER;
1051 Result =
KextFindKmodAddress (&ExecutableContext, LoadAddressOffset, ExecutableSize, &KmodAddress);
1053 return EFI_INVALID_PARAMETER;
1060 TmpInfoPlist = AllocateCopyPool (InfoPlistSize, InfoPlist);
1061 if (TmpInfoPlist == NULL) {
1062 return EFI_OUT_OF_RESOURCES;
1066 if (InfoPlistDocument == NULL) {
1067 FreePool (TmpInfoPlist);
1068 return EFI_INVALID_PARAMETER;
1072 if (InfoPlistRoot == NULL) {
1074 FreePool (TmpInfoPlist);
1075 return EFI_INVALID_PARAMETER;
1083 DEBUG_CODE_BEGIN ();
1086 if (BundleVersion != NULL) {
1087 for (FieldIndex = 0; FieldIndex < FieldCount; ++FieldIndex) {
1089 if (TmpKeyValue == NULL) {
1108 if (Executable == NULL) {
1109 for (FieldIndex = 0; FieldIndex < FieldCount; ++FieldIndex) {
1111 if (TmpKeyValue == NULL) {
1127 Failed |=
XmlNodeAppend (InfoPlistRoot,
"string", NULL, BundlePath) == NULL;
1128 if (Executable != NULL) {
1130 Failed |=
XmlNodeAppend (InfoPlistRoot,
"string", NULL, ExecutablePath) == NULL;
1131 Failed |= !
AsciiUint64ToLowerHex (ExecutableSourceAddrStr,
sizeof (ExecutableSourceAddrStr), Context->PrelinkedLastAddress);
1134 Failed |= !
AsciiUint64ToLowerHex (ExecutableLoadAddrStr,
sizeof (ExecutableLoadAddrStr), Context->PrelinkedLastLoadAddress);
1137 Failed |= !
AsciiUint64ToLowerHex (ExecutableSizeStr,
sizeof (ExecutableSizeStr), AlignedExecutableSize);
1147 FreePool (TmpInfoPlist);
1148 return EFI_OUT_OF_RESOURCES;
1151 if (Executable != NULL) {
1156 Context->PrelinkedLastLoadAddress,
1161 if (PrelinkedKext == NULL) {
1163 FreePool (TmpInfoPlist);
1164 return EFI_INVALID_PARAMETER;
1171 Context->PrelinkedSize += AlignedExecutableSize;
1172 Context->PrelinkedLastAddress += AlignedExecutableSize;
1173 Context->PrelinkedLastLoadAddress += AlignedExecutableSize;
1175 if (Context->IsKernelCollection) {
1184 if (EFI_ERROR (Status)) {
1187 "Failed to rebase injected kext %a/%a by %u\n",
1198 if (Context->Is32Bit) {
1199 Context->PrelinkedTextSegment->Segment32.Size += AlignedExecutableSize;
1200 Context->PrelinkedTextSegment->Segment32.FileSize += AlignedExecutableSize;
1201 Context->PrelinkedTextSection->Section32.Size += AlignedExecutableSize;
1203 Context->PrelinkedTextSegment->Segment64.Size += AlignedExecutableSize;
1204 Context->PrelinkedTextSegment->Segment64.FileSize += AlignedExecutableSize;
1205 Context->PrelinkedTextSection->Section64.Size += AlignedExecutableSize;
1213 NewInfoPlist =
XmlDocumentExport (InfoPlistDocument, &NewInfoPlistSize, 2, FALSE);
1216 FreePool (TmpInfoPlist);
1218 if (NewInfoPlist == NULL) {
1219 if (PrelinkedKext != NULL) {
1223 return EFI_OUT_OF_RESOURCES;
1227 if (EFI_ERROR (Status)) {
1228 FreePool (NewInfoPlist);
1229 if (PrelinkedKext != NULL) {
1236 if (
XmlNodeAppend (Context->KextList,
"dict", NULL, NewInfoPlist) == NULL) {
1237 if (PrelinkedKext != NULL) {
1241 return EFI_OUT_OF_RESOURCES;
1247 if (PrelinkedKext != NULL) {
1248 InsertTailList (&Context->PrelinkedKexts, &PrelinkedKext->
Link);
1253 InsertTailList (&Context->InjectedKexts, &PrelinkedKext->
InjectedLink);
1262 IN CONST CHAR8 *Identifier,
1269 ASSERT (Context != NULL);
1270 ASSERT (Identifier != NULL);
1274 if (EFI_ERROR (Status)) {
1275 DEBUG ((DEBUG_INFO,
"OCAK: Failed to pk find %a - %r\n", Identifier, Status));
1293 ASSERT (Context != NULL);
1299 if (!EFI_ERROR (Status)) {
1306 DEBUG ((DEBUG_INFO,
"OCAK: Failed to pk find %a - %r\n", KernelQuirk->
Identifier, Status));
1313 IN CONST CHAR8 *Identifier,
1320 ASSERT (Context != NULL);
1321 ASSERT (Identifier != NULL);
1324 if (EFI_ERROR (Status)) {
1325 DEBUG ((DEBUG_INFO,
"OCAK: Failed to pk find %a - %r\n", Identifier, Status));
VENDOR_DEVICE_PATH Header
@ MachHeaderFileTypeFileSet
KERNEL_QUIRK gKernelQuirks[]
STATIC UINT32 KernelVersion
EFI_STATUS InternalKxldStateRebuild(IN OUT PRELINKED_CONTEXT *Context)
#define PRELINK_INFO_SECTION
EFI_STATUS KcRebuildMachHeader(IN OUT PRELINKED_CONTEXT *Context)
EFI_STATUS PatcherBlockKext(IN OUT PATCHER_CONTEXT *Context)
#define PRELINK_INFO_DICTIONARY_KEY
EFI_STATUS PatcherExcludePrelinkedKext(IN CONST CHAR8 *Identifier, IN OUT PATCHER_CONTEXT *PatcherContext, IN OUT PRELINKED_CONTEXT *PrelinkedContext)
#define PRELINK_INFO_EXECUTABLE_LOAD_ADDR_KEY
#define PRELINK_TEXT_SECTION
#define PRELINK_INFO_BUNDLE_PATH_KEY
#define MAX_INFO_BUNDLE_VERSION_KEY_SIZE
#define PRELINK_INFO_INTEGER_ATTRIBUTES
VOID KcKextIndexFixups(IN OUT PRELINKED_CONTEXT *Context, IN OC_MACHO_CONTEXT *MachContext)
#define PRELINK_INFO_EXECUTABLE_RELATIVE_PATH_KEY
#define INFO_BUNDLE_EXECUTABLE_KEY
#define KC_LINKEDIT_SEGMENT
#define PRELINK_INFO_KMOD_INFO_KEY
#define PRELINK_INFO_EXECUTABLE_SOURCE_ADDR_KEY
EFI_STATUS PatcherApplyGenericPatch(IN OUT PATCHER_CONTEXT *Context, IN PATCHER_GENERIC_PATCH *Patch)
#define PLIST_EXPANSION_SIZE
EFI_STATUS KcInitKextFixupChains(IN OUT PRELINKED_CONTEXT *Context, IN UINT32 SegChainSize, IN UINT32 ReservedSize)
#define PRELINK_INFO_EXECUTABLE_SIZE_KEY
#define INFO_BUNDLE_VERSION_KEY
#define PRELINK_TEXT_SEGMENT
#define PRELINK_INFO_SEGMENT
EFI_STATUS KcKextApplyFileDelta(IN PRELINKED_CONTEXT *PrelinkedContext, IN OUT OC_MACHO_CONTEXT *Context, IN UINT32 Delta)
EFI_STATUS PatcherInitContextFromPrelinked(IN OUT PATCHER_CONTEXT *Context, IN OUT PRELINKED_CONTEXT *Prelinked, IN CONST CHAR8 *Name)
#define KC_REGION0_SEGMENT
BOOLEAN KextFindKmodAddress(IN OC_MACHO_CONTEXT *ExecutableContext, IN UINT64 LoadAddress, IN UINT32 Size, OUT UINT64 *Kmod)
UINT32 KcGetSegmentFixupChainsSize(IN UINT32 SegmentSize)
STATIC_ASSERT(BYTES_PER_PIXEL==sizeof(UINT32), "Non 4-byte pixels are unsupported!")
BOOLEAN MachoInitializeContext64(OUT OC_MACHO_CONTEXT *Context, IN VOID *FileData, IN UINT32 FileSize, IN UINT32 HeaderOffset, IN UINT32 InnerSize)
MACH_SECTION_ANY * MachoGetSectionByName(IN OUT OC_MACHO_CONTEXT *Context, IN MACH_SEGMENT_COMMAND_ANY *Segment, IN CONST CHAR8 *SectionName)
UINT64 MachoGetLastAddress(IN OUT OC_MACHO_CONTEXT *Context)
BOOLEAN MachoInitialiseSymtabsExternal(IN OUT OC_MACHO_CONTEXT *Context, IN OC_MACHO_CONTEXT *SymsContext)
UINT32 MachoExpandImage(IN OC_MACHO_CONTEXT *Context, OUT UINT8 *Destination, IN UINT32 DestinationSize, IN BOOLEAN Strip, OUT UINT64 *FileOffset OPTIONAL)
MACH_HEADER_ANY * MachoGetMachHeader(IN OUT OC_MACHO_CONTEXT *Context)
BOOLEAN MachoInitializeContext(OUT OC_MACHO_CONTEXT *Context, IN VOID *FileData, IN UINT32 FileSize, IN UINT32 HeaderOffset, IN UINT32 InnerSize, IN BOOLEAN Is32Bit)
UINT32 MachoGetExpandedImageSize(IN OC_MACHO_CONTEXT *Context)
MACH_SEGMENT_COMMAND_64 * MachoGetSegmentByName64(IN OUT OC_MACHO_CONTEXT *Context, IN CONST CHAR8 *SegmentName)
MACH_SEGMENT_COMMAND_ANY * MachoGetSegmentByName(IN OUT OC_MACHO_CONTEXT *Context, IN CONST CHAR8 *SegmentName)
BOOLEAN AsciiUint64ToLowerHex(OUT CHAR8 *Buffer, IN UINT32 BufferSize, IN UINT64 Value)
OC_TYPING_BUFFER_ENTRY Buffer[OC_TYPING_BUFFER_SIZE]
XML_NODE * XmlDocumentRoot(IN CONST XML_DOCUMENT *Document)
XML_DOCUMENT * XmlDocumentParse(IN OUT CHAR8 *Buffer, IN UINT32 Length, IN BOOLEAN WithRefs)
CONST CHAR8 * PlistKeyValue(IN XML_NODE *Node OPTIONAL)
UINT32 XmlNodeChildren(IN CONST XML_NODE *Node)
CHAR8 * XmlDocumentExport(IN CONST XML_DOCUMENT *Document, OUT UINT32 *Length OPTIONAL, IN UINT32 Skip, IN BOOLEAN PrependPlistInfo)
CONST CHAR8 * XmlNodeContent(IN CONST XML_NODE *Node)
UINT32 PlistDictChildren(IN CONST XML_NODE *Node)
BOOLEAN PlistIntegerValue(IN XML_NODE *Node OPTIONAL, OUT VOID *Value, IN UINT32 Size, IN BOOLEAN Hex)
XML_NODE * PlistNodeCast(IN XML_NODE *Node OPTIONAL, IN PLIST_NODE_TYPE Type)
XML_NODE * XmlNodeAppend(IN OUT XML_NODE *Node, IN CONST CHAR8 *Name, IN CONST CHAR8 *Attributes OPTIONAL, IN CONST CHAR8 *Content OPTIONAL)
XML_NODE * PlistDocumentRoot(IN CONST XML_DOCUMENT *Document)
XML_NODE * XmlNodeChild(IN CONST XML_NODE *Node, IN UINT32 Child)
VOID XmlDocumentFree(IN OUT XML_DOCUMENT *Document)
XML_NODE * PlistDictChild(IN CONST XML_NODE *Node, IN UINT32 Child, OUT XML_NODE **Value OPTIONAL)
EFI_STATUS PrelinkedContextApplyPatch(IN OUT PRELINKED_CONTEXT *Context, IN CONST CHAR8 *Identifier, IN PATCHER_GENERIC_PATCH *Patch)
VOID PrelinkedContextFree(IN OUT PRELINKED_CONTEXT *Context)
EFI_STATUS PrelinkedDependencyInsert(IN OUT PRELINKED_CONTEXT *Context, IN VOID *Buffer)
STATIC EFI_STATUS PrelinkedGetSegmentsFromMacho(IN OC_MACHO_CONTEXT *MachoContext, OUT MACH_SEGMENT_COMMAND_ANY **PrelinkedInfoSegment, OUT MACH_SECTION_ANY **PrelinkedInfoSection)
EFI_STATUS PrelinkedContextInit(IN OUT PRELINKED_CONTEXT *Context, IN OUT UINT8 *Prelinked, IN UINT32 PrelinkedSize, IN UINT32 PrelinkedAllocSize, IN BOOLEAN Is32Bit)
EFI_STATUS PrelinkedInjectPrepare(IN OUT PRELINKED_CONTEXT *Context, IN UINT32 LinkedExpansion, IN UINT32 ReservedExeSize)
EFI_STATUS PrelinkedContextBlock(IN OUT PRELINKED_CONTEXT *Context, IN CONST CHAR8 *Identifier, IN BOOLEAN Exclude)
EFI_STATUS PrelinkedContextApplyQuirk(IN OUT PRELINKED_CONTEXT *Context, IN KERNEL_QUIRK_NAME Quirk, IN UINT32 KernelVersion)
EFI_STATUS PrelinkedReserveKextSize(IN OUT UINT32 *ReservedInfoSize, IN OUT UINT32 *ReservedExeSize, IN UINT32 InfoPlistSize, IN UINT8 *Executable OPTIONAL, IN UINT32 ExecutableSize OPTIONAL, IN BOOLEAN Is32Bit)
EFI_STATUS InternalConnectExternalSymtab(IN OUT OC_MACHO_CONTEXT *Context, OUT OC_MACHO_CONTEXT *InnerContext, IN UINT8 *Buffer, IN UINT32 BufferSize, OUT BOOLEAN *KernelCollection OPTIONAL)
EFI_STATUS PrelinkedInjectKext(IN OUT PRELINKED_CONTEXT *Context, IN CONST CHAR8 *Identifier OPTIONAL, IN CONST CHAR8 *BundlePath, IN CONST CHAR8 *InfoPlist, IN UINT32 InfoPlistSize, IN CONST CHAR8 *ExecutablePath OPTIONAL, IN CONST UINT8 *Executable OPTIONAL, IN UINT32 ExecutableSize OPTIONAL, OUT CHAR8 BundleVersion[MAX_INFO_BUNDLE_VERSION_KEY_SIZE] OPTIONAL)
EFI_STATUS PrelinkedInjectComplete(IN OUT PRELINKED_CONTEXT *Context)
STATIC UINT64 PrelinkedFindLastLoadAddress(IN XML_NODE *KextList)
VOID InternalFreePrelinkedKext(IN PRELINKED_KEXT *Kext)
PRELINKED_KEXT * InternalCachedPrelinkedKext(IN OUT PRELINKED_CONTEXT *Prelinked, IN CONST CHAR8 *Identifier)
#define GET_PRELINKED_KEXT_FROM_LINK(This)
PRELINKED_KEXT * InternalCachedPrelinkedKernel(IN OUT PRELINKED_CONTEXT *Prelinked)
PRELINKED_KEXT * InternalLinkPrelinkedKext(IN OUT PRELINKED_CONTEXT *Context, IN OUT OC_MACHO_CONTEXT *Executable, IN XML_NODE *PlistRoot, IN UINT64 LoadAddress, IN UINT64 KmodAddress, IN UINT64 FileOffset)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
KERNEL_QUIRK_PATCH_FUNCTION * PatchFunction
UINT64 FileOffset
file offset of this segment
UINT64 VirtualAddress
memory address of this segment
OC_MACHO_CONTEXT MachContext