OcAppleKernelLib: Implement cacheless & mkext kext patching and quirks (#102)

This commit is contained in:
vit9696 2020-08-18 23:47:38 +03:00 committed by GitHub
parent 9a0f1bc12c
commit 04fa1c2394
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 1343 additions and 517 deletions

View File

@ -275,7 +275,7 @@ typedef struct {
//
typedef struct {
//
// Comment or NULL (0 base is used then).
// Comment or NULL.
//
CONST CHAR8 *Comment;
//
@ -329,14 +329,18 @@ typedef struct {
//
CONST CHAR16 *ExtensionsDirFileName;
//
// Injected kext list.
// List of injected kexts.
//
LIST_ENTRY InjectedKexts;
//
// Dependency bundle list for injected kexts.
// List of dependencies that need to be injected.
//
LIST_ENTRY InjectedDependencies;
//
// List of kext patches for built-in shipping kexts.
//
LIST_ENTRY PatchedKexts;
//
// List of built-in shipping kexts.
//
LIST_ENTRY BuiltInKexts;
@ -400,8 +404,121 @@ typedef struct {
// Array of kexts.
//
XML_NODE *MkextKexts;
//
// List of cached kexts, used for patching and blocking.
//
LIST_ENTRY CachedKexts;
} MKEXT_CONTEXT;
//
// Kernel quirk names.
//
typedef enum {
//
// Apply MSR E2 patches to AppleIntelCPUPowerManagement kext.
//
KernelQuirkAppleCpuPmCfgLock,
//
// Apply MSR E2 patches to XNU kernel (XCPM).
//
KernelQuirkAppleXcpmCfgLock,
//
// Apply extra MSR patches to XNU kernel (XCPM).
//
KernelQuirkAppleXcpmExtraMsrs,
//
// Apply max MSR_IA32_PERF_CONTROL patches to XNU kernel (XCPM).
//
KernelQuirkAppleXcpmForceBoost,
//
// Apply custom AppleSMBIOS kext GUID patch for Custom UpdateSMBIOSMode.
//
KernelQuirkCustomSmbiosGuid1,
KernelQuirkCustomSmbiosGuid2,
//
// Apply VT-d disabling patches to IOPCIFamily kext to disable IOMapper in macOS.
//
KernelQuirkDisableIoMapper,
//
// Disable AppleRTC checksum writing.
//
KernelQuirkDisableRtcChecksum,
//
// Apply dummy power management patches to AppleIntelCpuPowerManagement in macOS.
//
KernelQuirkDummyPowerManagement,
//
// Apply icon type patches to IOAHCIPort kext to force internal disk icons.
//
KernelQuirkExternalDiskIcons,
//
// Apply PCI bar size patches to IOPCIFamily kext for compatibility with select configuration.
//
KernelQuirkIncreasePciBarSize,
//
// Disable LAPIC interrupt kernel panic on AP cores.
//
KernelQuirkLapicKernelPanic,
//
// Apply kernel patches to remove kext dumping in the panic log.
//
KernelQuirkPanicNoKextDump,
//
// Disable power state change timeout kernel panic (10.15+).
//
KernelQuirkPowerTimeoutKernelPanic,
//
// Apply vendor patches to IOAHCIFamily kext to enable native features for third-party drives,
// such as TRIM on SSDs or hibernation support on 10.15.
//
KernelQuirkThirdPartyDrives,
//
// Apply port limit patches to AppleUSBXHCI and AppleUSBXHCIPCI kexts.
//
KernelQuirkXhciPortLimit1,
KernelQuirkXhciPortLimit2,
KernelQuirkXhciPortLimit3,
KernelQuirkMax
} KERNEL_QUIRK_NAME;
//
// Kernel quirk patch function.
//
typedef
EFI_STATUS
(KERNEL_QUIRK_PATCH_FUNCTION)(
IN OUT PATCHER_CONTEXT *Patcher
);
//
// Kernel quirk.
//
typedef struct {
//
// Target bundle ID. NULL for kernel.
//
CONST CHAR8 *BundleId;
//
// Quirk patch function.
//
KERNEL_QUIRK_PATCH_FUNCTION *PatchFunction;
} KERNEL_QUIRK;
/**
Applies the specified quirk.
@param[in] Name KERNEL_QUIRK_NAME specifying the quirk name.
@param[in,out] Patcher PATCHER_CONTEXT instance.
@returns EFI_SUCCESS on success.
**/
EFI_STATUS
KernelQuirkApply (
IN KERNEL_QUIRK_NAME Name,
IN OUT PATCHER_CONTEXT *Patcher
);
/**
Read Apple kernel for target architecture (possibly decompressing)
into pool allocated buffer.
@ -587,6 +704,36 @@ PrelinkedInjectKext (
IN UINT32 ExecutableSize OPTIONAL
);
/**
Apply kext patch to prelinked.
@param[in,out] Context Prelinked context.
@param[in] BundleId Kext bundle ID.
@param[in] Patch Patch to apply.
@return EFI_SUCCESS on success.
**/
EFI_STATUS
PrelinkedContextApplyPatch (
IN OUT PRELINKED_CONTEXT *Context,
IN CONST CHAR8 *BundleId,
IN PATCHER_GENERIC_PATCH *Patch
);
/**
Apply kext quirk to prelinked.
@param[in,out] Context Prelinked context.
@param[in] Quirk Kext quirk to apply.
@return EFI_SUCCESS on success.
**/
EFI_STATUS
PrelinkedContextApplyQuirk (
IN OUT PRELINKED_CONTEXT *Context,
IN KERNEL_QUIRK_NAME Quirk
);
EFI_STATUS
KcRebuildMachHeader (
IN OUT PRELINKED_CONTEXT *Context
@ -681,6 +828,22 @@ PatcherInitContextFromPrelinked (
IN CONST CHAR8 *Name
);
/**
Initialize patcher from mkext context for kext patching.
@param[in,out] Context Patcher context.
@param[in,out] Mkext Mkext context.
@param[in] Name Kext bundle identifier.
@return EFI_SUCCESS on success.
**/
EFI_STATUS
PatcherInitContextFromMkext(
IN OUT PATCHER_CONTEXT *Context,
IN OUT MKEXT_CONTEXT *Mkext,
IN CONST CHAR8 *Name
);
/**
Initialize patcher from buffer for e.g. kernel patching.
@ -739,127 +902,6 @@ PatcherBlockKext (
IN OUT PATCHER_CONTEXT *Context
);
/**
Apply MSR E2 patches to AppleIntelCPUPowerManagement kext.
@param Context Prelinked kernel context.
@return EFI_SUCCESS on success.
**/
EFI_STATUS
PatchAppleCpuPmCfgLock (
IN OUT PRELINKED_CONTEXT *Context
);
/**
Apply MSR E2 patches to XNU kernel (XCPM).
@param Patcher Patcher context.
@return EFI_SUCCESS on success.
**/
EFI_STATUS
PatchAppleXcpmCfgLock (
IN OUT PATCHER_CONTEXT *Patcher
);
/**
Apply extra MSR patches to XNU kernel (XCPM).
@param Patcher Patcher context.
@return EFI_SUCCESS on success.
**/
EFI_STATUS
PatchAppleXcpmExtraMsrs (
IN OUT PATCHER_CONTEXT *Patcher
);
/**
Apply max MSR_IA32_PERF_CONTROL patches to XNU kernel (XCPM).
@param Patcher Patcher context.
@return EFI_SUCCESS on success.
**/
EFI_STATUS
PatchAppleXcpmForceBoost (
IN OUT PATCHER_CONTEXT *Patcher
);
/**
Apply port limit patches to AppleUSBXHCI and AppleUSBXHCIPCI kexts.
@param Context Prelinked kernel context.
@return EFI_SUCCESS on success.
**/
EFI_STATUS
PatchUsbXhciPortLimit (
IN OUT PRELINKED_CONTEXT *Context
);
/**
Apply vendor patches to IOAHCIFamily kext to enable native features for third-party drives,
such as TRIM on SSDs or hibernation support on 10.15.
@param Context Prelinked kernel context.
@return EFI_SUCCESS on success.
**/
EFI_STATUS
PatchThirdPartyDriveSupport (
IN OUT PRELINKED_CONTEXT *Context
);
/**
Apply icon type patches to IOAHCIPort kext to force internal disk icons.
@param Context Prelinked kernel context.
@return EFI_SUCCESS on success.
**/
EFI_STATUS
PatchForceInternalDiskIcons (
IN OUT PRELINKED_CONTEXT *Context
);
/**
Apply VT-d disabling patches to IOPCIFamily kext to disable IOMapper in macOS.
@param Context Prelinked kernel context.
@return EFI_SUCCESS on success.
**/
EFI_STATUS
PatchAppleIoMapperSupport (
IN OUT PRELINKED_CONTEXT *Context
);
/**
Apply dummy power management patches to AppleIntelCpuPowerManagement in macOS.
@param Context Prelinked kernel context.
@return EFI_SUCCESS on success.
**/
EFI_STATUS
PatchDummyPowerManagement (
IN OUT PRELINKED_CONTEXT *Context
);
/**
Apply PCI bar size patches to IOPCIFamily kext for compatibility with select configuration.
@param Context Prelinked kernel context.
@return EFI_SUCCESS on success.
**/
EFI_STATUS
PatchIncreasePciBarSize (
IN OUT PRELINKED_CONTEXT *Context
);
/**
Apply modification to CPUID 1.
@ -878,66 +920,6 @@ PatchKernelCpuId (
IN UINT32 *DataMask
);
/**
Apply custom AppleSMBIOS kext GUID patch for Custom UpdateSMBIOSMode.
@param Context Prelinked kernel context.
@return EFI_SUCCESS on success.
**/
EFI_STATUS
PatchCustomSmbiosGuid (
IN OUT PRELINKED_CONTEXT *Context
);
/**
Apply kernel patches to remove kext dumping in the panic log.
@param Patcher Patcher context.
@return EFI_SUCCESS on success.
**/
EFI_STATUS
PatchPanicKextDump (
IN OUT PATCHER_CONTEXT *Patcher
);
/**
Disable LAPIC interrupt kernel panic on AP cores.
@param Patcher Patcher context.
@return EFI_SUCCESS on success.
**/
EFI_STATUS
PatchLapicKernelPanic (
IN OUT PATCHER_CONTEXT *Patcher
);
/**
Disable power state change timeout kernel panic (10.15+).
@param Patcher Patcher context.
@return EFI_SUCCESS on success.
**/
EFI_STATUS
PatchPowerStateTimeout (
IN OUT PATCHER_CONTEXT *Patcher
);
/**
Disable AppleRTC checksum writing.
@param Context Patcher context.
@return EFI_SUCCESS on success.
**/
EFI_STATUS
PatchAppleRtcChecksum (
IN OUT PRELINKED_CONTEXT *Context
);
/**
Initializes cacheless context for later modification.
Must be freed with CachelessContextFree on success.
@ -987,6 +969,36 @@ CachelessContextAddKext (
IN UINT32 ExecutableSize OPTIONAL
);
/**
Add patch to cacheless context to be applied later on.
@param[in,out] Context Cacheless context.
@param[in] BundleId Kext bundle ID.
@param[in] Patch Patch to apply.
@return EFI_SUCCESS on success.
**/
EFI_STATUS
CachelessContextAddPatch (
IN OUT CACHELESS_CONTEXT *Context,
IN CONST CHAR8 *BundleId,
IN PATCHER_GENERIC_PATCH *Patch
);
/**
Add kernel quirk to cacheless context to be applied later on.
@param[in,out] Context Cacheless context.
@param[in] Quirk Quirk to apply.
@return EFI_SUCCESS on success.
**/
EFI_STATUS
CachelessContextAddQuirk (
IN OUT CACHELESS_CONTEXT *Context,
IN KERNEL_QUIRK_NAME Quirk
);
/**
Creates virtual directory overlay EFI_FILE_PROTOCOL from cacheless context.
@ -1151,6 +1163,36 @@ MkextInjectKext (
IN UINT32 ExecutableSize OPTIONAL
);
/**
Apply kext patch to mkext.
@param[in,out] Context Mkext context.
@param[in] BundleId Kext bundle ID.
@param[in] Patch Patch to apply.
@return EFI_SUCCESS on success.
**/
EFI_STATUS
MkextContextApplyPatch (
IN OUT MKEXT_CONTEXT *Context,
IN CONST CHAR8 *BundleId,
IN PATCHER_GENERIC_PATCH *Patch
);
/**
Apply kext quirk to mkext.
@param[in,out] Context Mkext context.
@param[in] Quirk Kext quirk to apply.
@return EFI_SUCCESS on success.
**/
EFI_STATUS
MkextContextApplyQuirk (
IN OUT MKEXT_CONTEXT *Context,
IN KERNEL_QUIRK_NAME Quirk
);
/**
Refresh plist and checksum after kext
injection and/or patching.

View File

@ -27,6 +27,7 @@
#include <Library/OcVirtualFsLib.h>
#include "CachelessInternal.h"
#include "PrelinkedInternal.h"
STATIC
VOID
@ -46,6 +47,9 @@ FreeBuiltInKext (
if (BuiltinKext->BinaryFileName != NULL) {
FreePool (BuiltinKext->BinaryFileName);
}
if (BuiltinKext->BinaryPath != NULL) {
FreePool (BuiltinKext->BinaryPath);
}
while (!IsListEmpty (&BuiltinKext->Dependencies)) {
KextLink = GetFirstNode (&BuiltinKext->Dependencies);
@ -298,6 +302,9 @@ ScanExtensions (
return EFI_INVALID_PARAMETER;
}
//
// Create plist path.
//
Status = OcUnicodeSafeSPrint (
TmpPath,
sizeof (TmpPath),
@ -323,13 +330,44 @@ ScanExtensions (
return EFI_OUT_OF_RESOURCES;
}
//
// Create binary path. If plist is in root of kext, binary is also there.
//
if (BuiltinKext->BinaryFileName != NULL) {
Status = OcUnicodeSafeSPrint (
TmpPath,
sizeof (TmpPath),
L"%s\\%s\\%s%s",
FilePath,
FileInfo->FileName,
UseContents ? L"Contents\\MacOS\\" : L"\\",
BuiltinKext->BinaryFileName
);
if (EFI_ERROR (Status)) {
FreeBuiltInKext (BuiltinKext);
FileKext->Close (FileKext);
File->SetPosition (File, 0);
FreePool (FileInfo);
return EFI_INVALID_PARAMETER;
}
BuiltinKext->BinaryPath = AllocateCopyPool (StrSize (TmpPath), TmpPath);
if (BuiltinKext->BinaryPath == NULL) {
FreeBuiltInKext (BuiltinKext);
FileKext->Close (FileKext);
File->SetPosition (File, 0);
FreePool (FileInfo);
return EFI_OUT_OF_RESOURCES;
}
}
InsertTailList (&Context->BuiltInKexts, &BuiltinKext->Link);
DEBUG ((
DEBUG_VERBOSE,
"OCAK: Discovered bundle %a %s %s %u\n",
BuiltinKext->BundleId,
BuiltinKext->BinaryFileName,
BuiltinKext->PlistPath,
BuiltinKext->BinaryPath,
BuiltinKext->OSBundleRequiredValue
));
@ -376,6 +414,30 @@ ScanExtensions (
return EFI_SUCCESS;
}
STATIC
PATCHED_KEXT*
LookupPatchedKextForBundleId (
IN OUT CACHELESS_CONTEXT *Context,
IN CONST CHAR8 *BundleId
)
{
PATCHED_KEXT *PatchedKext;
LIST_ENTRY *KextLink;
KextLink = GetFirstNode (&Context->PatchedKexts);
while (!IsNull (&Context->PatchedKexts, KextLink)) {
PatchedKext = GET_PATCHED_KEXT_FROM_LINK (KextLink);
if (AsciiStrCmp (BundleId, PatchedKext->BundleId) == 0) {
return PatchedKext;
}
KextLink = GetNextNode (&Context->PatchedKexts, KextLink);
}
return NULL;
}
STATIC
BUILTIN_KEXT*
LookupBuiltinKextForBundleId (
@ -424,6 +486,31 @@ LookupBuiltinKextForPlistPath (
return NULL;
}
STATIC
BUILTIN_KEXT*
LookupBuiltinKextForBinaryPath (
IN OUT CACHELESS_CONTEXT *Context,
IN CONST CHAR16 *BinaryPath
)
{
BUILTIN_KEXT *BuiltinKext;
LIST_ENTRY *KextLink;
KextLink = GetFirstNode (&Context->BuiltInKexts);
while (!IsNull (&Context->BuiltInKexts, KextLink)) {
BuiltinKext = GET_BUILTIN_KEXT_FROM_LINK (KextLink);
if (BuiltinKext->BinaryPath != NULL
&& StrCmp (BinaryPath, BuiltinKext->BinaryPath) == 0) {
return BuiltinKext;
}
KextLink = GetNextNode (&Context->BuiltInKexts, KextLink);
}
return NULL;
}
STATIC
EFI_STATUS
ScanDependencies (
@ -492,6 +579,72 @@ ScanDependencies (
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
InternalAddKextPatch (
IN OUT CACHELESS_CONTEXT *Context,
IN CONST CHAR8 *BundleId,
IN PATCHER_GENERIC_PATCH *Patch OPTIONAL,
IN KERNEL_QUIRK_NAME QuirkName
)
{
PATCHED_KEXT *PatchedKext;
KEXT_PATCH *KextPatch;
KERNEL_QUIRK *KernelQuirk;
if (Patch == NULL) {
KernelQuirk = &gKernelQuirks[QuirkName];
ASSERT (KernelQuirk->BundleId != NULL);
BundleId = KernelQuirk->BundleId;
}
//
// Check if bundle is already present. If not, add to list.
//
PatchedKext = LookupPatchedKextForBundleId (Context, BundleId);
if (PatchedKext == NULL) {
PatchedKext = AllocateZeroPool (sizeof (*PatchedKext));
if (PatchedKext == NULL) {
return EFI_OUT_OF_RESOURCES;
}
PatchedKext->Signature = PATCHED_KEXT_SIGNATURE;
PatchedKext->BundleId = AllocateCopyPool (AsciiStrSize (BundleId), BundleId);
if (PatchedKext->BundleId == NULL) {
FreePool (PatchedKext);
return EFI_OUT_OF_RESOURCES;
}
InitializeListHead (&PatchedKext->Patches);
InsertTailList (&Context->PatchedKexts, &PatchedKext->Link);
}
//
// Add new patch.
//
KextPatch = AllocateZeroPool (sizeof (*KextPatch));
if (KextPatch == NULL) {
return EFI_OUT_OF_RESOURCES;
}
KextPatch->Signature = KEXT_PATCH_SIGNATURE;
if (Patch != NULL) {
CopyMem (&KextPatch->Patch, Patch, sizeof (KextPatch->Patch));
} else {
//
// Apply quirk if no Patch.
//
KextPatch->ApplyQuirk = TRUE;
KextPatch->QuirkName = QuirkName;
}
InsertTailList (&PatchedKext->Patches, &KextPatch->Link);
return EFI_SUCCESS;
}
EFI_STATUS
CachelessContextInit (
IN OUT CACHELESS_CONTEXT *Context,
@ -510,6 +663,7 @@ CachelessContextInit (
InitializeListHead (&Context->InjectedKexts);
InitializeListHead (&Context->InjectedDependencies);
InitializeListHead (&Context->PatchedKexts);
InitializeListHead (&Context->BuiltInKexts);
return EFI_SUCCESS;
@ -520,9 +674,12 @@ CachelessContextFree (
IN OUT CACHELESS_CONTEXT *Context
)
{
CACHELESS_KEXT *CachelessKext;
BUILTIN_KEXT *BuiltinKext;
LIST_ENTRY *KextLink;
CACHELESS_KEXT *CachelessKext;
PATCHED_KEXT *PatchedKext;
KEXT_PATCH *KextPatch;
BUILTIN_KEXT *BuiltinKext;
LIST_ENTRY *KextLink;
LIST_ENTRY *PatchLink;
ASSERT (Context != NULL);
@ -543,6 +700,22 @@ CachelessContextFree (
FreePool (CachelessKext);
}
while (!IsListEmpty (&Context->PatchedKexts)) {
KextLink = GetFirstNode (&Context->PatchedKexts);
PatchedKext = GET_PATCHED_KEXT_FROM_LINK (KextLink);
RemoveEntryList (KextLink);
while (!IsListEmpty (&PatchedKext->Patches)) {
PatchLink = GetFirstNode (&PatchedKext->Patches);
KextPatch = GET_KEXT_PATCH_FROM_LINK (PatchLink);
RemoveEntryList (PatchLink);
FreePool (KextPatch);
}
FreePool (PatchedKext);
}
while (!IsListEmpty (&Context->BuiltInKexts)) {
KextLink = GetFirstNode (&Context->BuiltInKexts);
BuiltinKext = GET_BUILTIN_KEXT_FROM_LINK (KextLink);
@ -759,6 +932,31 @@ CachelessContextAddKext (
return EFI_SUCCESS;
}
EFI_STATUS
CachelessContextAddPatch (
IN OUT CACHELESS_CONTEXT *Context,
IN CONST CHAR8 *BundleId,
IN PATCHER_GENERIC_PATCH *Patch
)
{
ASSERT (Context != NULL);
ASSERT (BundleId != NULL);
ASSERT (Patch != NULL);
return InternalAddKextPatch (Context, BundleId, Patch, 0);
}
EFI_STATUS
CachelessContextAddQuirk (
IN OUT CACHELESS_CONTEXT *Context,
IN KERNEL_QUIRK_NAME Quirk
)
{
ASSERT (Context != NULL);
return InternalAddKextPatch (Context, NULL, NULL, Quirk);
}
EFI_STATUS
CachelessContextOverlayExtensionsDir (
IN OUT CACHELESS_CONTEXT *Context,
@ -1012,12 +1210,17 @@ CachelessContextHookBuiltin (
)
{
EFI_STATUS Status;
EFI_TIME ModificationTime;
BUILTIN_KEXT *BuiltinKext;
KEXT_PATCH *KextPatch;
PATCHED_KEXT *PatchedKext;
DEPEND_KEXT *DependKext;
LIST_ENTRY *KextLink;
CHAR8 *InfoPlist;
UINT32 InfoPlistSize;
PATCHER_CONTEXT Patcher;
VOID *Buffer;
UINT32 BufferSize;
XML_DOCUMENT *InfoPlistDocument;
XML_NODE *InfoPlistRoot;
XML_NODE *InfoPlistValue;
@ -1048,6 +1251,31 @@ CachelessContextHookBuiltin (
return Status;
}
//
// Ensure all kexts to be patched will be loaded.
//
KextLink = GetFirstNode (&Context->PatchedKexts);
while (!IsNull (&Context->PatchedKexts, KextLink)) {
PatchedKext = GET_PATCHED_KEXT_FROM_LINK (KextLink);
BuiltinKext = LookupBuiltinKextForBundleId (Context, PatchedKext->BundleId);
if (BuiltinKext == NULL) {
//
// Kext is not present, skip.
//
DEBUG ((DEBUG_WARN, "OCAK: Attempted to patch non-existent kext %a\n", PatchedKext->BundleId));
} else {
BuiltinKext->PatchKext = TRUE;
Status = ScanDependencies (Context, PatchedKext->BundleId);
if (EFI_ERROR (Status)) {
return Status;
}
}
KextLink = GetNextNode (&Context->PatchedKexts, KextLink);
}
//
// Scan dependencies, adding any others besides ones being injected.
//
@ -1066,31 +1294,31 @@ CachelessContextHookBuiltin (
}
//
// Info.plist.
// Try to get Info.plist.
//
if (OcUnicodeEndsWith (FileName, L"Info.plist")) {
BuiltinKext = LookupBuiltinKextForPlistPath (Context, FileName);
if (BuiltinKext != NULL && BuiltinKext->PatchValidOSBundleRequired) {
DEBUG ((DEBUG_INFO, "OCAK: Processing patches for %s\n", FileName));
DEBUG ((DEBUG_INFO, "OCAK: Processing plist patches for %s\n", FileName));
//
// Open Info.plist
//
Status = AllocateCopyFileData (File, (UINT8**)&InfoPlist, &InfoPlistSize);
Status = AllocateCopyFileData (File, (UINT8 **) &Buffer, &BufferSize);
if (EFI_ERROR (Status)) {
return Status;
}
InfoPlistDocument = XmlDocumentParse (InfoPlist, InfoPlistSize, FALSE);
InfoPlistDocument = XmlDocumentParse (Buffer, BufferSize, FALSE);
if (InfoPlistDocument == NULL) {
FreePool (InfoPlist);
FreePool (Buffer);
return EFI_INVALID_PARAMETER;
}
InfoPlistRoot = PlistNodeCast (PlistDocumentRoot (InfoPlistDocument), PLIST_NODE_TYPE_DICT);
if (InfoPlistRoot == NULL) {
XmlDocumentFree (InfoPlistDocument);
FreePool (InfoPlist);
FreePool (Buffer);
return EFI_INVALID_PARAMETER;
}
@ -1117,7 +1345,7 @@ CachelessContextHookBuiltin (
Failed |= XmlNodeAppend (InfoPlistRoot, "string", NULL, OS_BUNDLE_REQUIRED_ROOT) == NULL;
if (Failed) {
XmlDocumentFree (InfoPlistDocument);
FreePool (InfoPlist);
FreePool (Buffer);
return EFI_OUT_OF_RESOURCES;
}
}
@ -1128,29 +1356,102 @@ CachelessContextHookBuiltin (
NewPlistData = XmlDocumentExport (InfoPlistDocument, &NewPlistDataSize, 0, TRUE);
if (NewPlistData == NULL) {
XmlDocumentFree (InfoPlistDocument);
FreePool (InfoPlist);
FreePool (Buffer);
return EFI_OUT_OF_RESOURCES;
}
XmlDocumentFree (InfoPlistDocument);
FreePool (InfoPlist);
FreePool (Buffer);
//
// Virtualize newly created Info.plist.
//
Status = CreateVirtualFileFileNameCopy (FileName, NewPlistData, NewPlistDataSize, NULL, VirtualFile);
Status = GetFileModificationTime (File, &ModificationTime);
if (EFI_ERROR (Status)) {
ZeroMem (&ModificationTime, sizeof (ModificationTime));
}
Status = CreateVirtualFileFileNameCopy (FileName, NewPlistData, NewPlistDataSize, &ModificationTime, VirtualFile);
if (EFI_ERROR (Status)) {
*VirtualFile = NULL;
FreePool (NewPlistData);
}
return Status;
}
} else {
//
// Try to get binary for built-in kext.
//
BuiltinKext = LookupBuiltinKextForBinaryPath (Context, FileName);
if (BuiltinKext != NULL && BuiltinKext->PatchKext) {
DEBUG ((DEBUG_INFO, "OCAK: Processing binary patches for %s\n", FileName));
PatchedKext = LookupPatchedKextForBundleId (Context, BuiltinKext->BundleId);
if (PatchedKext == NULL) {
return EFI_INVALID_PARAMETER;
}
Status = AllocateCopyFileData (File, (UINT8 **) &Buffer, &BufferSize);
if (EFI_ERROR (Status)) {
return Status;
}
Status = PatcherInitContextFromBuffer (&Patcher, Buffer, BufferSize);
if (EFI_ERROR (Status)) {
FreePool (Buffer);
return Status;
}
//
// Apply patches.
//
KextLink = GetFirstNode (&PatchedKext->Patches);
while (!IsNull (&PatchedKext->Patches, KextLink)) {
KextPatch = GET_KEXT_PATCH_FROM_LINK (KextLink);
if (KextPatch->ApplyQuirk) {
Status = KernelQuirkApply (KextPatch->QuirkName, &Patcher);
DEBUG ((
EFI_ERROR (Status) ? DEBUG_WARN : DEBUG_INFO,
"OCAK: Kernel quirk result for %a (%u) - %r\n",
PatchedKext->BundleId,
KextPatch->QuirkName,
Status
));
} else {
Status = PatcherApplyGenericPatch (&Patcher, &KextPatch->Patch);
DEBUG ((
EFI_ERROR (Status) ? DEBUG_WARN : DEBUG_INFO,
"OCAK: Kext patcher result for %a (%a) - %r\n",
PatchedKext->BundleId,
KextPatch->Patch.Comment,
Status
));
}
KextLink = GetNextNode (&PatchedKext->Patches, KextLink);
}
//
// Virtualize patched binary.
//
Status = GetFileModificationTime (File, &ModificationTime);
if (EFI_ERROR (Status)) {
ZeroMem (&ModificationTime, sizeof (ModificationTime));
}
Status = CreateVirtualFileFileNameCopy (FileName, Buffer, BufferSize, &ModificationTime, VirtualFile);
if (EFI_ERROR (Status)) {
*VirtualFile = NULL;
FreePool (Buffer);
}
return Status;
}
}
//
// TODO: hook binaries for patches here.
// No file hooked.
//
*VirtualFile = NULL;
return EFI_SUCCESS;

View File

@ -89,6 +89,54 @@ typedef struct {
CHAR16 *BinaryFileName;
} CACHELESS_KEXT;
//
// Kext patch.
//
typedef struct {
//
// Signature.
//
UINT32 Signature;
//
// Link for global list (PATCHED_BUILTIN_KEXT -> Patches).
//
LIST_ENTRY Link;
//
// Generic patch.
//
PATCHER_GENERIC_PATCH Patch;
//
// Apply Quirk instead of Patch.
//
BOOLEAN ApplyQuirk;
//
// Kernel quirk to apply.
//
KERNEL_QUIRK_NAME QuirkName;
} KEXT_PATCH;
//
// Built-in kext in SLE requiring patches.
//
typedef struct {
//
// Signature.
//
UINT32 Signature;
//
// Link for global list (CACHELESS_CONTEXT -> PatchedKexts).
//
LIST_ENTRY Link;
//
// Bundle ID.
//
CHAR8 *BundleId;
//
// List of patches to apply.
//
LIST_ENTRY Patches;
} PATCHED_KEXT;
//
// Built-in kexts in SLE.
//
@ -114,6 +162,10 @@ typedef struct {
//
CHAR16 *BinaryFileName;
//
// Binary file path.
//
CHAR16 *BinaryPath;
//
// Dependencies.
//
LIST_ENTRY Dependencies;
@ -167,13 +219,49 @@ typedef struct {
CACHELESS_KEXT_SIGNATURE \
))
//
// KEXT_PATCH signature for list identification.
//
#define KEXT_PATCH_SIGNATURE SIGNATURE_32 ('K', 'x', 't', 'P')
/**
Gets the next element in Patches list of KEXT_PATCH.
@param[in] This The current ListEntry.
**/
#define GET_KEXT_PATCH_FROM_LINK(This) \
(CR ( \
(This), \
KEXT_PATCH, \
Link, \
KEXT_PATCH_SIGNATURE \
))
//
// PATCHED_KEXT signature for list identification.
//
#define PATCHED_KEXT_SIGNATURE SIGNATURE_32 ('S', 'l', 'e', 'P')
/**
Gets the next element in PatchedKexts list of PATCHED_KEXT.
@param[in] This The current ListEntry.
**/
#define GET_PATCHED_KEXT_FROM_LINK(This) \
(CR ( \
(This), \
PATCHED_KEXT, \
Link, \
PATCHED_KEXT_SIGNATURE \
))
//
// BUILTIN_KEXT signature for list identification.
//
#define BUILTIN_KEXT_SIGNATURE SIGNATURE_32 ('S', 'l', 'e', 'B')
/**
Gets the next element in BuiltInKexts list of CACHELESS_KEXT.
Gets the next element in BuiltInKexts list of BUILTIN_KEXT.
@param[in] This The current ListEntry.
**/

View File

@ -1,5 +1,5 @@
/** @file
Commonly used kext patches.
Commonly used kext and kernel patches.
Copyright (c) 2018, vit9696. All rights reserved.<BR>
This program and the accompanying materials
@ -96,38 +96,27 @@ mAppleIntelCPUPowerManagementPatch2 = {
.Skip = 0
};
STATIC
EFI_STATUS
PatchAppleCpuPmCfgLock (
IN OUT PRELINKED_CONTEXT *Context
IN OUT PATCHER_CONTEXT *Patcher
)
{
EFI_STATUS Status;
EFI_STATUS Status2;
PATCHER_CONTEXT Patcher;
Status = PatcherInitContextFromPrelinked (
&Patcher,
Context,
"com.apple.driver.AppleIntelCPUPowerManagement"
);
Status = PatcherApplyGenericPatch (Patcher, &mAppleIntelCPUPowerManagementPatch);
if (!EFI_ERROR (Status)) {
Status = PatcherApplyGenericPatch (&Patcher, &mAppleIntelCPUPowerManagementPatch);
if (!EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OCAK: Patch v1 success com.apple.driver.AppleIntelCPUPowerManagement\n"));
}
DEBUG ((DEBUG_INFO, "OCAK: Patch v1 success com.apple.driver.AppleIntelCPUPowerManagement\n"));
}
Status2 = PatcherApplyGenericPatch (&Patcher, &mAppleIntelCPUPowerManagementPatch2);
if (!EFI_ERROR (Status2)) {
DEBUG ((DEBUG_INFO, "OCAK: Patch v2 success com.apple.driver.AppleIntelCPUPowerManagement\n"));
}
Status2 = PatcherApplyGenericPatch (Patcher, &mAppleIntelCPUPowerManagementPatch2);
if (!EFI_ERROR (Status2)) {
DEBUG ((DEBUG_INFO, "OCAK: Patch v2 success com.apple.driver.AppleIntelCPUPowerManagement\n"));
}
if (EFI_ERROR (Status) && EFI_ERROR (Status2)) {
DEBUG ((DEBUG_INFO, "OCAK: Failed to apply patches com.apple.driver.AppleIntelCPUPowerManagement - %r/%r\n", Status, Status2));
}
} else {
DEBUG ((DEBUG_INFO, "OCAK: Failed to find com.apple.driver.AppleIntelCPUPowerManagement - %r\n", Status));
Status2 = Status;
if (EFI_ERROR (Status) && EFI_ERROR (Status2)) {
DEBUG ((DEBUG_INFO, "OCAK: Failed to apply patches com.apple.driver.AppleIntelCPUPowerManagement - %r/%r\n", Status, Status2));
}
//
@ -207,9 +196,10 @@ mXcpmCfgLockDbgPatch = {
.Limit = 4096
};
STATIC
EFI_STATUS
PatchAppleXcpmCfgLock (
IN OUT PATCHER_CONTEXT *Patcher
IN OUT PATCHER_CONTEXT *Patcher
)
{
EFI_STATUS Status;
@ -330,9 +320,10 @@ mMiscPwrMgmtDbgPatch = {
.Limit = 0
};
STATIC
EFI_STATUS
PatchAppleXcpmExtraMsrs (
IN OUT PATCHER_CONTEXT *Patcher
IN OUT PATCHER_CONTEXT *Patcher
)
{
EFI_STATUS Status;
@ -449,9 +440,10 @@ mPerfCtrlMax[] = {
0xC3 ///< ret
};
STATIC
EFI_STATUS
PatchAppleXcpmForceBoost (
IN OUT PATCHER_CONTEXT *Patcher
IN OUT PATCHER_CONTEXT *Patcher
)
{
UINT8 *Start;
@ -587,35 +579,36 @@ mRemoveUsbLimitIoP1Patch = {
.Limit = 4096
};
STATIC
EFI_STATUS
PatchUsbXhciPortLimit (
IN OUT PRELINKED_CONTEXT *Context
PatchUsbXhciPortLimit1 (
IN OUT PATCHER_CONTEXT *Patcher
)
{
EFI_STATUS Status;
PATCHER_CONTEXT Patcher;
EFI_STATUS Status;
//
// On 10.14.4 and newer IOUSBHostFamily also needs limit removal.
// Thanks to ydeng discovering this.
//
Status = PatcherInitContextFromPrelinked (
&Patcher,
Context,
"com.apple.iokit.IOUSBHostFamily"
);
if (!EFI_ERROR (Status)) {
Status = PatcherApplyGenericPatch (&Patcher, &mRemoveUsbLimitIoP1Patch);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OCAK: Failed to apply P1 patch com.apple.iokit.IOUSBHostFamily - %r\n", Status));
} else {
DEBUG ((DEBUG_INFO, "OCAK: Patch success com.apple.iokit.IOUSBHostFamily\n"));
}
Status = PatcherApplyGenericPatch (Patcher, &mRemoveUsbLimitIoP1Patch);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OCAK: Failed to apply P1 patch com.apple.iokit.IOUSBHostFamily - %r\n", Status));
} else {
DEBUG ((DEBUG_INFO, "OCAK: Failed to find com.apple.iokit.IOUSBHostFamily - %r\n", Status));
DEBUG ((DEBUG_INFO, "OCAK: Patch success com.apple.iokit.IOUSBHostFamily\n"));
}
return Status;
}
STATIC
EFI_STATUS
PatchUsbXhciPortLimit2 (
IN OUT PATCHER_CONTEXT *Patcher
)
{
EFI_STATUS Status;
//
// TODO: Implement some locationID hack in IOUSBHFamily.
// The location ID is a 32 bit number which is unique among all USB devices in the system,
@ -637,47 +630,36 @@ PatchUsbXhciPortLimit (
//
// C~F are filled as many times as many USB Hubs are there on the port.
//
Status = PatcherInitContextFromPrelinked (
&Patcher,
Context,
"com.apple.driver.usb.AppleUSBXHCI"
);
Status = PatcherApplyGenericPatch (Patcher, &mRemoveUsbLimitV2Patch);
if (!EFI_ERROR (Status)) {
Status = PatcherApplyGenericPatch (&Patcher, &mRemoveUsbLimitV2Patch);
if (!EFI_ERROR (Status)) {
//
// We do not need to patch com.apple.driver.usb.AppleUSBXHCI if this patch was successful.
// Only legacy systems require com.apple.driver.usb.AppleUSBXHCI to be patched.
//
DEBUG ((DEBUG_INFO, "OCAK: Patch success com.apple.driver.usb.AppleUSBXHCI\n"));
return EFI_SUCCESS;
}
DEBUG ((DEBUG_INFO, "OCAK: Failed to apply patch com.apple.driver.usb.AppleUSBXHCI - %r\n", Status));
//
// We do not need to patch com.apple.driver.usb.AppleUSBXHCI if this patch was successful.
// Only legacy systems require com.apple.driver.usb.AppleUSBXHCI to be patched.
//
DEBUG ((DEBUG_INFO, "OCAK: Patch success com.apple.driver.usb.AppleUSBXHCI\n"));
} else {
DEBUG ((DEBUG_INFO, "OCAK: Failed to find com.apple.driver.usb.AppleUSBXHCI - %r\n", Status));
DEBUG ((DEBUG_INFO, "OCAK: Failed to apply patch com.apple.driver.usb.AppleUSBXHCI - %r\n", Status));
}
return Status;
}
STATIC
EFI_STATUS
PatchUsbXhciPortLimit3 (
IN OUT PATCHER_CONTEXT *Patcher
)
{
EFI_STATUS Status;
//
// If we are here, we are on legacy 10.13 or below, try the oldest patch.
//
Status = PatcherInitContextFromPrelinked (
&Patcher,
Context,
"com.apple.driver.usb.AppleUSBXHCIPCI"
);
if (!EFI_ERROR (Status)) {
Status = PatcherApplyGenericPatch (&Patcher, &mRemoveUsbLimitV1Patch);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OCAK: Failed to apply patch com.apple.driver.usb.AppleUSBXHCIPCI - %r\n", Status));
} else {
DEBUG ((DEBUG_INFO, "OCAK: Patch success com.apple.driver.usb.AppleUSBXHCIPCI\n"));
}
Status = PatcherApplyGenericPatch (Patcher, &mRemoveUsbLimitV1Patch);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OCAK: Failed to apply patch com.apple.driver.usb.AppleUSBXHCIPCI - %r\n", Status));
} else {
DEBUG ((DEBUG_INFO, "OCAK: Failed to find com.apple.driver.usb.AppleUSBXHCIPCI - %r\n", Status));
DEBUG ((DEBUG_INFO, "OCAK: Patch success com.apple.driver.usb.AppleUSBXHCIPCI\n"));
}
return Status;
@ -735,37 +717,27 @@ mIOAHCIBlockStoragePatchV2 = {
.Skip = 0
};
STATIC
EFI_STATUS
PatchThirdPartyDriveSupport (
IN OUT PRELINKED_CONTEXT *Context
IN OUT PATCHER_CONTEXT *Patcher
)
{
EFI_STATUS Status;
PATCHER_CONTEXT Patcher;
Status = PatcherInitContextFromPrelinked (
&Patcher,
Context,
"com.apple.iokit.IOAHCIBlockStorage"
);
if (!EFI_ERROR (Status)) {
Status = PatcherApplyGenericPatch (&Patcher, &mIOAHCIBlockStoragePatchV1);
Status = PatcherApplyGenericPatch (Patcher, &mIOAHCIBlockStoragePatchV1);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OCAK: Failed to apply patch com.apple.iokit.IOAHCIBlockStorage V1 - %r\n", Status));
} else {
DEBUG ((DEBUG_INFO, "OCAK: Patch success com.apple.iokit.IOAHCIBlockStorage V1\n"));
}
Status = PatcherApplyGenericPatch (&Patcher, &mIOAHCIBlockStoragePatchV2);
Status = PatcherApplyGenericPatch (Patcher, &mIOAHCIBlockStoragePatchV2);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OCAK: Failed to apply patch com.apple.iokit.IOAHCIBlockStorage V2 - %r\n", Status));
} else {
DEBUG ((DEBUG_INFO, "OCAK: Patch success com.apple.iokit.IOAHCIBlockStorage V2\n"));
}
} else {
DEBUG ((DEBUG_INFO, "OCAK: Failed to find com.apple.iokit.IOAHCIBlockStorage - %r\n", Status));
}
return Status;
}
@ -785,40 +757,30 @@ mIOAHCIPortPatchReplace[] = {
STATIC
PATCHER_GENERIC_PATCH
mIOAHCIPortPatch = {
.Comment = DEBUG_POINTER ("IOAHCIPort"),
.Base = NULL,
.Find = mIOAHCIPortPatchFind,
.Mask = NULL,
.Replace = mIOAHCIPortPatchReplace,
.ReplaceMask = NULL,
.Size = sizeof (mIOAHCIPortPatchFind),
.Count = 1,
.Skip = 0
.Comment = DEBUG_POINTER ("IOAHCIPort"),
.Base = NULL,
.Find = mIOAHCIPortPatchFind,
.Mask = NULL,
.Replace = mIOAHCIPortPatchReplace,
.ReplaceMask = NULL,
.Size = sizeof (mIOAHCIPortPatchFind),
.Count = 1,
.Skip = 0
};
STATIC
EFI_STATUS
PatchForceInternalDiskIcons (
IN OUT PRELINKED_CONTEXT *Context
IN OUT PATCHER_CONTEXT *Patcher
)
{
EFI_STATUS Status;
PATCHER_CONTEXT Patcher;
Status = PatcherInitContextFromPrelinked (
&Patcher,
Context,
"com.apple.driver.AppleAHCIPort"
);
if (!EFI_ERROR (Status)) {
Status = PatcherApplyGenericPatch (&Patcher, &mIOAHCIPortPatch);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OCAK: Failed to apply patch com.apple.driver.AppleAHCIPort - %r\n", Status));
} else {
DEBUG ((DEBUG_INFO, "OCAK: Patch success com.apple.driver.AppleAHCIPort\n"));
}
Status = PatcherApplyGenericPatch (Patcher, &mIOAHCIPortPatch);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OCAK: Failed to apply patch com.apple.driver.AppleAHCIPort - %r\n", Status));
} else {
DEBUG ((DEBUG_INFO, "OCAK: Failed to find com.apple.driver.AppleAHCIPort - %r\n", Status));
DEBUG ((DEBUG_INFO, "OCAK: Patch success com.apple.driver.AppleAHCIPort\n"));
}
return Status;
@ -850,29 +812,19 @@ mAppleIoMapperPatch = {
.Skip = 0
};
STATIC
EFI_STATUS
PatchAppleIoMapperSupport (
IN OUT PRELINKED_CONTEXT *Context
IN OUT PATCHER_CONTEXT *Patcher
)
{
EFI_STATUS Status;
PATCHER_CONTEXT Patcher;
Status = PatcherInitContextFromPrelinked (
&Patcher,
Context,
"com.apple.iokit.IOPCIFamily"
);
if (!EFI_ERROR (Status)) {
Status = PatcherApplyGenericPatch (&Patcher, &mAppleIoMapperPatch);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OCAK: Failed to apply patch com.apple.iokit.IOPCIFamily AppleIoMapper - %r\n", Status));
} else {
DEBUG ((DEBUG_INFO, "OCAK: Patch success com.apple.iokit.IOPCIFamily AppleIoMapper\n"));
}
Status = PatcherApplyGenericPatch (Patcher, &mAppleIoMapperPatch);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OCAK: Failed to apply patch com.apple.iokit.IOPCIFamily AppleIoMapper - %r\n", Status));
} else {
DEBUG ((DEBUG_INFO, "OCAK: Failed to find com.apple.iokit.IOPCIFamily for AppleIoMapper - %r\n", Status));
DEBUG ((DEBUG_INFO, "OCAK: Patch success com.apple.iokit.IOPCIFamily AppleIoMapper\n"));
}
return Status;
@ -898,29 +850,19 @@ mAppleDummyCpuPmPatch = {
.Skip = 0
};
STATIC
EFI_STATUS
PatchDummyPowerManagement (
IN OUT PRELINKED_CONTEXT *Context
IN OUT PATCHER_CONTEXT *Patcher
)
{
EFI_STATUS Status;
PATCHER_CONTEXT Patcher;
Status = PatcherInitContextFromPrelinked (
&Patcher,
Context,
"com.apple.driver.AppleIntelCPUPowerManagement"
);
if (!EFI_ERROR (Status)) {
Status = PatcherApplyGenericPatch (&Patcher, &mAppleDummyCpuPmPatch);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OCAK: Failed to apply patch dummy AppleIntelCPUPowerManagement - %r\n", Status));
} else {
DEBUG ((DEBUG_INFO, "OCAK: Patch success dummy AppleIntelCPUPowerManagement\n"));
}
Status = PatcherApplyGenericPatch (Patcher, &mAppleDummyCpuPmPatch);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OCAK: Failed to apply patch dummy AppleIntelCPUPowerManagement - %r\n", Status));
} else {
DEBUG ((DEBUG_INFO, "OCAK: Failed to find AppleIntelCPUPowerManagement for dummy - %r\n", Status));
DEBUG ((DEBUG_INFO, "OCAK: Patch success dummy AppleIntelCPUPowerManagement\n"));
}
return Status;
@ -953,34 +895,25 @@ mIncreasePciBarSizePatch = {
.Limit = EFI_PAGE_SIZE
};
STATIC
EFI_STATUS
PatchIncreasePciBarSize (
IN OUT PRELINKED_CONTEXT *Context
IN OUT PATCHER_CONTEXT *Patcher
)
{
EFI_STATUS Status;
PATCHER_CONTEXT Patcher;
Status = PatcherInitContextFromPrelinked (
&Patcher,
Context,
"com.apple.iokit.IOPCIFamily"
);
if (!EFI_ERROR (Status)) {
Status = PatcherApplyGenericPatch (&Patcher, &mIncreasePciBarSizePatch);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OCAK: Failed to apply patch com.apple.iokit.IOPCIFamily IncreasePciBarSize - %r\n", Status));
} else {
DEBUG ((DEBUG_INFO, "OCAK: Patch success com.apple.iokit.IOPCIFamily IncreasePciBarSize\n"));
}
Status = PatcherApplyGenericPatch (Patcher, &mIncreasePciBarSizePatch);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OCAK: Failed to apply patch com.apple.iokit.IOPCIFamily IncreasePciBarSize - %r\n", Status));
} else {
DEBUG ((DEBUG_INFO, "OCAK: Failed to find com.apple.iokit.IOPCIFamily for IncreasePciBarSize - %r\n", Status));
DEBUG ((DEBUG_INFO, "OCAK: Patch success com.apple.iokit.IOPCIFamily IncreasePciBarSize\n"));
}
return Status;
}
STATIC
CONST UINT8
mKernelCpuIdFindRelNew[] = {
@ -1027,6 +960,8 @@ mKernelCpuidFindMcRel[] = {
cpu->cpuid_cpufamily = 0xAAAAAAAA;
return 0xAAAAAAAA;
**/
STATIC
CONST UINT8
mKernelCpuidReplaceDbg[] = {
@ -1454,48 +1389,30 @@ mCustomSmbiosGuidPatchReplace[] = {
STATIC
PATCHER_GENERIC_PATCH
mCustomSmbiosGuidPatch = {
.Comment = DEBUG_POINTER ("CustomSmbiosGuid"),
.Base = NULL,
.Find = mCustomSmbiosGuidPatchFind,
.Mask = NULL,
.Replace = mCustomSmbiosGuidPatchReplace,
.ReplaceMask = NULL,
.Size = sizeof (mCustomSmbiosGuidPatchFind),
.Count = 1,
.Skip = 0
.Comment = DEBUG_POINTER ("CustomSmbiosGuid"),
.Base = NULL,
.Find = mCustomSmbiosGuidPatchFind,
.Mask = NULL,
.Replace = mCustomSmbiosGuidPatchReplace,
.ReplaceMask = NULL,
.Size = sizeof (mCustomSmbiosGuidPatchFind),
.Count = 1,
.Skip = 0
};
STATIC
EFI_STATUS
PatchCustomSmbiosGuid (
IN OUT PRELINKED_CONTEXT *Context
IN OUT PATCHER_CONTEXT *Patcher
)
{
EFI_STATUS Status;
PATCHER_CONTEXT Patcher;
UINT32 Index;
STATIC CONST CHAR8 *Kexts[] = {
"com.apple.driver.AppleSMBIOS",
"com.apple.driver.AppleACPIPlatform"
};
for (Index = 0; Index < ARRAY_SIZE (Kexts); ++Index) {
Status = PatcherInitContextFromPrelinked (
&Patcher,
Context,
Kexts[Index]
);
if (!EFI_ERROR (Status)) {
Status = PatcherApplyGenericPatch (&Patcher, &mCustomSmbiosGuidPatch);
if (!EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OCAK: SMBIOS Patch success %a\n", Kexts[Index]));
} else {
DEBUG ((DEBUG_INFO, "OCAK: Failed to apply SMBIOS patch %a - %r\n", Kexts[Index], Status));
}
} else {
DEBUG ((DEBUG_INFO, "OCAK: Failed to find SMBIOS kext %a - %r\n", Kexts[Index], Status));
}
Status = PatcherApplyGenericPatch (Patcher, &mCustomSmbiosGuidPatch);
if (!EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OCAK: SMBIOS Patch success\n"));
} else {
DEBUG ((DEBUG_INFO, "OCAK: Failed to apply SMBIOS patch - %r\n", Status));
}
return Status;
@ -1527,9 +1444,10 @@ mPanicKextDumpPatch = {
.Skip = 0
};
STATIC
EFI_STATUS
PatchPanicKextDump (
IN OUT PATCHER_CONTEXT *Patcher
IN OUT PATCHER_CONTEXT *Patcher
)
{
EFI_STATUS Status;
@ -1676,9 +1594,10 @@ mLapicKernelPanicMasterPatch = {
.Limit = 4096
};
STATIC
EFI_STATUS
PatchLapicKernelPanic (
IN OUT PATCHER_CONTEXT *Patcher
IN OUT PATCHER_CONTEXT *Patcher
)
{
EFI_STATUS Status;
@ -1744,9 +1663,10 @@ mPowerStateTimeoutPanicMasterPatch = {
.Limit = 0
};
STATIC
EFI_STATUS
PatchPowerStateTimeout (
IN OUT PATCHER_CONTEXT *Patcher
IN OUT PATCHER_CONTEXT *Patcher
)
{
EFI_STATUS Status;
@ -1806,30 +1726,55 @@ mAppleRtcChecksumPatch = {
.Limit = 0
};
STATIC
EFI_STATUS
PatchAppleRtcChecksum (
IN OUT PRELINKED_CONTEXT *Context
IN PATCHER_CONTEXT *Patcher
)
{
EFI_STATUS Status;
PATCHER_CONTEXT Patcher;
EFI_STATUS Status;
Status = PatcherInitContextFromPrelinked (
&Patcher,
Context,
"com.apple.driver.AppleRTC"
);
if (!EFI_ERROR (Status)) {
Status = PatcherApplyGenericPatch (&Patcher, &mAppleRtcChecksumPatch);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OCAK: Failed to apply patch com.apple.driver.AppleRTC DisableRtcChecksum - %r\n", Status));
} else {
DEBUG ((DEBUG_INFO, "OCAK: Patch success com.apple.driver.AppleRTC DisableRtcChecksum\n"));
}
Status = PatcherApplyGenericPatch (Patcher, &mAppleRtcChecksumPatch);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OCAK: Failed to apply patch com.apple.driver.AppleRTC DisableRtcChecksum - %r\n", Status));
} else {
DEBUG ((DEBUG_INFO, "OCAK: Failed to find com.apple.driver.AppleRTC for DisableRtcChecksum - %r\n", Status));
DEBUG ((DEBUG_INFO, "OCAK: Patch success com.apple.driver.AppleRTC DisableRtcChecksum\n"));
}
return Status;
}
//
// Quirks table.
//
KERNEL_QUIRK gKernelQuirks[] = {
[KernelQuirkAppleCpuPmCfgLock] = { "com.apple.driver.AppleIntelCPUPowerManagement", PatchAppleCpuPmCfgLock },
[KernelQuirkAppleXcpmCfgLock] = { NULL, PatchAppleXcpmCfgLock },
[KernelQuirkAppleXcpmExtraMsrs] = { NULL, PatchAppleXcpmExtraMsrs },
[KernelQuirkAppleXcpmForceBoost] = { NULL, PatchAppleXcpmForceBoost },
[KernelQuirkCustomSmbiosGuid1] = { "com.apple.driver.AppleSMBIOS", PatchCustomSmbiosGuid },
[KernelQuirkCustomSmbiosGuid2] = { "com.apple.driver.AppleACPIPlatform", PatchCustomSmbiosGuid },
[KernelQuirkDisableIoMapper] = { "com.apple.iokit.IOPCIFamily", PatchAppleIoMapperSupport },
[KernelQuirkDisableRtcChecksum] = { "com.apple.driver.AppleRTC", PatchAppleRtcChecksum },
[KernelQuirkDummyPowerManagement] = { "com.apple.driver.AppleIntelCPUPowerManagement", PatchDummyPowerManagement },
[KernelQuirkExternalDiskIcons] = { "com.apple.driver.AppleAHCIPort", PatchForceInternalDiskIcons },
[KernelQuirkIncreasePciBarSize] = { "com.apple.iokit.IOPCIFamily", PatchIncreasePciBarSize },
[KernelQuirkLapicKernelPanic] = { NULL, PatchLapicKernelPanic },
[KernelQuirkPanicNoKextDump] = { NULL, PatchPanicKextDump },
[KernelQuirkPowerTimeoutKernelPanic] = { NULL, PatchPowerStateTimeout },
[KernelQuirkThirdPartyDrives] = { "com.apple.iokit.IOAHCIBlockStorage", PatchThirdPartyDriveSupport },
[KernelQuirkXhciPortLimit1] = { "com.apple.iokit.IOUSBHostFamily", PatchUsbXhciPortLimit1 },
[KernelQuirkXhciPortLimit2] = { "com.apple.driver.usb.AppleUSBXHCI", PatchUsbXhciPortLimit2 },
[KernelQuirkXhciPortLimit3] = { "com.apple.driver.usb.AppleUSBXHCIPCI", PatchUsbXhciPortLimit3 },
};
EFI_STATUS
KernelQuirkApply (
IN KERNEL_QUIRK_NAME Name,
IN OUT PATCHER_CONTEXT *Patcher
)
{
ASSERT (Patcher != NULL);
return gKernelQuirks[Name].PatchFunction (Patcher);
}

View File

@ -24,6 +24,7 @@
#include <Library/OcMiscLib.h>
#include <Library/OcXmlLib.h>
#include "MkextInternal.h"
#include "PrelinkedInternal.h"
EFI_STATUS
@ -44,6 +45,23 @@ PatcherInitContextFromPrelinked (
return EFI_SUCCESS;
}
EFI_STATUS
PatcherInitContextFromMkext(
IN OUT PATCHER_CONTEXT *Context,
IN OUT MKEXT_CONTEXT *Mkext,
IN CONST CHAR8 *Name
)
{
MKEXT_KEXT *Kext;
Kext = InternalCachedMkextKext (Mkext, Name);
if (Kext == NULL) {
return EFI_NOT_FOUND;
}
return PatcherInitContextFromBuffer (Context, &Mkext->Mkext[Kext->BinaryOffset], Kext->BinarySize);
}
EFI_STATUS
PatcherInitContextFromBuffer (
IN OUT PATCHER_CONTEXT *Context,

View File

@ -15,18 +15,16 @@
#include <Uefi.h>
#include <IndustryStandard/AppleFatBinaryImage.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/OcAppleKernelLib.h>
#include <Library/OcCompressionLib.h>
#include <Library/OcFileLib.h>
#include <Library/OcGuardLib.h>
#include <Library/OcStringLib.h>
#include "MkextInternal.h"
#include "PrelinkedInternal.h"
//
@ -82,6 +80,7 @@ BOOLEAN
ParseMkextV2Plist (
IN MKEXT_V2_HEADER *Mkext,
OUT UINT8 **Plist,
OUT UINT32 *PlistSize,
OUT XML_DOCUMENT **PlistDoc,
OUT XML_NODE **PlistBundles
)
@ -169,6 +168,7 @@ ParseMkextV2Plist (
if (AsciiStrCmp (BundleArrayKey, MKEXT_INFO_DICTIONARIES_KEY) == 0) {
*Plist = PlistBuffer;
*PlistSize = PlistFullSize;
*PlistDoc = PlistXml;
*PlistBundles = PlistBundleArray;
@ -213,16 +213,249 @@ UpdateMkextV2Plist (
return 0;
}
MkextBuffer = (UINT8*)Mkext;
MkextBuffer = (UINT8 *) Mkext;
CopyMem (&MkextBuffer[Offset], ExportedInfo, ExportedInfoSize);
FreePool (ExportedInfo);
Mkext->PlistOffset = SwapBytes32 (Offset);
Mkext->PlistFullSize = SwapBytes32 (ExportedInfoSize);
Mkext->PlistCompressedSize = 0;
Mkext->PlistOffset = SwapBytes32 (Offset);
Mkext->PlistFullSize = SwapBytes32 (ExportedInfoSize);
Mkext->PlistCompressedSize = 0;
return ExportedInfoSize;
}
MKEXT_KEXT *
InternalCachedMkextKext (
IN OUT MKEXT_CONTEXT *Context,
IN CONST CHAR8 *BundleId
)
{
MKEXT_HEADER_ANY *MkextHeader;
MKEXT_V2_FILE_ENTRY *MkextV2FileEntry;
MKEXT_KEXT *MkextKext;
LIST_ENTRY *KextLink;
UINT32 Index;
UINT32 PlistOffsetSize;
UINT32 BinOffsetSize;
BOOLEAN IsKextMatch;
UINT32 PlistOffset;
UINT32 PlistSize;
CHAR8 *PlistBuffer;
XML_DOCUMENT *PlistXml;
XML_NODE *PlistRoot;
UINT32 PlistBundlesCount;
XML_NODE *PlistBundle;
UINT32 PlistBundleIndex;
UINT32 PlistBundleCount;
CONST CHAR8 *PlistBundleKey;
XML_NODE *PlistBundleKeyValue;
CONST CHAR8 *KextBundleId;
UINT32 KextBinOffset;
UINT32 KextBinSize;
MkextHeader = Context->MkextHeader;
//
// Try to get cached kext.
//
KextLink = GetFirstNode (&Context->CachedKexts);
while (!IsNull (&Context->CachedKexts, KextLink)) {
MkextKext = GET_MKEXT_KEXT_FROM_LINK (KextLink);
if (AsciiStrCmp (BundleId, MkextKext->BundleId) == 0) {
return MkextKext;
}
KextLink = GetNextNode (&Context->CachedKexts, KextLink);
}
//
// Search mkext and add kext to cache.
//
IsKextMatch = FALSE;
//
// Mkext v1.
//
if (Context->MkextVersion == MKEXT_VERSION_V1) {
for (Index = 0; Index < Context->NumKexts; Index++) {
//
// Do not cache binaryless or compressed kexts.
//
if (MkextHeader->V1.Kexts[Index].Plist.CompressedSize != 0
|| MkextHeader->V1.Kexts[Index].Binary.CompressedSize != 0
|| MkextHeader->V1.Kexts[Index].Binary.Offset == 0) {
continue;
}
PlistOffset = SwapBytes32 (MkextHeader->V1.Kexts[Index].Plist.Offset);
PlistSize = SwapBytes32 (MkextHeader->V1.Kexts[Index].Plist.FullSize);
KextBinOffset = SwapBytes32 (MkextHeader->V1.Kexts[Index].Binary.Offset);
KextBinSize = SwapBytes32 (MkextHeader->V1.Kexts[Index].Binary.FullSize);
//
// Verify plist and binary are within bounds.
//
if (OcOverflowAddU32 (PlistOffset, PlistSize, &PlistOffsetSize)
|| PlistOffsetSize > Context->MkextSize
|| OcOverflowAddU32 (KextBinOffset, KextBinSize, &BinOffsetSize)
|| BinOffsetSize > Context->MkextSize) {
return NULL;
}
PlistBuffer = AllocateCopyPool (PlistSize, &Context->Mkext[PlistOffset]);
if (PlistBuffer == NULL) {
return NULL;
}
PlistXml = XmlDocumentParse (PlistBuffer, PlistSize, FALSE);
if (PlistXml == NULL) {
FreePool (PlistBuffer);
return NULL;
}
PlistRoot = PlistNodeCast (PlistDocumentRoot (PlistXml), PLIST_NODE_TYPE_DICT);
if (PlistRoot == NULL) {
XmlDocumentFree (PlistXml);
FreePool (PlistBuffer);
return NULL;
}
KextBundleId = NULL;
PlistBundleCount = PlistDictChildren (PlistRoot);
for (PlistBundleIndex = 0; PlistBundleIndex < PlistBundleCount; PlistBundleIndex++) {
PlistBundleKey = PlistKeyValue (PlistDictChild (PlistRoot, PlistBundleIndex, &PlistBundleKeyValue));
if (PlistBundleKey == NULL || PlistBundleKeyValue == NULL) {
continue;
}
if (AsciiStrCmp (PlistBundleKey, INFO_BUNDLE_IDENTIFIER_KEY) == 0) {
KextBundleId = XmlNodeContent (PlistBundleKeyValue);
break;
}
}
IsKextMatch = KextBundleId != NULL && AsciiStrCmp (KextBundleId, BundleId) == 0;
XmlDocumentFree (PlistXml);
FreePool (PlistBuffer);
if (IsKextMatch && KextBinOffset > 0 && KextBinSize > 0) {
break;
}
}
//
// Bundle was not found, or invalid.
//
if (!IsKextMatch) {
return NULL;
}
//
// Mkext v2.
//
} else if (Context->MkextVersion == MKEXT_VERSION_V2) {
KextBundleId = NULL;
KextBinOffset = 0;
//
// Enumerate bundle dicts.
//
PlistBundlesCount = XmlNodeChildren (Context->MkextKexts);
for (Index = 0; Index < PlistBundlesCount; Index++) {
PlistBundle = PlistNodeCast (XmlNodeChild (Context->MkextKexts, Index), PLIST_NODE_TYPE_DICT);
if (PlistBundle == NULL) {
return NULL;
}
PlistBundleCount = PlistDictChildren (PlistBundle);
for (PlistBundleIndex = 0; PlistBundleIndex < PlistBundleCount; PlistBundleIndex++) {
PlistBundleKey = PlistKeyValue (PlistDictChild (PlistBundle, PlistBundleIndex, &PlistBundleKeyValue));
if (PlistBundleKey == NULL || PlistBundleKeyValue == NULL) {
continue;
}
if (AsciiStrCmp (PlistBundleKey, INFO_BUNDLE_IDENTIFIER_KEY) == 0) {
KextBundleId = XmlNodeContent (PlistBundleKeyValue);
}
if (AsciiStrCmp (PlistBundleKey, MKEXT_EXECUTABLE_KEY) == 0) {
//
// Ensure binary offset is before plist offset.
//
if (!PlistIntegerValue (PlistBundleKeyValue, &KextBinOffset, sizeof (KextBinOffset), TRUE)) {
return NULL;
}
}
}
if (KextBundleId != NULL
&& AsciiStrCmp (KextBundleId, BundleId) == 0
&& KextBinOffset > 0
&& KextBinOffset < Context->MkextSize - sizeof (MKEXT_V2_FILE_ENTRY)) {
IsKextMatch = TRUE;
break;
}
KextBundleId = NULL;
KextBinOffset = 0;
}
//
// Bundle was not found, or invalid.
//
if (!IsKextMatch) {
return NULL;
}
//
// Parse v2 binary header.
// We cannot support compressed binaries.
//
MkextV2FileEntry = (MKEXT_V2_FILE_ENTRY *) &Context->Mkext[KextBinOffset];
if (MkextV2FileEntry->CompressedSize != 0) {
return NULL;
}
KextBinOffset += OFFSET_OF (MKEXT_V2_FILE_ENTRY, Data);
KextBinSize = SwapBytes32 (MkextV2FileEntry->FullSize);
//
// Ensure binary is within mkext bounds.
//
if (OcOverflowAddU32 (KextBinOffset, KextBinSize, &BinOffsetSize)
|| BinOffsetSize > Context->MkextSize) {
return NULL;
}
//
// Unsupported version.
//
} else {
return NULL;
}
MkextKext = AllocateZeroPool (sizeof (*MkextKext));
if (MkextKext == NULL) {
return NULL;
}
MkextKext->Signature = MKEXT_KEXT_SIGNATURE;
MkextKext->BinaryOffset = KextBinOffset;
MkextKext->BinarySize = KextBinSize;
MkextKext->BundleId = AllocateCopyPool (AsciiStrSize (BundleId), BundleId);
if (MkextKext->BundleId == NULL) {
FreePool (MkextKext);
return NULL;
}
InsertTailList (&Context->CachedKexts, &MkextKext->Link);
return MkextKext;
}
EFI_STATUS
MkextDecompress (
IN CONST UINT8 *Buffer,
@ -296,6 +529,8 @@ MkextDecompress (
return EFI_INVALID_PARAMETER;
}
MkextHeaderOut = NULL;
//
// Mkext v1.
//
@ -367,7 +602,7 @@ MkextDecompress (
|| DecompressLZSS (
&OutBuffer[CurrentOffset],
PlistFullSize,
&((UINT8*)Buffer)[PlistOffset],
&((UINT8 *) Buffer)[PlistOffset],
PlistCompSize
) != PlistFullSize) {
return EFI_INVALID_PARAMETER;
@ -396,7 +631,7 @@ MkextDecompress (
|| DecompressLZSS (
&OutBuffer[CurrentOffset],
BinFullSize,
&((UINT8*)Buffer)[BinOffset],
&((UINT8 *) Buffer)[BinOffset],
BinCompSize
) != BinFullSize) {
return EFI_INVALID_PARAMETER;
@ -460,7 +695,7 @@ MkextDecompress (
MkextHeaderOut = (MKEXT_HEADER_ANY *) OutBuffer;
}
if (!ParseMkextV2Plist (&MkextHeader->V2, &PlistBuffer, &PlistXml, &PlistBundles)) {
if (!ParseMkextV2Plist (&MkextHeader->V2, &PlistBuffer, &PlistFullSize, &PlistXml, &PlistBundles)) {
return EFI_INVALID_PARAMETER;
}
@ -689,18 +924,14 @@ MkextContextInit (
UINT8 *PlistBuffer;
XML_DOCUMENT *PlistXml;
UINT32 PlistOffset;
UINT32 PlistFullSize;
XML_NODE *PlistBundles;
UINT32 PlistBundlesCount;
XML_NODE *PlistBundle;
UINT32 PlistBundleIndex;
UINT32 PlistBundleCount;
CONST CHAR8 *PlistBundleKey;
XML_NODE *BundleExecutable;
UINT32 BinOffset;
//
// Assumptions:
// Kexts are fully decompressed and aligned to 8 bytes with plist (for v2) at end of mkext.
// Kexts are aligned to 8 bytes.
// Patching or blocking requires kexts to be decompressed.
// Plist (for v2) is at end of mkext.
// Mkext is big-endian per XNU requirements.
//
@ -754,9 +985,6 @@ MkextContextInit (
StartingOffset = 0;
for (Index = 0; Index < NumKexts; Index++) {
CurrentOffset = SwapBytes32 (MkextHeader->V1.Kexts[Index].Plist.Offset);
if (MkextHeader->V1.Kexts[Index].Plist.CompressedSize != 0) {
return EFI_UNSUPPORTED;
}
if (StartingOffset == 0 || CurrentOffset < StartingOffset) {
StartingOffset = CurrentOffset;
}
@ -766,9 +994,6 @@ MkextContextInit (
//
if (MkextHeader->V1.Kexts[Index].Binary.FullSize > 0) {
CurrentOffset = SwapBytes32 (MkextHeader->V1.Kexts[Index].Binary.Offset);
if (MkextHeader->V1.Kexts[Index].Binary.CompressedSize != 0) {
return EFI_UNSUPPORTED;
}
if (CurrentOffset < StartingOffset) {
StartingOffset = CurrentOffset;
}
@ -791,43 +1016,14 @@ MkextContextInit (
//
} else if (MkextVersion == MKEXT_VERSION_V2) {
if (MkextSize < sizeof (MKEXT_V2_HEADER)
|| !ParseMkextV2Plist (&MkextHeader->V2, &PlistBuffer, &PlistXml, &PlistBundles)) {
|| !ParseMkextV2Plist (&MkextHeader->V2, &PlistBuffer, &PlistFullSize, &PlistXml, &PlistBundles)) {
return EFI_INVALID_PARAMETER;
}
PlistOffset = SwapBytes32 (MkextHeader->V2.PlistOffset);
//
// Enumerate bundle dicts.
//
PlistBundlesCount = XmlNodeChildren (PlistBundles);
for (Index = 0; Index < PlistBundlesCount; Index++) {
PlistBundle = PlistNodeCast (XmlNodeChild (PlistBundles, Index), PLIST_NODE_TYPE_DICT);
if (PlistBundle == NULL) {
XmlDocumentFree (PlistXml);
FreePool (PlistBuffer);
return EFI_INVALID_PARAMETER;
}
PlistBundleCount = PlistDictChildren (PlistBundle);
for (PlistBundleIndex = 0; PlistBundleIndex < PlistBundleCount; PlistBundleIndex++) {
PlistBundleKey = PlistKeyValue (PlistDictChild (PlistBundle, PlistBundleIndex, &BundleExecutable));
if (PlistBundleKey == NULL) {
continue;
}
if (AsciiStrCmp (PlistBundleKey, MKEXT_EXECUTABLE_KEY) == 0) {
//
// Ensure binary offset is before plist offset.
//
if (!PlistIntegerValue (BundleExecutable, &BinOffset, sizeof (BinOffset), TRUE)
|| BinOffset == 0
|| BinOffset >= PlistOffset) {
XmlDocumentFree (PlistXml);
FreePool (PlistBuffer);
return EFI_INVALID_PARAMETER;
}
}
}
if (OcOverflowAddU32 (PlistOffset, PlistFullSize, &Tmp)
|| Tmp != MkextSize) {
return EFI_INVALID_PARAMETER;
}
//
@ -845,6 +1041,7 @@ MkextContextInit (
Context->MkextVersion = MkextVersion;
Context->Is64Bit = Is64Bit;
Context->NumKexts = NumKexts;
InitializeListHead (&Context->CachedKexts);
if (MkextVersion == MKEXT_VERSION_V1) {
Context->NumMaxKexts = NumMaxKexts;
@ -863,8 +1060,20 @@ MkextContextFree (
IN OUT MKEXT_CONTEXT *Context
)
{
MKEXT_KEXT *MkextKext;
LIST_ENTRY *KextLink;
ASSERT (Context != NULL);
while (!IsListEmpty (&Context->CachedKexts)) {
KextLink = GetFirstNode (&Context->CachedKexts);
MkextKext = GET_MKEXT_KEXT_FROM_LINK (KextLink);
RemoveEntryList (KextLink);
FreePool (MkextKext->BundleId);
FreePool (MkextKext);
}
if (Context->MkextInfoDocument != NULL) {
XmlDocumentFree (Context->MkextInfoDocument);
}
@ -949,6 +1158,8 @@ MkextInjectKext (
ASSERT (InfoPlist != NULL);
ASSERT (InfoPlistSize > 0);
BinOffset = 0;
//
// Mkext v1.
//
@ -1131,6 +1342,53 @@ MkextInjectKext (
return EFI_SUCCESS;
}
EFI_STATUS
MkextContextApplyPatch (
IN OUT MKEXT_CONTEXT *Context,
IN CONST CHAR8 *BundleId,
IN PATCHER_GENERIC_PATCH *Patch
)
{
EFI_STATUS Status;
PATCHER_CONTEXT Patcher;
ASSERT (Context != NULL);
ASSERT (BundleId != NULL);
ASSERT (Patch != NULL);
Status = PatcherInitContextFromMkext (&Patcher, Context, BundleId);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OCAK: Failed to find %a - %r\n", BundleId, Status));
return Status;
}
return PatcherApplyGenericPatch (&Patcher, Patch);
}
EFI_STATUS
MkextContextApplyQuirk (
IN OUT MKEXT_CONTEXT *Context,
IN KERNEL_QUIRK_NAME Quirk
)
{
EFI_STATUS Status;
KERNEL_QUIRK *KernelQuirk;
PATCHER_CONTEXT Patcher;
ASSERT (Context != NULL);
KernelQuirk = &gKernelQuirks[Quirk];
ASSERT (KernelQuirk->BundleId != NULL);
Status = PatcherInitContextFromMkext (&Patcher, Context, KernelQuirk->BundleId);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OCAK: Failed to find %a - %r\n", KernelQuirk->BundleId, Status));
return Status;
}
return KernelQuirk->PatchFunction (&Patcher);
}
EFI_STATUS
MkextInjectPatchComplete (
IN OUT MKEXT_CONTEXT *Context

View File

@ -0,0 +1,72 @@
/** @file
Mkext support.
Copyright (c) 2020, Goldfish64. All rights reserved.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef MKEXT_INTERNAL_H
#define MKEXT_INTERNAL_H
#include <Library/OcAppleKernelLib.h>
//
// Cached mkext kext.
//
typedef struct {
//
// Signature.
//
UINT32 Signature;
//
// Link for global list (MKEXT_CONTEXT -> CachedKexts).
//
LIST_ENTRY Link;
//
// Kext bundle ID.
//
CHAR8 *BundleId;
//
// Offset of binary in mkext.
//
UINT32 BinaryOffset;
//
// Size of binary in mkext.
//
UINT32 BinarySize;
} MKEXT_KEXT;
//
// MKEXT_KEXT signature for list identification.
//
#define MKEXT_KEXT_SIGNATURE SIGNATURE_32 ('M', 'k', 'x', 'T')
/**
Gets the next element in CachedKexts list of MKEXT_KEXT.
@param[in] This The current ListEntry.
**/
#define GET_MKEXT_KEXT_FROM_LINK(This) \
(CR ( \
(This), \
MKEXT_KEXT, \
Link, \
MKEXT_KEXT_SIGNATURE \
))
MKEXT_KEXT *
InternalCachedMkextKext (
IN OUT MKEXT_CONTEXT *Context,
IN CONST CHAR8 *BundleId
);
#endif // MKEXT_INTERNAL_H

View File

@ -1134,3 +1134,50 @@ PrelinkedInjectKext (
return EFI_SUCCESS;
}
EFI_STATUS
PrelinkedContextApplyPatch (
IN OUT PRELINKED_CONTEXT *Context,
IN CONST CHAR8 *BundleId,
IN PATCHER_GENERIC_PATCH *Patch
)
{
EFI_STATUS Status;
PATCHER_CONTEXT Patcher;
ASSERT (Context != NULL);
ASSERT (BundleId != NULL);
ASSERT (Patch != NULL);
Status = PatcherInitContextFromPrelinked (&Patcher, Context, BundleId);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OCAK: Failed to find %a - %r\n", BundleId, Status));
return Status;
}
return PatcherApplyGenericPatch (&Patcher, Patch);
}
EFI_STATUS
PrelinkedContextApplyQuirk (
IN OUT PRELINKED_CONTEXT *Context,
IN KERNEL_QUIRK_NAME Quirk
)
{
EFI_STATUS Status;
KERNEL_QUIRK *KernelQuirk;
PATCHER_CONTEXT Patcher;
ASSERT (Context != NULL);
KernelQuirk = &gKernelQuirks[Quirk];
ASSERT (KernelQuirk->BundleId != NULL);
Status = PatcherInitContextFromPrelinked (&Patcher, Context, KernelQuirk->BundleId);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OCAK: Failed to find %a - %r\n", KernelQuirk->BundleId, Status));
return Status;
}
return KernelQuirk->PatchFunction (&Patcher);
}

View File

@ -32,6 +32,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
//
#define KEXT_OFFSET_STR_LEN 24
//
// Kernel quirks array.
//
extern KERNEL_QUIRK gKernelQuirks[];
typedef struct PRELINKED_KEXT_ PRELINKED_KEXT;
typedef struct {

View File

@ -221,18 +221,48 @@ OcKernelLoadKextsAndReserve (
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
OcKernelApplyQuirk (
IN KERNEL_QUIRK_NAME Quirk,
IN KERNEL_CACHE_TYPE CacheType,
IN OUT VOID *Context,
IN OUT PATCHER_CONTEXT *KernelPatcher
)
{
//
// Apply kernel quirks to kernel, kext patches to context.
//
if (Context == NULL) {
ASSERT (KernelPatcher != NULL);
return KernelQuirkApply (Quirk, KernelPatcher);
} else {
if (CacheType == CacheTypeCacheless) {
return CachelessContextAddQuirk ((CACHELESS_CONTEXT *) Context, Quirk);
} else if (CacheType == CacheTypeMkext) {
return MkextContextApplyQuirk ((MKEXT_CONTEXT *) Context, Quirk);
} else if (CacheType == CacheTypePrelinked) {
return PrelinkedContextApplyQuirk ((PRELINKED_CONTEXT *) Context, Quirk);
}
}
return EFI_UNSUPPORTED;
}
STATIC
VOID
OcKernelApplyPatches (
IN OC_GLOBAL_CONFIG *Config,
IN UINT32 DarwinVersion,
IN PRELINKED_CONTEXT *Context,
IN KERNEL_CACHE_TYPE CacheType,
IN VOID *Context,
IN OUT UINT8 *Kernel,
IN UINT32 Size
)
{
EFI_STATUS Status;
PATCHER_CONTEXT Patcher;
PATCHER_CONTEXT KernelPatcher;
UINT32 Index;
PATCHER_GENERIC_PATCH Patch;
OC_KERNEL_PATCH_ENTRY *UserPatch;
@ -248,7 +278,7 @@ OcKernelApplyPatches (
ASSERT (Kernel != NULL);
Status = PatcherInitContextFromBuffer (
&Patcher,
&KernelPatcher,
Kernel,
Size
);
@ -285,21 +315,6 @@ OcKernelApplyPatches (
continue;
}
if (!IsKernelPatch) {
Status = PatcherInitContextFromPrelinked (
&Patcher,
Context,
Target
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_WARN, "OC: Kernel patcher %a (%a) init failure - %r\n", Target, Comment, Status));
continue;
} else {
DEBUG ((DEBUG_INFO, "OC: Kernel patcher %a (%a) init succeed\n", Target, Comment));
}
}
//
// Ignore patch if:
// - There is nothing to replace.
@ -344,7 +359,18 @@ OcKernelApplyPatches (
Patch.Skip = UserPatch->Skip;
Patch.Limit = UserPatch->Limit;
Status = PatcherApplyGenericPatch (&Patcher, &Patch);
if (IsKernelPatch) {
Status = PatcherApplyGenericPatch (&KernelPatcher, &Patch);
} else {
if (CacheType == CacheTypeCacheless) {
Status = CachelessContextAddPatch ((CACHELESS_CONTEXT *) Context, Target, &Patch);
} else if (CacheType == CacheTypeMkext) {
Status = MkextContextApplyPatch ((MKEXT_CONTEXT *) Context, Target, &Patch);
} else if (CacheType == CacheTypePrelinked) {
Status = PrelinkedContextApplyPatch ((PRELINKED_CONTEXT *) Context, Target, &Patch);
}
}
DEBUG ((
EFI_ERROR (Status) ? DEBUG_WARN : DEBUG_INFO,
"OC: Kernel patcher result %u for %a (%a) - %r\n",
@ -357,55 +383,58 @@ OcKernelApplyPatches (
if (!IsKernelPatch) {
if (Config->Kernel.Quirks.AppleCpuPmCfgLock) {
PatchAppleCpuPmCfgLock (Context);
OcKernelApplyQuirk (KernelQuirkAppleCpuPmCfgLock, CacheType, Context, NULL);
}
if (Config->Kernel.Quirks.ExternalDiskIcons) {
PatchForceInternalDiskIcons (Context);
OcKernelApplyQuirk (KernelQuirkExternalDiskIcons, CacheType, Context, NULL);
}
if (Config->Kernel.Quirks.ThirdPartyDrives) {
PatchThirdPartyDriveSupport (Context);
OcKernelApplyQuirk (KernelQuirkThirdPartyDrives, CacheType, Context, NULL);
}
if (Config->Kernel.Quirks.XhciPortLimit) {
PatchUsbXhciPortLimit (Context);
OcKernelApplyQuirk (KernelQuirkXhciPortLimit1, CacheType, Context, NULL);
OcKernelApplyQuirk (KernelQuirkXhciPortLimit2, CacheType, Context, NULL);
OcKernelApplyQuirk (KernelQuirkXhciPortLimit3, CacheType, Context, NULL);
}
if (Config->Kernel.Quirks.DisableIoMapper) {
PatchAppleIoMapperSupport (Context);
OcKernelApplyQuirk (KernelQuirkDisableIoMapper, CacheType, Context, NULL);
}
if (Config->Kernel.Quirks.DisableRtcChecksum) {
PatchAppleRtcChecksum (Context);
OcKernelApplyQuirk (KernelQuirkDisableRtcChecksum, CacheType, Context, NULL);
}
if (Config->Kernel.Quirks.IncreasePciBarSize) {
PatchIncreasePciBarSize (Context);
OcKernelApplyQuirk (KernelQuirkIncreasePciBarSize, CacheType, Context, NULL);
}
if (Config->Kernel.Quirks.CustomSmbiosGuid) {
PatchCustomSmbiosGuid (Context);
OcKernelApplyQuirk (KernelQuirkCustomSmbiosGuid1, CacheType, Context, NULL);
OcKernelApplyQuirk (KernelQuirkCustomSmbiosGuid2, CacheType, Context, NULL);
}
if (Config->Kernel.Quirks.DummyPowerManagement) {
PatchDummyPowerManagement (Context);
OcKernelApplyQuirk (KernelQuirkDummyPowerManagement, CacheType, Context, NULL);
}
} else {
if (Config->Kernel.Quirks.AppleXcpmCfgLock) {
PatchAppleXcpmCfgLock (&Patcher);
OcKernelApplyQuirk (KernelQuirkAppleXcpmCfgLock, CacheType, NULL, &KernelPatcher);
}
if (Config->Kernel.Quirks.AppleXcpmExtraMsrs) {
PatchAppleXcpmExtraMsrs (&Patcher);
OcKernelApplyQuirk (KernelQuirkAppleXcpmExtraMsrs, CacheType, NULL, &KernelPatcher);
}
if (Config->Kernel.Quirks.AppleXcpmForceBoost) {
PatchAppleXcpmForceBoost (&Patcher);
OcKernelApplyQuirk (KernelQuirkAppleXcpmForceBoost, CacheType, NULL, &KernelPatcher);
}
if (Config->Kernel.Quirks.PanicNoKextDump) {
PatchPanicKextDump (&Patcher);
OcKernelApplyQuirk (KernelQuirkPanicNoKextDump, CacheType, NULL, &KernelPatcher);
}
if (Config->Kernel.Emulate.Cpuid1Data[0] != 0
@ -413,7 +442,7 @@ OcKernelApplyPatches (
|| Config->Kernel.Emulate.Cpuid1Data[2] != 0
|| Config->Kernel.Emulate.Cpuid1Data[3] != 0) {
PatchKernelCpuId (
&Patcher,
&KernelPatcher,
mOcCpuInfo,
Config->Kernel.Emulate.Cpuid1Data,
Config->Kernel.Emulate.Cpuid1Mask
@ -421,11 +450,11 @@ OcKernelApplyPatches (
}
if (Config->Kernel.Quirks.LapicKernelPanic) {
PatchLapicKernelPanic (&Patcher);
OcKernelApplyQuirk (KernelQuirkLapicKernelPanic, CacheType, NULL, &KernelPatcher);
}
if (Config->Kernel.Quirks.PowerTimeoutKernelPanic) {
PatchPowerStateTimeout (&Patcher);
OcKernelApplyQuirk (KernelQuirkPowerTimeoutKernelPanic, CacheType, NULL, &KernelPatcher);
}
}
}
@ -522,7 +551,7 @@ OcKernelProcessPrelinked (
Status = PrelinkedContextInit (&Context, Kernel, *KernelSize, AllocatedSize);
if (!EFI_ERROR (Status)) {
OcKernelApplyPatches (Config, DarwinVersion, &Context, NULL, 0);
OcKernelApplyPatches (Config, DarwinVersion, CacheTypePrelinked, &Context, NULL, 0);
OcKernelBlockKexts (Config, DarwinVersion, &Context);
@ -640,6 +669,8 @@ OcKernelProcessMkext (
return Status;
}
OcKernelApplyPatches (Config, DarwinVersion, CacheTypeMkext, &Context, NULL, 0);
for (Index = 0; Index < Config->Kernel.Add.Count; ++Index) {
Kext = Config->Kernel.Add.Values[Index];
@ -768,6 +799,11 @@ OcKernelInitCacheless (
}
}
//
// Process patches and blocks.
//
OcKernelApplyPatches (Config, DarwinVersion, CacheTypeCacheless, Context, NULL, 0);
return CachelessContextOverlayExtensionsDir (Context, File);
}
@ -884,7 +920,7 @@ OcKernelFileOpen (
if (!EFI_ERROR (Status)) {
mOcDarwinVersion = OcKernelReadDarwinVersion (Kernel, KernelSize);
OcKernelApplyPatches (mOcConfiguration, mOcDarwinVersion, NULL, Kernel, KernelSize);
OcKernelApplyPatches (mOcConfiguration, mOcDarwinVersion, 0, NULL, Kernel, KernelSize);
PrelinkedStatus = OcKernelProcessPrelinked (
mOcConfiguration,

View File

@ -12,15 +12,29 @@ OBJS = $(PROJECT).o \
KxldState.o \
PrelinkedKext.o \
PrelinkedContext.o \
MkextContext.o \
MkextReader.o \
Vtables.o \
Link.o \
KernelReader.o \
KernelCollection.o \
DataPatcher.o \
lzss.o \
lzvn.o
lzvn.o \
adler32.o \
compress.o \
crc32.o \
deflate.o \
infback.o \
inffast.o \
inflate.o \
inftrees.o \
trees.o \
uncompr.o \
zlib_uefi.o
VPATH = ../../Library/OcAppleKernelLib:$\
../../Library/OcMiscLib:$\
../../Library/OcCompressionLib/lzss:$\
../../Library/OcCompressionLib/lzvn
../../Library/OcCompressionLib/lzvn:$\
../../Library/OcCompressionLib/zlib
include ../../User/Makefile