Skip to content

Commit

Permalink
OcAppleKernelLib: Add LegacyCommpage quirk
Browse files Browse the repository at this point in the history
Replaces default 64-bit commpage bcopy implementation with one that does not require SSSE3, required for legacy platforms without SSSE3. Resolves a "commpage no match for last" panic due to no available bcopy implementations.
  • Loading branch information
Goldfish64 committed Oct 4, 2020
1 parent 369db9c commit f18a2a7
Show file tree
Hide file tree
Showing 10 changed files with 192 additions and 2 deletions.
Binary file modified Docs/Configuration.pdf
Binary file not shown.
10 changes: 10 additions & 0 deletions Docs/Configuration.tex
Original file line number Diff line number Diff line change
Expand Up @@ -2373,6 +2373,16 @@ \subsection{Quirks Properties}\label{kernelpropsquirks}
\textbf{Requirement}: 10.6 (64-bit)\\
\textbf{Description}: Disables kernel panic on LAPIC interrupts.

\item
\texttt{LegacyCommpage}\\
\textbf{Type}: \texttt{plist\ boolean}\\
\textbf{Failsafe}: \texttt{false}\\
\textbf{Requirement}: 10.4\\
\textbf{Description}: Replaces the default 64-bit commpage bcopy implementation with
one that does not require SSSE3, useful for legacy platforms. This prevents a
\texttt{commpage no match for last} panic due to no available 64-bit bcopy functions
that do not require SSSE3.

\item
\texttt{PanicNoKextDump}\\
\textbf{Type}: \texttt{plist\ boolean}\\
Expand Down
Binary file modified Docs/Differences/Differences.pdf
Binary file not shown.
15 changes: 13 additions & 2 deletions Docs/Differences/Differences.tex
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
\documentclass[]{article}
%DIF LATEXDIFF DIFFERENCE FILE
%DIF DEL PreviousConfiguration.tex Sun Sep 13 11:48:11 2020
%DIF ADD ../Configuration.tex Sat Oct 3 11:23:49 2020
%DIF ADD ../Configuration.tex Sat Oct 3 19:40:48 2020

\usepackage{lmodern}
\usepackage{amssymb,amsmath}
Expand Down Expand Up @@ -2459,7 +2459,18 @@ \subsection{Quirks Properties}\label{kernelpropsquirks}
\textbf{Description}: Disables kernel panic on LAPIC interrupts.

\item
\texttt{PanicNoKextDump}\\
\DIFaddbegin \texttt{\DIFadd{LegacyCommpage}}\\
\textbf{\DIFadd{Type}}\DIFadd{: }\texttt{\DIFadd{plist\ boolean}}\\
\textbf{\DIFadd{Failsafe}}\DIFadd{: }\texttt{\DIFadd{false}}\\
\textbf{\DIFadd{Requirement}}\DIFadd{: 10.4}\\
\textbf{\DIFadd{Description}}\DIFadd{: Replaces the default 64-bit commpage bcopy implementation with
one that does not require SSSE3, useful for legacy platforms. This prevents a
}\texttt{\DIFadd{commpage no match for last}} \DIFadd{panic due to no available 64-bit bcopy functions
that do not require SSSE3.
}

