Skip to content

Commit f113dc4

Browse files
committed
bugs: Apple's bad QA now gets its own module!
Add new logic to figure out EAN ProMotion state from WindowServer syslogs. Yes, this is utterly ugly, but it's the best I've got for now. Signed-off-by: Hector Martin <[email protected]>
1 parent 3547cdd commit f113dc4

2 files changed

Lines changed: 172 additions & 90 deletions

File tree

src/bugs.py

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
# SPDX-License-Identifier: MIT
2+
import subprocess, json, datetime, logging, sys
3+
from util import *
4+
5+
BUGGY_SFR_MIN = "14.0"
6+
7+
ALLOWED_MACOS_MIN = "14.1.1"
8+
9+
PROMOTION_DEVICES = {
10+
"j314cap",
11+
"j314sap",
12+
"j316cap",
13+
"j316sap",
14+
"j414cap",
15+
"j414sap",
16+
"j416cap",
17+
"j416sap",
18+
"j514cap",
19+
"j514sap",
20+
"j516cap",
21+
"j516sap",
22+
}
23+
24+
def get_boottime():
25+
p = subprocess.run(["sysctl", "-n", "kern.boottime"], capture_output=True, check=True)
26+
ts = int(p.stdout.split(b"sec = ")[1].split(b",")[0])
27+
dt = datetime.datetime.fromtimestamp(ts, datetime.timezone.utc)
28+
logging.info(f"System boot time: {dt}")
29+
return dt
30+
31+
def get_logs(start, process):
32+
logging.info(f"Getting {process} system logs")
33+
start_ts = int(start.timestamp())
34+
p = subprocess.run(["log", "show", "-p", process,
35+
"--start", f"@{start_ts}", "--style", "json",
36+
"--timezone", "utc"],
37+
capture_output=True, check=True)
38+
l = json.loads(p.stdout)
39+
for entry in json.loads(p.stdout):
40+
ts = entry["timestamp"].replace("+0000", "+00:00")
41+
dt = datetime.datetime.fromisoformat(ts)
42+
yield (dt, entry["eventMessage"])
43+
44+
def get_startup_display_mode():
45+
logging.info("get_startup_display_mode()")
46+
boot_time = get_boottime()
47+
startup = False
48+
for ts, message in get_logs(boot_time, "WindowServer"):
49+
logging.info(f"Log: {ts} {message}")
50+
delta = ts - boot_time
51+
if delta > datetime.timedelta(seconds=10):
52+
logging.warning("Failed to find startup/mode logs for WindowServer")
53+
break
54+
if "Server is starting up" in message:
55+
assert not startup
56+
startup = True
57+
if startup and "Display 1 current mode" in message:
58+
mode = int(message.split("[")[1].split(" ")[0])
59+
logging.info(f"Internal panel boot mode: {mode}")
60+
return mode
61+
62+
return None
63+
64+
def request_upgrade():
65+
p_error("Mismatched System Firmware / System Recovery detected!")
66+
print()
67+
p_warning("You have a machine with a ProMotion display, with a System Firmware version")
68+
p_warning("newer than 14.0 and a System Recovery version older than 14.0. Due to a")
69+
p_warning("critical macOS bug, this combination can lead to an unbootable system under")
70+
p_warning("certain conditions.")
71+
print()
72+
p_plain("Your machine is not currently in imminent danger, but will be safer if you")
73+
p_plain("upgrade to macOS Sonoma 14.1.1 or later. With this version, Apple added a")
74+
p_plain("temporary workaround that will make it harder to hit the bug in practice.")
75+
print()
76+
p_message("Please upgrade your system to macOS 14.1.1 or later and run this installer")
77+
p_message("again to continue. Do NOT change your display configuration until the upgrade")
78+
p_message("is complete.")
79+
print()
80+
81+
def sadness(sysinfo):
82+
p_error("Your machine is affected by a critical macOS bug!")
83+
print()
84+
p_warning("You have a machine with a ProMotion display, with a System Firmware version")
85+
p_warning("newer than 14.0 and a System Recovery version older than 14.0. Due to a")
86+
p_warning("critical Apple bug, this combination can lead to an unbootable system under")
87+
p_warning("certain conditions.")
88+
print()
89+
if split_ver(sysinfo.sros_ver) < split_ver(BUGGY_SFR_MIN):
90+
p_error("We have determined that your machine is affected and currently has an")
91+
p_error("inoperable System Recovery. This is a dangerous condition that can make it")
92+
p_error("impossible to recover from certain situations. Installing Asahi Linux is also")
93+
p_error("not possible in this state.")
94+
else:
95+
p_error("We have determined that your machine is affected and would not be able to")
96+
p_error("successfully complete an Asahi Linux installation, as it cannot boot older")
97+
p_error("versions of macOS Recovery in this state.")
98+
print()
99+
p_error("We cannot continue with the install. Sorry. You will have to wait for Apple")
100+
p_error("to fix this properly in a future update. This bug is entirely outside of our")
101+
p_error("control and there is no easy workaround at this time.")
102+
print()
103+
p_plain("More information:")
104+
print()
105+
p_plain( f" {col(BLUE, BRIGHT)}https://github.com/AsahiLinux/docs/wiki/macOS-Sonoma-Boot-Failures{col()}")
106+
107+
def you_are_safe(main):
108+
p_plain("Good news! Your machine should be unaffected by the critical ProMotion")
109+
p_plain("boot failure bug at this time. If you have any other versions of macOS")
110+
p_plain("installed side-by-side, we strongly recommend not booting them until")
111+
p_plain("Apple properly and fully fixes this bug, as that could cause the issue")
112+
p_plain("to trigger and your machine to become unbootable. Asahi Linux installs")
113+
p_plain("are safe and will not cause any danger to your system.")
114+
print()
115+
p_message("Press enter to continue.")
116+
main.input()
117+
118+
def run_checks(main):
119+
if main.sysinfo.device_class not in PROMOTION_DEVICES:
120+
return
121+
122+
if split_ver(main.sysinfo.sfr_ver) < split_ver(BUGGY_SFR_MIN):
123+
return
124+
125+
p_progress("Checking whether your machine is affected by critical Apple bugs...")
126+
print()
127+
128+
hz = main.sysinfo.get_refresh_rate()
129+
if hz is None:
130+
p_warning("Could not check ProMotion display status")
131+
p_plain("This probably means your laptop lid is closed. Please open it and try again.")
132+
p_plain("(You're going to have to use the power button soon anyway!)")
133+
print()
134+
sys.exit(1)
135+
136+
p_info(f" Current display refresh rate: {col()}{hz} Hz")
137+
print()
138+
if hz != 120.0:
139+
p_error("Your display is not set to ProMotion mode (120 Hz). Please change your")
140+
p_error("display refresh rate to ProMotion mode in System Settings, then reboot")
141+
p_error("your machine with the lid open and try again.")
142+
print()
143+
p_error("Due to a critical Apple bug, it is not safe to install multiple operating")
144+
p_error("systems on your Mac with a non-ProMotion refresh rate configured.")
145+
print()
146+
sys.exit(1)
147+
148+
mode = get_startup_display_mode()
149+
if mode is None:
150+
p_warning("Could not check boot-time display configuration")
151+
p_plain("This can happen if you have not rebooted your machine in several days.")
152+
p_plain("Please reboot your machine with the laptop lid open, then try again.")
153+
print()
154+
sys.exit(1)
155+
156+
if split_ver(main.sysinfo.macos_ver) < split_ver(ALLOWED_MACOS_MIN):
157+
if mode != 2:
158+
p_warning("Mismatch between screen boot mode and current screen mode detected.")
159+
print()
160+
p_plain("Please reboot your machine and try again.")
161+
print()
162+
else:
163+
request_upgrade()
164+
sys.exit(1)
165+
166+
if mode == 2:
167+
you_are_safe(main)
168+
else:
169+
sadness(main.sysinfo)
170+
sys.exit(1)

