Skip to content

Commit

Permalink
Add ClearTaskSwitchBit booter quirk (#573)
Browse files Browse the repository at this point in the history
This quirk is needed to boot macOS 10.7 and older when using a 32-bit kernel on a 64-bit UEFI firmware that makes uses of FPU or SSE instructions in runtime services (such as Hyper-V).
  • Loading branch information
Goldfish64 authored Feb 23, 2025
1 parent 24246c6 commit 45f8ba2
Show file tree
Hide file tree
Showing 12 changed files with 129 additions and 43 deletions.
16 changes: 16 additions & 0 deletions Docs/Configuration.tex
Original file line number Diff line number Diff line change
Expand Up @@ -1517,6 +1517,22 @@ \subsection{Quirks Properties}\label{booterpropsquirks}

\emph{Note}: Most types of firmware, apart from Apple and VMware, need this quirk.

\item
\texttt{ClearTaskSwitchBit}\\
\textbf{Type}: \texttt{plist\ boolean}\\
\textbf{Failsafe}: \texttt{false}\\
\textbf{Description}: Clear task switch bit during UEFI runtime services calls.

This quirk resolves FPU-related crashes in UEFI runtime services when using either the
32-bit kernel on a 64-bit UEFI implementation, or the 64-bit kernel on a 32-bit UEFI implementation
by removing the task switch (\texttt{TS}) bit from \texttt{CR0} register during their execution.
These crashes occur if there is any FPU/SSE instruction usage in UEFI runtime services as XNU
is unable to handle exceptions from mixed-mode code. This quirk requires \texttt{OC\_FIRMWARE\_RUNTIME}
protocol implemented in \texttt{OpenRuntime.efi}.

\emph{Note}: This quirk should only be required when running older macOS versions when the
32-bit kernel is used on a 64-bit UEFI implementation, such as Microsoft Hyper-V.

\item
\texttt{DevirtualiseMmio}\\
\textbf{Type}: \texttt{plist\ boolean}\\
Expand Down
2 changes: 2 additions & 0 deletions Docs/Sample.plist
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,8 @@
<false/>
<key>AvoidRuntimeDefrag</key>
<true/>
<key>ClearTaskSwitchBit</key>
<false/>
<key>DevirtualiseMmio</key>
<false/>
<key>DisableSingleUser</key>
Expand Down
2 changes: 2 additions & 0 deletions Docs/SampleCustom.plist
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,8 @@
<false/>
<key>AvoidRuntimeDefrag</key>
<true/>
<key>ClearTaskSwitchBit</key>
<false/>
<key>DevirtualiseMmio</key>
<false/>
<key>DisableSingleUser</key>
Expand Down
5 changes: 5 additions & 0 deletions Include/Acidanthera/Library/OcAfterBootCompatLib.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,11 @@ typedef struct OC_ABC_SETTINGS_ {
///
BOOLEAN EnableWriteUnprotector;
///
/// Clear task switch bit in UEFI runtime services. Fixes crashes due to SSE instruction
/// usage on some firmware configurations (i.e. Hyper-V Gen2 with 32-bit macOS kernel).
///
BOOLEAN ClearTaskSwitchBit;
///
/// Signal OSInfo protocol that every loaded non-macOS OS is macOS.
/// Works around disabled IGPU in Windows and Linux on Apple laptops.
///
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 @@ -136,6 +136,7 @@ OC_DECLARE (OC_BOOTER_PATCH_ARRAY)
#define OC_BOOTER_QUIRKS_FIELDS(_, __) \
_(BOOLEAN , AllowRelocationBlock , , FALSE , ()) \
_(BOOLEAN , AvoidRuntimeDefrag , , FALSE , ()) \
_(BOOLEAN , ClearTaskSwitchBit , , FALSE , ()) \
_(BOOLEAN , DevirtualiseMmio , , FALSE , ()) \
_(BOOLEAN , DisableSingleUser , , FALSE , ()) \
_(BOOLEAN , DisableVariableWrite , , FALSE , ()) \
Expand Down
7 changes: 7 additions & 0 deletions Include/Acidanthera/Protocol/OcFirmwareRuntime.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,13 @@ typedef struct OC_FWRT_CONFIG_ {
/// Secure boot variable protection.
///
BOOLEAN ProtectSecureBoot;
///
/// Make UEFI runtime services drop CR0 TS bit on calls to prevent a 0x7 exception
/// from being triggered due to SSE instruction usage on some firmware configurations.
/// Currently this affects Hyper-V generation 2 VMs when invoking EFI runtime services
/// from the 32-bit macOS kernel.
///
BOOLEAN ClearTaskSwitchBit;
} OC_FWRT_CONFIG;

/**
Expand Down
5 changes: 3 additions & 2 deletions Library/OcAfterBootCompatLib/OcAfterBootCompatLib.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ OcAbcInitialize (

DEBUG ((
DEBUG_INFO,
"OCABC: ALRBL %d RTDFRG %d DEVMMIO %d NOSU %d NOVRWR %d NOSB %d FBSIG %d NOHBMAP %d SMSLIDE %d WRUNPROT %d\n",
"OCABC: ALRBL %d RTDFRG %d DEVMMIO %d NOSU %d NOVRWR %d NOSB %d FBSIG %d NOHBMAP %d SMSLIDE %d WRUNPROT %d CLRTS %d\n",
Settings->AllowRelocationBlock,
Settings->AvoidRuntimeDefrag,
Settings->DevirtualiseMmio,
Expand All @@ -122,7 +122,8 @@ OcAbcInitialize (
Settings->ForceBooterSignature,
Settings->DiscardHibernateMap,
Settings->EnableSafeModeSlide,
Settings->EnableWriteUnprotector
Settings->EnableWriteUnprotector,
Settings->ClearTaskSwitchBit
));

DEBUG ((
Expand Down
10 changes: 6 additions & 4 deletions Library/OcAfterBootCompatLib/ServiceOverrides.c
Original file line number Diff line number Diff line change
Expand Up @@ -1311,11 +1311,13 @@ OcStartImage (
// Disable them when this is no longer Apple.
//
if (BootCompat->ServiceState.AppleBootNestedCount > 0) {
Config.WriteProtection = BootCompat->Settings.DisableVariableWrite;
Config.WriteUnprotector = BootCompat->Settings.EnableWriteUnprotector;
Config.ClearTaskSwitchBit = BootCompat->Settings.ClearTaskSwitchBit;
Config.WriteProtection = BootCompat->Settings.DisableVariableWrite;
Config.WriteUnprotector = BootCompat->Settings.EnableWriteUnprotector;
} else {
Config.WriteProtection = FALSE;
Config.WriteUnprotector = FALSE;
Config.ClearTaskSwitchBit = FALSE;
Config.WriteProtection = FALSE;
Config.WriteUnprotector = FALSE;
}

BootCompat->ServiceState.FwRuntime->SetMain (
Expand Down
1 change: 1 addition & 0 deletions Library/OcConfigurationLib/OcConfigurationLib.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ OC_SCHEMA
mBooterQuirksSchema[] = {
OC_SCHEMA_BOOLEAN_IN ("AllowRelocationBlock", OC_GLOBAL_CONFIG, Booter.Quirks.AllowRelocationBlock),
OC_SCHEMA_BOOLEAN_IN ("AvoidRuntimeDefrag", OC_GLOBAL_CONFIG, Booter.Quirks.AvoidRuntimeDefrag),
OC_SCHEMA_BOOLEAN_IN ("ClearTaskSwitchBit", OC_GLOBAL_CONFIG, Booter.Quirks.ClearTaskSwitchBit),
OC_SCHEMA_BOOLEAN_IN ("DevirtualiseMmio", OC_GLOBAL_CONFIG, Booter.Quirks.DevirtualiseMmio),
OC_SCHEMA_BOOLEAN_IN ("DisableSingleUser", OC_GLOBAL_CONFIG, Booter.Quirks.DisableSingleUser),
OC_SCHEMA_BOOLEAN_IN ("DisableVariableWrite", OC_GLOBAL_CONFIG, Booter.Quirks.DisableVariableWrite),
Expand Down
1 change: 1 addition & 0 deletions Library/OcMainLib/OpenCoreUefi.c
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,7 @@ OcLoadBooterUefiSupport (
AbcSettings.AllowRelocationBlock = Config->Booter.Quirks.AllowRelocationBlock;
AbcSettings.EnableSafeModeSlide = Config->Booter.Quirks.EnableSafeModeSlide;
AbcSettings.EnableWriteUnprotector = Config->Booter.Quirks.EnableWriteUnprotector;
AbcSettings.ClearTaskSwitchBit = Config->Booter.Quirks.ClearTaskSwitchBit;
AbcSettings.ForceExitBootServices = Config->Booter.Quirks.ForceExitBootServices;
AbcSettings.ForceBooterSignature = Config->Booter.Quirks.ForceBooterSignature;
CopyMem (AbcSettings.BooterSignature, Signature, sizeof (AbcSettings.BooterSignature));
Expand Down
Loading

0 comments on commit 45f8ba2

Please sign in to comment.