Skip to content

Commit 7720c64

Browse files
committed
Apple really screwed this one up. :(
Signed-off-by: Hector Martin <[email protected]>
1 parent 9647c9b commit 7720c64

2 files changed

Lines changed: 89 additions & 5 deletions

File tree

src/main.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
MIN_MACOS_VERSION = "13.5"
2222
MIN_MACOS_VERSION_EXPERT = "12.3"
2323

24+
# Apple...
25+
BUGGY_SFR_MIN = "14.0"
26+
2427
@dataclass
2528
class IPSW:
2629
version: str
@@ -46,6 +49,21 @@ class Device:
4649
0x6022: "13.4", # T6022, M2 Ultra
4750
}
4851

52+
PROMOTION_DEVICES = {
53+
"j314cap",
54+
"j314sap",
55+
"j316cap",
56+
"j316sap",
57+
"j414cap",
58+
"j414sap",
59+
"j416cap",
60+
"j416sap",
61+
"j514cap", # Speculative
62+
"j514sap",
63+
"j516cap",
64+
"j516sap",
65+
}
66+
4967
DEVICES = {
5068
"j274ap": Device("11.0", False), # Mac mini (M1, 2020)
5169
"j293ap": Device("11.0", False), # MacBook Pro (13-inch, M1, 2020)
@@ -825,6 +843,47 @@ def main(self):
825843
self.sysinfo = system.SystemInfo()
826844
self.sysinfo.show()
827845
print()
846+
847+
if self.sysinfo.sfr_full_ver != self.sysinfo.sros_full_ver:
848+
p_error("Mismatched System Firmware / System Recovery detected!")
849+
print()
850+
p_error("Critical bugs in Apple's update process introduced in macOS Sonoma 14.0 and")
851+
p_error("macOS Ventura 13.6 can cause your System Recovery to not be updated properly.")
852+
p_error("It is not safe to install a new OS on this computer until this is resolved.")
853+
p_error("Please apply all macOS updates available and try again. If the problem remains,")
854+
p_error("you will have to wait until Apple fixes their buggy update process.")
855+
print()
856+
p_error("More information:")
857+
p_error("https://github.com/AsahiLinux/docs/wiki/macOS-Sonoma-Boot-Failures")
858+
print()
859+
sys.exit(1)
860+
861+
if (self.sysinfo.device_class in PROMOTION_DEVICES and
862+
split_ver(self.sysinfo.sfr_ver) > split_ver(BUGGY_SFR_MIN)):
863+
p_warning( "WARNING: You have a MacBook Pro with a ProMotion display, and you have")
864+
p_warning(f"System Firmware version {BUGGY_SFR_MIN} or newer. These firmware versions are")
865+
p_warning( "buggy and will NOT correctly boot older versions of macOS, nor Asahi Linux,")
866+
p_warning( "if the display is configured for a refresh rate other than ProMotion (120Hz).")
867+
print()
868+
hz = self.sysinfo.get_refresh_rate()
869+
p_info(f" Current refresh rate: {col()}{hz}")
870+
print()
871+
if hz != "120.00Hz":
872+
p_error("Your display is not set to ProMotion mode (120 Hz). Please change your")
873+
p_error("display refresh rate to ProMotion mode in System Settings and try again.")
874+
print()
875+
p_error("It is not safe to multi-boot with a non-ProMotion refresh rate until")
876+
p_error("Apple fixes this bug.")
877+
print()
878+
sys.exit(1)
879+
880+
p_warning("You are currently using ProMotion mode. You may continue the install")
881+
p_warning("but you MUST NOT change the refresh rate until Apple fixes this bug.")
882+
p_warning("There is nothing we can do on our end. Proceed at your own risk.")
883+
print()
884+
if not self.yesno("Continue anyway?"):
885+
sys.exit(0)
886+
828887
self.chip_min_ver = CHIP_MIN_VER.get(self.sysinfo.chip_id, None)
829888
self.device = DEVICES.get(self.sysinfo.device_class, None)
830889
if not self.chip_min_ver or not self.device or (self.device.expert_only and not self.expert):

src/system.py

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# SPDX-License-Identifier: MIT
2-
import base64, plistlib, struct, subprocess, logging
2+
import base64, plistlib, struct, subprocess, logging, json
33

44
from util import *
55

@@ -82,6 +82,17 @@ def fetch(self):
8282
if consoleuser != "_mbsetupuser":
8383
self.login_user = consoleuser
8484

85+
self.sros_full_ver = "0"
86+
87+
base = "/System/Volumes/iSCPreboot/SystemRecovery"
88+
for p in os.listdir(base):
89+
try:
90+
v = self.get_restore_version(os.path.join(base, p, "RestoreVersion.plist"))
91+
except Exception:
92+
continue
93+
if split_ver(v) > split_ver(self.sros_full_ver):
94+
self.sros_full_ver = v
95+
8596
def get_nvram_data(self):
8697
nvram_data = subprocess.run(["nvram", "-p"],
8798
stdout=subprocess.PIPE, check=True).stdout
@@ -129,12 +140,13 @@ def show(self):
129140
p_info(f" Default boot VGID: {col()}{self.default_boot}")
130141
p_info(f" Boot mode: {col()}{self.boot_mode}")
131142
p_info(f" OS version: {col()}{self.macos_ver} ({self.macos_build})")
132-
p_info(f" SFR version: {col()}{self.sfr_full_ver}")
133-
p_info(f" System rOS version: {col()}{self.sfr_ver} ({self.sfr_build})")
143+
p_info(f" Main firmware version: {col()}{self.sfr_ver} ({self.sfr_build})")
134144
if self.fsfr_ver:
135-
p_info(f" Fallback rOS version: {col()}{self.fsfr_ver} ({self.fsfr_build})")
145+
p_info(f" Fallback firmware version: {col()}{self.fsfr_ver} ({self.fsfr_build})")
136146
else:
137-
p_info(f" No Fallback rOS")
147+
p_info(f" No Fallback System Firmware / rOS")
148+
p_info(f" SFR version: {col()}{self.sfr_full_ver}")
149+
p_info(f" SystemRecovery version: {col()}{self.sros_full_ver}")
138150
p_info(f" Login user: {col()}{self.login_user}")
139151

140152
def get_child(self, obj, name):
@@ -155,3 +167,16 @@ def get_str(self, val):
155167
def get_int(self, val):
156168
return struct.unpack("<I", val)[0]
157169

170+
def get_refresh_rate(self):
171+
j = subprocess.run(["system_profiler", "SPDisplaysDataType", "-json"],
172+
stdout=subprocess.PIPE, check=True).stdout
173+
174+
main_display = None
175+
for a in json.loads(j)["SPDisplaysDataType"]:
176+
for disp in a.get("spdisplays_ndrvs", []):
177+
if disp["_name"] != "Color LCD":
178+
continue
179+
assert main_display is None
180+
main_display = disp
181+
182+
return main_display["_spdisplays_resolution"].split()[-1]

0 commit comments

Comments
 (0)