src/main.py

Lines changed: 2 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import os, os.path, shlex, subprocess, sys, time, termios, json, getpass, reporting
44
from dataclasses import dataclass
55

6-
import system, osenum, stub, diskutil, osinstall, asahi_firmware, m1n1
6+
import system, osenum, stub, diskutil, osinstall, asahi_firmware, m1n1, bugs
77
from util import *
88

99
PART_ALIGN = psize("1MiB")
@@ -21,9 +21,6 @@
2121
MIN_MACOS_VERSION = "13.5"
2222
MIN_MACOS_VERSION_EXPERT = "12.3"
2323

24-
# Apple...
25-
BUGGY_SFR_MIN = "14.0"
26-
2724
@dataclass
2825
class IPSW:
2926
version: str
@@ -50,21 +47,6 @@ class Device:
5047
0x6022: "13.4", # T6022, M2 Ultra
5148
}
5249

53-
PROMOTION_DEVICES = {
54-
"j314cap",
55-
"j314sap",
56-
"j316cap",
57-
"j316sap",
58-
"j414cap",
59-
"j414sap",
60-
"j416cap",
61-
"j416sap",
62-
"j514cap", # Speculative
63-
"j514sap",
64-
"j516cap",
65-
"j516sap",
66-
}
67-
6850
DEVICES = {
6951
"j274ap": Device("11.0", False), # Mac mini (M1, 2020)
7052
"j293ap": Device("11.0", False), # MacBook Pro (13-inch, M1, 2020)
@@ -850,77 +832,7 @@ def main(self):
850832
self.sysinfo.show()
851833
print()
852834

853-
if (self.sysinfo.device_class in PROMOTION_DEVICES and
854-
split_ver(self.sysinfo.sfr_ver) >= split_ver(BUGGY_SFR_MIN)):
855-
856-
hz = self.sysinfo.get_refresh_rate()
857-
if hz is None:
858-
p_error("Could not check ProMotion display status")
859-
print("This probably means your laptop lid is closed. Please open it and try again.")
860-
print("(You're going to have to use the power button soon anyway!)")
861-
print()
862-
sys.exit(1)
863-
864-
if split_ver(self.sysinfo.sros_ver) < split_ver(BUGGY_SFR_MIN) and not self.expert:
865-
p_error("Mismatched System Firmware / System Recovery detected!")
866-
print()
867-
p_warning("You have a machine with a ProMotion display, with a System Firmware version")
868-
p_warning("newer than 14.0 and a System Recovery version older than 14.0. Due to a")
869-
p_warning("critical Apple bug, this combination can lead to an unbootable system under")
870-
p_warning("certain conditions.")
871-
print()
872-
p_error("Given the complexity of the issue, we cannot detect whether this install is")
873-
p_error("safe or could render your machine unbootable as a side-effect of the")
874-
p_error("installation process. This is out of our control, as the fault lies entirely")
875-
p_error("in Apple's code (which is involved in the install process).")
876-
print()
877-
p_error("We cannot continue with the install. Sorry. You will have to wait for Apple")
878-
p_error("to fix this properly in a future update. We promise we tried everything we")
879-
p_error("could to find a safe way to proceed, but Apple's haphazard updates and changes")
880-
p_error("in response to this bug made the situation so complicated we had to give up")
881-
p_error("until they fix it properly.")
882-
print()
883-
p_plain( f" {col(BLUE, BRIGHT)}https://github.com/AsahiLinux/docs/wiki/macOS-Sonoma-Boot-Failures{col()}")
884-
print()
885-
p_plain("If you have another Mac handy, doing a DFU \"Revive\" using Apple Configurator")
886-
p_plain("from the other machine may put your machine into a safer state that allows us")
887-
p_plain("to continue with the installation.")
888-
print()
889-
sys.exit(1)
890-
else:
891-
p_warning( "WARNING: You have a MacBook Pro with a ProMotion display, and you have")
892-
p_warning(f"System Firmware version {BUGGY_SFR_MIN} or newer. These firmware versions are")
893-
p_warning( "buggy and will NOT correctly boot older versions of macOS, nor Asahi Linux,")
894-
p_warning( "if the display is configured for a refresh rate other than ProMotion (120Hz).")
895-
print()
896-
p_info(f" Current refresh rate: {col()}{hz} Hz")
897-
print()
898-
if hz != 120.0:
899-
p_error("Your display is not set to ProMotion mode (120 Hz). Please change your")
900-
p_error("display refresh rate to ProMotion mode in System Settings and try again.")
901-
print()
902-
p_error("It is not safe to multi-boot with a non-ProMotion refresh rate until")
903-
p_error("Apple fixes this bug.")
904-
print()
905-
sys.exit(1)
906-
907-
p_warning("It is possible for your machine to be in a silently broken state, which")
908-
p_warning("will cause it to boot to a black during the installation. We have no way")
909-
p_warning("to reliably know ahead of time whether this will happen.")
910-
print()
911-
p_warning("If you have never changed your display refresh rate away from ProMotion")
912-
p_warning("mode, you should be safe. If you indeed get stuck with a black screen")
913-
p_warning("after the boot logo, you must follow these steps:")
914-
print()
915-
p_plain(" 1. Fully shut down the machine by holding down the power button for 20 sec")
916-
p_plain(" 2. QUICKLY press, release, and press and hold the power button")
917-
print()
918-
p_warning("This will allow you to get into the boot picker and boot into macOS again.")
919-
p_warning("In this case, installing Asahi Linux will not be possible for you until")
920-
p_warning("Apple fully fixes this mess.")
921-
print()
922-
if not self.yesno("Continue anyway?"):
923-
sys.exit(0)
835+
bugs.run_checks(self)
924836

925837
self.chip_min_ver = CHIP_MIN_VER.get(self.sysinfo.chip_id, None)
926838
self.device = DEVICES.get(self.sysinfo.device_class, None)

0 commit comments

Comments
 (0)