mirror of
https://github.com/acidanthera/OpenCorePkg.git
synced 2025-12-08 19:25:01 +00:00
1998 lines
53 KiB
C
1998 lines
53 KiB
C
/** @file
|
|
Commonly used kext and kernel patches.
|
|
|
|
Copyright (c) 2018, vit9696. All rights reserved.<BR>
|
|
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.
|
|
|
|
**/
|
|
|
|
#include <Base.h>
|
|
|
|
#include <IndustryStandard/AppleIntelCpuInfo.h>
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/OcDebugLogLib.h>
|
|
#include <Library/OcAppleKernelLib.h>
|
|
#include <Library/PrintLib.h>
|
|
#include <Library/OcFileLib.h>
|
|
#include <Library/OcStringLib.h>
|
|
#include <Library/UefiLib.h>
|
|
|
|
STATIC CONST UINT8 mMovEcxE2[] = {
|
|
0xB9, 0xE2, 0x00, 0x00, 0x00 // mov ecx, 0E2h
|
|
};
|
|
|
|
STATIC CONST UINT8 mMovCxE2[] = {
|
|
0x66, 0xB9, 0xE2, 0x00 // mov cx, 0E2h
|
|
};
|
|
|
|
STATIC CONST UINT8 mWrmsr[] = {
|
|
0x0F, 0x30 // wrmsr
|
|
};
|
|
|
|
STATIC CONST UINTN mWrmsrMaxDistance = 32;
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
PatchAppleCpuPmCfgLock (
|
|
IN OUT PATCHER_CONTEXT *Patcher,
|
|
IN UINT32 KernelVersion
|
|
)
|
|
{
|
|
UINTN Count;
|
|
UINT8 *Walker;
|
|
UINT8 *WalkerEnd;
|
|
UINT8 *WalkerTmp;
|
|
|
|
if (Patcher == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
Count = 0;
|
|
Walker = (UINT8 *) MachoGetMachHeader (&Patcher->MachContext);
|
|
WalkerEnd = Walker + MachoGetFileSize (&Patcher->MachContext) - mWrmsrMaxDistance;
|
|
|
|
//
|
|
// Thx to Clover developers for the approach.
|
|
//
|
|
while (Walker < WalkerEnd) {
|
|
//
|
|
// Match (e)cx 0E2h assignment.
|
|
//
|
|
if (Walker[0] == mMovEcxE2[0]
|
|
&& Walker[1] == mMovEcxE2[1]
|
|
&& Walker[2] == mMovEcxE2[2]
|
|
&& Walker[3] == mMovEcxE2[3]
|
|
&& Walker[4] == mMovEcxE2[4]) {
|
|
STATIC_ASSERT (sizeof (mMovEcxE2) == 5, "Unsupported mMovEcxE2");
|
|
Walker += sizeof (mMovEcxE2);
|
|
} else if (Walker[0] == mMovCxE2[0]
|
|
&& Walker[1] == mMovCxE2[1]
|
|
&& Walker[2] == mMovCxE2[2]
|
|
&& Walker[3] == mMovCxE2[3]) {
|
|
STATIC_ASSERT (sizeof (mMovCxE2) == 4, "Unsupported mMovCxE2");
|
|
Walker += sizeof (mMovCxE2);
|
|
} else {
|
|
++Walker;
|
|
continue;
|
|
}
|
|
|
|
WalkerTmp = Walker + mWrmsrMaxDistance;
|
|
|
|
while (Walker < WalkerTmp) {
|
|
if (Walker[0] == mWrmsr[0]
|
|
&& Walker[1] == mWrmsr[1]) {
|
|
STATIC_ASSERT (sizeof (mWrmsr) == 2, "Unsupported mWrmsr");
|
|
++Count;
|
|
//
|
|
// Patch matched wrmsr with nop.
|
|
//
|
|
*Walker++ = 0x90;
|
|
*Walker++ = 0x90;
|
|
break;
|
|
}
|
|
|
|
if ((Walker[0] == 0xC9 && Walker[1] == 0xC3) ///< leave; ret
|
|
|| (Walker[0] == 0x5D && Walker[1] == 0xC3)) { ///< pop rbp; ret
|
|
//
|
|
// Stop searching upon matching return sequences.
|
|
//
|
|
Walker += 2;
|
|
break;
|
|
}
|
|
|
|
if ((Walker[0] == 0xB9 && Walker[3] == 0 && Walker[4] == 0) ///< mov ecx, 00000xxxxh
|
|
|| (Walker[0] == 0x66 && Walker[1] == 0xB9 && Walker[3] == 0)) { ///< mov cx, 00xxh
|
|
//
|
|
// Stop searching upon matching reassign sequences.
|
|
//
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Continue searching.
|
|
//
|
|
++Walker;
|
|
}
|
|
}
|
|
|
|
//
|
|
// At least one patch must be successful for this to work.
|
|
//
|
|
return Count > 0 ? EFI_SUCCESS : EFI_NOT_FOUND;
|
|
}
|
|
|
|
#pragma pack(push, 1)
|
|
|
|
//
|
|
// XCPM record definition, extracted from XNU debug kernel.
|
|
//
|
|
typedef struct XCPM_MSR_RECORD_ {
|
|
UINT32 xcpm_msr_num;
|
|
UINT32 xcpm_msr_applicable_cpus;
|
|
UINT32 *xcpm_msr_flag_p;
|
|
UINT64 xcpm_msr_bits_clear;
|
|
UINT64 xcpm_msr_bits_set;
|
|
UINT64 xcpm_msr_initial_value;
|
|
UINT64 xcpm_msr_rb_value;
|
|
} XCPM_MSR_RECORD;
|
|
|
|
#pragma pack(pop)
|
|
|
|
STATIC
|
|
UINT8
|
|
mXcpmCfgLockRelFind[] = {
|
|
0xB9, 0xE2, 0x00, 0x00, 0x00, 0x0F, 0x30 // mov ecx, 0xE2 ; wrmsr
|
|
};
|
|
|
|
STATIC
|
|
UINT8
|
|
mXcpmCfgLockRelReplace[] = {
|
|
0xB9, 0xE2, 0x00, 0x00, 0x00, 0x90, 0x90 // mov ecx, 0xE2 ; nop
|
|
};
|
|
|
|
STATIC
|
|
PATCHER_GENERIC_PATCH
|
|
mXcpmCfgLockRelPatch = {
|
|
.Comment = DEBUG_POINTER ("XcpmCfgLockRel"),
|
|
.Base = "_xcpm_idle",
|
|
.Find = mXcpmCfgLockRelFind,
|
|
.Mask = NULL,
|
|
.Replace = mXcpmCfgLockRelReplace,
|
|
.ReplaceMask = NULL,
|
|
.Size = sizeof (mXcpmCfgLockRelFind),
|
|
.Count = 2,
|
|
.Skip = 0,
|
|
.Limit = 4096
|
|
};
|
|
|
|
STATIC
|
|
UINT8
|
|
mXcpmCfgLockDbgFind[] = {
|
|
0xBF, 0xE2, 0x00, 0x00, 0x00, 0xE8 // mov edi, 0xE2 ; call (wrmsr64)
|
|
};
|
|
|
|
STATIC
|
|
UINT8
|
|
mXcpmCfgLockDbgReplace[] = {
|
|
0xEB, 0x08, 0x90, 0x90, 0x90, 0xE8 // jmp LBL ; nop; nop; nop; call (wrmsr64); LBL:
|
|
};
|
|
|
|
STATIC
|
|
PATCHER_GENERIC_PATCH
|
|
mXcpmCfgLockDbgPatch = {
|
|
.Comment = DEBUG_POINTER ("XcpmCfgLockDbg"),
|
|
.Base = "_xcpm_cst_control_evaluate",
|
|
.Find = mXcpmCfgLockDbgFind,
|
|
.Mask = NULL,
|
|
.Replace = mXcpmCfgLockDbgReplace,
|
|
.ReplaceMask = NULL,
|
|
.Size = sizeof (mXcpmCfgLockDbgFind),
|
|
.Count = 2,
|
|
.Skip = 0,
|
|
.Limit = 4096
|
|
};
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
PatchAppleXcpmCfgLock (
|
|
IN OUT PATCHER_CONTEXT *Patcher,
|
|
IN UINT32 KernelVersion
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
XCPM_MSR_RECORD *Record;
|
|
XCPM_MSR_RECORD *Last;
|
|
|
|
UINT32 Replacements;
|
|
|
|
ASSERT (Patcher != NULL);
|
|
|
|
if (!OcMatchDarwinVersion (KernelVersion, KERNEL_VERSION_MOUNTAIN_LION_MIN, 0)) {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Skipping XcpmCfgLock on %u\n", KernelVersion));
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
Last = (XCPM_MSR_RECORD *) ((UINT8 *) MachoGetMachHeader (&Patcher->MachContext)
|
|
+ MachoGetFileSize (&Patcher->MachContext) - sizeof (XCPM_MSR_RECORD));
|
|
|
|
Replacements = 0;
|
|
|
|
Status = PatcherGetSymbolAddress (Patcher, "_xcpm_core_scope_msrs", (UINT8 **) &Record);
|
|
if (!EFI_ERROR (Status)) {
|
|
while (Record < Last) {
|
|
if (Record->xcpm_msr_num == 0xE2) {
|
|
DEBUG ((
|
|
DEBUG_INFO,
|
|
"OCAK: Replacing _xcpm_core_scope_msrs data %u %u\n",
|
|
Record->xcpm_msr_num,
|
|
Record->xcpm_msr_applicable_cpus
|
|
));
|
|
Record->xcpm_msr_applicable_cpus = 0;
|
|
++Replacements;
|
|
} else {
|
|
DEBUG ((
|
|
DEBUG_INFO,
|
|
"OCAK: Not matching _xcpm_core_scope_msrs data %u %u\n",
|
|
Record->xcpm_msr_num,
|
|
Record->xcpm_msr_applicable_cpus
|
|
));
|
|
break;
|
|
}
|
|
++Record;
|
|
}
|
|
|
|
//
|
|
// Now the HWP patch at _xcpm_idle() for Release XNU.
|
|
//
|
|
Status = PatcherApplyGenericPatch (
|
|
Patcher,
|
|
&mXcpmCfgLockRelPatch
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Failed to locate _xcpm_idle release patch - %r, trying dbg\n", Status));
|
|
Status = PatcherApplyGenericPatch (
|
|
Patcher,
|
|
&mXcpmCfgLockDbgPatch
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_WARN, "OCAK: Failed to locate _xcpm_idle patches - %r\n", Status));
|
|
}
|
|
}
|
|
} else {
|
|
DEBUG ((DEBUG_WARN, "OCAK: Failed to locate _xcpm_core_scope_msrs - %r\n", Status));
|
|
}
|
|
|
|
return Replacements > 0 ? EFI_SUCCESS : EFI_NOT_FOUND;
|
|
}
|
|
|
|
STATIC
|
|
UINT8
|
|
mMiscPwrMgmtRelFind[] = {
|
|
0xB9, 0xAA, 0x01, 0x00, 0x00, 0x0F, 0x30 // mov ecx, 0x1aa; wrmsr
|
|
};
|
|
|
|
STATIC
|
|
UINT8
|
|
mMiscPwrMgmtRelReplace[] = {
|
|
0xB9, 0xAA, 0x01, 0x00, 0x00, 0x90, 0x90 // mov ecx, 0x1aa; nop
|
|
};
|
|
|
|
STATIC
|
|
PATCHER_GENERIC_PATCH
|
|
mMiscPwrMgmtRelPatch = {
|
|
.Comment = DEBUG_POINTER ("MiscPwrMgmtRel"),
|
|
.Base = NULL,
|
|
.Find = mMiscPwrMgmtRelFind,
|
|
.Mask = NULL,
|
|
.Replace = mMiscPwrMgmtRelReplace,
|
|
.ReplaceMask = NULL,
|
|
.Size = sizeof (mMiscPwrMgmtRelFind),
|
|
.Count = 0,
|
|
.Skip = 0,
|
|
.Limit = 0
|
|
};
|
|
|
|
STATIC
|
|
UINT8
|
|
mMiscPwrMgmtDbgFind[] = {
|
|
0xBF, 0xAA, 0x01, 0x00, 0x00, 0xE8 // mov edi, 0x1AA ; call (wrmsr64)
|
|
};
|
|
|
|
STATIC
|
|
UINT8
|
|
mMiscPwrMgmtDbgReplace[] = {
|
|
0xEB, 0x08, 0x90, 0x90, 0x90, 0xE8 // jmp LBL ; nop; nop; nop; call (wrmsr64); LBL:
|
|
};
|
|
|
|
STATIC
|
|
PATCHER_GENERIC_PATCH
|
|
mMiscPwrMgmtDbgPatch = {
|
|
//
|
|
// NOTE: This substitution is going to take place
|
|
// at both _xcpm_hwp_enable()
|
|
// and _xcpm_enable_hw_coordination() (which is inlined in Release XNU).
|
|
//
|
|
.Comment = DEBUG_POINTER ("MiscPwrMgmtDbg"),
|
|
.Base = NULL,
|
|
.Find = mMiscPwrMgmtDbgFind,
|
|
.Mask = NULL,
|
|
.Replace = mMiscPwrMgmtDbgReplace,
|
|
.ReplaceMask = NULL,
|
|
.Size = sizeof (mMiscPwrMgmtDbgFind),
|
|
.Count = 0,
|
|
.Skip = 0,
|
|
.Limit = 0
|
|
};
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
PatchAppleXcpmExtraMsrs (
|
|
IN OUT PATCHER_CONTEXT *Patcher,
|
|
IN UINT32 KernelVersion
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
XCPM_MSR_RECORD *Record;
|
|
XCPM_MSR_RECORD *Last;
|
|
UINT32 Replacements;
|
|
|
|
ASSERT (Patcher != NULL);
|
|
|
|
if (!OcMatchDarwinVersion (KernelVersion, KERNEL_VERSION_MOUNTAIN_LION_MIN, 0)) {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Skipping XcpmExtraMsrs on %u\n", KernelVersion));
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
Last = (XCPM_MSR_RECORD *) ((UINT8 *) MachoGetMachHeader (&Patcher->MachContext)
|
|
+ MachoGetFileSize (&Patcher->MachContext) - sizeof (XCPM_MSR_RECORD));
|
|
|
|
Replacements = 0;
|
|
|
|
Status = PatcherGetSymbolAddress (Patcher, "_xcpm_pkg_scope_msrs", (UINT8 **) &Record);
|
|
if (!EFI_ERROR (Status)) {
|
|
while (Record < Last) {
|
|
//
|
|
// Most Record->xcpm_msr_applicable_cpus has
|
|
// 0xDC or 0xDE in its lower 16-bit and thus here we
|
|
// AND 0xFF0000FDU in order to match both. (The result will be 0xDC)
|
|
//
|
|
if ((Record->xcpm_msr_applicable_cpus & 0xFF0000FDU) == 0xDC) {
|
|
DEBUG ((
|
|
DEBUG_INFO,
|
|
"OCAK: Replacing _xcpm_pkg_scope_msrs data %u %u\n",
|
|
Record->xcpm_msr_num,
|
|
Record->xcpm_msr_applicable_cpus
|
|
));
|
|
Record->xcpm_msr_applicable_cpus = 0;
|
|
++Replacements;
|
|
} else {
|
|
DEBUG ((
|
|
DEBUG_INFO,
|
|
"OCAK: Not matching _xcpm_pkg_scope_msrs data %u %u\n",
|
|
Record->xcpm_msr_num,
|
|
Record->xcpm_msr_applicable_cpus
|
|
));
|
|
break;
|
|
}
|
|
++Record;
|
|
}
|
|
} else {
|
|
DEBUG ((DEBUG_WARN, "OCAK: Failed to locate _xcpm_pkg_scope_msrs - %r\n", Status));
|
|
}
|
|
|
|
Status = PatcherGetSymbolAddress (Patcher, "_xcpm_SMT_scope_msrs", (UINT8 **) &Record);
|
|
if (!EFI_ERROR (Status)) {
|
|
while (Record < Last) {
|
|
if (Record->xcpm_msr_flag_p == NULL) {
|
|
DEBUG ((
|
|
DEBUG_INFO,
|
|
"OCAK: Replacing _xcpm_SMT_scope_msrs data %u %u\n",
|
|
Record->xcpm_msr_num,
|
|
Record->xcpm_msr_applicable_cpus
|
|
));
|
|
Record->xcpm_msr_applicable_cpus = 0;
|
|
++Replacements;
|
|
} else {
|
|
DEBUG ((
|
|
DEBUG_INFO,
|
|
"OCAK: Not matching _xcpm_SMT_scope_msrs data %u %u %p\n",
|
|
Record->xcpm_msr_num,
|
|
Record->xcpm_msr_applicable_cpus,
|
|
Record->xcpm_msr_flag_p
|
|
));
|
|
break;
|
|
}
|
|
++Record;
|
|
}
|
|
} else {
|
|
DEBUG ((DEBUG_WARN, "OCAK: Failed to locate _xcpm_SMT_scope_msrs - %r\n", Status));
|
|
}
|
|
|
|
//
|
|
// Now patch writes to MSR_MISC_PWR_MGMT
|
|
//
|
|
Status = PatcherApplyGenericPatch (Patcher, &mMiscPwrMgmtRelPatch);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Failed to patch writes to MSR_MISC_PWR_MGMT - %r, trying dbg\n", Status));
|
|
Status = PatcherApplyGenericPatch (Patcher, &mMiscPwrMgmtDbgPatch);
|
|
}
|
|
|
|
if (!EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Patched writes to MSR_MISC_PWR_MGMT\n"));
|
|
++Replacements;
|
|
} else {
|
|
DEBUG ((DEBUG_WARN, "OCAK: Failed to patch writes to MSR_MISC_PWR_MGMT - %r\n", Status));
|
|
}
|
|
|
|
return Replacements > 0 ? EFI_SUCCESS : EFI_NOT_FOUND;
|
|
}
|
|
|
|
STATIC
|
|
UINT8
|
|
mPerfCtrlFind1[] = {
|
|
0xB9, 0x99, 0x01, 0x00, 0x00, ///< mov ecx, 199h
|
|
0x0F, 0x30 ///< wrmsr
|
|
};
|
|
|
|
STATIC
|
|
UINT8
|
|
mPerfCtrlFind2[] = {
|
|
0xB9, 0x99, 0x01, 0x00, 0x00, ///< mov ecx, 199h
|
|
0x31, 0xD2, ///< xor edx, edx
|
|
0x0F, 0x30 ///< wrmsr
|
|
};
|
|
|
|
STATIC
|
|
UINT8
|
|
mPerfCtrlMax[] = {
|
|
0xB9, 0x99, 0x01, 0x00, 0x00, ///< mov ecx, 199h
|
|
0x31, 0xD2, ///< xor edx, edx
|
|
0xB8, 0x00, 0xFF, 0x00, 0x00, ///< mov eax, 0xFF00
|
|
0x0F, 0x30, ///< wrmsr
|
|
0xC3 ///< ret
|
|
};
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
PatchAppleXcpmForceBoost (
|
|
IN OUT PATCHER_CONTEXT *Patcher,
|
|
IN UINT32 KernelVersion
|
|
)
|
|
{
|
|
UINT8 *Start;
|
|
UINT8 *Last;
|
|
UINT8 *Current;
|
|
|
|
ASSERT (Patcher != NULL);
|
|
|
|
if (!OcMatchDarwinVersion (KernelVersion, KERNEL_VERSION_MOUNTAIN_LION_MIN, 0)) {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Skipping XcpmForceBoost on %u\n", KernelVersion));
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
Start = (UINT8 *) MachoGetMachHeader (&Patcher->MachContext);
|
|
Last = Start + MachoGetFileSize (&Patcher->MachContext) - EFI_PAGE_SIZE*2;
|
|
Start += EFI_PAGE_SIZE;
|
|
Current = Start;
|
|
|
|
while (Current < Last) {
|
|
if (Current[0] == mPerfCtrlFind1[0]
|
|
&& Current[1] == mPerfCtrlFind1[1]
|
|
&& Current[2] == mPerfCtrlFind1[2]
|
|
&& Current[3] == mPerfCtrlFind1[3]) {
|
|
if (CompareMem (&Current[4], &mPerfCtrlFind1[4], sizeof (mPerfCtrlFind1) - 4) == 0
|
|
|| CompareMem (&Current[4], &mPerfCtrlFind2[4], sizeof (mPerfCtrlFind2) - 4) == 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
++Current;
|
|
}
|
|
|
|
if (Current == Last) {
|
|
DEBUG ((DEBUG_WARN, "OCAK: Failed to locate MSR_IA32_PERF_CONTROL write\n"));
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
Start = Current - EFI_PAGE_SIZE;
|
|
Current -= 4;
|
|
|
|
while (Current >= Start) {
|
|
if (Current[0] == 0x55
|
|
&& Current[1] == 0x48
|
|
&& Current[2] == 0x89
|
|
&& Current[3] == 0xE5) {
|
|
break;
|
|
}
|
|
|
|
--Current;
|
|
}
|
|
|
|
if (Current < Start) {
|
|
DEBUG ((DEBUG_WARN, "OCAK: Failed to locate MSR_IA32_PERF_CONTROL prologue\n"));
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO, "OCAK: Patch write max to MSR_IA32_PERF_CONTROL\n"));
|
|
CopyMem (Current, mPerfCtrlMax, sizeof (mPerfCtrlMax));
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
STATIC
|
|
UINT8
|
|
mRemoveUsbLimitV1Find[] = {
|
|
0xff, 0xff, 0x10
|
|
};
|
|
|
|
STATIC
|
|
UINT8
|
|
mRemoveUsbLimitV1Replace[] = {
|
|
0xff, 0xff, 0x40
|
|
};
|
|
|
|
STATIC
|
|
PATCHER_GENERIC_PATCH
|
|
mRemoveUsbLimitV1Patch = {
|
|
.Comment = DEBUG_POINTER ("RemoveUsbLimitV1"),
|
|
.Base = "__ZN15AppleUSBXHCIPCI11createPortsEv",
|
|
.Find = mRemoveUsbLimitV1Find,
|
|
.Mask = NULL,
|
|
.Replace = mRemoveUsbLimitV1Replace,
|
|
.ReplaceMask = NULL,
|
|
.Size = sizeof (mRemoveUsbLimitV1Replace),
|
|
.Count = 1,
|
|
.Skip = 0,
|
|
.Limit = 8192
|
|
};
|
|
|
|
STATIC
|
|
UINT8
|
|
mRemoveUsbLimitV2Find[] = {
|
|
0x0f, 0x0f, 0x83
|
|
};
|
|
|
|
STATIC
|
|
UINT8
|
|
mRemoveUsbLimitV2Replace[] = {
|
|
0x40, 0x0f, 0x83
|
|
};
|
|
|
|
STATIC
|
|
PATCHER_GENERIC_PATCH
|
|
mRemoveUsbLimitV2Patch = {
|
|
.Comment = DEBUG_POINTER ("RemoveUsbLimitV2"),
|
|
.Base = "__ZN12AppleUSBXHCI11createPortsEv",
|
|
.Find = mRemoveUsbLimitV2Find,
|
|
.Mask = NULL,
|
|
.Replace = mRemoveUsbLimitV2Replace,
|
|
.ReplaceMask = NULL,
|
|
.Size = sizeof (mRemoveUsbLimitV2Replace),
|
|
.Count = 1,
|
|
.Skip = 0,
|
|
.Limit = 4096
|
|
};
|
|
|
|
STATIC
|
|
UINT8
|
|
mRemoveUsbLimitIoP1Find[] = {
|
|
0x0f, 0x0f, 0x87
|
|
};
|
|
|
|
STATIC
|
|
UINT8
|
|
mRemoveUsbLimitIoP1Replace[] = {
|
|
0x40, 0x0f, 0x87
|
|
};
|
|
|
|
STATIC
|
|
PATCHER_GENERIC_PATCH
|
|
mRemoveUsbLimitIoP1Patch = {
|
|
.Comment = DEBUG_POINTER ("RemoveUsbLimitIoP1"),
|
|
.Base = "__ZN16AppleUSBHostPort15setPortLocationEj",
|
|
.Find = mRemoveUsbLimitIoP1Find,
|
|
.Mask = NULL,
|
|
.Replace = mRemoveUsbLimitIoP1Replace,
|
|
.ReplaceMask = NULL,
|
|
.Size = sizeof (mRemoveUsbLimitIoP1Replace),
|
|
.Count = 1,
|
|
.Skip = 0,
|
|
.Limit = 4096
|
|
};
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
PatchUsbXhciPortLimit1 (
|
|
IN OUT PATCHER_CONTEXT *Patcher,
|
|
IN UINT32 KernelVersion
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
//
|
|
// On 10.14.4 and newer IOUSBHostFamily also needs limit removal.
|
|
// Thanks to ydeng discovering this.
|
|
//
|
|
if (!OcMatchDarwinVersion (KernelVersion, KERNEL_VERSION(18, 5, 0), 0)) {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Skipping port patch IOUSBHostFamily on %u\n", KernelVersion));
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
if (Patcher == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
Status = PatcherApplyGenericPatch (Patcher, &mRemoveUsbLimitIoP1Patch);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Failed to apply port patch com.apple.iokit.IOUSBHostFamily - %r\n", Status));
|
|
} else {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Patch success port com.apple.iokit.IOUSBHostFamily\n"));
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
PatchUsbXhciPortLimit2 (
|
|
IN OUT PATCHER_CONTEXT *Patcher,
|
|
IN UINT32 KernelVersion
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
if (!OcMatchDarwinVersion (KernelVersion, KERNEL_VERSION_HIGH_SIERRA_MIN, 0)) {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Skipping modern port patch AppleUSBXHCI on %u\n", KernelVersion));
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
if (Patcher == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
//
|
|
// TODO: Implement some locationID hack in IOUSBHostFamily.
|
|
// The location ID is a 32 bit number which is unique among all USB devices in the system,
|
|
// and which will not change on a system reboot unless the topology of the bus itself changes.
|
|
// See AppleUSBHostPort::setPortLocation():
|
|
// locationId = getLocationId();
|
|
// if (!(locationId & 0xF)) {
|
|
// int32_t shift = 20;
|
|
// while (locationId & (0xF << shift)) {
|
|
// shift -= 4;
|
|
// if (Shift < 0) { setLocationId(locationId); return; }
|
|
// }
|
|
// setLocationId(locationId | ((portNumber & 0xF) << shift));
|
|
// }
|
|
// The value (e.g. 0x14320000) is represented as follows: 0xAABCDEFG
|
|
// AA — Ctrl number 8 bits (e.g. 0x14, aka XHCI)
|
|
// B - Port number 4 bits (e.g. 0x3, aka SS03)
|
|
// C~F - Bus number 4 bits (e.g. 0x2, aka IOUSBHostHIDDevice)
|
|
//
|
|
// C~F are filled as many times as many USB Hubs are there on the port.
|
|
//
|
|
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"));
|
|
} else {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Failed to apply patch com.apple.driver.usb.AppleUSBXHCI - %r\n", Status));
|
|
}
|
|
|
|
//
|
|
// TODO: Check when the patch changed actually.
|
|
//
|
|
if (EFI_ERROR (Status)
|
|
&& OcMatchDarwinVersion (KernelVersion, KERNEL_VERSION_HIGH_SIERRA_MIN, KERNEL_VERSION_HIGH_SIERRA_MAX)) {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Assuming success for AppleUSBXHCI on %u\n", KernelVersion));
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
PatchUsbXhciPortLimit3 (
|
|
IN OUT PATCHER_CONTEXT *Patcher,
|
|
IN UINT32 KernelVersion
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
if (!OcMatchDarwinVersion (KernelVersion, KERNEL_VERSION_EL_CAPITAN_MIN, KERNEL_VERSION_HIGH_SIERRA_MAX)) {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Skipping legacy port patch AppleUSBXHCIPCI on %u\n", KernelVersion));
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
if (Patcher == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
//
|
|
// If we are here, we are on legacy 10.13 or below, try the oldest patch.
|
|
//
|
|
Status = PatcherApplyGenericPatch (Patcher, &mRemoveUsbLimitV1Patch);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Failed to apply legacy port patch AppleUSBXHCIPCI - %r\n", Status));
|
|
} else {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Patch success apply legacy port AppleUSBXHCIPCI\n"));
|
|
}
|
|
|
|
//
|
|
// TODO: Check when the patch changed actually.
|
|
//
|
|
if (EFI_ERROR (Status)
|
|
&& OcMatchDarwinVersion (KernelVersion, KERNEL_VERSION_HIGH_SIERRA_MIN, KERNEL_VERSION_HIGH_SIERRA_MAX)) {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Assuming success for legacy port AppleUSBXHCIPCI on %u\n", KernelVersion));
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
STATIC
|
|
UINT8
|
|
mIOAHCIBlockStoragePatchV1Find[] = {
|
|
0x41, 0x50, 0x50, 0x4C, 0x45, 0x20, 0x53, 0x53, 0x44, 0x00
|
|
};
|
|
|
|
STATIC
|
|
UINT8
|
|
mIOAHCIBlockStoragePatchV1Replace[] = {
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
|
};
|
|
|
|
STATIC
|
|
PATCHER_GENERIC_PATCH
|
|
mIOAHCIBlockStoragePatchV1 = {
|
|
.Comment = DEBUG_POINTER ("IOAHCIBlockStorageV1"),
|
|
.Base = NULL,
|
|
.Find = mIOAHCIBlockStoragePatchV1Find,
|
|
.Mask = NULL,
|
|
.Replace = mIOAHCIBlockStoragePatchV1Replace,
|
|
.ReplaceMask = NULL,
|
|
.Size = sizeof (mIOAHCIBlockStoragePatchV1Find),
|
|
.Count = 1,
|
|
.Skip = 0
|
|
};
|
|
|
|
STATIC
|
|
UINT8
|
|
mIOAHCIBlockStoragePatchV2Find[] = {
|
|
0x41, 0x50, 0x50, 0x4C, 0x45, 0x00
|
|
};
|
|
|
|
STATIC
|
|
UINT8
|
|
mIOAHCIBlockStoragePatchV2Replace[] = {
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
|
};
|
|
|
|
STATIC
|
|
PATCHER_GENERIC_PATCH
|
|
mIOAHCIBlockStoragePatchV2 = {
|
|
.Comment = DEBUG_POINTER ("IOAHCIBlockStorageV2"),
|
|
.Base = NULL,
|
|
.Find = mIOAHCIBlockStoragePatchV2Find,
|
|
.Mask = NULL,
|
|
.Replace = mIOAHCIBlockStoragePatchV2Replace,
|
|
.ReplaceMask = NULL,
|
|
.Size = sizeof (mIOAHCIBlockStoragePatchV2Find),
|
|
.Count = 1,
|
|
.Skip = 0
|
|
};
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
PatchThirdPartyDriveSupport (
|
|
IN OUT PATCHER_CONTEXT *Patcher,
|
|
IN UINT32 KernelVersion
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
if (Patcher == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
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"));
|
|
}
|
|
|
|
if (OcMatchDarwinVersion (KernelVersion, KERNEL_VERSION_CATALINA_MIN, 0)) {
|
|
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: Skipping IOAHCIBlockStorage V2 on %u\n", KernelVersion));
|
|
}
|
|
|
|
//
|
|
// This started to be required on 10.6.7 or so.
|
|
// We cannot trust which minor SnowLeo version is this, just let it pass.
|
|
//
|
|
if (EFI_ERROR (Status)
|
|
&& OcMatchDarwinVersion (KernelVersion, KERNEL_VERSION_SNOW_LEOPARD_MIN, KERNEL_VERSION_SNOW_LEOPARD_MAX)) {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Assuming success for IOAHCIBlockStorage on %u\n", KernelVersion));
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
STATIC
|
|
UINT8
|
|
mIOAHCIPortPatchFind[] = {
|
|
0x45, 0x78, 0x74, 0x65, 0x72, 0x6E, 0x61, 0x6C
|
|
};
|
|
|
|
STATIC
|
|
UINT8
|
|
mIOAHCIPortPatchReplace[] = {
|
|
0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x61, 0x6C
|
|
};
|
|
|
|
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
|
|
};
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
PatchForceInternalDiskIcons (
|
|
IN OUT PATCHER_CONTEXT *Patcher,
|
|
IN UINT32 KernelVersion
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
if (Patcher == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
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"));
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
STATIC
|
|
UINT8
|
|
mAppleIoMapperPatchFind[] = {
|
|
0x44, 0x4D, 0x41, 0x52, 0x00 // DMAR\0
|
|
};
|
|
|
|
STATIC
|
|
UINT8
|
|
mAppleIoMapperPatchReplace[] = {
|
|
0x52, 0x41, 0x4D, 0x44, 0x00 // RAMD\0
|
|
};
|
|
|
|
STATIC
|
|
PATCHER_GENERIC_PATCH
|
|
mAppleIoMapperPatch = {
|
|
.Comment = DEBUG_POINTER ("AppleIoMapper"),
|
|
.Base = NULL,
|
|
.Find = mAppleIoMapperPatchFind,
|
|
.Mask = NULL,
|
|
.Replace = mAppleIoMapperPatchReplace,
|
|
.ReplaceMask = NULL,
|
|
.Size = sizeof (mAppleIoMapperPatchFind),
|
|
.Count = 1,
|
|
.Skip = 0
|
|
};
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
PatchAppleIoMapperSupport (
|
|
IN OUT PATCHER_CONTEXT *Patcher,
|
|
IN UINT32 KernelVersion
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
if (Patcher == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
if (!OcMatchDarwinVersion (KernelVersion, KERNEL_VERSION_MOUNTAIN_LION_MIN, 0)) {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Skipping AppleIoMapper patch on %u\n", KernelVersion));
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
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"));
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
STATIC
|
|
UINT8
|
|
mAppleDummyCpuPmPatchReplace[] = {
|
|
0xB8, 0x01, 0x00, 0x00, 0x00, 0xC3 // mov eax, 1 ; ret
|
|
};
|
|
|
|
STATIC
|
|
PATCHER_GENERIC_PATCH
|
|
mAppleDummyCpuPmPatch = {
|
|
.Comment = DEBUG_POINTER ("DummyCpuPm"),
|
|
.Base = "__ZN28AppleIntelCPUPowerManagement5startEP9IOService",
|
|
.Find = NULL,
|
|
.Mask = NULL,
|
|
.Replace = mAppleDummyCpuPmPatchReplace,
|
|
.ReplaceMask = NULL,
|
|
.Size = sizeof (mAppleDummyCpuPmPatchReplace),
|
|
.Count = 1,
|
|
.Skip = 0
|
|
};
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
PatchDummyPowerManagement (
|
|
IN OUT PATCHER_CONTEXT *Patcher,
|
|
IN UINT32 KernelVersion
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
if (Patcher == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
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"));
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
STATIC
|
|
UINT8
|
|
mIncreasePciBarSizePatchFind[] = {
|
|
0x00, 0x00, 0x00, 0x40
|
|
};
|
|
|
|
STATIC
|
|
UINT8
|
|
mIncreasePciBarSizePatchReplace[] = {
|
|
0x00, 0x00, 0x00, 0x80
|
|
};
|
|
|
|
STATIC
|
|
PATCHER_GENERIC_PATCH
|
|
mIncreasePciBarSizePatch = {
|
|
.Comment = DEBUG_POINTER ("IncreasePciBarSize"),
|
|
.Base = "__ZN17IOPCIConfigurator24probeBaseAddressRegisterEP16IOPCIConfigEntryjj",
|
|
.Find = mIncreasePciBarSizePatchFind,
|
|
.Mask = NULL,
|
|
.Replace = mIncreasePciBarSizePatchReplace,
|
|
.ReplaceMask = NULL,
|
|
.Size = sizeof (mIncreasePciBarSizePatchFind),
|
|
.Count = 1,
|
|
.Skip = 0,
|
|
.Limit = EFI_PAGE_SIZE
|
|
};
|
|
|
|
STATIC
|
|
UINT8
|
|
mIncreasePciBarSizePatchLegacyFind[] = {
|
|
0x01, 0x00, 0x00, 0x40
|
|
};
|
|
|
|
STATIC
|
|
UINT8
|
|
mIncreasePciBarSizePatchLegacyReplace[] = {
|
|
0x01, 0x00, 0x00, 0x80
|
|
};
|
|
|
|
STATIC
|
|
PATCHER_GENERIC_PATCH
|
|
mIncreasePciBarSizeLegacyPatch = {
|
|
.Comment = DEBUG_POINTER ("IncreasePciBarSizeLegacy"),
|
|
.Base = "__ZN17IOPCIConfigurator24probeBaseAddressRegisterEP16IOPCIConfigEntryjj",
|
|
.Find = mIncreasePciBarSizePatchLegacyFind,
|
|
.Mask = NULL,
|
|
.Replace = mIncreasePciBarSizePatchLegacyReplace,
|
|
.ReplaceMask = NULL,
|
|
.Size = sizeof (mIncreasePciBarSizePatchLegacyFind),
|
|
.Count = 1,
|
|
.Skip = 0,
|
|
.Limit = EFI_PAGE_SIZE
|
|
};
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
PatchIncreasePciBarSize (
|
|
IN OUT PATCHER_CONTEXT *Patcher,
|
|
IN UINT32 KernelVersion
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
if (Patcher == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
if (!OcMatchDarwinVersion (KernelVersion, KERNEL_VERSION_YOSEMITE_MIN, 0)) {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Skipping com.apple.iokit.IOPCIFamily IncreasePciBarSize on %u\n", KernelVersion));
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
Status = PatcherApplyGenericPatch (Patcher, &mIncreasePciBarSizePatch);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Failed to apply patch com.apple.iokit.IOPCIFamily IncreasePciBarSize - %r\n", Status));
|
|
Status = PatcherApplyGenericPatch (Patcher, &mIncreasePciBarSizeLegacyPatch);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Failed to apply legacy patch com.apple.iokit.IOPCIFamily IncreasePciBarSize - %r\n", Status));
|
|
} else {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Patch success legacy com.apple.iokit.IOPCIFamily IncreasePciBarSize\n"));
|
|
}
|
|
} else {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Patch success com.apple.iokit.IOPCIFamily IncreasePciBarSize\n"));
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
STATIC
|
|
CONST UINT8
|
|
mCustomSmbiosGuidPatchFind[] = {
|
|
0x45, 0x42, 0x39, 0x44, 0x32, 0x44, 0x33, 0x31
|
|
};
|
|
|
|
STATIC
|
|
CONST UINT8
|
|
mCustomSmbiosGuidPatchReplace[] = {
|
|
0x45, 0x42, 0x39, 0x44, 0x32, 0x44, 0x33, 0x35
|
|
};
|
|
|
|
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
|
|
};
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
PatchCustomSmbiosGuid (
|
|
IN OUT PATCHER_CONTEXT *Patcher,
|
|
IN UINT32 KernelVersion
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
if (Patcher == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
STATIC
|
|
CONST UINT8
|
|
mPanicKextDumpPatchFind[] = {
|
|
0x00, 0x25, 0x2E, 0x2A, 0x73, 0x00 ///< \0%.*s\0
|
|
};
|
|
|
|
STATIC
|
|
CONST UINT8
|
|
mPanicKextDumpPatchReplace[] = {
|
|
0x00, 0x00, 0x2E, 0x2A, 0x73, 0x00
|
|
};
|
|
|
|
STATIC
|
|
PATCHER_GENERIC_PATCH
|
|
mPanicKextDumpPatch = {
|
|
.Comment = DEBUG_POINTER ("PanicKextDump"),
|
|
.Base = NULL,
|
|
.Find = mPanicKextDumpPatchFind,
|
|
.Mask = NULL,
|
|
.Replace = mPanicKextDumpPatchReplace,
|
|
.ReplaceMask = NULL,
|
|
.Size = sizeof (mPanicKextDumpPatchFind),
|
|
.Count = 1,
|
|
.Skip = 0
|
|
};
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
PatchPanicKextDump (
|
|
IN OUT PATCHER_CONTEXT *Patcher,
|
|
IN UINT32 KernelVersion
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT8 *Record;
|
|
UINT8 *Last;
|
|
|
|
ASSERT (Patcher != NULL);
|
|
|
|
if (!OcMatchDarwinVersion (KernelVersion, KERNEL_VERSION_HIGH_SIERRA_MIN, 0)) {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Skipping PanicKextDump on %u\n", KernelVersion));
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
Last = ((UINT8 *) MachoGetMachHeader (&Patcher->MachContext)
|
|
+ MachoGetFileSize (&Patcher->MachContext) - EFI_PAGE_SIZE);
|
|
|
|
//
|
|
// This should work on 10.15 and all debug kernels.
|
|
//
|
|
Status = PatcherGetSymbolAddress (
|
|
Patcher,
|
|
"__ZN6OSKext19printKextPanicListsEPFiPKczE",
|
|
(UINT8 **) &Record
|
|
);
|
|
if (EFI_ERROR (Status) || Record >= Last) {
|
|
DEBUG ((DEBUG_WARN, "OCAK: Failed to locate printKextPanicLists (%p) - %r\n", Record, Status));
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
*Record = 0xC3;
|
|
|
|
//
|
|
// This one is for 10.13~10.14 release kernels, which do dumping inline.
|
|
// A bit risky, but let's hope it works well.
|
|
//
|
|
Status = PatcherApplyGenericPatch (Patcher, &mPanicKextDumpPatch);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Failed to apply kext dump patch - %r\n", Status));
|
|
} else {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Patch success kext dump\n"));
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
STATIC
|
|
CONST UINT8
|
|
mLapicKernelPanicPatchFind[] = {
|
|
// mov eax, gs:1Ch or gs:18h on 10.15.4+ or gs:20h on 11.0.
|
|
0x65, 0x8B, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00,
|
|
// cmp eax, cs:_master_cpu <- address masked out
|
|
0x3B, 0x00, 0x00, 0x00, 0x00, 0x00
|
|
};
|
|
|
|
STATIC
|
|
CONST UINT8
|
|
mLapicKernelPanicPatchMask[] = {
|
|
0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0xFF,
|
|
0xFF, 0x00, 0x00, 0x00, 0x00, 0x00
|
|
};
|
|
|
|
STATIC
|
|
CONST UINT8
|
|
mLapicKernelPanicPatchReplace[] = {
|
|
// xor eax, eax
|
|
0x31, 0xC0,
|
|
// nop further
|
|
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90
|
|
};
|
|
|
|
STATIC
|
|
PATCHER_GENERIC_PATCH
|
|
mLapicKernelPanicPatch = {
|
|
.Comment = DEBUG_POINTER ("LapicKernelPanic"),
|
|
.Base = "_lapic_interrupt",
|
|
.Find = mLapicKernelPanicPatchFind,
|
|
.Mask = mLapicKernelPanicPatchMask,
|
|
.Replace = mLapicKernelPanicPatchReplace,
|
|
.ReplaceMask = NULL,
|
|
.Size = sizeof (mLapicKernelPanicPatchReplace),
|
|
.Count = 1,
|
|
.Skip = 0,
|
|
.Limit = 1024
|
|
};
|
|
|
|
STATIC
|
|
CONST UINT8
|
|
mLapicKernelPanicPatchLegacyFind[] = {
|
|
// mov eax, gs:1Ch on 10.9.5 and 14h on 10.8.5.
|
|
0x65, 0x8B, 0x04, 0x25, 0x10, 0x00, 0x00, 0x00,
|
|
// lea rcx, _master_cpu
|
|
0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
// cmp eax, [rcx]
|
|
0x00, 0x00
|
|
};
|
|
|
|
STATIC
|
|
CONST UINT8
|
|
mLapicKernelPanicPatchLegacyMask[] = {
|
|
0xFF, 0xFF, 0xFF, 0xFF, 0xF3, 0xFF, 0xFF, 0xFF,
|
|
0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00
|
|
};
|
|
|
|
STATIC
|
|
CONST UINT8
|
|
mLapicKernelPanicPatchLegacyReplace[] = {
|
|
// xor eax, eax
|
|
0x31, 0xC0,
|
|
// nop further
|
|
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90
|
|
};
|
|
|
|
STATIC
|
|
PATCHER_GENERIC_PATCH
|
|
mLapicKernelPanicLegacyPatch = {
|
|
.Comment = DEBUG_POINTER ("LapicKernelPanicLegacy"),
|
|
.Base = "_lapic_interrupt",
|
|
.Find = mLapicKernelPanicPatchLegacyFind,
|
|
.Mask = mLapicKernelPanicPatchLegacyMask,
|
|
.Replace = mLapicKernelPanicPatchLegacyReplace,
|
|
.ReplaceMask = NULL,
|
|
.Size = sizeof (mLapicKernelPanicPatchLegacyReplace),
|
|
.Count = 1,
|
|
.Skip = 0,
|
|
.Limit = 1024
|
|
};
|
|
|
|
STATIC
|
|
UINT8
|
|
mLapicKernelPanicMasterPatchFind[] = {
|
|
// cmp cs:_debug_boot_arg, 0 <- address masked out
|
|
0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
|
};
|
|
|
|
STATIC
|
|
UINT8
|
|
mLapicKernelPanicMasterPatchMask[] = {
|
|
0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF
|
|
};
|
|
|
|
STATIC
|
|
UINT8
|
|
mLapicKernelPanicMasterPatchReplace[] = {
|
|
// xor eax, eax ; nop further
|
|
0x31, 0xC0, 0x90, 0x90, 0x90, 0x90, 0x90
|
|
};
|
|
|
|
STATIC
|
|
PATCHER_GENERIC_PATCH
|
|
mLapicKernelPanicMasterPatch = {
|
|
.Comment = DEBUG_POINTER ("LapicKernelPanicMaster"),
|
|
.Base = "_lapic_interrupt",
|
|
.Find = mLapicKernelPanicMasterPatchFind,
|
|
.Mask = mLapicKernelPanicMasterPatchMask,
|
|
.Replace = mLapicKernelPanicMasterPatchReplace,
|
|
.ReplaceMask = NULL,
|
|
.Size = sizeof (mLapicKernelPanicMasterPatchFind),
|
|
.Count = 1,
|
|
.Skip = 0,
|
|
.Limit = 4096
|
|
};
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
PatchLapicKernelPanic (
|
|
IN OUT PATCHER_CONTEXT *Patcher,
|
|
IN UINT32 KernelVersion
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
ASSERT (Patcher != NULL);
|
|
|
|
//
|
|
// This one is for <= 10.15 release kernels.
|
|
// TODO: Fix debug kernels and check whether we want more patches.
|
|
//
|
|
Status = PatcherApplyGenericPatch (Patcher, &mLapicKernelPanicPatch);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Failed to apply modern lapic patch - %r\n", Status));
|
|
|
|
Status = PatcherApplyGenericPatch (Patcher, &mLapicKernelPanicLegacyPatch);
|
|
if (!EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Patch success legacy lapic\n"));
|
|
} else {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Failed to apply modern lapic patch - %r\n", Status));
|
|
}
|
|
} else {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Patch success lapic\n"));
|
|
|
|
//
|
|
// Also patch away the master core check to never require lapic_dont_panic=1.
|
|
// This one is optional, and seems to never be required in real world.
|
|
//
|
|
Status = PatcherApplyGenericPatch (Patcher, &mLapicKernelPanicMasterPatch);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Failed to apply extended lapic patch - %r\n", Status));
|
|
} else {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Patch success extended lapic\n"));
|
|
}
|
|
|
|
Status = EFI_SUCCESS;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
STATIC
|
|
UINT8
|
|
mPowerStateTimeoutPanicFind[] = {
|
|
// com.apple\0
|
|
0x63, 0x6F, 0x6D, 0x2E, 0x61, 0x70, 0x70, 0x6C, 0x65, 0x00
|
|
};
|
|
|
|
STATIC
|
|
UINT8
|
|
mPowerStateTimeoutPanicReplace[] = {
|
|
// not.apple\0
|
|
0x6E, 0x6F, 0x74, 0x2E, 0x61, 0x70, 0x70, 0x6C, 0x65, 0x00
|
|
};
|
|
|
|
STATIC
|
|
PATCHER_GENERIC_PATCH
|
|
mPowerStateTimeoutPanicMasterPatch = {
|
|
.Comment = DEBUG_POINTER ("PowerStateTimeout"),
|
|
.Base = NULL,
|
|
.Find = mPowerStateTimeoutPanicFind,
|
|
.Mask = NULL,
|
|
.Replace = mPowerStateTimeoutPanicReplace,
|
|
.ReplaceMask = NULL,
|
|
.Size = sizeof (mPowerStateTimeoutPanicFind),
|
|
.Count = 1,
|
|
.Skip = 0,
|
|
.Limit = 0
|
|
};
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
PatchPowerStateTimeout (
|
|
IN OUT PATCHER_CONTEXT *Patcher,
|
|
IN UINT32 KernelVersion
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
ASSERT (Patcher != NULL);
|
|
|
|
if (!OcMatchDarwinVersion (KernelVersion, KERNEL_VERSION_CATALINA_MIN, 0)) {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Skipping power state patch on %u\n", KernelVersion));
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
Status = PatcherApplyGenericPatch (Patcher, &mPowerStateTimeoutPanicMasterPatch);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Failed to apply power state patch - %r\n", Status));
|
|
} else {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Patch success power state\n"));
|
|
}
|
|
|
|
//
|
|
// TODO: Implement a patch to not require setpowerstate_panic=0 on debug kernels.
|
|
//
|
|
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// There currently are 2 places main RTC checksum is calculated in AppleRTC.kext
|
|
// __ZN8AppleRTC14updateChecksumEv and __ZN8AppleRTC19rtcRecordTracePointEjjj.
|
|
// Since we do not want to completely break RTC and/or saving tracepoints to RTC
|
|
// we patch-out __ZN8AppleRTC8rtcWriteEjh call arguments (0x58 and 0x59) with
|
|
// invalid (out of range) value 0xFFFF in 4 places.
|
|
//
|
|
// 10.5 and below do not have __ZN8AppleRTC19rtcRecordTracePointEjjj.
|
|
//
|
|
|
|
STATIC
|
|
UINT8
|
|
mAppleRtcChecksumPatchFind32[] = {
|
|
0xC7, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00
|
|
};
|
|
|
|
STATIC
|
|
UINT8
|
|
mAppleRtcChecksumPatchMask32[] = {
|
|
0xFF, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF
|
|
};
|
|
|
|
STATIC
|
|
UINT8
|
|
mAppleRtcChecksumPatchReplace32[] = {
|
|
0xC7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00
|
|
};
|
|
|
|
STATIC
|
|
UINT8
|
|
mAppleRtcChecksumPatchFind64[] = {
|
|
0xBE, 0x58, 0x00, 0x00, 0x00
|
|
};
|
|
|
|
STATIC
|
|
UINT8
|
|
mAppleRtcChecksumPatchMask64[] = {
|
|
0xFF, 0xFE, 0xFF, 0xFF, 0xFF
|
|
};
|
|
|
|
STATIC
|
|
UINT8
|
|
mAppleRtcChecksumPatchReplace64[] = {
|
|
0xBE, 0xFF, 0xFF, 0x00, 0x00
|
|
};
|
|
|
|
STATIC
|
|
PATCHER_GENERIC_PATCH
|
|
mAppleRtcChecksumPatch32 = {
|
|
.Comment = DEBUG_POINTER ("DisableRtcChecksum32"),
|
|
.Base = NULL,
|
|
.Find = mAppleRtcChecksumPatchFind32,
|
|
.Mask = mAppleRtcChecksumPatchMask32,
|
|
.Replace = mAppleRtcChecksumPatchReplace32,
|
|
.ReplaceMask = mAppleRtcChecksumPatchMask32,
|
|
.Size = sizeof (mAppleRtcChecksumPatchFind32),
|
|
.Count = 4,
|
|
.Skip = 0,
|
|
.Limit = 0
|
|
};
|
|
|
|
STATIC
|
|
PATCHER_GENERIC_PATCH
|
|
mAppleRtcChecksumPatch64 = {
|
|
.Comment = DEBUG_POINTER ("DisableRtcChecksum64"),
|
|
.Base = NULL,
|
|
.Find = mAppleRtcChecksumPatchFind64,
|
|
.Mask = mAppleRtcChecksumPatchMask64,
|
|
.Replace = mAppleRtcChecksumPatchReplace64,
|
|
.ReplaceMask = NULL,
|
|
.Size = sizeof (mAppleRtcChecksumPatchFind64),
|
|
.Count = 4,
|
|
.Skip = 0,
|
|
.Limit = 0
|
|
};
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
PatchAppleRtcChecksum (
|
|
IN OUT PATCHER_CONTEXT *Patcher,
|
|
IN UINT32 KernelVersion
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
if (Patcher == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
Status = PatcherApplyGenericPatch (Patcher, Patcher->Is32Bit ? &mAppleRtcChecksumPatch32 : &mAppleRtcChecksumPatch64);
|
|
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"));
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
PatchSegmentJettison (
|
|
IN OUT PATCHER_CONTEXT *Patcher,
|
|
IN UINT32 KernelVersion
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT8 *RemoveBs;
|
|
UINT8 *StaticMfree;
|
|
UINT8 *CurrFreeCall;
|
|
CHAR8 *Jettisoning;
|
|
UINT8 *Last;
|
|
UINTN Index;
|
|
UINT32 Diff;
|
|
UINT32 Diff2;
|
|
|
|
if (!OcMatchDarwinVersion (KernelVersion, KERNEL_VERSION_BIG_SUR_MIN, 0)) {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Skipping SegmentJettison on %u\n", KernelVersion));
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
Last = (UINT8 *) MachoGetMachHeader (&Patcher->MachContext)
|
|
+ MachoGetFileSize (&Patcher->MachContext) - sizeof (EFI_PAGE_SIZE) * 2;
|
|
|
|
Status = PatcherGetSymbolAddress (Patcher, "__ZN6OSKext19removeKextBootstrapEv", (UINT8 **) &RemoveBs);
|
|
if (EFI_ERROR (Status) || RemoveBs > Last) {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Missing removeKextBootstrap - %r\n", Status));
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
Status = PatcherGetSymbolAddress (Patcher, "_ml_static_mfree", (UINT8 **) &StaticMfree);
|
|
if (EFI_ERROR (Status) || StaticMfree > Last) {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Missing ml_static_mfree - %r\n", Status));
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
if (RemoveBs - StaticMfree > MAX_INT32) {
|
|
DEBUG ((DEBUG_INFO, "OCAK: ml_static_mfree %p removeKextBootstrap %p are too far\n", StaticMfree, RemoveBs));
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
//
|
|
// Find the call to _ml_static_mfree.
|
|
//
|
|
Diff = (UINT32)((UINTN)StaticMfree - (UINTN)RemoveBs - 5);
|
|
|
|
CurrFreeCall = NULL;
|
|
for (Index = 0; Index < EFI_PAGE_SIZE; ++Index) {
|
|
if (RemoveBs[0] == 0xE8
|
|
&& CompareMem (&RemoveBs[1], &Diff, sizeof (Diff)) == 0) {
|
|
CurrFreeCall = RemoveBs;
|
|
DEBUG ((
|
|
DEBUG_VERBOSE,
|
|
"OCAK: CurrFreeCall %02X %02X %02X %02X %02X %X\n",
|
|
RemoveBs[0],
|
|
RemoveBs[1],
|
|
RemoveBs[2],
|
|
RemoveBs[3],
|
|
RemoveBs[4],
|
|
Diff
|
|
));
|
|
} else if (CurrFreeCall != NULL
|
|
&& RemoveBs[0] == 0x48 && RemoveBs[1] == 0x8D && RemoveBs[2] == 0x15) {
|
|
//
|
|
// Check if this lea rdx, address is pointing to "Jettisoning fileset Linkedit segments from..."
|
|
//
|
|
CopyMem (&Diff2, &RemoveBs[3], sizeof (Diff2));
|
|
Jettisoning = (CHAR8 *) RemoveBs + Diff2 + 7;
|
|
if ((UINT8 *) Jettisoning <= Last
|
|
&& AsciiStrnCmp (Jettisoning, "Jettisoning fileset", L_STR_LEN ("Jettisoning fileset")) == 0) {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Found jettisoning fileset\n"));
|
|
SetMem (CurrFreeCall, 5, 0x90);
|
|
return EFI_SUCCESS;
|
|
}
|
|
}
|
|
|
|
++RemoveBs;
|
|
--Diff;
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO, "OCAK: Failed to find jettisoning fileset - %p\n", CurrFreeCall));
|
|
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
STATIC
|
|
UINT8
|
|
mBTFeatureFlagsReplace[] = {
|
|
0x55, // push rbp
|
|
0x83, 0xCE, 0x0F // or esi, 0x0F
|
|
};
|
|
|
|
STATIC
|
|
PATCHER_GENERIC_PATCH
|
|
mBTFeatureFlagsPatchV1 = {
|
|
.Comment = DEBUG_POINTER ("BTFeatureFlagsV1"),
|
|
.Base = "__ZN25IOBluetoothHostController25SetControllerFeatureFlagsEj",
|
|
.Find = NULL,
|
|
.Mask = NULL,
|
|
.Replace = mBTFeatureFlagsReplace,
|
|
.ReplaceMask = NULL,
|
|
.Size = sizeof (mBTFeatureFlagsReplace),
|
|
.Count = 1,
|
|
.Skip = 0
|
|
};
|
|
|
|
STATIC
|
|
PATCHER_GENERIC_PATCH
|
|
mBTFeatureFlagsPatchV2 = {
|
|
.Comment = DEBUG_POINTER ("BTFeatureFlagsV2"),
|
|
.Base = "__ZN24IOBluetoothHCIController25SetControllerFeatureFlagsEj",
|
|
.Find = NULL,
|
|
.Mask = NULL,
|
|
.Replace = mBTFeatureFlagsReplace,
|
|
.ReplaceMask = NULL,
|
|
.Size = sizeof (mBTFeatureFlagsReplace),
|
|
.Count = 1,
|
|
.Skip = 0
|
|
};
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
PatchBTFeatureFlags (
|
|
IN OUT PATCHER_CONTEXT *Patcher,
|
|
IN UINT32 KernelVersion
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
ASSERT (Patcher != NULL);
|
|
|
|
if (!OcMatchDarwinVersion (KernelVersion, KERNEL_VERSION_MOUNTAIN_LION_MIN, 0)) {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Skipping BTFeatureFlags on %u\n", KernelVersion));
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
Status = PatcherApplyGenericPatch (
|
|
Patcher,
|
|
&mBTFeatureFlagsPatchV1
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Failed to find BT FeatureFlags symbol v1 - %r, trying v2\n", Status));
|
|
Status = PatcherApplyGenericPatch (
|
|
Patcher,
|
|
&mBTFeatureFlagsPatchV2
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Failed to find BT FeatureFlags symbol v2 - %r\n", Status));
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// 32-bit commpage_descriptor structure from XNU.
|
|
//
|
|
typedef struct {
|
|
//
|
|
// Address of code.
|
|
//
|
|
UINT32 CodeAddress;
|
|
//
|
|
// Length of code in bytes.
|
|
//
|
|
UINT32 CodeLength;
|
|
//
|
|
// Address to place this function at.
|
|
//
|
|
UINT32 CommpageAddress;
|
|
//
|
|
// CPU capability bits we must have.
|
|
//
|
|
UINT32 MustHave;
|
|
//
|
|
// CPU capability bits we can't have.
|
|
//
|
|
UINT32 CantHave;
|
|
} COMMPAGE_DESCRIPTOR;
|
|
|
|
//
|
|
// 64-bit commpage_descriptor structure from XNU.
|
|
//
|
|
typedef struct {
|
|
//
|
|
// Address of code.
|
|
//
|
|
UINT64 CodeAddress;
|
|
//
|
|
// Length of code in bytes.
|
|
//
|
|
UINT32 CodeLength;
|
|
//
|
|
// Address to place this function at.
|
|
//
|
|
UINT32 CommpageAddress;
|
|
//
|
|
// CPU capability bits we must have.
|
|
//
|
|
UINT32 MustHave;
|
|
//
|
|
// CPU capability bits we can't have.
|
|
//
|
|
UINT32 CantHave;
|
|
} COMMPAGE_DESCRIPTOR_64;
|
|
|
|
typedef union {
|
|
COMMPAGE_DESCRIPTOR Desc32;
|
|
COMMPAGE_DESCRIPTOR_64 Desc64;
|
|
} COMMPAGE_DESCRIPTOR_ANY;
|
|
|
|
#define COMM_PAGE_BCOPY 0xFFFF0780
|
|
#define kHasSupplementalSSE3 0x00000100
|
|
|
|
STATIC CONST UINT8 mAsmLegacyBcopy64[] = {
|
|
#include "LegacyBcopy.h"
|
|
};
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
PatchLegacyCommpage (
|
|
IN OUT PATCHER_CONTEXT *Patcher,
|
|
IN UINT32 KernelVersion
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT8 *Start;
|
|
UINT8 *Last;
|
|
UINT8 *CommpageRoutines;
|
|
UINT8 *Target;
|
|
UINT64 Address;
|
|
UINT32 MaxSize;
|
|
|
|
COMMPAGE_DESCRIPTOR_ANY *Commpage;
|
|
UINT32 CommpageCodeLength;
|
|
UINT32 CommpageAddress;
|
|
UINT32 CommpageMustHave;
|
|
|
|
ASSERT (Patcher != NULL);
|
|
|
|
Start = ((UINT8 *) MachoGetMachHeader (&Patcher->MachContext));
|
|
Last = Start + MachoGetFileSize (&Patcher->MachContext) - EFI_PAGE_SIZE * 2 - (Patcher->Is32Bit ? sizeof (COMMPAGE_DESCRIPTOR) : sizeof (COMMPAGE_DESCRIPTOR_64));
|
|
|
|
//
|
|
// This is a table of pointers to commpage entries.
|
|
//
|
|
Status = PatcherGetSymbolAddress (Patcher, "_commpage_64_routines", (UINT8 **) &CommpageRoutines);
|
|
if (EFI_ERROR (Status) || CommpageRoutines >= Last) {
|
|
DEBUG ((DEBUG_WARN, "OCAK: Failed to locate _commpage_64_routines (%p) - %r\n", CommpageRoutines, Status));
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
//
|
|
// Iterate through table looking for bcopy_sse4_64 (on 10.4) or bcopy_sse3x_64 (10.5+) entry.
|
|
//
|
|
Address = Patcher->Is32Bit ? *((UINT32 *) CommpageRoutines) : *((UINT64 *) CommpageRoutines);
|
|
while (Address > 0) {
|
|
Commpage = MachoGetFilePointerByAddress (&Patcher->MachContext, Address, &MaxSize);
|
|
if (Commpage == NULL
|
|
|| MaxSize < (Patcher->Is32Bit ? sizeof (COMMPAGE_DESCRIPTOR) : sizeof (COMMPAGE_DESCRIPTOR_64))) {
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Locate the bcopy commpage entry that requires SSSE3 and replace it with our own implementation.
|
|
//
|
|
CommpageAddress = Patcher->Is32Bit ? Commpage->Desc32.CommpageAddress : Commpage->Desc64.CommpageAddress;
|
|
CommpageMustHave = Patcher->Is32Bit ? Commpage->Desc32.MustHave : Commpage->Desc64.MustHave;
|
|
if (CommpageAddress == COMM_PAGE_BCOPY
|
|
&& (CommpageMustHave & kHasSupplementalSSE3) == kHasSupplementalSSE3) {
|
|
Address = Patcher->Is32Bit ? Commpage->Desc32.CodeAddress : Commpage->Desc64.CodeAddress;
|
|
CommpageCodeLength = Patcher->Is32Bit ? Commpage->Desc32.CodeLength : Commpage->Desc64.CodeLength;
|
|
DEBUG ((
|
|
DEBUG_VERBOSE,
|
|
"OCAK: Found 64-bit _COMM_PAGE_BCOPY function @ 0x%llx (0x%X bytes)\n",
|
|
Address,
|
|
CommpageCodeLength
|
|
));
|
|
|
|
Target = MachoGetFilePointerByAddress (&Patcher->MachContext, Address, &MaxSize);
|
|
if (Target == NULL
|
|
|| MaxSize < sizeof (mAsmLegacyBcopy64)
|
|
|| CommpageCodeLength < sizeof (mAsmLegacyBcopy64)) {
|
|
break;
|
|
}
|
|
|
|
CopyMem (Target, mAsmLegacyBcopy64, sizeof (mAsmLegacyBcopy64));
|
|
if (Patcher->Is32Bit) {
|
|
Commpage->Desc32.CodeLength = sizeof (mAsmLegacyBcopy64);
|
|
Commpage->Desc32.MustHave &= ~kHasSupplementalSSE3;
|
|
} else {
|
|
Commpage->Desc64.CodeLength = sizeof (mAsmLegacyBcopy64);
|
|
Commpage->Desc64.MustHave &= ~kHasSupplementalSSE3;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
CommpageRoutines += Patcher->Is32Bit ? sizeof (UINT32) : sizeof (UINT64);
|
|
if (CommpageRoutines >= Last) {
|
|
break;
|
|
}
|
|
Address = Patcher->Is32Bit ? *((UINT32 *) CommpageRoutines) : *((UINT64 *) CommpageRoutines);
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO, "OCAK: Failed to find 64-bit _COMM_PAGE_BCOPY function\n"));
|
|
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
PatchForceSecureBootScheme (
|
|
IN OUT PATCHER_CONTEXT *Patcher,
|
|
IN UINT32 KernelVersion
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT8 *Last;
|
|
UINT8 *SelectAp;
|
|
UINT8 *HybridAp;
|
|
UINT32 Diff;
|
|
|
|
if (!OcMatchDarwinVersion (KernelVersion, KERNEL_VERSION_BIG_SUR_MIN, 0)) {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Skipping sb scheme on %u\n", KernelVersion));
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
if (Patcher == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
//
|
|
// This code is for debugging APFS snapshot verification for Big Sur.
|
|
// macOS chooses verification scheme based on the hardware:
|
|
// - __img4_chip_x86_software_8012 (software x86 8012)
|
|
// for CPUs with VMM flag enabled via cpuid_features.
|
|
// - __img4_chip_x86 (x86)
|
|
// for platforms with no or v1 (0x10000) coprocessor (apple-coprocessor-version).
|
|
// - __img4_chip_ap_hybrid_medium (medium-security hybrid arm/x86 ap)
|
|
// for platforms with v2 (0x20000) coprocessor and medium (1) policy (AppleSecureBootPolicy).
|
|
// - __img4_chip_ap_hybrid_relaxed (relaxed hybrid arm/x86 ap)
|
|
// for platforms with v2 coprocessor and relaxed (0) policy.
|
|
// - __img4_chip_ap_hybrid (hybrid arm/x86 ap)
|
|
// for platfirms with v2 or newer coprocessor and personalised policy (2).
|
|
//
|
|
|
|
Last = ((UINT8 *) MachoGetMachHeader (&Patcher->MachContext)
|
|
+ MachoGetFileSize (&Patcher->MachContext) - 64);
|
|
|
|
Status = PatcherGetSymbolAddress (Patcher, "_img4_chip_select_effective_ap", &SelectAp);
|
|
if (EFI_ERROR (Status) || SelectAp > Last) {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Missing _img4_chip_select_effective_ap - %r\n", Status));
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
Status = PatcherGetSymbolAddress (Patcher, "__img4_chip_x86", &HybridAp);
|
|
if (EFI_ERROR (Status) || HybridAp > Last) {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Missing __img4_chip_x86 - %r\n", Status));
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO, "OCAK: Forcing sb scheme on %u\n", KernelVersion));
|
|
|
|
SelectAp[0] = 0x48;
|
|
SelectAp[1] = 0x8D;
|
|
SelectAp[2] = 0x05;
|
|
Diff = (UINT32) (HybridAp - SelectAp - 7);
|
|
CopyMem (&SelectAp[3], &Diff, sizeof (Diff));
|
|
SelectAp[7] = 0xC3;
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
STATIC
|
|
UINT8
|
|
mApfsTimeoutFind[] = {
|
|
0x48, 0x3D, 0x7F, 0x96, 0x98, 0x00
|
|
};
|
|
|
|
STATIC
|
|
UINT8
|
|
mApfsTimeoutReplace[] = {
|
|
0x48, 0x3D, 0x00, 0x00, 0x00, 0x00
|
|
};
|
|
|
|
STATIC
|
|
PATCHER_GENERIC_PATCH
|
|
mApfsTimeoutPatch = {
|
|
.Comment = DEBUG_POINTER ("ApfsTimeout"),
|
|
.Base = NULL,
|
|
.Find = mApfsTimeoutFind,
|
|
.Mask = NULL,
|
|
.Replace = mApfsTimeoutReplace,
|
|
.ReplaceMask = NULL,
|
|
.Size = sizeof (mApfsTimeoutFind),
|
|
.Count = 1,
|
|
.Skip = 0,
|
|
.Limit = 0
|
|
};
|
|
|
|
VOID
|
|
PatchSetApfsTimeout (
|
|
IN UINT32 Timeout
|
|
)
|
|
{
|
|
// FIXME: This is really ugly, make quirks take a context param.
|
|
DEBUG ((DEBUG_INFO, "OCAK: Registering %u APFS timeout\n", Timeout));
|
|
CopyMem (&mApfsTimeoutReplace[2], &Timeout, sizeof (Timeout));
|
|
}
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
PatchSetApfsTrimTimeout (
|
|
IN OUT PATCHER_CONTEXT *Patcher,
|
|
IN UINT32 KernelVersion
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
if (!OcMatchDarwinVersion (KernelVersion, KERNEL_VERSION_MOJAVE_MIN, 0)) {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Skipping apfs timeout on %u\n", KernelVersion));
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
if (Patcher == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
Status = PatcherApplyGenericPatch (Patcher, &mApfsTimeoutPatch);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Failed to apply patch SetApfsTrimTimeout - %r\n", Status));
|
|
} else {
|
|
DEBUG ((DEBUG_INFO, "OCAK: Patch success SetApfsTrimTimeout\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 },
|
|
[KernelQuirkSegmentJettison] = { NULL, PatchSegmentJettison },
|
|
[KernelQuirkExtendBTFeatureFlags] = { "com.apple.iokit.IOBluetoothFamily", PatchBTFeatureFlags },
|
|
[KernelQuirkLegacyCommpage] = { NULL, PatchLegacyCommpage },
|
|
[KernelQuirkForceSecureBootScheme] = { "com.apple.security.AppleImage4", PatchForceSecureBootScheme },
|
|
[KernelQuirkSetApfsTrimTimeout] = { "com.apple.filesystems.apfs", PatchSetApfsTrimTimeout },
|
|
};
|
|
|
|
EFI_STATUS
|
|
KernelApplyQuirk (
|
|
IN KERNEL_QUIRK_NAME Name,
|
|
IN OUT PATCHER_CONTEXT *Patcher,
|
|
IN UINT32 KernelVersion
|
|
)
|
|
{
|
|
ASSERT (Patcher != NULL);
|
|
|
|
return gKernelQuirks[Name].PatchFunction (Patcher, KernelVersion);
|
|
}
|