\item
\DIFaddend \texttt{PanicNoKextDump}\\
\textbf{Type}: \texttt{plist\ boolean}\\
\textbf{Failsafe}: \texttt{false}\\
\textbf{Requirement}: 10.13 (not required for older)\\
Expand Down
Binary file modified Docs/Errata/Errata.pdf
Binary file not shown.
4 changes: 4 additions & 0 deletions Include/Acidanthera/Library/OcAppleKernelLib.h
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,10 @@ typedef enum {
//
KernelQuirkPanicNoKextDump,
//
// Replaces the 64-bit commpage bcopy implementation with one that does not use SSSE3.
//
KernelQuirkLegacyCommpage,
//
// Disable power state change timeout kernel panic (10.15+).
//
KernelQuirkPowerTimeoutKernelPanic,
Expand Down
1 change: 1 addition & 0 deletions Include/Acidanthera/Library/OcConfigurationLib.h
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@
_(BOOLEAN , ExternalDiskIcons , , FALSE , ()) \
_(BOOLEAN , IncreasePciBarSize , , FALSE , ()) \
_(BOOLEAN , LapicKernelPanic , , FALSE , ()) \
_(BOOLEAN , LegacyCommpage , , FALSE , ()) \
_(BOOLEAN , PanicNoKextDump , , FALSE , ()) \
_(BOOLEAN , PowerTimeoutKernelPanic , , FALSE , ()) \
_(BOOLEAN , ThirdPartyDrives , , FALSE , ()) \
Expand Down
159 changes: 159 additions & 0 deletions Library/OcAppleKernelLib/CommonPatches.c
Original file line number Diff line number Diff line change
Expand Up @@ -1671,6 +1671,164 @@ PatchBTFeatureFlags (
return EFI_SUCCESS;
}

//
// 32-bit commpage_descriptor structure from XNU.
//
typedef struct {
//
// Address of code.
//
UINT32 CodeAddress;
//
// Length of code in bytes.
//
UINT32 CodeLength;
//
// Put at this address (_COMM_PAGE_BCOPY, etc).
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;
//
// Put at this address (_COMM_PAGE_BCOPY, etc).
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 UINT8 bcopyImplementation[74] = {
0x48, 0x87, 0xFE, 0x48, 0x89, 0xD1, 0x48, 0x89, 0xF8, 0x48, 0x29, 0xF0, 0x48, 0x39, 0xC8, 0x72,
0x12, 0x48, 0xC1, 0xE9, 0x03, 0xFC, 0xF3, 0x48, 0xA5, 0x48, 0x89, 0xD1, 0x48, 0x83, 0xE1, 0x07,
0xF3, 0xA4, 0xC3, 0x48, 0x01, 0xCF, 0x48, 0x01, 0xCE, 0x48, 0xFF, 0xCF, 0x48, 0xFF, 0xCE, 0x48,
0x83, 0xE1, 0x07, 0xFD, 0xF3, 0xA4, 0x48, 0x89, 0xD1, 0x48, 0xC1, 0xE9, 0x03, 0x48, 0x83, 0xEE,
0x07, 0x48, 0x83, 0xEF, 0x07, 0xF3, 0x48, 0xA5, 0xFC, 0xC3
};

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 (bcopyImplementation)
|| CommpageCodeLength < sizeof (bcopyImplementation)) {
break;
}

CopyMem (Target, bcopyImplementation, sizeof (bcopyImplementation));
if (Patcher->Is32Bit) {
Commpage->Desc32.CodeLength = sizeof (bcopyImplementation);
Commpage->Desc32.MustHave &= ~kHasSupplementalSSE3;
} else {
Commpage->Desc64.CodeLength = sizeof (bcopyImplementation);
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;
}

//
// Quirks table.
//
Expand All @@ -1695,6 +1853,7 @@ KERNEL_QUIRK gKernelQuirks[] = {
[KernelQuirkXhciPortLimit3] = { "com.apple.driver.usb.AppleUSBXHCIPCI", PatchUsbXhciPortLimit3 },
[KernelQuirkSegmentJettison] = { NULL, PatchSegmentJettison },
[KernelQuirkExtendBTFeatureFlags] = { "com.apple.iokit.IOBluetoothFamily", PatchBTFeatureFlags },
[KernelQuirkLegacyCommpage] = { NULL, PatchLegacyCommpage }
};

EFI_STATUS
Expand Down
1 change: 1 addition & 0 deletions Library/OcConfigurationLib/OcConfigurationLib.c
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,7 @@ mKernelQuirksSchema[] = {
OC_SCHEMA_BOOLEAN_IN ("ExternalDiskIcons", OC_GLOBAL_CONFIG, Kernel.Quirks.ExternalDiskIcons),
OC_SCHEMA_BOOLEAN_IN ("IncreasePciBarSize", OC_GLOBAL_CONFIG, Kernel.Quirks.IncreasePciBarSize),
OC_SCHEMA_BOOLEAN_IN ("LapicKernelPanic", OC_GLOBAL_CONFIG, Kernel.Quirks.LapicKernelPanic),
OC_SCHEMA_BOOLEAN_IN ("LegacyCommpage", OC_GLOBAL_CONFIG, Kernel.Quirks.LegacyCommpage),
OC_SCHEMA_BOOLEAN_IN ("PanicNoKextDump", OC_GLOBAL_CONFIG, Kernel.Quirks.PanicNoKextDump),
OC_SCHEMA_BOOLEAN_IN ("PowerTimeoutKernelPanic", OC_GLOBAL_CONFIG, Kernel.Quirks.PowerTimeoutKernelPanic),
OC_SCHEMA_BOOLEAN_IN ("ThirdPartyDrives", OC_GLOBAL_CONFIG, Kernel.Quirks.ThirdPartyDrives),
Expand Down
4 changes: 4 additions & 0 deletions Platform/OpenCore/OpenCoreKernelPatch.c
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,10 @@ OcKernelApplyPatches (
if (Config->Kernel.Quirks.DisableLinkeditJettison) {
OcKernelApplyQuirk (KernelQuirkSegmentJettison, CacheType, DarwinVersion, NULL, &KernelPatcher);
}

if (Config->Kernel.Quirks.LegacyCommpage) {
OcKernelApplyQuirk (KernelQuirkLegacyCommpage, CacheType, DarwinVersion, NULL, &KernelPatcher);
}
}
}

Expand Down

0 comments on commit f18a2a7

Please sign in to comment.