From 081bb56dd062356df72d93f1d98206c036c4ab17 Mon Sep 17 00:00:00 2001
From: Mykola Grymalyuk <48863253+khronokernel@users.noreply.github.com>
Date: Mon, 12 Jul 2021 19:13:30 -0600
Subject: [PATCH] Add backend to support latebloom
Kext currently not enabled until ready for mass community usage
---
OpenCore-Patcher.command | 26 ++++++++++---------
Resources/Build.py | 5 ++++
Resources/Constants.py | 9 +++++++
Resources/ModelArray.py | 33 +++++++++++++++++++++++-
Resources/Utilities.py | 22 ++++++++++++++++
payloads/Config/config.plist | 20 +++++++++++++-
payloads/Kexts/Misc/latebloom-v0.17.zip | Bin 0 -> 14385 bytes
7 files changed, 101 insertions(+), 14 deletions(-)
create mode 100644 payloads/Kexts/Misc/latebloom-v0.17.zip
diff --git a/OpenCore-Patcher.command b/OpenCore-Patcher.command
index 6edeb2a7a..f33f35da3 100755
--- a/OpenCore-Patcher.command
+++ b/OpenCore-Patcher.command
@@ -19,18 +19,6 @@ class OpenCoreLegacyPatcher:
self.constants.detected_os = int(platform.uname().release.partition(".")[0])
self.set_defaults(self.computer.real_model, True)
- custom_cpu_model_value = Utilities.get_nvram("revcpuname", "4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102", decode=True)
- if custom_cpu_model_value is not None:
- # TODO: Fix to not use two separate variables
- self.constants.custom_cpu_model = 1
- self.constants.custom_cpu_model_value = custom_cpu_model_value.split("%00")[0]
-
- if "-v" in (Utilities.get_nvram("boot-args") or ""):
- self.constants.verbose_debug = True
-
- # Check if running in RecoveryOS
- self.constants.recovery_status = Utilities.check_recovery()
-
def set_defaults(self, model, host_is_target):
# Defaults
self.constants.sip_status = True
@@ -72,6 +60,20 @@ class OpenCoreLegacyPatcher:
# MacBook8,1 has an odd bug where it cannot install Monterey with Minimal spoofing
self.constants.serial_settings == "Moderate"
+ custom_cpu_model_value = Utilities.get_nvram("revcpuname", "4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102", decode=True)
+ if custom_cpu_model_value is not None:
+ # TODO: Fix to not use two separate variables
+ self.constants.custom_cpu_model = 1
+ self.constants.custom_cpu_model_value = custom_cpu_model_value.split("%00")[0]
+
+ if "-v" in (Utilities.get_nvram("boot-args") or ""):
+ self.constants.verbose_debug = True
+
+ self.constants.latebloom_delay, self.constants.latebloom_range, self.constants.latebloom_debug = Utilities.latebloom_detection(model)
+
+ # Check if running in RecoveryOS
+ self.constants.recovery_status = Utilities.check_recovery()
+
def build_opencore(self):
Build.BuildOpenCore(self.constants.custom_model or self.constants.computer.real_model, self.constants).build_opencore()
diff --git a/Resources/Build.py b/Resources/Build.py
index 0cb695d6b..7c9c3ad2e 100644
--- a/Resources/Build.py
+++ b/Resources/Build.py
@@ -189,12 +189,17 @@ class BuildOpenCore:
# Misc
("FeatureUnlock.kext", self.constants.featureunlock_version, self.constants.featureunlock_path, lambda: self.model in ModelArray.SidecarPatch),
("DebugEnhancer.kext", self.constants.debugenhancer_version, self.constants.debugenhancer_path, lambda: self.constants.kext_debug is True),
+ #("latebloom.kext", self.constants.latebloom_version, self.constants.latebloom_path, lambda: self.model in ModelArray.PCIRaceCondition),
]:
self.enable_kext(name, version, path, check)
if self.constants.allow_oc_everywhere is False:
self.get_item_by_kv(self.config["Kernel"]["Patch"], "Identifier", "com.apple.driver.AppleSMC")["Enabled"] = True
+ if self.get_kext_by_bundle_path("latebloom.kext")["Enabled"] is True:
+ print(f"Setting latebloom delay of {self.constants.latebloom_delay}, range {self.constants.latebloom_range}, debug {self.constants.latebloom_debug}")
+ self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += f" latebloom={self.constants.latebloom_delay}, lb_range={self.constants.latebloom_range}, lb_debug={self.constants.latebloom_debug}"
+
if not self.constants.custom_model and (self.constants.allow_oc_everywhere is True or self.model in ModelArray.MacPro71):
# Use Innie's same logic:
# https://github.com/cdf/Innie/blob/v1.3.0/Innie/Innie.cpp#L90-L97
diff --git a/Resources/Constants.py b/Resources/Constants.py
index 67576e55b..a87d0f730 100644
--- a/Resources/Constants.py
+++ b/Resources/Constants.py
@@ -42,6 +42,7 @@ class Constants:
self.debugenhancer_version = "1.0.3"
self.innie_version = "1.3.0"
self.fw_kext = "1.0.0"
+ self.latebloom_version = "0.17"
self.disk = ""
self.patch_disk = ""
self.patcher_support_pkg_version = "0.0.13" # PatcherSupportPkg
@@ -90,6 +91,10 @@ class Constants:
self.enable_wake_on_wlan = False
self.allow_ivy_igpu = False
self.moj_cat_accel = False
+ self.latebloom_status = False
+ self.latebloom_delay = 0
+ self.latebloom_range = 0
+ self.latebloom_debug = 0
# OS Versions
self.tiger = 8
@@ -284,6 +289,10 @@ class Constants:
@property
def innie_path(self):
return self.payload_kexts_path / Path(f"Misc/Innie-v{self.innie_version}.zip")
+
+ @property
+ def latebloom_path(self):
+ return self.payload_kexts_path / Path(f"Misc/latebloom-v{self.latebloom_version}.zip")
@property
def plist_folder_path(self):
diff --git a/Resources/ModelArray.py b/Resources/ModelArray.py
index b8f3b68f5..6009b509e 100644
--- a/Resources/ModelArray.py
+++ b/Resources/ModelArray.py
@@ -994,4 +994,35 @@ NoFireWireSupport = [
"MacBookAir3,2",
]
-RecoveryIgnore = ["Update", "VM", "Recovery", "Preboot"]
+PCIRaceCondition = [
+ "MacBook4,1",
+ "MacBook5,1",
+ "MacBook5,2",
+ "MacBook6,1",
+ "MacBook7,1",
+ "MacBookAir2,1",
+ "MacBookAir3,1",
+ "MacBookAir3,2",
+ "MacBookPro4,1",
+ "MacBookPro5,1",
+ "MacBookPro5,2",
+ "MacBookPro5,3",
+ "MacBookPro5,4",
+ "MacBookPro5,5",
+ "MacBookPro6,1",
+ "MacBookPro6,2",
+ "MacBookPro7,1",
+ "Macmini3,1",
+ "Macmini4,1",
+ "Macmini5,1",
+ "Macmini5,2",
+ "Macmini5,3",
+ "iMac7,1",
+ "iMac8,1",
+ "iMac9,1",
+ "iMac10,1",
+ "iMac11,1",
+ "iMac11,2",
+ "iMac11,3",
+ "Dortania1,1",
+]
\ No newline at end of file
diff --git a/Resources/Utilities.py b/Resources/Utilities.py
index 3fa454cff..24ca2b3a2 100644
--- a/Resources/Utilities.py
+++ b/Resources/Utilities.py
@@ -7,6 +7,7 @@ import os
import plistlib
import subprocess
from pathlib import Path
+import re
import requests
@@ -49,6 +50,27 @@ def get_disk_path():
return root_mount_path
+def latebloom_detection(model):
+ if model in ["MacPro4,1", "MacPro5,1", "iMac7,1", "iMac8,1"]:
+ # These machines are more likely to experience boot hangs, increase delays to accomodate
+ lb_delay = "250"
+ else:
+ lb_delay = "100"
+ lb_range = "1"
+ lb_debug = "0"
+ if get_nvram("boot-args", decode=False):
+ if "latebloom=" in get_nvram("boot-args", decode=False):
+ lb_delay = re.search(r"(?:[, ])latebloom=(\d+)", get_nvram("boot-args", decode=False))
+ lb_delay = lb_delay[1]
+ if "lb_range=" in get_nvram("boot-args", decode=False):
+ lb_range = re.search(r"(?:[, ])lb_range=(\d+)", get_nvram("boot-args", decode=False))
+ lb_range = lb_range[1]
+ if "lb_debug=" in get_nvram("boot-args", decode=False):
+ lb_debug = re.search(r"(?:[, ])lb_debug=(\d+)", get_nvram("boot-args", decode=False))
+ lb_debug = lb_debug[1]
+ return int(lb_range), int(lb_range), int(lb_debug)
+
+
def csr_decode(csr_active_config, os_sip):
if csr_active_config is None:
csr_active_config = b"\x00\x00\x00\x00"
diff --git a/payloads/Config/config.plist b/payloads/Config/config.plist
index dda43d9c7..de93fff23 100644
--- a/payloads/Config/config.plist
+++ b/payloads/Config/config.plist
@@ -940,7 +940,7 @@
BundlePath
DebugEnhancer.kext
Comment
-
+ Enhance DEBUG output in system logs
Enabled
ExecutablePath
@@ -952,6 +952,24 @@
PlistPath
Contents/Info.plist
+
+ Arch
+ x86_64
+ BundlePath
+ latebloom.kext
+ Comment
+ Work-around PCI race condition
+ Enabled
+
+ ExecutablePath
+ Contents/MacOS/latebloom
+ MaxKernel
+
+ MinKernel
+ 20.4.0
+ PlistPath
+ Contents/Info.plist
+
Block
diff --git a/payloads/Kexts/Misc/latebloom-v0.17.zip b/payloads/Kexts/Misc/latebloom-v0.17.zip
new file mode 100644
index 0000000000000000000000000000000000000000..62f88be2f18dc1102e75c12de589627680e908d9
GIT binary patch
literal 14385
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